Solved

Force Form To Show

Posted on 2001-08-07
33
269 Views
Last Modified: 2010-04-06
I have an app that checks for command-line options in the OnActivate event and based on the option specified a procedure might be called.  The problem is that if a procedure is called from the OnActiviate the form doesn't show until after the procedure has finished.  It did use to show first but not any more.  How can I force the form to show?
0
Comment
Question by:dokken
  • 10
  • 8
  • 6
  • +5
33 Comments
 
LVL 4

Expert Comment

by:YodaMage
Comment Utility
Why don't you move your call to the OnShow then? Or check your options in the on activate, then based on result, use a boolean to call the procedure from the OnShow?
0
 
LVL 4

Expert Comment

by:fva
Comment Utility
It's possible to show it but even if you can make it to show first it won't respond to user actions until the proc finishes. I would suggest other approaches:

1. Show a splash screen instead the main one until the processing finishes. This would be better suited if the processing is mandatory for the main program to run properly.

2. Start a thread and run the proc inside it. This would be better if the completion of the proc is not required in order to start using the application.

F.
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
use

application.processmessages;

in your activate event
(not tested)

meikl ;-)
0
 
LVL 3

Expert Comment

by:nnbbb09
Comment Utility
Hello,

I think the reason your form won't show is because you've started some lengthy process before all the windows paint messages have been processed properly. This is a PAQ that I answered a while ago that deals with the same sort of problem. http://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20118669
What happens is that the main form posts a message to itself which you need to write a handler for. The message goes to the end of the queue, the form paints itself correctly. Your custom message is then handled and you can start your processing.

Hope this helps

Jo

0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
now tested

procedure TForm1.FormActivate(Sender: TObject);
var i : Integer;
begin
  Application.Processmessages;
  i := gettickcount;
  while gettickcount - i < 5000 do; //nothing for five seconds as sample for doing somewaht
  showmessage('On End');
end;

meikl ;-)
0
 
LVL 2

Accepted Solution

by:
FrodoBeggins earned 250 total points
Comment Utility
NEVER use Application.Processmessages in an event handler! It may cause big and hard-to-find problems.

The form will not show because it can't handle PAINT and other messages until you are in the OnActivate event handler. This is the reason. Application.Processmessages is a walkarround, bur very bad. It may work, but once an 100 starts to crush your app.

The solution I see is: if you need to do something send a custom message to your own message queue. In your main form's unit write:

unit Main;
const
  WM_MYMESSAGE1 = WM_USER + 100;
  WM_MYMESSAGE2 = WM_USER + 101;
...
type TMainForm = class(TForm)
.....
privte
  procedure WMDoSomething1(var Message: TMessage); message WM_MYMESSAGE1;
  procedure WMDoSomething2(var Message: TMessage); message WM_MYMESSAGE2;
....
procedure TMainForm.WMDoSomething1(var Message: TMessage);
begin
  //DoSomething1;
end;

procedure TMainForm.WMDoSomething2(var Message: TMessage);
begin
  //DoSomething2;
end;

procedure TMainForm.FormActivate(Sender: TObject);
begin
  ...
  // need to call procedure 1
  SendMessage(MainForm.Handle, WM_MYMESSAGE1, 0, 0);
end;

I hope you get the idea ;-)

Rgds,
Frodo


0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
NEVER had a problem with
application.processmessages
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
to: FrodoBeggins
just to say, if the application does not process the messages,
your custom-messages will only then processed when the application becomes idle

in short to all,

the form is not shown, because the applcation got not the time
to process the message for show and paint the form,

with application.processmessages you force the application to process all waiting messages,
also the show and paint-messages for display the form

regards

meikl ;-)
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Hehe. I had. Many problems.
This is common rule. ProcessMessages may cause reentrancy problems.

Rfds,
Frodo
0
 
LVL 4

Expert Comment

by:YodaMage
Comment Utility
The only problems I've seem with processmessages, is that it sometimes slows down a HUGE looping procedure, especially if many data aware components and controls are not disabled first.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
In very specific situations Application.ProcessMessages may really make problems due to strange reentrance situations, but I would not go that far to say, that you should never use it in an event handler, that's by far too strict IMHO. You should simply not use it in situations where it is dangerous. Here is a little example for such a situation:

type
  TForm1 = class...
  private
    globalList : TList;
    procedure ReceivedDeviceChangedMessage(...); message WM_DEVICECHANGE;
    ...
  end;

procedure TForm.ReceivedDeviceChangedMessage(...);
begin
  for i1 := 0 to globalList.Count - 1 do begin
    DoSomethingComplicated(globalList[i1]);
    Application.ProcessMessages;
  end;
  globalList.Delete(0);
end;

In this situation is might happen, that the Application.ProcessMessages call handles just another WM_DEVICECHANGE message. In that case the first WM_DEVICECHANGE handler will throw out an exception, because the list got shorter during Application.ProcessMessages.

I didn't first believe it, but even SendMessage can have the same problems, because if our thread calls SendMessage, then while waiting for the result of the message our thread is not totally blocked, it still reacts to messages that are sent from other threads via SendMessage. So SendMessage can have the same problems as in the example above. As a result I sometimes call SendMessageTimeout with the SMTO_BLOCK flag to avoid this reentrance problem...   :-(

