Recent

Author Topic: Procedure to run upon application-start?  (Read 26443 times)

Elmug

  • Hero Member
  • *****
  • Posts: 849
Procedure to run upon application-start?
« on: July 24, 2011, 08:11:26 am »
Dear forum people,

Is there a way, or facilities in Lazarus, such that when the application first starts, one's procedure is automatically run?

And, I suppose, the same procedure can be run if one so wishes, by pushing a button.

Thanks!

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Procedure to run upon application-start?
« Reply #1 on: July 24, 2011, 08:45:17 am »
Elmug, try looking into the main lpr file.... As you can see, forms get created there (at least your main form). You can add your own procedure call before that.
I suggest you keep the procedure in a different unit; you'd have to add this unit to the uses clauses of the lpr, obviously.

Then you can also call the same procedure from a button or similar on your form...
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #2 on: July 24, 2011, 09:17:14 am »
Elmug, try looking into the main lpr file.... As you can see, forms get created there (at least your main form). You can add your own procedure call before that.
I suggest you keep the procedure in a different unit; you'd have to add this unit to the uses clauses of the lpr, obviously.

Then you can also call the same procedure from a button or similar on your form...

Hi BigChimp,

The problem that it seems to me that WHAT I want to initialize is components in the application! And how could I do that if the application has not yet run?...And now, when the application is running, I supposed my procedure could not be run UNLESS a button or something is first activated?

I thought that in the .lpr I could initialize printers, or external devices or things that have nothing to do with the application.

But maybe if I declare the procedure PUBLIC? Or something like that, which I've never done, maybe then I coul run it from the .lpr?

Thanks.

DirkS

  • Sr. Member
  • ****
  • Posts: 251
Re: Procedure to run upon application-start?
« Reply #3 on: July 24, 2011, 09:52:33 am »
Quote
The problem that it seems to me that WHAT I want to initialize is components in the application! And how could I do that if the application has not yet run?...And now, when the application is running, I supposed my procedure could not be run UNLESS a button or something is first activated?
Assuming you have a 'standard' application with a main form you could add a call to your procedure in the main form's OnCreate, OnActivate or OnShow events. Which one to choose depends on the specific situation.

Gr.
Dirk.

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #4 on: July 25, 2011, 02:25:51 am »
Thank you Dirk!

Sounds like what I am after.

I will investigate it. But sure looks like that ought to be it.

 :)

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: Procedure to run upon application-start?
« Reply #5 on: July 25, 2011, 04:13:51 am »
Depends upon the complexity of what you want to achieve.  99% of the time, you want to put your code in the Forms OnCreate or or in the lpi itself as DirkS has suggested.

You can also add an Initialization and Finalization section at the bottom of your unit.  Code you put in there will run during Application Initialization and Finalization (oddly enough :-) ).  As I said though, most of the time you want to follow DirkS's suggestions...

Code: [Select]
Unit Test;

Interface
....

Implementation

Var
  MyObject : TMyObject;

....

Initialization
  MyObject := TMyObject.Create;

Finalization
  MyObject.Free;

End. 
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #6 on: July 25, 2011, 06:22:35 am »
Thanks Mike.

I will check your suggestions in the best chance I have for that.


avra

  • Hero Member
  • *****
  • Posts: 2583
    • Additional info
Re: Procedure to run upon application-start?
« Reply #7 on: July 25, 2011, 12:01:32 pm »
Quote
The problem that it seems to me that WHAT I want to initialize is components in the application! And how could I do that if the application has not yet run?

Open your LPR file and do it like this:
Code: [Select]
begin
  {$I project1.lrs}
  Application.Initialize;
  Application.CreateForm(TfrmMain, frmMain);
  //  ----------- CALL YOUR PROCEDURE HERE WHEN ALL FORMS ARE CREATED ---------
  Application.Run;
end.
« Last Edit: July 25, 2011, 12:03:54 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #8 on: July 26, 2011, 12:24:13 am »
Quote
The problem that it seems to me that WHAT I want to initialize is components in the application! And how could I do that if the application has not yet run?

Open your LPR file and do it like this:
Code: [Select]
begin
  {$I project1.lrs}
  Application.Initialize;
  Application.CreateForm(TfrmMain, frmMain);
  //  ----------- CALL YOUR PROCEDURE HERE WHEN ALL FORMS ARE CREATED ---------
  Application.Run;
end.

Thank you very much for this, Avra.

This makes a lot of sense and straightforward. I will try it soon. It is also a simple but powerful way, seems to me, along with what I also was told that any code one writes in there is respected by Lazarus, as that file is no done anew every time one compiles. I figure if Lazarus wants to change any other thing there, it will not bother that code we put in there. :)

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #9 on: July 28, 2011, 12:19:45 am »
Hi again on this topic.

I was studying things, and found that the Form has the capability to run an event from Unit1 (or whatever name of the project) via its very own OnActivate handler.

I already used it on my project, where I needed to format some strings of floats,  that are displayed in raw mode upon start, but now they are displayed in a formatted way, and it was rather easy and logical thing that this mechanism is included.

All of the aproaches discussed, however, have their peculiar faculties that I am sure would be the best options on other cases. :)

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
Re: Procedure to run upon application-start?
« Reply #10 on: July 29, 2011, 03:59:23 am »
Nicely found :-) 

