mdlittle
asked on
Progress dialog
I need someone to provide me with source code or and example of how to implement a progress dialog. More specifically I need to be able to display a modal dialog box with an abort button and progress bar while a background process occurs. The user can click abort and stop the process.
All I need to know is how to do this. If I try using a form and call the form, it does not show until the process completes. I have tried the update and repaint methods but neither works.
All I need to know is how to do this. If I try using a form and call the form, it does not show until the process completes. I have tried the update and repaint methods but neither works.
I also did something like you want to do. I think your 'main' proces is eating to much processor time.
Maybe you can try to insert at a few places in the 'eating' routine the following (e.g.) :
// be sure that the progesswindow is visible
repeat
// do something
Application.ProcessMessage s;
// do something else
// update your progress bar
Application.ProcessMessage s;
// again do something;
until ...
It's probably not the best solution, but it worked in my case.
Another thing you can try, is to use a thread.
Hope this helps...
Maybe you can try to insert at a few places in the 'eating' routine the following (e.g.) :
// be sure that the progesswindow is visible
repeat
// do something
Application.ProcessMessage
// do something else
// update your progress bar
Application.ProcessMessage
// again do something;
until ...
It's probably not the best solution, but it worked in my case.
Another thing you can try, is to use a thread.
Hope this helps...
What you're asking for is impossible by definition and by logic!
quoted from Delphi help: "Use ShowModal to show a form as a modal form, which means the user must put the form away before the application can continue to run."
How would that be supposed to work? You want to call Formx.ShowModal and then do your calculations? How and where would you get the ModalResult?? ShowModal is a FUNCTION! How can you continue processing the next line before its return value is determined? Imagine the following:
res:=Formx.ShowModal;
IF (res<>mrAbort) THEN DoCalculations;
..
Enough about the porblems, I have a workaround to suggest:
You can "fake" a modal window by keeping the user from closing it - it's not quite as effective as a "real" modal window, but it'll do the trick.
Unfortunately, i cannot post the forms for you, so you'll have to create 2 simple forms for testing... I purposely didn't rename any components.
FORM1: Button1, Button2 -> just used to call your "calculations" and to check if a button can be clicked...
procedure TForm1.Button1Click(Sender : TObject);
VAR i,j,k,p:integer;
begin
p:=0;
Form2.Show;
WHILE (p<100) AND (NOT Form2.AbortClicked) DO BEGIN
INC(p,5);
Form2.ProgressBar1.Positio n:=p;
k:=0;
FOR i:=1 TO 100 DO BEGIN
FOR j:=1 TO 100000 DO INC(k,1); // very bad style, but in this case: simulate complex calculations...
Application.ProcessMessage s; // avoid blocking the application
END;
END;
IF Form2.AbortClicked THEN ShowMessage('Aborted') ELSE ShowMessage('Done');
Form2.Hide;
end;
procedure TForm1.Button2Click(Sender : TObject); //just to test if it can be clicked
begin
ShowMessage('Hi');
end;
FORM2:
public
AbortClicked:boolean;
procedure TForm2.FormDeactivate(Send er: TObject);
begin
IF (ProgressBar1.Position<Pro gressBar1. Max) AND (NOT AbortClicked) THEN self.Show;
end;
procedure TForm2.FormCloseQuery(Send er: TObject; var CanClose: Boolean);
begin
CanClose:=(ProgressBar1.Po sition=Pro gressBar1. Max) OR (AbortClicked);
end;
procedure TForm2.Button1Click(Sender : TObject);
begin
AbortClicked:=true;
Self.Close;
end;
procedure TForm2.FormShow(Sender: TObject);
begin
AbortClicked:=false;
end;
The first two handlers won't allow the form to close unless
a) "Abort" was clicked
b) calculation is done
the next handler sets the flag for "AbortClicked", FormShow initializes the flag to false
That's the "easiest" and - imho - most effective way of doing this.
If you need a "really modal" window (blocking all actions on other windows (incl. a "ping")), that can be done as well, but at a higher work 6 performance cost.
1) You'd have to split your calculations into steps that can be executed one by one
2) Your modal window needs a timer to call each one of the steps and update its status
3) in order to do so, your modal window needs to take a pointer to a function that executes some portion of your calculation and then returns the percentage that is complete
Point 1) is the hardest and since I don't know if that can even be easily done, I won't elaborate on this solution...
Let me know if you get my code to work (of course I tested it) and if that helps...
quoted from Delphi help: "Use ShowModal to show a form as a modal form, which means the user must put the form away before the application can continue to run."
How would that be supposed to work? You want to call Formx.ShowModal and then do your calculations? How and where would you get the ModalResult?? ShowModal is a FUNCTION! How can you continue processing the next line before its return value is determined? Imagine the following:
res:=Formx.ShowModal;
IF (res<>mrAbort) THEN DoCalculations;
..
Enough about the porblems, I have a workaround to suggest:
You can "fake" a modal window by keeping the user from closing it - it's not quite as effective as a "real" modal window, but it'll do the trick.
Unfortunately, i cannot post the forms for you, so you'll have to create 2 simple forms for testing... I purposely didn't rename any components.
FORM1: Button1, Button2 -> just used to call your "calculations" and to check if a button can be clicked...
procedure TForm1.Button1Click(Sender
VAR i,j,k,p:integer;
begin
p:=0;
Form2.Show;
WHILE (p<100) AND (NOT Form2.AbortClicked) DO BEGIN
INC(p,5);
Form2.ProgressBar1.Positio
k:=0;
FOR i:=1 TO 100 DO BEGIN
FOR j:=1 TO 100000 DO INC(k,1); // very bad style, but in this case: simulate complex calculations...
Application.ProcessMessage
END;
END;
IF Form2.AbortClicked THEN ShowMessage('Aborted') ELSE ShowMessage('Done');
Form2.Hide;
end;
procedure TForm1.Button2Click(Sender
begin
ShowMessage('Hi');
end;
FORM2:
public
AbortClicked:boolean;
procedure TForm2.FormDeactivate(Send
begin
IF (ProgressBar1.Position<Pro
end;
procedure TForm2.FormCloseQuery(Send
begin
CanClose:=(ProgressBar1.Po
end;
procedure TForm2.Button1Click(Sender
begin
AbortClicked:=true;
Self.Close;
end;
procedure TForm2.FormShow(Sender: TObject);
begin
AbortClicked:=false;
end;
The first two handlers won't allow the form to close unless
a) "Abort" was clicked
b) calculation is done
the next handler sets the flag for "AbortClicked", FormShow initializes the flag to false
That's the "easiest" and - imho - most effective way of doing this.
If you need a "really modal" window (blocking all actions on other windows (incl. a "ping")), that can be done as well, but at a higher work 6 performance cost.
1) You'd have to split your calculations into steps that can be executed one by one
2) Your modal window needs a timer to call each one of the steps and update its status
3) in order to do so, your modal window needs to take a pointer to a function that executes some portion of your calculation and then returns the percentage that is complete
Point 1) is the hardest and since I don't know if that can even be easily done, I won't elaborate on this solution...
Let me know if you get my code to work (of course I tested it) and if that helps...
2Holger: Are you know about threads?
First thread can show window as modal,
and second thread can make calculation and
update progress bar.
>> You want to call Formx.ShowModal and then do your calculations.
You can start background thread first and then call
ShowModal.
First thread can show window as modal,
and second thread can make calculation and
update progress bar.
>> You want to call Formx.ShowModal and then do your calculations.
You can start background thread first and then call
ShowModal.
>>What you're asking for is impossible by definition and by logic!
What about Windows Explorer?
When you copy files progress window is modal, isn't it?
What about Windows Explorer?
When you copy files progress window is modal, isn't it?
ok, ok, I "change" my answer:
It IS possible, but of course a lot more complicated: you'd need to create a new class for performing your calculations (or at least for calling functions that do your calculations) that can be instantiated to do your calculations while "the rest of the proram" continues "business as usual" (or vice versa)
Will this program "ship" professionally?
Let me know what you want - if you want a sample using threads, it would be helpful if you could let me know a little bit about the type of "background process" you want to occur so I won't post a sample that you can't use....
It IS possible, but of course a lot more complicated: you'd need to create a new class for performing your calculations (or at least for calling functions that do your calculations) that can be instantiated to do your calculations while "the rest of the proram" continues "business as usual" (or vice versa)
Will this program "ship" professionally?
Let me know what you want - if you want a sample using threads, it would be helpful if you could let me know a little bit about the type of "background process" you want to occur so I won't post a sample that you can't use....
ok, I guess I've done wayyy to much web development lately... that's where you use "workarounds" all the time. I still say that the above probably is the simplest solution if you write a program for yourself or just for fun...
The "cleaner" (and wayyyy more professional) solution would look like this:
* Of course you still need a form that displays your progress.... do it any way you want, the components shouldn't be accessed from anybody else anyway...
then you add:
private
{ Private declarations }
FProgress:integer;
procedure SetProgress(p:integer);
public
property Progress:integer read FProgress write SetProgress;
procedure TForm2.SetProgress;
begin
FProgress:=P;
ProgressBar1.Position:=P; //display progress
IF P=ProgressBar1.Max THEN ModalResult:=mrOK; //close form when done
end;
then, as I said above, you need to create a thread class that does your calculations.
For your own project, you do it by choosing File | New and then Choose "ThreadObject"
Then add your code that does calculations.... I post a unit that you can just Cut&Copy:
unit Unit3;
interface
uses
Classes, Unit2; //unit2 is the one containing your ProgressForm...
type
TProgressThread = class(TThread)
private
{ Private declarations }
ProgressForm:TForm2;
Progress:integer;
protected
procedure Execute; override;
procedure UpdateProgress;
public
constructor Create(P:TForm2); //pass it the form to use for progress-display
end;
implementation
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example,
Synchronize(UpdateCaption) ;
and UpdateCaption could look like,
procedure TProgressThread.UpdateCapt ion;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ TProgressThread }
constructor TProgressThread.Create;
BEGIN
ProgressForm:=P;
FreeOnTerminate:=true; //change this for your calculations to first retrieve results before calling Destroy
inherited Create(false); //false meaning to start the thread right away rather than creating it in "suspended" mode
END;
procedure TProgressThread.Execute;
VAR i,j,k:integer;
begin
{ Place thread code here }
FOR i:=1 TO 100 DO BEGIN
Progress:=i;
Synchronize(UpdateProgress ); // tell everybody we're working
k:=0;
FOR j:=1 TO 2000000 DO INC(k); //pretend we're working... (a little bit)
IF Terminated THEN Exit; //but stop if asked nicely
END;
end;
procedure TProgressThread.UpdateProg ress;
begin
ProgressForm.Progress:=Pro gress;
end;
end.
Of course you would need to adjust this Class to take any parameters it needs to perform its task and return any results you want it to return.
In your "main unit" (whichever calls the so-called "background-process" (it's not really in the background if a modal progress box blocks the application in the mean time, is it?)), the call would look like this:
procedure TForm1.Button1Click(Sender : TObject);
VAR res:integer;
Pr:TProgressThread;
begin
pr:=TProgressThread.Create (Form2);
res:=Form2.ShowModal;
IF res<>mrOK THEN pr.Terminate;
IF res<>mrOK THEN ShowMessage('Aborted') ELSE ShowMessage('Done');
//destroy thread now IF you set FreeonTerminate to false in the Thread's constructor (e.g. to retrieve results) - the thread is either done or was aborted and is no longer needed
end;
Let me know if you like that solution better and if you have any problems/questions...
Good luck!
The "cleaner" (and wayyyy more professional) solution would look like this:
* Of course you still need a form that displays your progress.... do it any way you want, the components shouldn't be accessed from anybody else anyway...
then you add:
private
{ Private declarations }
FProgress:integer;
procedure SetProgress(p:integer);
public
property Progress:integer read FProgress write SetProgress;
procedure TForm2.SetProgress;
begin
FProgress:=P;
ProgressBar1.Position:=P; //display progress
IF P=ProgressBar1.Max THEN ModalResult:=mrOK; //close form when done
end;
then, as I said above, you need to create a thread class that does your calculations.
For your own project, you do it by choosing File | New and then Choose "ThreadObject"
Then add your code that does calculations.... I post a unit that you can just Cut&Copy:
unit Unit3;
interface
uses
Classes, Unit2; //unit2 is the one containing your ProgressForm...
type
TProgressThread = class(TThread)
private
{ Private declarations }
ProgressForm:TForm2;
Progress:integer;
protected
procedure Execute; override;
procedure UpdateProgress;
public
constructor Create(P:TForm2); //pass it the form to use for progress-display
end;
implementation
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example,
Synchronize(UpdateCaption)
and UpdateCaption could look like,
procedure TProgressThread.UpdateCapt
begin
Form1.Caption := 'Updated in a thread';
end; }
{ TProgressThread }
constructor TProgressThread.Create;
BEGIN
ProgressForm:=P;
FreeOnTerminate:=true; //change this for your calculations to first retrieve results before calling Destroy
inherited Create(false); //false meaning to start the thread right away rather than creating it in "suspended" mode
END;
procedure TProgressThread.Execute;
VAR i,j,k:integer;
begin
{ Place thread code here }
FOR i:=1 TO 100 DO BEGIN
Progress:=i;
Synchronize(UpdateProgress
k:=0;
FOR j:=1 TO 2000000 DO INC(k); //pretend we're working... (a little bit)
IF Terminated THEN Exit; //but stop if asked nicely
END;
end;
procedure TProgressThread.UpdateProg
begin
ProgressForm.Progress:=Pro
end;
end.
Of course you would need to adjust this Class to take any parameters it needs to perform its task and return any results you want it to return.
In your "main unit" (whichever calls the so-called "background-process" (it's not really in the background if a modal progress box blocks the application in the mean time, is it?)), the call would look like this:
procedure TForm1.Button1Click(Sender
VAR res:integer;
Pr:TProgressThread;
begin
pr:=TProgressThread.Create
res:=Form2.ShowModal;
IF res<>mrOK THEN pr.Terminate;
IF res<>mrOK THEN ShowMessage('Aborted') ELSE ShowMessage('Done');
//destroy thread now IF you set FreeonTerminate to false in the Thread's constructor (e.g. to retrieve results) - the thread is either done or was aborted and is no longer needed
end;
Let me know if you like that solution better and if you have any problems/questions...
Good luck!
Quick sample:
unit TheProgressForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ExtCtrls;
type
TProgressThread = class(TThread)
private
FCount,
FPos : LongInt;
FOnFeedback,
FOnComplete : TNotifyEvent;
procedure GiveFeedback;
public
procedure Execute; override;
constructor Create(Count : LongInt);
property TotalCount: LongInt read FCount;
property Position: LongInt read FPos;
property OnFeedback: TNotifyEvent read FOnFeedback write FOnFeedback;
property OnComplete: TNotifyEvent read FOnComplete write FOnComplete;
end;
TForm_Progress = class(TForm)
Progress_Panel: TPanel;
ProgressBar1: TProgressBar;
Bottom_Panel: TPanel;
Button_Panel: TPanel;
Button_Cancel: TButton;
Main_Panel: TPanel;
Label_Wait: TLabel;
Label_Progress: TLabel;
procedure Button_CancelClick(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
ProgressThread : TProgressThread;
FCount : LongInt;
procedure StartThread;
procedure VisualFeedback(Sender: TObject);
procedure ThreadCompleted(Sender: TObject);
public
{ Public declarations }
function ShowProgressModal(Count : LongInt): Integer;
end;
var
Form_Progress: TForm_Progress;
implementation
{$R *.DFM}
constructor TProgressThread.Create(Cou nt : LongInt);
begin
inherited Create(false);
FOnFeedback := nil;
FOnComplete := nil;
FCount := Count;
FPos := 0;
end;
procedure TProgressThread.GiveFeedba ck;
begin
if Assigned(FOnFeedback)
then FOnFeedback(Self);
end;
procedure TProgressThread.Execute;
var Index : Integer;
begin
for Index := 0 to FCount do
begin
FPos := Index;
Synchronize(GiveFeedback);
if Terminated
then Exit;
end;
if Assigned(FOnComplete)
then FOnComplete(Self);
end;
procedure TForm_Progress.VisualFeedb ack(Sender : TObject);
begin
with Sender as TProgressThread do
begin
ProgressBar1.Position := Trunc(100 / FCount * FPos);
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
procedure TForm_Progress.ThreadCompl eted(Sende r: TObject);
begin
ModalResult := mrOK;
end;
procedure TForm_Progress.StartThread ;
begin
ProgressThread := TProgressThread.Create(FCo unt);
ProgressThread.FreeOnTermi nate := true;
ProgressThread.OnFeedback := VisualFeedback;
ProgressThread.OnComplete := ThreadCompleted;
ProgressThread.Execute;
end;
function TForm_Progress.ShowProgres sModal(Cou nt: LongInt): Integer;
begin
FCount := Count;
Result := Self.ShowModal;
end;
procedure TForm_Progress.Button_Canc elClick(Se nder: TObject);
begin
ProgressThread.Terminate;
end;
procedure TForm_Progress.FormShow(Se nder: TObject);
begin
StartThread;
end;
end.
// create a blank form with a button.
// include TheProgressForm in your uses clause
// add this code to the ObClick handler of the button
procedure TForm1.Button1Click(Sender : TObject);
var MyForm_Progress : TForm_Progress;
begin
MyForm_Progress := TForm_Progress.Create(Self );
if MyForm_Progress.ShowProgre ssModal(20 00) = mrOK
then MessageBox(Self.Handle, 'Operation completed', 'Note', mb_ok)
else MessageBox(Self.Handle, 'Operation aborted', 'Note', mb_ok);
MyForm_Progress.Free;
end;
Slash/d003303
unit TheProgressForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ExtCtrls;
type
TProgressThread = class(TThread)
private
FCount,
FPos : LongInt;
FOnFeedback,
FOnComplete : TNotifyEvent;
procedure GiveFeedback;
public
procedure Execute; override;
constructor Create(Count : LongInt);
property TotalCount: LongInt read FCount;
property Position: LongInt read FPos;
property OnFeedback: TNotifyEvent read FOnFeedback write FOnFeedback;
property OnComplete: TNotifyEvent read FOnComplete write FOnComplete;
end;
TForm_Progress = class(TForm)
Progress_Panel: TPanel;
ProgressBar1: TProgressBar;
Bottom_Panel: TPanel;
Button_Panel: TPanel;
Button_Cancel: TButton;
Main_Panel: TPanel;
Label_Wait: TLabel;
Label_Progress: TLabel;
procedure Button_CancelClick(Sender:
procedure FormShow(Sender: TObject);
private
{ Private declarations }
ProgressThread : TProgressThread;
FCount : LongInt;
procedure StartThread;
procedure VisualFeedback(Sender: TObject);
procedure ThreadCompleted(Sender: TObject);
public
{ Public declarations }
function ShowProgressModal(Count : LongInt): Integer;
end;
var
Form_Progress: TForm_Progress;
implementation
{$R *.DFM}
constructor TProgressThread.Create(Cou
begin
inherited Create(false);
FOnFeedback := nil;
FOnComplete := nil;
FCount := Count;
FPos := 0;
end;
procedure TProgressThread.GiveFeedba
begin
if Assigned(FOnFeedback)
then FOnFeedback(Self);
end;
procedure TProgressThread.Execute;
var Index : Integer;
begin
for Index := 0 to FCount do
begin
FPos := Index;
Synchronize(GiveFeedback);
if Terminated
then Exit;
end;
if Assigned(FOnComplete)
then FOnComplete(Self);
end;
procedure TForm_Progress.VisualFeedb
begin
with Sender as TProgressThread do
begin
ProgressBar1.Position := Trunc(100 / FCount * FPos);
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
procedure TForm_Progress.ThreadCompl
begin
ModalResult := mrOK;
end;
procedure TForm_Progress.StartThread
begin
ProgressThread := TProgressThread.Create(FCo
ProgressThread.FreeOnTermi
ProgressThread.OnFeedback := VisualFeedback;
ProgressThread.OnComplete := ThreadCompleted;
ProgressThread.Execute;
end;
function TForm_Progress.ShowProgres
begin
FCount := Count;
Result := Self.ShowModal;
end;
procedure TForm_Progress.Button_Canc
begin
ProgressThread.Terminate;
end;
procedure TForm_Progress.FormShow(Se
begin
StartThread;
end;
end.
// create a blank form with a button.
// include TheProgressForm in your uses clause
// add this code to the ObClick handler of the button
procedure TForm1.Button1Click(Sender
var MyForm_Progress : TForm_Progress;
begin
MyForm_Progress := TForm_Progress.Create(Self
if MyForm_Progress.ShowProgre
then MessageBox(Self.Handle, 'Operation completed', 'Note', mb_ok)
else MessageBox(Self.Handle, 'Operation aborted', 'Note', mb_ok);
MyForm_Progress.Free;
end;
Slash/d003303
and here's the form's code:
object Form_Progress: TForm_Progress
Left = 195
Top = 109
Width = 369
Height = 164
Caption = 'Progress'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Progress_Panel: TPanel
Left = 0
Top = 43
Width = 361
Height = 42
Align = alBottom
BevelOuter = bvNone
BorderWidth = 14
TabOrder = 0
object ProgressBar1: TProgressBar
Left = 14
Top = 14
Width = 333
Height = 14
Align = alClient
Min = 0
Max = 100
TabOrder = 0
end
end
object Bottom_Panel: TPanel
Left = 0
Top = 85
Width = 361
Height = 52
Align = alBottom
BevelOuter = bvNone
BorderWidth = 12
TabOrder = 1
object Button_Panel: TPanel
Left = 272
Top = 12
Width = 77
Height = 28
Align = alRight
BevelOuter = bvNone
TabOrder = 0
object Button_Cancel: TButton
Left = 1
Top = 1
Width = 75
Height = 25
Caption = 'Cancel'
Default = True
ModalResult = 2
TabOrder = 0
OnClick = Button_CancelClick
end
end
end
object Main_Panel: TPanel
Left = 0
Top = 0
Width = 361
Height = 43
Align = alClient
BevelOuter = bvNone
TabOrder = 2
object Label_Wait: TLabel
Left = 15
Top = 12
Width = 228
Height = 13
Caption = 'Processing, please wait or press cancel to abort.'
end
object Label_Progress: TLabel
Left = 15
Top = 32
Width = 3
Height = 13
end
end
end
object Form_Progress: TForm_Progress
Left = 195
Top = 109
Width = 369
Height = 164
Caption = 'Progress'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Progress_Panel: TPanel
Left = 0
Top = 43
Width = 361
Height = 42
Align = alBottom
BevelOuter = bvNone
BorderWidth = 14
TabOrder = 0
object ProgressBar1: TProgressBar
Left = 14
Top = 14
Width = 333
Height = 14
Align = alClient
Min = 0
Max = 100
TabOrder = 0
end
end
object Bottom_Panel: TPanel
Left = 0
Top = 85
Width = 361
Height = 52
Align = alBottom
BevelOuter = bvNone
BorderWidth = 12
TabOrder = 1
object Button_Panel: TPanel
Left = 272
Top = 12
Width = 77
Height = 28
Align = alRight
BevelOuter = bvNone
TabOrder = 0
object Button_Cancel: TButton
Left = 1
Top = 1
Width = 75
Height = 25
Caption = 'Cancel'
Default = True
ModalResult = 2
TabOrder = 0
OnClick = Button_CancelClick
end
end
end
object Main_Panel: TPanel
Left = 0
Top = 0
Width = 361
Height = 43
Align = alClient
BevelOuter = bvNone
TabOrder = 2
object Label_Wait: TLabel
Left = 15
Top = 12
Width = 228
Height = 13
Caption = 'Processing, please wait or press cancel to abort.'
end
object Label_Progress: TLabel
Left = 15
Top = 32
Width = 3
Height = 13
end
end
end
...some cosmetics:
procedure TForm_Progress.VisualFeedb ack(Sender : TObject);
begin
with ProgressThread do
begin
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
procedure TForm_Progress.FormShow(Se nder: TObject);
var SaveCursor : TCursor;
begin
SaveCursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
StartThread;
Screen.Cursor := SaveCursor;
end;
Slash/d003303
procedure TForm_Progress.VisualFeedb
begin
with ProgressThread do
begin
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
procedure TForm_Progress.FormShow(Se
var SaveCursor : TCursor;
begin
SaveCursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
StartThread;
Screen.Cursor := SaveCursor;
end;
Slash/d003303
ASKER
Thanks for the code... but I am getting and EDivideZero excpetion when I attempt to compile the sample. The line that vomits is:
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
ASKER
Adjusted points to 1000
Is this one for d003303 exclusively now?
Would you like me to improve my suggestion? It was a working solution so I'm guessing you like the other answer better...
The "bug" in d003303's suggestion should be fairly easy to fix... but I think there's something else that might cause problems.
What are the "new" conditions to getting the points now?
Just wondering before betting on a dead horse... (i.e. spending time on a solution you don't like...)
Would you like me to improve my suggestion? It was a working solution so I'm guessing you like the other answer better...
The "bug" in d003303's suggestion should be fairly easy to fix... but I think there's something else that might cause problems.
What are the "new" conditions to getting the points now?
Just wondering before betting on a dead horse... (i.e. spending time on a solution you don't like...)
ASKER
I have not been able to test you solution. If it fits my criteria then I will release the points. I have done my best to specify my needs and am desperate for a result.
Of course I did write and test the project... it worked (otherwise, I wouldn't have posted it)
Unless there are specific reasons against it, it will be a lot easier if you post your e-mail address and I'll zip and mail my project...
Posting projects is rather difficult because of the forms "and stuff"...
If you don't want to post your e-mail, you can mail it to me at HolgerStr@hotmail.com - let me know if you did because I hardly ever check that Hotmail-account...
Hope to hear from you soon...
Unless there are specific reasons against it, it will be a lot easier if you post your e-mail address and I'll zip and mail my project...
Posting projects is rather difficult because of the forms "and stuff"...
If you don't want to post your e-mail, you can mail it to me at HolgerStr@hotmail.com - let me know if you did because I hardly ever check that Hotmail-account...
Hope to hear from you soon...
ASKER
mlittle@netcom.com
Yo,
get rid of the bug with
procedure TForm_Progress.VisualFeedb ack(Sender : TObject);
begin
with ProgressThread do
begin
try
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
except
ProgressBar1.Position := 0;
end;
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
Slash/d003303
get rid of the bug with
procedure TForm_Progress.VisualFeedb
begin
with ProgressThread do
begin
try
ProgressBar1.Position := Trunc(100 / TotalCount * Position);
except
ProgressBar1.Position := 0;
end;
Label_Progress.Caption := Format('%d of %d processed', [TotalCount, Position]);
end;
end;
Slash/d003303
ASKER
Slash/d003303, Your suggestion works great. Please resubmit the suggestion so that I can award you the points.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER