In Delphi XE7 (or XE8), put a TjvProgressDialog (from JVCL) on a form and name it dlgProgress1. And a TButton and name it btnProgressDialogTest.
This code first starts Notepad from a separate thread (ShellExecAndWaitTask), then it opens the progress dialog (dlgProgress1) with an infinite progress loop:
var
ShellExecAndWaitTask: System.Threading.ITask;
procedure TForm1.btnProgressDialogTestClick(Sender: TObject);
begin
ShellExecAndWaitTask := TTask.Create(
procedure
begin
JclShell.ShellExecAndWait('notepad'); // BTW, is this thread-safe?
CodeSite.Send('Notepad has been closed');
end);
ShellExecAndWaitTask.Start;
dlgProgress1.Caption := 'ProgressDialog Test';
dlgProgress1.Text := 'Close Notepad to automatically close this progress dialog';
dlgProgress1.Tag := 0;
dlgProgress1.Position := 0;
dlgProgress1.ShowCancel := True;
dlgProgress1.ShowModal;
CodeSite.Send('Progress dialog has been closed');
end;
procedure TForm1.dlgProgress1Progress(Sender: TObject; var AContinue: Boolean);
begin
if dlgProgress1.Tag = 0 then
begin
if dlgProgress1.Position < dlgProgress1.Max then
dlgProgress1.Position := dlgProgress1.Position + 1;
if dlgProgress1.Position = dlgProgress1.Max then
dlgProgress1.Tag := 1;
end
else
begin
if dlgProgress1.Position > 0 then
dlgProgress1.Position := dlgProgress1.Position - 1;
if dlgProgress1.Position = 0 then
dlgProgress1.Tag := 0;
end;
AContinue := Assigned(ShellExecAndWaitTask); // why this never becomes false?
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(ShellExecAndWaitTask) then
ShellExecAndWaitTask.Cancel;
end;
When you close Notepad, shouldn't Assigned(ShellExecAndWaitTask)
in the dlgProgress1Progress
event handler become false and close the progress dialog by setting AContinue
to false? Instead it stays always true although the ShellExecAndWaitTask
task has been terminated! Why?
EDIT:
Following David's advice I changed the code. Now it works, but is it thread-safe?
var
ShellExecAndWaitTask: System.Threading.ITask;
ShellExecAndWaitTaskTerminated: Boolean;
procedure TForm1.btnProgressDialogTestClick(Sender: TObject);
begin
ShellExecAndWaitTask := TTask.Create(
procedure
begin
JclShell.ShellExecAndWait('notepad'); // BTW, is this thread-safe?
CodeSite.Send('Notepad has been closed');
TThread.Queue(TThread.CurrentThread,
procedure
begin
ShellExecAndWaitTaskTerminated := True;
end);
end);
ShellExecAndWaitTaskTerminated := False;
ShellExecAndWaitTask.Start;
dlgProgress1.Caption := 'ProgressDialog Test';
dlgProgress1.Text := 'Close Notepad to automatically close this progress dialog';
dlgProgress1.Tag := 0;
dlgProgress1.Position := 0;
dlgProgress1.ShowCancel := True;
dlgProgress1.ShowModal;
CodeSite.Send('Progress dialog has been closed');
end;
procedure TForm1.dlgProgress1Progress(Sender: TObject; var AContinue: Boolean);
begin
if dlgProgress1.Tag = 0 then
begin
if dlgProgress1.Position < dlgProgress1.Max then
dlgProgress1.Position := dlgProgress1.Position + 1;
if dlgProgress1.Position = dlgProgress1.Max then
dlgProgress1.Tag := 1;
end
else
begin
if dlgProgress1.Position > 0 then
dlgProgress1.Position := dlgProgress1.Position - 1;
if dlgProgress1.Position = 0 then
dlgProgress1.Tag := 0;
end;
AContinue := not ShellExecAndWaitTaskTerminated;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(ShellExecAndWaitTask) then
ShellExecAndWaitTask.Cancel;
end;