Как создать универсальную функцию для отображения диалоговых окон с сообщениями в Delphi FMX: пример на Pascal с обработкой различных типов кнопок и иконок.
Универсальная функция для отображения диалоговых окон в Delphi FMX
В разработке кросс-платформенных приложений с использованием Delphi FireMonkey (FMX) часто возникает необходимость выводить диалоговые окна с сообщениями. Однако, в отличие от Windows, на мобильных платформах (Android/iOS) подход к обработке таких диалогов должен быть асинхронным, чтобы не блокировать основной поток приложения.
Проблема блокирующих диалогов
Как отмечают эксперты в комментариях к исходному вопросу, блокировка основного потока на Android приведёт к аварийному завершению приложения через несколько секунд. Это фундаментальное отличие мобильных платформ от Windows, где блокирующие диалоги работают корректно.
Рассмотрим решение, которое будет работать корректно на всех платформах, включая мобильные.
Универсальная функция для отображения сообщений
type
TDialogCallback = procedure(Result: TModalResult) of object;
procedure ShowGenericMessage(const MessageText: string;
Icon: Integer;
Callback: TDialogCallback = nil);
var
DialogType: TMsgDlgType;
Buttons: TMsgDlgButtons;
DefaultButton: TMsgDlgBtn;
begin
if MessageText = '' then Exit;
// Определяем тип диалога по значку
DialogType := mtCustom;
if (Icon and MB_ICONQUESTION) = MB_ICONQUESTION then
DialogType := mtConfirmation
else if (Icon and MB_ICONWARNING) = MB_ICONWARNING then
DialogType := mtWarning
else if (Icon and MB_ICONERROR) = MB_ICONERROR then
DialogType := mtError
else if (Icon and MB_ICONINFORMATION) = MB_ICONINFORMATION then
DialogType := mtInformation;
// Определяем кнопки
if (Icon and MB_YESNO) = MB_YESNO then
begin
Buttons := [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo];
DefaultButton := TMsgDlgBtn.mbNo;
end
else if (Icon and MB_OKCANCEL) = MB_OKCANCEL then
begin
Buttons := [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel];
DefaultButton := TMsgDlgBtn.mbCancel;
end
else
begin
Buttons := [TMsgDlgBtn.mbOK];
DefaultButton := TMsgDlgBtn.mbOK;
end;
// Отображаем диалог
TDialogService.MessageDialog(MessageText, DialogType, Buttons, DefaultButton, 0,
procedure(const AResult: TModalResult)
begin
if Assigned(Callback) then
Callback(AResult);
end);
end;
Пример использования
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowGenericMessage('Вы уверены, что хотите удалить этот элемент?',
MB_ICONQUESTION or MB_YESNO,
procedure(Result: TModalResult)
begin
if Result = mrYes then
DeleteItem;
end);
end;
Альтернативное решение с синхронным поведением на Windows
Если вам необходимо поддерживать синхронное поведение на Windows, можно создать гибридное решение:
function ShowGenericMessageSync(const MessageText: string; Icon: Integer): TModalResult;
{$IFDEF MSWINDOWS}
var
Event: TEvent;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
Event := TEvent.Create;
try
ShowGenericMessage(MessageText, Icon,
procedure(AResult: TModalResult)
begin
Result := AResult;
Event.SetEvent;
end);
Event.WaitFor(INFINITE);
finally
Event.Free;
end;
{$ELSE}
Result := mrNone;
ShowGenericMessage(MessageText, Icon,
procedure(AResult: TModalResult)
begin
Result := AResult;
// Обработка результата должна быть в колбэке
end);
{$ENDIF}
end;
Рекомендации по архитектуре приложения
Разделение логики: Для мобильных платформ перестройте архитектуру приложения так, чтобы вся обработка после диалога выполнялась в колбэке.
Состояния приложения: Используйте механизм состояний для управления потоком выполнения после закрытия диалога.
Унификация кода: По возможности используйте одинаковый подход для всех платформ (асинхронный), это упростит поддержку кода.
Заключение
При разработке кросс-платформенных приложений важно учитывать особенности каждой платформы. Представленное решение позволяет создавать универсальные диалоговые окна, которые корректно работают на всех платформах, поддерживаемых FireMonkey. Для Windows сохраняется возможность синхронного вызова, а для мобильных платформ используется асинхронный подход с колбэками.
Использование такой архитектуры не только решает проблему блокировки основного потока на мобильных устройствах, но и способствует созданию более чистого и поддерживаемого кода.
Этот код предоставляет универсальную функцию для отображения диалоговых окон в Delphi FMX, учитывающую особенности мобильных платформ и обеспечивающую асинхронное выполнение для предотвращения блокировки основного потока.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS