Solved

Running code after the form is shown

Posted on 2014-04-17
19
788 Views
Last Modified: 2014-04-28
Hi all.

I needed to run the code not in OnShow event, but  after the form had made visible to the user. I found this trick

procedure TfrmIncorrectPaths.FormShow(Sender: TObject);
begin
  lblCount.Caption := '';
  lblMatches.Caption := '';
  tmr1.Enabled := True;
end;

procedure TfrmIncorrectPaths.tmr1Timer(Sender: TObject);
begin
  if Counter < 2 then
    Inc(Counter)
  else
  begin
    tmr1.Enabled := False;
    PostMessage(Self.Handle, WM_AFTER_SHOW, 0, 0);
  end;
end;

procedure TfrmIncorrectPaths.WmAfterShow(var Msg: TMessage);
begin
  //here the loop
end;

Open in new window


The timer is a my addition in order to grant all controls were drawn on the form.
The problem arises in the loop I place in WmAfterShow event. Please, take a look at this question: www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_28414283.html. There you find all details and a solution. The problem is that the solution doesn't work in the WmAfterShow event: it seems like the call to Progress.StepProgress were made again and again: I really don't understand.

The most surprising thing is that if I don't call ProgressBar.StepProgress(1) from the main program, the ProgressBar fills up almost to half bar and thn stops, but it should simply do nothing!!!

Thanks
Marco
0
Comment
Question by:Marco Gasi
  • 10
  • 7
  • 2
19 Comments
 
LVL 26

Expert Comment

by:Sinisa Vuk
ID: 40006453
I often use Onactivate event:

//put global flag in form class
..
   bFormActivated: Boolean;
...

procedure TForm1.FormCreate(Sender: TObject);
begin
  ...
  bFormActivated := False;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  if not bFormActivated then
  begin
    bFormActivated := True;
    // do after show stuff here ....
    // even: PostMessage(Self.Handle, WM_AFTER_SHOW, 0, 0); 
  end;
end;

Open in new window

0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40006484
I really appreciate your effort, but it's still filling up in a few seconds.
I'm thinking about change design for this, even I hate not understanding what's going wrong...
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40007327
that's a little odd ...
and by the look of the details in the other question, i'm guessing it's full of bugs

if you want a progress form, why not create procedures to update the form/show progress without needing to worry about an instance ... ???
what i call ... black box technique

the use of Application.ProcessMessages is really not the way to go

procedure TfrmIncorrectPaths.FormShow(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_AFTER_SHOW, 0, 0);
end;

procedure TfrmIncorrectPaths.WmAfterShow(var Msg: TMessage);
begin
  lblCount.Caption := '';
  lblCount.Update;
  lblMatches.Caption := '';
  lblMatches.Update;
end;

Open in new window

0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 31

Author Comment

by:Marco Gasi
ID: 40007418
Hi, Geert. Thanks for your comment.
Why you say it probably is full of bugs? I suppose you're speaking about my program not about the component (too few lines of code to have many bugs, I presume)
I would appreciate some input: that's is tùmy main 'creature' and it's terrible hear it is full of bugs!


why not create procedures to update the form/show progress without needing to worry about an instance ... ???
instance? of the component dialog? where is the problem?
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40007570
And why Application.ProcessMessages is not the way to go? Cantù, Texeira and Pacheco uses and suggests to use it in their manuals when you have to update labels to give feedback about a long process... Where is my error?
0
 
LVL 26

Accepted Solution

by:
Sinisa Vuk earned 500 total points
ID: 40008353
There is no need to do additional things/tricks on events (Show,Activate,..).
I remember that have similar problem once.... Progress component is just ms progress bar in behind. Ms does some changes (vista, win 7...).

(I repost my comment here)
Try another thing:
- set max to 100 (or do not set at all - because default is 100)
- calculate position to range of 0..100 (as percentage):  pos := muldiv(i, 100, 10000)
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40010355
@geert: nothing to say? Almost 48 hours ago you said you guess my software is full of bugs: well, I'm still waiting for your explanation. Maybe have you toke a holiday? :-)
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40014463
nothing to say ?
lol, yes, lots, but i was very busy ... :)
holiday ? i wish ... :)

because some well-know persona use Application.ProcessMessages it doesn't mean it's good everywhere ... it isn't in threaded apps...

