Recent

Author Topic: "MousePreview" monitoring mouse clicks?  (Read 7644 times)

ArminLinder

  • Sr. Member
  • ****
  • Posts: 318
  • Keep it simple.
"MousePreview" monitoring mouse clicks?
« on: February 22, 2017, 10:36:58 am »
Hi,

on a form I wish to clear the status line when either any button or key is pressed anywhere, or a mouse click occurs.

For keys, this was not difficult: set KeyPreview to true, and in the FormKeyUp handler do the job.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3.   EditStatus.Text := 'Cleared by keypress';
  4. end;
  5.  
  6. procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  7.   Shift: TShiftState; X, Y: Integer);
  8. begin
  9.   EditStatus.Text := 'Cleared by mouse click';
  10. end;
  11.  

As you can see, I tried the same with OnMouseUp, but had no good results, the event does not fire, if the mouse is over any visible control, e.g. a button or even a panel, which is almost always the case.

Is there an alternative to defining an OnMouseUp handler into each and every control, something like a "MousePreview" like there is a "KeyPreview"?

Thnx

Armin.
« Last Edit: February 22, 2017, 10:57:52 am by Nimral »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

balazsszekely

  • Guest
Re: "MousePreview" monitoring mouse clicks?
« Reply #1 on: February 22, 2017, 10:49:06 am »
Hi Nimral,

You're under windows, just create a mouse hook and you're good to go. If you find the hook a difficult solution, with a timer watch the mouse position(Mouse.CursorPos) translate to your form(ScreenToClient) then calculate which component is below the mouse. The third solution is to redirect every MouseUp to a single event at least for those component you're interested in. The second and third solution are cross-platform.

ArminLinder

  • Sr. Member
  • ****
  • Posts: 318
  • Keep it simple.
Re: "MousePreview" monitoring mouse clicks?
« Reply #2 on: February 22, 2017, 11:09:40 am »
Thanks, GetMem,

from what I see here ...

http://stackoverflow.com/questions/25482429/hooking-the-mouse-and-keyboard-in-lazarus

creating a mouse hook doesn't seem to be too much of work, but it ruins the platform-independentness I have right now.

Solution #2: haven't tried this yet, but as far as your suggestion goes, I'd be able to track the mouse position, OK, but how would I detect a mouse click then? I don't see how this approach could help me.

Solution #3: that's exactly what I'd like to avoid, having to overwrite each and every control's OnMouseUp.

Let's see if someone else has an additional approach, if not, I'll implement #1.

Thanks,

Armin.
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

balazsszekely

  • Guest
Re: "MousePreview" monitoring mouse clicks?
« Reply #3 on: February 22, 2017, 11:41:27 am »
Quote
Solution #3: that's exactly what I'd like to avoid, having to overwrite each and every control's OnMouseUp.
I'm not sure what do you mean by overwrite here? OnFormCreate, with a recursively function, loop through form controls and assign a common OnMouseUp to each control you're interested in. This can be done selectively(only for buttons for example, or for a mixed type of controls tagged with a unique Tag). When OnMouseUp is fired just check the sender(tag, name) and take the appropriate action. I don't know what exactly are you trying to achieve but it shouldn't be to difficult with the above method.

ArminLinder

  • Sr. Member
  • ****
  • Posts: 318
  • Keep it simple.
Re: "MousePreview" monitoring mouse clicks?
« Reply #4 on: February 22, 2017, 12:37:51 pm »
I see your point.

You still overwrite each and every control's OnMouseUp, but you don't do it by hand, which is kind of a progress.

Problem I see: this move is quite unexpected for anyone modifying my code in the future, including me in a year's time or so :-) So if someone decides to define his own MouseUp event for any control, my routine would silently reverse his definition on FormCreate.

I still don't like the approach, though you showed me some kind of automating it :-)

No bad words, just a matter of taste :-)

Greetz, Armin.
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

balazsszekely

  • Guest
Re: "MousePreview" monitoring mouse clicks?
« Reply #5 on: February 22, 2017, 01:23:49 pm »
@Nimral

Quote
I still don't like the approach, though you showed me some kind of automating it :-)
You can make it fully automated. I mean if somebody creates a MouseDown event from the designer, you can redirect to this event after it was catched on the generic event.

Ok. I'm not gonna insist further.  :)
« Last Edit: February 22, 2017, 01:32:36 pm by GetMem »

Sergei

  • New member
  • *
  • Posts: 8
