• 0
Kitty

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

Вопросы

Здравствуйте.
У меня есть код, который успешно без проблем отрабатывает в 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 я вижу диалоговое окно без каких-либо проблем и сообщений об ошибке.
Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 ответов на этот вопрос

  • 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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 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++ с использованием анонимной процедуры.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

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

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