Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showmessage command is executed before the application form appears

I was wondering why the command "showmessage" is executed before the application form appears, I mean, whenever I run the program, first appears the message, then the application form:

procedure TForm1.FormCreate(Sender: TObject);
begin
button1.hide;
button2.hide;
image3.picture.loadfromfile('c:\EAS\std.bmp');
showmessage ('Hi');
end;

end.

The first thing delphi does, it to show the message "Hi". Then it does the rest (Form appeared, hide buttons, load images etc). Even though showmessage is last, it is executed first. How do I make the message appear after the form is appeared, the buttons are hiden are the image is loaded?

like image 358
user2296565 Avatar asked Jan 25 '26 20:01

user2296565


1 Answers

The reason is that the form is created (hence, OnCreate is fired), before it is shown.

Solution 1

One solution is to post a window message to the form when the form is created. Try this:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const
  WM_GREETING = WM_USER + 1;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
  protected
    procedure WMGreeting(var Message: TMessage); message WM_GREETING;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_GREETING, 0, 0);
end;

procedure TForm1.WMGreeting(var Message: TMessage);
begin
  ShowMessage('Created and shown!');
end;

end.

Solution 2

A different solution is to make use of the OnActivate event, which is called every time the form obtains keyboard focus: Add a private field FMessageShown: boolean to the form class. Then, in OnActivate, if the flag is false (as it is by default, being a field of a class), then display your message and set the flag to true:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
    FMessageShown: boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
begin
  if not FMessageShown then
  begin
    ShowMessage('Created and shown.');
    FMessageShown := true;
  end;
end;

end.

In practice, both methods work perfectly. The downside of the first solution is that it may rely somewhat on 'implementation details', while the downside of the latter one is quite obvious: you check a flag every time the form regets keyboard focus, even weeks after the form was initially created and the message was shown.

Solution 3

A solution that has neither disadvantage, but assumes that you won't need the OnActivate event for some other purpouse, is simply to 'unassign' the event after its first (hence, only) execution:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
begin
  ShowMessage('Created and shown.');
  OnActivate := nil;
end;

end.

(This approach, however, can be extended to cases where you do need the event for other purpouses too, if you replace OnActivate := nil by OnActivate := MySecondEventHandler.)

like image 197
Andreas Rejbrand Avatar answered Jan 27 '26 10:01

Andreas Rejbrand



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!