Cette question est beaucoup plus complexe que prévu initialement; ce qui en fait une bonne question. Initialement, je pensais que Application.processmessages était la bonne façon, mais c'est un champ de mines potentiel à moins que vous soyez prudent (merci @skamradt pour le signaler). Cela n'aide pas non plus avec un seul appel de blocage. Un thread d'arrière-plan est nécessaire comme suit: (merci @mghie pour signaler les erreurs qui sont maintenant résolues ). Il peut toujours y avoir des problèmes avec l'objet de base de données étant appelé dans différents threads - de sorte que le thread d'arrière-plan peut avoir besoin de sa propre connexion de base de données pour cette opération (si possible).
Dans l'exemple ci-dessous, je n'ai pas spécifiquement montré le code pour créer et détruire la fenêtre de progression car cela rendra le code encore plus long, et c'est facile à faire.
Nous avons donc besoin de deux objets à faire:
Tout d'abord le fil d'arrière-plan pour traiter la requête.
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.
La forme qui invoque la requête:
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.
Quelle base de données? Au moins un que je connais (DBISAM/ElevateDB) offre un événement OnProgress très pratique sur leur composant de requête. Vous pouvez coder dans leur rapport pour le temps écoulé, le pourcentage terminé, etc. –
petite suggestion: Je mettrais le 'try' avant le' frm.Init' – mjn
Notez que l'appel 'frm.Close' entraînera des fuites de mémoire à moins que le formulaire a un gestionnaire 'OnClose' qui définit' caFree'. Utiliser 'frm.Release' serait beaucoup plus sûr. – mghie