from what i see, you are trying to indicate progress on a form ?
for that ... some questions...
> the form needs to stay on top ?
> the progress is inside another form ?
> progress value comes from threaded procedures ?
> multiple instances of the form are allowed ?
> how are the instances maintained, by the caller ? implicitly ?
> the form needs completely redrawing on progress, or just the updated components ?
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40014642
Hi, geert, wellcome back!
Let me explain the goal. I have one program where frequently I have to execute some task in the background and I wanted to how a modal dialog to say the user: 'Hey, wait, please.' Using a stndard modal form doesn't work because it prevents the task to be executed (probably I should start a secondary thread, but I didn't want to do this every time these tasks had to been executed: i use several secondary threads later in my program). Looking arond the web, I found you can use EnableTaskWindows and DisableTaskWindows to make a form 'modal', preventing the user access the underlying main form. Being a repetitive task, I thought to create a small components to do just this. Then I added an animated gif (the classic loader) and then I wantd to use a progress bar to show the state of the process.
So, answering to your questions,

> the form needs to stay on top ?
   Yes, it does
> the progress is inside another form ?
   Yes, it is in the main form
> progress value comes from threaded procedures ?
   No, it comes from the main thread (of the main form)
> multiple instances of the form are allowed ?
   Not at all
> how are the instances maintained, by the caller ? implicitly ?
  No multiple instances, no maintaining operations...
> the form needs completely redrawing on progress, or just the updated components ?
   Only the bar is updated

But what made me anxious has been read that a so skilled Delphi programmer wrote he guess my program is full of bugs: I'm an amateur, and I'm working hard to become a better programmer. I know there is a lot I still ignore, but 'full of bugs ' is really too mutch! :-)

Cheers
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40016859
full of bugs ... it sounds heavy, but it's not meant as such
a lot of programmers, including me, do things because they were taught that way or found a piece of code that way
copy/paste is still the fastest way of coding ... :)

it's not really bugs i'm indicating.
it's flaws in the implementation of the good ideas you have

let me point out a few...
reusable code using components with a progress indicator inside your main form
that's a very summarized description, and it holds a few caveats ...

reusable code ... technically you don't need components to do that
> just add 1 unit to the uses clause (and to your project)
and use the procs/funcs from that unit to control the progressbar

progress indicator inside your main form
> that's a difficult one ... will you be using an existing progress bar or do you expect the reusable code to create 1 for you at the bottom of the main form ... or does it have to be at the top of the main form ?
what about extra information ? > on a label, a colored panel, a statusbar ???
if you want reusable code and want as much benefit from it as possible, the reusable code should take care of all of that

animated gif ... aaaahhh ... that's a problem
in delphi ... everything on the screen is drawn by the main form
if it's busy with something else, which is not running in a thread, then the screen can't change
so either the main thread is drawing redrawing the animated gif ... or it's doing calculations ... not both ... with dividing it's time between both ... it could seem multiple things are done, but the calculation needs to leave time to update the gif
leaving time to another process is very hard to implement correctly

multiple instances
> an instance of object/class
instance := TForm1.Create(application);
or
inst1 := TfrmProgressDialog.Create(Self);
inst2 := TfrmProgressDialog.Create(Application);
at the moment there is your "component" is not forcing single instance
it's allowing multiple instances of the progress dialog

threading
in a threaded environment, you'd have to make sure everything is protected from updates from inside multiple threads, so you need threadsafe progress update procedures

bugs are a general summary of wrong implementations, typos, etc.
in your mainform there is a lot of code (creating an instance of your component TfrmProgressDialog, freeing it, updating the display, etc) which could all be done from inside the reusable code ...

i'll setup a very basic sample on how to do that
most of this can be found in the articles i wrote ... :)
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40016862
full of bugs ... it sounds heavy, but it's not meant as such
a lot of programmers, including me, do things because they were taught that way or found a piece of code that way
copy/paste is still the fastest way of coding ... :)

it's not really bugs i'm indicating.
it's flaws in the implementation of the good ideas you have

let me point out a few...
reusable code using components with a progress indicator inside your main form
that's a very summarized description, and it holds a few caveats ...