OnActivate is fired every time the form is activated.  This will happen if you switch focus to a different application in your OS, then switch back again.  Be wary of putting any code in OnActivate that you only want to run once, and only once (such as creates and such).   I use OnActivate myself at times, and I wrap the code I want to run inside a "semaphore" for want of a better word. 

From the sounds of what you're doing at the moment, there's no harm in putting your code inside OnActivate - doesn't matter if it runs several times, however if you do run into an issue where you only want code to run once, then you're looking for something like....

Keep up the good work :-)

Code: [Select]
Type
  Myform = Class(TForm)
... 
  Private
    FActivated : Boolean;
...
  End;

MyForm.FormCreate(Sender: TObject);
Begin
  FActivated := False;
End;

MyForm.FormActivate(Sender: TObject);
Begin
  If Not FActivated Then
  Begin
    //  Put any code in here that you only want to run ONCE

    FActivated := True;
  End;

  // Put code in here that you want to run each and every time your form receives focus
End;
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #11 on: July 29, 2011, 05:45:52 am »
Hi and THANK YOU, Mike,

for this great advice. I will re-inspect what I am doing since I also was wondering how this OnActivate works.

From what you say, and from what I gather, what I have done is not correct and will affect my situation, and I have not most likely noticed it since the condition to notice was not there all this time.

So I will surely check and verify the wrong aspect of it,  and see about resolving it as you suggest, because, yes, I only want it to run ONCE, not every time one goes to another application and comes back. %)

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #12 on: July 29, 2011, 10:11:43 pm »
Hi Mike again,

I am now pretty sure that, as you advised, it would just be a matter of having a flag to raise up as soon as the code is run the first time (a boolean, an integer, or almost any variable). So that one's code would only run once and would run immediately after the form is activated the first time.

I also think that this can have many uses, such as checking the setup of the system in which the form is to run. Screen resolution settings, for instance.

Thanks again!

Elmug

  • Hero Member
  • *****
  • Posts: 849
Re: Procedure to run upon application-start?
« Reply #13 on: August 04, 2011, 07:19:13 am »
Nicely found :-) 

OnActivate is fired every time the form is activated.  This will happen if you switch focus to a different application in your OS, then switch back again.  Be wary of putting any code in OnActivate that you only want to run once, and only once (such as creates and such).   I use OnActivate myself at times, and I wrap the code I want to run inside a "semaphore" for want of a better word. 

From the sounds of what you're doing at the moment, there's no harm in putting your code inside OnActivate - doesn't matter if it runs several times, however if you do run into an issue where you only want code to run once, then you're looking for something like....

Keep up the good work :-)

Code: [Select]
Type
  Myform = Class(TForm)
... 
  Private
    FActivated : Boolean;
...
  End;

MyForm.FormCreate(Sender: TObject);
Begin
  FActivated := False;
End;

MyForm.FormActivate(Sender: TObject);
Begin
  If Not FActivated Then
  Begin
    //  Put any code in here that you only want to run ONCE

    FActivated := True;
  End;

  // Put code in here that you want to run each and every time your form receives focus
End;

Hi Mike, and forum people,

I come back to this thread to mention that I have now discovered that OnActivate DOES NOT fire every time the Form is re-entered, as when left and coming back from another application.

By testing, the  OnActivate, for the Form1 only fires ONCE, when it gets started.

Therefore, no need for boolean if one wishes to have some code run upon start of application only.

However, please correct me if wrong. %)


avra

  • Hero Member
  • *****
  • Posts: 2583
    • Additional info
Re: Procedure to run upon application-start?
« Reply #14 on: August 04, 2011, 10:35:29 am »
Form.OnActivate fires when form gets active status. This happens only once in your test because you have just one form. Add Form2 and you will see that it fires whenever Form1 gets gets back it's focus from Form2, Form1.OnActivate will fire.

Add one button on Form1 and create new form and try this:
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  Tag := Tag + 1;
  Caption := 'Last was Form.OnActivate. Counter=' + IntToStr(Tag);
end;
You can create TForm1.FormActivate by double clicking on event OnActive of Form1, and you should have Unit2.pas added to uses of Unit1.pas. Counter will get 1 when application is started, and it will be incremented each time you close Form2 (since you have only 2 forms in your test application).

For further experiments you can try to add this:
Code: [Select]
procedure TForm1.FormShow(Sender: TObject);
begin
  Tag := Tag + 10;
  Caption := 'Last was Form.OnShow. Counter=' + IntToStr(Tag);
end;

procedure TForm1.FormWindowStateChange(Sender: TObject);
begin
  Tag := Tag + 100;
  Caption := 'Last was Form.OnWindowStateChange. Counter=' + IntToStr(Tag);
end;
Experiment minimize/restore application and watch what happens.

You can also experiment with events of ApplicationProperties component, but I think that you really need event like Application.OnActivate. This could be easily accessed in Delphi, but in Lazarus you should try something like this:
Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.AddOnActivateHandler(@FormActivate);
end;
This will actually fire Form1.FormActivate when Application.OnActivate triggers. Now your OnActivate event on Form1 will fire on both getting focus from another form in the same application, and on getting focus from another application. If you need separate event just for last one, I am sure you will figure it out ;-)
« Last Edit: August 04, 2011, 10:37:11 am by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

 

TinyPortal © 2005-2018