Solved

Running code after the form is shown

Posted on 2014-04-17
19
694 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 25

Expert Comment

by:Sinisa Vuk
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
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 25

Accepted Solution

by:
Sinisa Vuk earned 500 total points
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
@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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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 30

Author Comment

by:Marco Gasi
Comment Utility
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 30

Author Closing Comment

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

Author Comment

by:Marco Gasi
Comment Utility
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 36

Expert Comment

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

Author Comment

by:Marco Gasi
Comment Utility
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 36

Expert Comment

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

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

743 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now