Этот вопрос намного сложнее, чем предполагалось изначально; что делает это хорошим вопросом.
Изначально я думал, что Application.processmessages - правильный путь, однако это потенциальное минное поле, если вы не будете осторожны (спасибо @skamradt за это). Это также не помогает с одним блокирующим вызовом.
Необходим фоновый поток следующим образом: (спасибо @mghie за указание на ошибки, которые
сейчас решены). Могут быть проблемы с вызовом объекта базы данных в разных потоках, поэтому фоновому потоку может потребоваться собственное подключение к базе данных для этой операции (если это практически возможно).
В приведенном ниже примере я специально не показывал код для создания и уничтожения окна прогресса, так как он сделает код еще длиннее и его легко выполнить.
Итак, для этого нам нужны два объекта:
Во-первых, фоновый поток для обработки запроса.
unit BackgroundProcess;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, windows;
const
WM_MY_BACKGROUNDNOTIFY = WM_USER + 555; { change this }
NOTIFY_BEGIN = 22;
NOTIFY_END = 33;
type
TBackgroundQueryThread = class(TThread)
private
hwndnotify : HWND;
protected
procedure Execute; override;
public
constructor Create(owner: TForm);
end;
implementation
constructor TBackgroundQueryThread.Create(owner: TForm) ;
begin
inherited Create(False);
hwndnotify := owner.Handle;
FreeOnTerminate := true;
resume;
end;
procedure TBackgroundQueryThread.Execute;
begin
PostMessage(hwndnotify, WM_MY_BACKGROUNDNOTIFY, NOTIFY_BEGIN, 0);
Sleep(2000); (* Query goes here. *)
PostMessage(hwndnotify, WM_MY_BACKGROUNDNOTIFY, NOTIFY_END, 0);
end;
end.
Форма, которая вызывает запрос:
unit mainform;
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, windows, BackgroundProcess;
type
TForm1 = class(TForm)
private
frm : tFrmPopupElapsed;
{ private declarations }
procedure OnMyBackgrounNotify(var Msg: TMessage); message WM_MY_BACKGROUNDNOTIFY;
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
procedure TForm1.OnMyBackgrounNotify(var Msg: TMessage);
begin
if (msg.WParam = NOTIFY_BEGIN) THEN
BEGIN
if (frm = nil) THEN
BEGIN
frm := tFrmPopupElapsed.Create(nil);
frm.Init; // this procedure enables the timer
frm.Show();
END;
END;
if (msg.WParam = NOTIFY_END) THEN
BEGIN
if (frm <> nil) THEN
BEGIN
frm.Close;
END;
END;
end;
end.