В современном программировании на Delphi и Pascal часто возникает необходимость создания модальных диалогов, которые информируют пользователя о процессе выполнения длительных задач. Такие диалоги должны быть неперекрывающими, чтобы пользователь не мог закрыть их случайно, и содержать визуальную обратную связь, например, анимацию GIF. В данной статье мы рассмотрим, как создать такой диалог, учитывая несколько важных нюансов.
Проблемы, с которыми можно столкнуться
Блокировка основного потока UI: Если выполнять длительные задачи в основном потоке пользовательского интерфейса, то приложение станет неотзывчивым, и пользователь не сможет выполнять другие действия.
Оставление системных "призрачных" окон: Если не обработать правильно закрытие диалога, то система может оставить его "призраком", что приведет к утечкам памяти и другим проблемам.
Перенос задач в отдельный поток: Чтобы не блокировать основной поток UI, задачи нужно выполнять в отдельном потоке. Однако это может усложнить управление процессами и обновление информации в диалоге.
Обновление сообщений для пользователя: Нужно обеспечить возможность обновлять сообщения в диалоге во время выполнения задач.
Обработка исключений: Если в отдельном потоке возникнет исключение, нужно правильно обработать его, чтобы не повредить основное приложение.
Отображение анимированного GIF в диалоге: Чтобы создать визуальную обратную связь, в диалог нужно добавить анимированный GIF. Однако это может потребовать дополнительных усилий по настройке и управлению анимацией.
Решение этих проблем
Чтобы решить эти проблемы, мы создадим класс TWaiting, который будет представлять собой модальный диалог с анимацией GIF. Этот класс будет использовать отдельный поток для выполнения задач и обеспечивать обновление сообщений для пользователя. Кроме того, мы добавим обработку исключений, чтобы гарантировать корректное закрытие диалога и предотвратить утечки памяти.
Пример кода на Object Pascal (Delphi)
type
TWaiting = class(TForm)
WaitAnimation: TImage;
WaitMessage: TLabel;
WaitTitle: TLabel;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
strict private
class var FException: Exception;
private
class var WaitForm : TWaiting;
class procedure OnTerminateTask(Sender: TObject);
class procedure HandleException;
class procedure DoHandleException;
public
class procedure Start(const ATitle: String; const ATask: TProc);
class procedure Status(AMessage : String);
end;
implementation
{$R *.dfm}
procedure TWaiting.FormCreate(Sender: TObject);
begin
TGIFImage(WaitAnimation.Picture.Graphic).Animate := True;
end;
procedure TWaiting.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
class procedure TWaiting.Start(const ATitle: String; const ATask: TProc);
var
T : TThread;
begin
if (not Assigned(WaitForm))then
WaitForm := TWaiting.Create(nil);
T := TThread.CreateAnonymousThread(
procedure
begin
try
ATask;
except
HandleException;
end;
end);
T.OnTerminate := OnTerminateTask;
T.Start;
WaitForm.WaitTitle.Caption := ATitle;
WaitForm.ShowModal;
DoHandleException;
end;
class procedure TWaiting.Status(AMessage: String);
begin
TThread.Synchronize(TThread.CurrentThread,
procedure
begin
if (Assigned(WaitForm)) then
begin
WaitForm.WaitMessage.Caption := AMessage;
WaitForm.Update;
end;
end);
end;
class procedure TWaiting.OnTerminateTask(Sender: TObject);
begin
if (Assigned(WaitForm)) then
begin
WaitForm.Close;
WaitForm := nil;
end;
end;
class procedure TWaiting.HandleException;
begin
FException := Exception(AcquireExceptionObject);
end;
class procedure TWaiting.DoHandleException;
begin
if (Assigned(FException)) then
begin
try
if (FException is Exception) then
raise FException at ReturnAddress;
finally
FException := nil;
ReleaseExceptionObject;
end;
end;
end;
end.
Пример использования
procedure TFSales.FinalizeSale;
begin
TWaiting.Start('Processing Sale...',
procedure
begin
TWaiting.Status('Sending data to database');
Sleep(2000);
TWaiting.Status('Updating Inventory');
Sleep(2000);
end);
end;
Этот пример создает модальный диалог с анимацией GIF, который информирует пользователя о процессе завершения продажи. Диалог обновляет сообщение во время выполнения задач и гарантирует корректное закрытие даже в случае возникновения исключений.
Заключение
В данной статье мы рассмотрели, как создать неперекрывающий модальный диалог с анимацией GIF в Delphi и Pascal, учитывая несколько важных нюансов. Используя класс TWaiting, мы можем создавать диалоги, которые не блокируют основной поток UI, не оставляют системных "призрачных" окон, выполняют задачи в отдельном потоке, обновляют сообщения для пользователя, обрабатывают исключения и отображают анимированный GIF. Это позволяет создавать интуитивно понятные и удобные для пользователя диалоги, которые информируют о процессе выполнения длительных задач.
Данная статья посвящена созданию модальных диалогов в программировании на Delphi и Pascal с анимацией GIF для информирования пользователя о длительных задачах, учитывая важные нюансы, такие как блокировка основного потока UI, оставление системных "призрач
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.