I'm trying to show an information message and an animated gif (an Hourglass) while my application is busy (loading a query).
I have defined a Form to show that Message (using the code shown in this post: How to use Animated Gif in a delphi form). This is the constructor.
constructor TfrmMessage.Show(DisplayMessage: string);
begin
inherited Create(Application);
lblMessage.Caption := DisplayMessage;
// Set the Message Window on Top
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NoMove or SWP_NoSize);
Visible := True;
// Animate the HourGlass image
(imgHourGlass.Picture.Graphic as TGIFImage).Animate := True;
Update;
end;
The problem is that the animated Gif remains still while the main thread is busy (loading the query).
I have tried drawing manually the animation on a separate thread.
type
TDrawHourGlass = class(TThread)
private
FfrmMessage: TForm;
public
constructor Create(AfrmMessage: TForm);
procedure Execute; override;
procedure ShowFrame1;
procedure ShowFrame2;
procedure ShowFrame3;
procedure ShowFrame4;
procedure ShowFrame5;
end;
constructor TDrawHourGlass.Create(AfrmMessage: TForm);
begin
inherited Create(False);
FfrmMessage := AfrmMessage;
end;
procedure TDrawHourGlass.Execute;
var FrameActual: integer;
begin
FrameActual := 1;
while not Terminated do begin
case FrameActual of
1: Synchronize(ShowFrame1);
2: Synchronize(ShowFrame2);
3: Synchronize(ShowFrame3);
4: Synchronize(ShowFrame4);
5: Synchronize(ShowFrame5);
end;
FrameActual := FrameActual + 1;
if FrameActual > 6 then FrameActual := 1;
sleep(200);
end;
end;
procedure TDrawHourGlass.ShowFrame1;
begin
(FfrmMessage as TfrmMessage).imgHourGlass.Picture.Bitmap.Assign((FfrmMessage as TfrmMessage).Frame1.Picture.Graphic);
(FfrmMessage as TfrmMessage).imgHourGlass.Update;
end;
implementation
procedure TDrawHourGlass.ShowFrame2;
begin
(FfrmMessage as TfrmMessage).imgHourGlass.Picture.Bitmap.Assign((FfrmMessage as TfrmMessage).Frame2.Picture.Graphic);
(FfrmMessage as TfrmMessage).imgHourGlass.Update;
end;
procedure TDrawHourGlass.ShowFrame3;
begin
(FfrmMessage as TfrmMessage).imgHourGlass.Picture.Bitmap.Assign((FfrmMessage as TfrmMessage).Frame3.Picture.Graphic);
(FfrmMessage as TfrmMessage).imgHourGlass.Update;
end;
procedure TDrawHourGlass.ShowFrame4;
begin
(FfrmMessage as TfrmMessage).imgHourGlass.Picture.Bitmap.Assign((FfrmMessage as TfrmMessage).Frame4.Picture.Graphic);
(FfrmMessage as TfrmMessage).imgHourGlass.Update;
end;
procedure TDrawHourGlass.ShowFrame5;
begin
(FfrmMessage as TfrmMessage).imgHourGlass.Picture.Bitmap.Assign((FfrmMessage as TfrmMessage).Frame5.Picture.Graphic);
(FfrmMessage as TfrmMessage).imgHourGlass.Update;
end;
But I get the same result, while the main thread is busy the animation remains still, because the calls (FfrmMessage as TfrmMessage).imgHourGlass.Update; to draw each frame, waits until the main thread has finished (even when not calling them within a Synchronize).
Do you have a suggestion what can I also try ?.
Thank you.
AllocateHwnd
, or useSynchronize
to pass the dataset to the main thread. The animation keep running in the main thread. Create that form when the thread starts, destroy it when thread is terminated or starts waiting for another execution. – VictoriaSynchronize
will execute after such call finishes). Rule of thumb for a responsible UI is, keep the main thread without any long running blocking calls (which such REST call is, so move that call to a worker thread). – Victoria