Перейти к содержанию
Fire Monkey от А до Я
  • 0

[Android] [XE7] Ошибка класса ENotImplemented


Kitty

Вопрос

Здравствуйте.
У меня есть код, который успешно без проблем отрабатывает в RAD XE6. В готовом APK нет никаких проблем.
Если перенести этот код в RAD XE7, то в готовом APK возникает ошибка класса ENotImplemented, сообщение Blocking dialogs not implemented on this platform.
Ошибка возникает при нажатии на кнопку, в которой есть такой код:

if (MessageDlg(L"Удалить секцию: " + LabelSection->Text + L"?", TMsgDlgType::mtConfirmation, TMsgDlgButtons() << TMsgDlgBtn::mbYes << TMsgDlgBtn::mbNo, 0) == mrYes)
{
//***
}

Подскажите, пожалуйста, как исправить, чтобы работало в созданном APK из RAD XE7?
В APK из RAD XE6 я вижу диалоговое окно без каких-либо проблем и сообщений об ошибке.
Спасибо.

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Администраторы

Добрый день,
 
Используйте вариант функции MessageDlg с дополнительным параметром ACloseDialogEvent. Теперь диалоги не блокируемые на андроиде. Поэтому результат выполнения диалога приходит в указанный Callback.

MessageDlg('Удалить секцию: ' + LabelSection.Text + '?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], -1, procedure (const AResult: TModalResult) begin 
  if AResurlt = mrYes then
    //
end)

Ссылка на эту тему:

Ссылка на комментарий
  • 0

Проскочила фраза на просторах интернета:

The catch is that the anonymous procedure is now required for Android, but implementing an anonymous procedure in C++ is more difficult than in Delphi.

 

Все мои попытки сделать это в С++ Builder не увенчались успехом. Кто нибудь может выложить рабочий код на С++?

Спасибо.

Ссылка на комментарий
  • 0

Если найдется гуру на С++, подскажите пожалуйста, скелет вызова 3 раза анонимного метода с разными сообщениями и один раз MessageDlg для условия if. В коде после MessageDlg вызываются ShowMessage, получается надо из анонимного метода вызвать другой анонимный метод?

void StopTimers()
{
 MainForm->Timer1->Enabled = false;
 MainForm->Button1->Enabled = true;
}


void __fastcall TMainForm::ButtonDeleteClick(TObject *Sender)
{
  try
	 {
	  if(LabelSection->Text != "")
	  {
		if (MessageDlg(L"Удалить секцию: " + LabelSection->Text + L"?", TMsgDlgType::mtConfirmation, TMsgDlgButtons() << TMsgDlgBtn::mbYes << TMsgDlgBtn::mbNo, 0) == mrYes)
		{

		   #ifdef __ANDROID__
		   String path = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetSharedDownloadsPath(), L"files.ini");
		   #elif _Windows
		   String path = System::Ioutils::TPath::Combine(GetCurrentDir(), L"files.ini");
		   #endif

		   if(FileExists(path))
			 {
			  std::unique_ptr<TIniFile> FileINI(new TIniFile(path));
			  FileINI->EraseSection(LabelSection->Text);
			  FileINI->UpdateFile();

			  if(!Control())
				 {
				  StopTimers();
				  Application->Terminate();
				  return;
				 }

			   //IniContent был заполнен в функции Control()
			   ListView1->Items->Clear();
			   std::map<String, std::vector<String> >::iterator It = IniContent.begin();//map был заполнен в Control()
			   int i = 1;

				 while (It != IniContent.end())
				  {
				   TListViewItem * item = ListView1->Items->Add();
				   item->Text = L"№" + IntToStr(i) + " " + IniContent[(*It).first][1];//имя файла из ini
				   item->Detail = MainForm->IniContent[(*It).first][2];//about из ini файла
				   item->BitmapRef = Image1->Bitmap;
				   item->Data[sText] = TValue::From<UnicodeString>((*It).first);//время из ini пишем справа в списке
				   //ShowMessage((*It).first);
				   It++;
				   i++;
				  }

			  //***
			  if(!IniContent.empty())
			  ShowMessage(L"Секция удалена из файла расписания.");

			  ChangeTabAction1->Tab = TabItem1;
			  ChangeTabAction1->ExecuteTarget(this);

			 }
			 else
				{
				 ShowMessage(L"Не найден файл files.ini. Программа будет закрыта.");
				 Application->Terminate();
				}
		}

	  }
	}
	catch(Exception &E)
		  {
		   StopTimers();
		   ShowMessage(L"Произошла ошибка в ButtonDeleteClick. Класс ошибки: " + E.ClassName() +
		   L"\nСообщение ошибки: " + E.Message + L" Программа будет закрыта.");
		   Application->Terminate();
		  }
}