Regards, Madshi.
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Well, get the foloqing scenario.
You enter OnActivate, do something, process the messages... and somewhere in the messages the form gets activated again. Nowa you get in OnActivate again, BEFORE you've finished the first activate processing. Can you imagine HOW MANY problems can occure? :))

here's an example:

var BlahBlah:TStingList;

procedure Form1.FormActivate(Sender : TObject);
begin
  BlahBlah := TStringList.Create;
  // do something...
  Application.ProcessMessages;
  // do something...
  BlahBlah.Free;
end.

Now, the form gets activated, creates the stringlist, proccesses another activation, creates the stringlist... Oops! Ith is already created :)

This, of cource, is just a basic example. Do you needa a more complex one?

Rgds,
Frodo
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Well, Madshi, let's say "Use ProcessMessages in an event handler only if you are sure what are you doing" :-)

You are right about SendMessage too. My mistake. Should use PeekMessage in the example.

Rgds,
Frodo
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
kretzschmar: Right, my own messages will be processed after all previous messages, like PAINT. The form will get shown, and then will execute the code in DoSomething1.

Rgds,
Frodo
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
its simple to avoid such situations,

by using a flag or just deassigning
the procedure from the event for this code step,

and if you had many problems,
then your coding concept wasn't good enough

;-)
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Yes, there is a walkarround. I couldn't see your flags-warning when you told us to use ProcessMessages ;-))

Anyway, the flag stuff has a bad side too. You suggest to skip some of the processing in the procedure. But that may have a side effects too. I usualy write event-handlers with the thought they'll be executed afterwards, the events will get handled. I'm not sure if it is good coding concept or not, but... :-))

Rgds,
Frodo
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
at least it depends, what you are doing,
but i guess the use of application.processmessages is the easiest method for dokken
(depending what he is doing)

meikl ;-)
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
OK. I definitely agree with you. Your method is easier to implement, mine - more robust. Of course I say mine is better, and you don't agree. That's called deadlock, right ;-))

I can't get further without more secific knowing of what exactly should be done.

Rgds,
Frodo
0
 
LVL 3

Expert Comment

by:nnbbb09
Comment Utility

Frodo, I agree that my/your solution is more robust than using application.processmessages. Incidentally I think the message should be posted from the FormShow event.

Jo
0
 

Author Comment

by:dokken
Comment Utility
Wow, a lot posts.  I added Application.ProcessMessages to the first line of the OnActivate event but the form still didn't show.

If I move the code to the OnShow should that show the form first or will I end up with the same thing?

This used to work, I don't know what changed it.
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
:-)) waiting for dokkens response

i know this trick, which u use, frodo,
even the release-method of tform does the same
to ensure that the method where its called is left,
but i don't think that this must be done on every event-procedure,
even i think the need for this happens not often.

meikl ;-)
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Dokken, you need to put Application.ProcessMessages in your lenghty operation's loop. It does not help you at the first line of OnActivate :)

meikl, it is done in the release method not because something should be done after the current procedure finishes (as in our case). Well, not only. It is used there to call CMRelease, which calls free, which frees the form. If release directly calls free, then when it comes to execute the next line of release's procedure, or anything which comes after release, the form will be gone but you'll work with it. And poof! - Access violation :)

Rgds,
Frodo
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Working with already-freed object is not good coding concept, in my oppinion ;-))

Rgds,
Frodo
0
 

Author Comment

by:dokken
Comment Utility
FrodoBeggins, I do have Application.ProcessMessages in the code being run from the OnActivate event.  It's in there numerous times.
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
Well, I'm so happy for you. I have a mountain house. So?

Seriously, If you select the processmessages method, you may crush, once for 1000 times, or 10E14,  or never... I'm glad it works for you. But I will not use it. A question of vision, I guess... :)

Rgds,
Frodo
0
 

Author Comment

by:dokken
Comment Utility
I was replying to your line "you need to put Application.ProcessMessages in your lenghty operation's loop. It does not help you at the first line of OnActivate".  I wasn't commenting on whether or not it was a good idea to place that within an event.

0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Okay, here comes what I'm usually doing if I want the form to be shown first and then do something: I put it in FormPaint (because FormShow is too early, too) like this:

procedure TForm1.FormPaint(...);
begin
  OnPaint := nil;  // to make sure we're only doing this one time
  CallYourLengthyProc;
end;

Regards, Madshi.
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
yup, thats it, madshi :-)
0
 
LVL 3

Expert Comment

by:rondi
Comment Utility
i use that all the time, too :>)
0
 
LVL 3

Expert Comment

by:rondi
Comment Utility
i use that all the time, too :>)
0
 

Author Comment

by:dokken
Comment Utility
Madshi,  Almost works... it's not painting the entire thing though until after it finishes what it's doing.
0
 

Author Comment

by:dokken
Comment Utility
You guys are not going to believe this.  I moved the code back to OnActivate (where it originally was) and now it's showing the form first like I wanted it to.  No code was changed.  This is what I was I talking about in my question, sometimes it works and sometimes it doesn't.  Except now certain things that did work are producing Access Violations.  I'm going to try creating a message queue as suggested.
0
 

Author Comment

by:dokken
Comment Utility
Works great.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
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.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

771 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

8 Experts available now in Live!

Get 1:1 Help Now