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