Ссылка на комментарий
  • 0

Попытка №1. Помогите исправить ошибку:

class TMyMessageDlgCloseProc1 : public TInterfacedObject, public Fmx::Dialogs::TInputCloseDialogProc
{
public:
	HRESULT STDMETHODCALLTYPE QueryInterface (const GUID& riid, void** ppvObject) { return TInterfacedObject::QueryInterface (riid, ppvObject); }
	ULONG STDMETHODCALLTYPE AddRef() { return TInterfacedObject::_AddRef(); }
	ULONG STDMETHODCALLTYPE Release() { return TInterfacedObject::_Release(); }

	void __fastcall Invoke(const TModalResult AResult)
	{
		if (AResult == mrYes)
		{
		 //***
		}
	}
};
 _di_TInputCloseDialogProc proc = new TMyMessageDlgCloseProc1;
MessageDlg(L"Удалить:  " + LabelSection->Text + L"?", TMsgDlgType::mtConfirmation, TMsgDlgButtons() << TMsgDlgBtn::mbYes << TMsgDlgBtn::mbNo, 0, proc);

[bccaarm Error] MobUnit1.cpp(694): allocating an object of abstract class type 'TMyMessageDlgCloseProc1'
  sysmac.h(300): unimplemented pure virtual method 'QueryInterface' in 'TMyMessageDlgCloseProc1'

Ссылка на комментарий
  • 0

 

Добрый день,

 

Используйте вариант функции MessageDlg с дополнительным параметром ACloseDialogEvent. Теперь диалоги не блокируемые на андроиде. Поэтому результат выполнения диалога приходит в указанный Callback.

MessageDlg('Удалить секцию: ' + LabelSection.Text + '?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], -1, procedure (const AResult: TModalResult) begin 
  if AResurlt = mrYes then
    //
end)

 

Получаю аналогичную ошибку "blocking dialogs not implemented on this platform" при использовании InputQuery

  try
    if InputQuery( 'Enter New Item', 'Name', TaskName) and (TaskName.Trim <> '') then
    begin
      FDQueryInsert.ParamByName('ShopItem').AsString := TaskName;
      FDQueryInsert.ExecSQL();
      FDQuery1.Close;
      FDQuery1.Open;
    end;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;

 

Подскажите что дописать в InputQuery?

Ссылка на комментарий
  • 0
  • Модераторы

 

 

Добрый день,

 

Используйте вариант функции MessageDlg с дополнительным параметром ACloseDialogEvent. Теперь диалоги не блокируемые на андроиде. Поэтому результат выполнения диалога приходит в указанный Callback.

MessageDlg('Удалить секцию: ' + LabelSection.Text + '?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], -1, procedure (const AResult: TModalResult) begin 
  if AResurlt = mrYes then
    //
end)

 

Получаю аналогичную ошибку "blocking dialogs not implemented on this platform" при использовании InputQuery

  try
    if InputQuery( 'Enter New Item', 'Name', TaskName) and (TaskName.Trim <> '') then
    begin
      FDQueryInsert.ParamByName('ShopItem').AsString := TaskName;
      FDQueryInsert.ExecSQL();
      FDQuery1.Close;
      FDQuery1.Open;
    end;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;

 

Подскажите что дописать в InputQuery?

 

в FMX он работает по другому

 

InputQuery имеет еще параметры

смотрим внимательно

type
  TInputCloseQueryEvent = procedure(Sender: TObject; const Values: array of string; var CanClose: Boolean) of object;
  TInputCloseQueryFunc = reference to function(const Values: array of string): Boolean;
  TInputCloseQueryProc = reference to procedure(const AResult: TModalResult; const AValues: array of string);
  TInputCloseBoxProc = reference to procedure(const AResult: TModalResult; const AValue: string);
  TInputCloseDialogProc = reference to procedure(const AResult: TModalResult);
  TInputCloseDialogEvent = procedure(Sender: TObject; const AResult: TModalResult) of object;
  TInputCloseQueryWithResultEvent = procedure(Sender: TObject; const AResult: TModalResult; const AValues: array of string) of object;
  TInputCloseBoxEvent = procedure(Sender: TObject; const AResult: TModalResult; const AValue: string) of object;
Ссылка на комментарий
  • 0

Нашлось решение для С++: http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE7/CPP/Mobile%20Snippets/MessageAlerts/

Все хорошо, только как руссофицировать кнопки в MessageDlg?

Смею предположить, что эти названия лежат в константах в файле "FMX.Consts.pas", только как там его в C++ :)

