Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1527
  • Last Modified:

Running code after the form is shown

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
Marco Gasi
Asked:
Marco Gasi
  • 10
  • 7
  • 2
1 Solution
 
Sinisa VukCommented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Geert GruwezOracle dbaCommented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Marco GasiFreelancerAuthor Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Sinisa VukCommented:
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
 
Marco GasiFreelancerAuthor Commented:
@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
 
Geert GruwezOracle dbaCommented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Geert GruwezOracle dbaCommented:
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
 
Geert GruwezOracle dbaCommented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Geert GruwezOracle dbaCommented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Marco GasiFreelancerAuthor Commented:
Thanks to both for your assistance. Every time I ask a question, I feel lucky to be part of this great community!
0
 
Marco GasiFreelancerAuthor Commented:
And here's the link to a new, fantastic question!

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

Cheers
0
 
Geert GruwezOracle dbaCommented:
Thanks to both for your assistance.
> it's also possible to split points if multiple people assist
0
 
Marco GasiFreelancerAuthor Commented:
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
 
Geert GruwezOracle dbaCommented:
okay never mind, it's just odd
thanking 2 people and only assigning points to 1
leave it at that
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 10
  • 7
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now