Re: "MousePreview" monitoring mouse clicks?
« Reply #6 on: November 17, 2017, 01:14:20 pm »
Another possible solution is here: http://forum.lazarus-ide.org/index.php?topic=16843.0

It registers a global hook for user events and seems cross-platform (I'm on Win 64).

Code: Pascal  [Select][+][-]
  1. uses
  2.   ..., Forms, LMessages;
  3.  
  4. procedure TForm1.FormCreate(Sender: TObject);
  5. begin
  6.   Application.AddOnUserInputHandler(@MouseHook);
  7. end;
  8.  
  9. procedure TForm1.FormDestroy(Sender: TObject);
  10. begin
  11.   // To prevent possible system resource leaks
  12.   Application.RemoveOnUserInputHandler(@MouseHook);
  13. end;
  14.  
  15. procedure TForm1.MouseHook(Sender: TObject; Msg: Cardinal);
  16. begin
  17.    if (Msg <> LM_MOUSEMOVE) and (Msg <> LM_NCMOUSEMOVE) then Exit;
  18.  
  19.   // Do stuff
  20. end;
  21.  
« Last Edit: November 17, 2017, 03:10:34 pm by Sergei »

741

  • New Member
  • *
  • Posts: 27
Re: "MousePreview" monitoring mouse clicks?
« Reply #7 on: August 01, 2025, 10:37:40 pm »
I just tried this technique and I get "Error variable identifier expected" as follows

TfrmMain = class(TForm)
   ...
procedure MouseHook(Sender: TObject; Msg: Cardinal);
   ...
end;
   
   
procedure TfrmMain.FormCreate(Sender: TObject);
begin
...
   Application.AddOnUserInputHandler(@MouseHook); //Error Variable Identifier expected
...
end;

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1565
    • Lebeau Software
Re: "MousePreview" monitoring mouse clicks?
« Reply #8 on: August 01, 2025, 11:34:37 pm »
Code: [Select]
Application.AddOnUserInputHandler(@MouseHook); //Error Variable Identifier expected

Did you make sure there is not another identifier named MouseHook in scope somewhere?  Try using a more unique name, like MyMouseHook or DoMouseHook.  Or, try qualifying the method: @Self.MouseHook.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

741

  • New Member
  • *
  • Posts: 27
Re: "MousePreview" monitoring mouse clicks?
« Reply #9 on: August 02, 2025, 11:59:16 am »
Hi

Thanks for the input. This still fails (with the same error) - here is a simple test case.

Code: Pascal  [Select][+][-]
  1.    TTest = class
  2.       procedure MouseHook_SJB(Sender: TObject; Msg: Cardinal);
  3.       procedure TestHook;
  4.    end;
  5. ...
  6. ...
  7. procedure TTest.TestHook;
  8. begin
  9.   Application.AddOnUserInputHandler(@Self.MouseHook_SJB);
  10. end;
  11.  

Also, I notice that omitting the @ allows compilation

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.FormCreate(Sender: TObject);
  2. var
  3.    strIniFileFullName: string;
  4. begin
  5.    Application.AddOnUserInputHandler(@Self.MouseHook1);  //ERROR
  6.    Application.AddOnUserInputHandler(MouseHook1);        //NO Error
  7.    Application.AddOnUserInputHandler(@MouseHook1);       //Error
  8.  

I am trying to recall - Is the procedure name itself a pointer?


UPDATE: Omitting the @ seems to make it work.
« Last Edit: August 02, 2025, 12:16:16 pm by 741 »

dseligo

  • Hero Member
  • *****
  • Posts: 1601
Re: "MousePreview" monitoring mouse clicks?
« Reply #10 on: August 02, 2025, 12:44:33 pm »
Code: [Select]
   Application.AddOnUserInputHandler(@Self.MouseHook1);  //ERROR
   Application.AddOnUserInputHandler(MouseHook1);        //NO Error

I am trying to recall - Is the procedure name itself a pointer?


UPDATE: Omitting the @ seems to make it work.

You use mode Delphi.

If you use mode Delphi than you omit @, otherwise (in mode ObjFPC) you put @.

See here (number 2): https://www.freepascal.org/daily/doc/prog/progse76.html
And here (number 1): https://www.freepascal.org/daily/doc/prog/progse74.html

741

  • New Member
  • *
  • Posts: 27
Re: "MousePreview" monitoring mouse clicks?
« Reply #11 on: August 02, 2025, 09:31:50 pm »
Thank you!

 

TinyPortal © 2005-2018