Ссылка на комментарий
  • 0

InputQuery имеет еще параметры

смотрим внимательно

type
  TInputCloseQueryEvent = procedure(Sender: TObject; const Values: array of string; var CanClose: Boolean) of object;
  TInputCloseQueryFunc = reference to function(const Values: array of string): Boolean;
  TInputCloseQueryProc = reference to procedure(const AResult: TModalResult; const AValues: array of string);
  TInputCloseBoxProc = reference to procedure(const AResult: TModalResult; const AValue: string);
  TInputCloseDialogProc = reference to procedure(const AResult: TModalResult);
  TInputCloseDialogEvent = procedure(Sender: TObject; const AResult: TModalResult) of object;
  TInputCloseQueryWithResultEvent = procedure(Sender: TObject; const AResult: TModalResult; const AValues: array of string) of object;
  TInputCloseBoxEvent = procedure(Sender: TObject; const AResult: TModalResult; const AValue: string) of object;

Вернулся к этому вопросу и так абсолютно ничего не понял. Пишу так:

if (InputQuery('Enter New Item', ['Name'], TaskName,
function(const Values: array of string): Boolean
begin
Result:=true;
end
)) then ...

На что также в приложении при вызове InputQuery получаю "blocking dialogs not implemented on this platform". В чем ошибка?

Изменено пользователем Rusland
Ссылка на комментарий
  • 0
  • Модераторы
procedure TForm22.Button1Click(Sender: TObject);
var
  aParams: TMapsEngineYandexLocator;
  params, values: array of string;
begin
  // 37.151.215.206  Астана, Казахстан
  SetLength(params, 1);
  SetLength(values, 1);
  params[0] := 'Внешний IP';
  InputQuery('Введите...', params, values,
    procedure(const AResult: TModalResult; const AValues: array of string)
    begin
      if AResult = mrOk then
      begin
        mEngine.SetOptionsYandexLocator('');
        aParams.IP.IPAddress_v4 := AValues[0];
        TTask.Run(
          procedure
          begin
            mEngine.YandexLocator(aParams, TMapsEngineYandexLocatorType.IP, myLoc);

            mEngine.SetOptionsYandex(''); // получить через Yandex
            mEngine.Geocoding(myLoc, aData);

            TThread.Synchronize(nil,
              procedure
              begin
                lbCoordinate.Text := 'lat: ' + myLoc.Latitude.tostring + ' lon: ' + myLoc.Longitude.tostring;
                lbAddress.Text := aData.CountryCode + ' ' + aData.City + ' ' + aData.FormattedAddress;
              end);
          end);
      end;
    end);
end;
Ссылка на комментарий
  • 0

Kitty, я воспользовался вашим примером MessageAlert, но реализовать элементарную развязку IF не смог.

struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc> {
void __fastcall Invoke(const System::Uitypes::TModalResult AResult) {
      switch (AResult) {
      case mrYes :
        ShowMessage("You chose Yes");

 

// Здесь мне нужно запустить свою процедуру.

        break;
      case mrNo:
        ShowMessage("You chose No");
        break;
      case mrCancel:
        ShowMessage("You chose Cancel");
        break;
      }
    }
  };
_di_TInputCloseDialogProc handler = new TCloseDialogHandler();

MessageDlg("Choose a button:", TMsgDlgType::mtInformation, TMsgDlgButtons() << TMsgDlgBtn::mbYes << TMsgDlgBtn::mbNo << TMsgDlgBtn::mbCancel , 0, handler);
 

Отразить какую кнопку выбрал пользователь в этой (анонимной) процедуре можно, но как заставить по mrYes выполнить нужные мне команды?

Помогите, кто знает.

Ссылка на комментарий
  • 0
struct TCloseDialogHandler :public TCppInterfacedObject<TInputCloseDialogProc> {
void __fastcall Invoke(const System::Uitypes::TModalResult AResult) {
	  switch (AResult) {
case mrYes : ShowMessage("You chose Yes");
break;
case mrNo: ShowMessage("You chose No");
  break;
case mrCancel: ShowMessage("You chose Cancel");
break;
}
}
  };
  
  
void __fastcall TForm1::SpeedButtonClick(TObject *Sender)
{

_di_TInputCloseDialogProc handler =new TCloseDialogHandler();

  MessageDlg(L"Внимание! Здесь вопрос?",
					TMsgDlgType::mtConfirmation,
					TMsgDlgButtons() << TMsgDlgBtn::mbYes
									 << TMsgDlgBtn::mbNo,
					0, handler );
}

 

- Рабочий пример использования MessageDlg на C++ с использованием анонимной процедуры.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...