Recent

Author Topic: Windows Messages and Class Helper  (Read 3886 times)

pmesquita

  • New Member
  • *
  • Posts: 29
Windows Messages and Class Helper
« on: June 17, 2021, 05:29:50 pm »
Personal,
How are we going? I hope well...

I need a procedure to be executed when the form is minimized, but it will be wrong to copy and put the same code in countless forms, so I had the brilliant idea of creating a Helper

The problem starts with that when compiling, the compiler says that "MESSAGE" is not allowed in helper types.

Is it possible to override the WmSysCommand procedure using a class helper and only importing the FormHelper.pas unit into the other units?

Here's an example of how I'm doing...

Code: Pascal  [Select][+][-]
  1. unit helpers_class;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeswitch advancedrecords+}
  5.  
  6. interface
  7.  
  8. uses
  9. Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls,
  10. LCLType, ExtCtrls, StdCtrls, Messages, LMessages;
  11.  
  12. Type
  13.   { SISUtilHelperForms }
  14.   HelperForms = Class Helper For TForm;
  15.    Private
  16.     { Private Declarations }
  17.     Procedure WmSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
  18.   End;
  19.  
  20. implementation
  21.  
  22. { HelperForms }
  23. Procedure HelperForms.WmSysCommand(var Msg: TWMSysCommand);
  24.  Begin
  25.   If (msg.CmdType = SC_MINIMIZE) Then
  26.    ShowMessage('Application.Minimize');
  27.  
  28.   inherited;
  29.  End;
  30.  
  31. End.
  32.  

Error:
Code: Pascal  [Select][+][-]
  1. helper_class.pas(17,53) Error: "MESSAGE" is not allowed in helper types

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 955
    • Lebeau Software
Re: Windows Messages and Class Helper
« Reply #1 on: June 17, 2021, 07:01:11 pm »
Is it possible to override the WmSysCommand procedure using a class helper and only importing the FormHelper.pas unit into the other units?

No.  For one, because of the error you already found.  'message' dispatching simply doesn't work with a helper class.  But also, because WMSysCommand() is not a virtual method, but even if it were, a helper class can't override a virtual method anyway.

So, there is simply no avoiding having to catch the WM_SYSCOMMAND message in each Form individually, and then delegating to the desired handler.  If you want to consolidate your handler across multiple Forms, create a base class derived from TForm, and then derive your Forms from that base class as needed.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

pmesquita

  • New Member
  • *
  • Posts: 29
Re: Windows Messages and Class Helper
« Reply #2 on: June 17, 2021, 08:15:33 pm »
I understood...I suspected I wouldn't be able to intercept Windows messages...

In this case of creating a class derived from a TForm... is there any example or is the process the same as I create a component for example TEditCustom = Class(TEdit) ... ?

Lulu

  • Full Member
  • ***
  • Posts: 131
Re: Windows Messages and Class Helper
« Reply #3 on: June 17, 2021, 09:43:12 pm »
You can create a form1 with the IDE, add some stuff in, then to derive another form from it, menu->File->New...  select 'composant du projet hérité' (my ide is in french) and on the right select form1. The IDE will create a new form inherited from form1
fpc 3.2.0 Lazarus 2.0.10  -  AMD A8-6600K  -  Windows 10  64bits

engkin

  • Hero Member
  • *****
  • Posts: 2854
Re: Windows Messages and Class Helper
« Reply #4 on: June 18, 2021, 04:48:50 am »
The message in your class helper makes me think you want to know when the *application* is minimized. If so then use:
Application.AddOnMinimizeHandler

But then that was not your question. If you want to know when a *form* is minimized, you can change the WindowProc of the form. Using your class helper, it would be like:
Code: Pascal  [Select][+][-]
  1. unit helpers_class;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeswitch advancedrecords+}
  5.  
  6. interface
  7.  
  8. uses
  9. Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls,
  10. LCLType, ExtCtrls, StdCtrls, Messages, LMessages;
  11.  
  12. Type
  13.   { SISUtilHelperForms }
  14.   HelperForms = Class Helper For TForm
  15.   private
  16.     procedure WmSysCommand(var TheMessage: TLMessage);
  17.   public
  18.     procedure Catch_SC_MINIMIZE;
  19.   End;
  20.  
  21.  
  22. implementation
  23.  
  24. var
  25.   OrgWindowProc:array of TWndMethod;
  26.  
  27. { HelperForms }
  28.  
  29. procedure HelperForms.Catch_SC_MINIMIZE;
  30. var
  31.   idx:integer;
  32. begin
  33.   idx:=Length(OrgWindowProc);
  34.   SetLength(OrgWindowProc, idx+1);
  35.   OrgWindowProc[idx]:=WindowProc;
  36.   Tag:=idx;
  37.   WindowProc:=@WmSysCommand;
  38. end;
  39.  
  40. procedure HelperForms.WmSysCommand(var TheMessage: TLMessage);
  41. var
  42.   msg: TWMSysCommand absolute TheMessage;
  43.  Begin
  44.   If (msg.CmdType = SC_MINIMIZE) Then
  45.    ShowMessage('Application.Minimize');
  46.  
  47.   OrgWindowProc[Tag](TheMessage);
  48.   //inherited;
  49.  End;
  50.  
  51. End.

To use it, after you create the form, call the helper:
Code: Pascal  [Select][+][-]
  1. program project1;
  2. ...
  3.   Application.CreateForm(TForm1,Form1);
  4.   Application.CreateForm(TForm2,Form2);
  5.  
  6.   Form1.Catch_SC_MINIMIZE;
  7.   Form2.Catch_SC_MINIMIZE;
  8. ...

That's not the only way. Here I use the Tag property to store the index of the original WindowProc.

I just noticed you posted this in Windows section. You can use SetWindowLong with GWL_WNDPROC to do the same, without using the Tag property.
« Last Edit: June 18, 2021, 04:54:09 am by engkin »

 

TinyPortal © 2005-2018