Execute action after form is shown
Lazarus doesn't support something like form OnShown/OnShowAfter event where custom code can be executed after form was shown. This is useful mainly to do run custom code after main form is shown. It would serve as kind of one time OnApplicationStart event. In would be useful for example for loading of previous opened project/game file just after application start which can take longer time and main form should be already visible at that moment.
There are multiple ways how to solve this problem.
Methods
OnActivate event
The form's OnActivate event is fired every time when the form gets focus. Also this event is fired after the OnShow event. Therefore, it is possible to use this event to execute code only once after the OnShow event. A boolean state variable is needed that the code will be executed only once.
type
TForm1 = class(TForm)
...
private
FActivated: Boolean;
...
end;
...
procedure TForm1.FormActivate(Sender: TObject);
begin
if not FActivated then begin
FActivated := True;
// Code to be executed when the form is activated for the 1st time.
end;
end;
Send custom message
It is possible to define custom message and send it to application message queue so it will be handled as soon as possible.
uses
..., LMessages, LCLIntf;
const
LM_STARTUP = LM_USER;
procedure TFormMain.FormShow(Sender: TObject);
begin
// On on show code
SendMessage(Handle, LM_STARTUP, 0, 0);
end;
procedure TFormMain.LMStartup(var Msg: TLMessage);
begin
// After show code
end;
QueueAsyncCall
There is a way how to execute asynchronous operations in Lazarus using Asynchronous Calls. This is useful mainly for parallel processing but it can be used also for execution of form after show handler.
{$mode delphi}
procedure TFormMain.FormShow(Sender: TObject);
begin
// On on show code
Application.QueueAsyncCall(AfterShow, 0);
end;
procedure TFormMain.AfterShow(Ptr: IntPtr);
begin
// After show code
end;
TTimer
You can use TTimer instance for delayed execution of startup code. Create instance of TTimer component and set its property Enabled to False and Interval to 1. Then from the end of FormShow handler enable timer manually. It will be executed as soon as possible. You need to disable timer at the start of timer handler.
procedure TFormMain.FormShow(Sender: TObject);QueueAsyncCall
begin
// On on show code
Timer1.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
// After show code
end;