Forum > LCL

How to use function LCLIntf.AddEventHandler?

(1/1)

Hartmut:
In my GUI-program I want to use function LCLIntf.AddEventHandler to handle some communication with other clients via internet.

Function AddEventHandler is declared as:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function AddEventHandler(AHandle: THandle; AFlags: dword; AEventHandler: TWaitHandleEvent;                         AData: PtrInt): PEventHandler;My question is about the 1st parameter 'AHandle': what must I use here on Windows and on Linux?

Linux:
The documentation (which is hard stuff for me) https://wiki.freepascal.org/Main_Loop_Hooks says in chapter "Pipes and Process Termination" (which my be wrong for function AddEventHandler):

--- Quote ---For gtk/unix, use the PID to watch as AHandle.
--- End quote ---
But when I use the PID from function system.GetProcessID as parameter 'AHandle' then I get always a Message in the Console:

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---(unit1:4198): GLib-WARNING **: 10:25:46.429: ../../../../glib/giounix.c:410Error while getting flags for FD: Ung├╝ltiger Dateideskriptor (9)The line number 4198 is wrong, so it does not help. The 2 German words mean "Invalid filedescriptor".

If I use instead a small number like 0..9 as parameter 'AHandle' then I do NOT get this Message. But with a high random number like 12345 I get this Message too. So I think the PID is here wrong.

Windows:
When I use the PID as parameter 'AHandle' then I get always endless Messages in the Console:

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---[TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6[TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6[TWin32WidgetSet.AppProcessMessages] MsgWaitForMultipleObjects returned: 6...If I use instead a small number like 3 or 7..9 as parameter 'AHandle' then it works, but I don't think this is reliable.

What I want:
I want a hook in the Main Loop, so that my procedure is called frequently, e.g. 10-20 times a second to handle some communication with other clients via internet.

I'm using Lazarus 2.0.10. Thanks in advance.

ASerge:

--- Quote from: Hartmut on June 20, 2022, 11:21:54 am ---My question is about the 1st parameter 'AHandle': what must I use here on Windows and on Linux?

--- End quote ---
In Windows, this is a kernel object descriptor (handle), not an ID.
Example:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, StdCtrls, InterfaceBase; type  TForm1 = class(TForm)    Memo1: TMemo;    procedure FormCreate(Sender: TObject);    procedure FormDestroy(Sender: TObject);  private    FTimer: THandle;    FHandler: PEventHandler;    procedure EventFire(AData: PtrInt; AFlags: LongWord);  public   end; var  Form1: TForm1; implementation {$R *.lfm} uses Windows, LCLIntf; procedure TForm1.EventFire(AData: PtrInt; AFlags: LongWord);begin  Memo1.Append(TimeToStr(Time));end; procedure TForm1.FormCreate(Sender: TObject);const  CPeriod = 5 * MSecsPerSec;var  DueTime: Int64 = 0; // First call immediately nowbegin  FTimer := CreateWaitableTimer(nil, False, '');  if not SetWaitableTimer(FTimer, DueTime, CPeriod, nil, nil, False) then    RaiseLastOSError;  FHandler := AddEventHandler(FTimer, 0, @EventFire, 0);end; procedure TForm1.FormDestroy(Sender: TObject);begin  CancelWaitableTimer(FTimer);  RemoveEventHandler(FHandler);  CloseHandle(FTimer);end; end.

Hartmut:
Thank you very much ASerge for your reply and your demo. I got it to work and assume that I understand how it works.
Now I have 2 questions left:
 - What can I do on Linux?
 - If I create this special timer on Windows, why don't I use a normal 'TTimer'? Please what are the benefits of your solution over a TTimer-solution, which would work on Linux too?

Thanks for any help.

ASerge:

--- Quote from: Hartmut on June 20, 2022, 07:20:33 pm --- - If I create this special timer on Windows, why don't I use a normal 'TTimer'? Please what are the benefits of your solution over a TTimer-solution, which would work on Linux too?

--- End quote ---
This is just a demonstration. WaitableTimer is more accurate, but for GUI applications a regular TTimer is usually enough. Especially in such an example, when the kernel object is waited in the same queue as the windows event (WM_TIMER).
AddEventHandler is most often used to wait for the end of pipeline channels, completion of file operations, waiting for directory change events, network sockets, etc.

Hartmut:
Thanks a lot ASerge for that explanations. Now I understand more about the purpose of function AddEventHandler. I had thought, this would be the easiest solution but possibly I was wrong, because I have no handle already.
If there comes no easy suggestion for Linux, I will use a 'TTimer' instead.

Navigation

[0] Message Index

Go to full version