12

What is the recommended way to ensure that the mainform is fully maximized and all controls are redrawn before showing a modal form on application first load?

I need to show a modal dialog when the application starts (not a login screen) but if I set the form to wsMaximized whilst the screen maximizes, the controls do not have chance to redraw and you are left with an ugly mess.

I show the modal screen at present using the following:

procedure TForm1.FormActivate(Sender: TObject);
var
  frmOrderLookup:TfrmOrderLookup;
begin
  onactivate := nil;
  frmOrderLookup:=TfrmOrderLookup.Create(nil);
  try
    frmOrderLookup.showmodal;
  finally
    frmOrderLookup.Free;
  end;
end;
Mark Robinson
  • 943
  • 9
  • 26

1 Answers1

14

What I normally do is post a custom message back to my form. That way it won't get processed until other messages for the form have already been handled. By the time this message gets processed, your form should have already finished redrawing.

type
  TMyForm = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure HandleLookupMessage(var Message: TMessage); message WM_USER + 1;
  end;

procedure TMyForm.HandleLookupMessage(var Message: TMessage);
var
  frmOrderLookup: TfrmOrderLookup;
begin
  frmOrderLookup := TfrmOrderLookup.Create(Application);
  try
    frmOrderLookup.ShowModal;
  finally
    frmOrderLookup.Release;
  end;
end;

procedure TMyForm.FormCreate(Sender: TObject);
begin
  // Maximise form here if needed
  PostMessage(Handle, WM_USER + 1, 0, 0);
end;

If you're worried about the message getting to your application again somehow, you can always add a private boolean variable to indicate that it's been handled once.

afrazier
  • 4,784
  • 2
  • 27
  • 30
  • 1
    +1. If you post the message in `OnShow` instead, it'll get processed later in the process; that eliminates any chance of it getting sent too soon. (And shouldn't it be `FormCreate` instead? `OnCreate` is the name of the property itself.) – Ken White Jun 08 '12 at 12:45
  • @Ken: Thanks for the correction. As for using `OnShow`, I think that the form is going to be created, shown, then activated all before `Application.Run` starts pumping the message queue, so it doesn't much matter. Other forms and datamodules are also doing to be created (and have their `OnCreate` events triggered) first too. I haven't had this idiom fail me yet in practice when used from `OnCreate`. – afrazier Jun 08 '12 at 13:43
  • Thanks for your help - +1 to @KenWhite too for the OnShow recommendation – Mark Robinson Jun 08 '12 at 14:04
  • @afrazier: Unless some third-party component on your form calls `Application.ProcessMessages` or something while it's being created. :-) The problem with doing it in `OnActivate` is that you have to remember to disable `OnActivate`, because it can get fired more than once. Doing it in `OnShow` solves both those potential issues. – Ken White Jun 08 '12 at 14:31
  • @Ken: `OnShow` can get triggered again, so it will need unhooked as well. It's uncommon for the main form to be hidden then reshown, but not impossible. And what kind of god-awful third party component would call `Application.ProcessMessages` during creation? ACK! :-) Let me know so I can stay far, far away. – afrazier Jun 08 '12 at 14:50
  • They're out there. Believe me - I've tracked down bugs in them before in products that I don't use any longer. I prefer to wait as late in the creation process as possible to post the message, but suit yourself. (If I ever see a question from you that could be solved by doing so, I'm going to post an answer saying "I told you so! I told you so!" and point you back here. ) – Ken White Jun 08 '12 at 14:53