reusable code ... technically you don't need components to do that
> just add 1 unit to the uses clause (and to your project)
and use the procs/funcs from that unit to control the progressbar

progress indicator inside your main form
> that's a difficult one ... will you be using an existing progress bar or do you expect the reusable code to create 1 for you at the bottom of the main form ... or does it have to be at the top of the main form ?
what about extra information ? > on a label, a colored panel, a statusbar ???
if you want reusable code and want as much benefit from it as possible, the reusable code should take care of all of that

animated gif ... aaaahhh ... that's a problem
in delphi ... everything on the screen is drawn by the main form
if it's busy with something else, which is not running in a thread, then the screen can't change
so either the main thread is redrawing the animated gif ... or it's doing calculations ... not both ... with dividing it's time between both ... it could seem multiple things are done, but the calculation needs to leave time to update the gif
leaving time to another process is very hard to implement correctly

multiple instances
> an instance of object/class
instance := TForm1.Create(application);
or
inst1 := TfrmProgressDialog.Create(Self);
inst2 := TfrmProgressDialog.Create(Application);
at the moment there is your "component" is not forcing single instance
it's allowing multiple instances of the progress dialog

modal form
not really necessary ...
i see you are using threads, i have multiple apps in which a task can be started in background, with a progress indicator showing the status of each
this allows the main form to start multiple tasks ...

threading
in a threaded environment, you'd have to make sure everything is protected from updates from inside multiple threads, so you need threadsafe progress update procedures

bugs are a general summary of wrong implementations, typos, etc.
in your mainform there is a lot of code (creating an instance of your component TfrmProgressDialog, freeing it, updating the display, etc) which could all be done from inside the reusable code ...

i'll setup a very basic sample on how to do that
most of this can be found in the articles i wrote ... :)
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40016888
Hi, Geert.
First, let me thank you for the effort and the time you're spending here.
And let me say I'm very relieved your words about my bugs were not so bad :-)

There is a misunderstanding: when you asked if progress were in main form I suppoe you had read my component code in the other quetion so I thought you meant 'is the logic which moves the progress bar ion the main form?'

Okay, the progress is in a form created by the component.
Now, I moved the logic in a secondary thread and even I changed the logic it self, so all these problems are solved: the animated gif is smoothly animated because all ops happen in another thread, the progress bar is not used because i decided to use regex to process data in a more efficient way and now my data are ready to use in seconds instead of minutes.

So, I'm sorry to wasted your time, but since I don't want simply ask-and-wait and usualy I proceed to find a solution, this quetion has been solved by Sinisa and it is now really outdated. Don't misunderstand me: I implemented the new logic yesterday in the evening, so it's a relly hot new :-)

About you articles, I read them, as I'm reading a lot of books you suggest in your site (I'm reading the Sedgewick one just now).

If you have no objection, I would close this question awarding points to Sinisa: when I had that problem, its solution worked for me until I kept that logic design.

Now I'm finding other problems and Iìm going to open a new question about that. I'll post here the link so maybe I'll can concretely thank you by points there.

Let me know your thought.
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40017084
it's up to you how to award this question
points usually come down to what the asker used most
i only gave some remarks, not any real code

i might implement all those suggestions in a new article ... :)
a standalone progress indicator
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40017320
I'l read it for sure :-) Mmmhhh, I could be so presumptious to write it me self!!!
Jokes apart, really thank you for all your help, Geert.

Cheers.
0
 
LVL 31

Author Closing Comment

by:Marco Gasi
ID: 40017713
Thanks to both for your assistance. Every time I ask a question, I feel lucky to be part of this great community!
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40018098
And here's the link to a new, fantastic question!

http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_28418459.html

Cheers
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40026969
Thanks to both for your assistance.
> it's also possible to split points if multiple people assist
0
 
LVL 31

Author Comment

by:Marco Gasi
ID: 40027116
Hi Geert. I had asked for your opinion about awarding points in this specific question and you literally replied:

it's up to you how to award this question
points usually come down to what the asker used most
i only gave some remarks, not any real code
This is the reason I awarded points only to sinisa, whose code has actually solved the original issue.
If you thought I had to split points you could say it when I ask for it, but why saying it now, almost a week after I closed the question?
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40027297
okay never mind, it's just odd
thanking 2 people and only assigning points to 1
leave it at that
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question