Recent

Author Topic: Extended Mouse Hook Demo by KodeZwerg  (Read 631 times)

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1398
  • Fifty shades of code.
    • Delphi & FreePascal
Extended Mouse Hook Demo by KodeZwerg
« on: December 14, 2022, 01:24:22 am »
Since I have corrected an example from here and showed in this thread, what just covered the left mouse button up event, here is a full example to discuss or freely use.

I hope you like it and it is understandable.
Full Demo Project in attachment, just source I show you here.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. (*
  4. Getting Pixel coordinate and color under mouse cursor routine plus mousehook, rewritten by KodeZwerg
  5.  
  6. used Resources for hook
  7. https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msllhookstruct
  8. https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644986(v=vs.85)
  9. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
  10. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-callnexthookex
  11. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-unhookwindowshookex
  12. used Resources for GetPixel
  13. https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdcw
  14. https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getpixel
  15. https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deletedc
  16. *)
  17.  
  18.  
  19. {$mode objfpc}{$H+}
  20.  
  21. interface
  22.  
  23. uses
  24.   Windows, // hooks with windows api
  25.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  26.  
  27. type
  28.  
  29.   { TForm1 }
  30.  
  31.   TForm1 = class(TForm)
  32.     Label1: TLabel;
  33.     Label2: TLabel;
  34.     Label3: TLabel;
  35.     Label4: TLabel;
  36.     Label5: TLabel;
  37.     Label6: TLabel;
  38.     procedure FormCreate(Sender: TObject);
  39.     procedure FormDestroy(Sender: TObject);
  40.   strict private
  41.   private
  42.   public
  43.   end;
  44.  
  45. type
  46.   // structure for pixel information
  47.   TMyPixel = packed record
  48.     R, G, B : Byte;
  49.     X, Y    : LongInt;
  50.     Color   : TColor;
  51.   end;
  52.   // structure for low level mouse events
  53.   TMSLLHOOKSTRUCT = record
  54.     pt          : TPoint;
  55.     mouseData   : DWORD;
  56.     flags       : DWORD;
  57.     time        : DWORD;
  58.     dwExtraInfo : ULONG_PTR;
  59.   end;
  60.   PMSLLHOOKSTRUCT = ^TMSLLHOOKSTRUCT;
  61.  
  62. // mouse hook message handler
  63. function LowLevelMouseProc(nCode: LongInt; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;
  64. // get pixel informations
  65. function MyGetPixel(const X, Y: LongInt; var MyPixel: TMyPixel): Boolean;
  66.  
  67. var
  68.   Form1: TForm1;
  69.   mHook: HHOOK; // the hook, if 0 or -1 then its garbage
  70.  
  71. implementation
  72.  
  73. {$R *.lfm}
  74.  
  75. function LowLevelMouseProc(nCode: LongInt; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;
  76. var
  77.   msLL: PMSLLHOOKSTRUCT absolute lParam;
  78.   Pixel : TMyPixel;
  79. begin
  80.   if ((mHook = 0) or (mHook = INVALID_HANDLE_VALUE)) then
  81.     Exit(0);
  82.   Result := CallNextHookEx(mHook, nCode, wParam, lParam);
  83.   with msLL^ do
  84.     begin
  85.       // react on mouse messages
  86.       case wParam of
  87.         WM_MOUSEMOVE     : if MyGetPixel(pt.X, pt.Y, Pixel) then
  88.                              begin
  89.                                Form1.Label1.Caption := Format('X: %d - Y: %d', [Pixel.X, Pixel.Y]);
  90.                                Form1.Label2.Caption := Format('R: %d - G: %d - B: %d - Color: %d', [Pixel.R, Pixel.G, Pixel.B, Pixel.Color]);
  91.                              end;
  92.         WM_LBUTTONDOWN   : Form1.Label6.Caption := 'WM_LBUTTONDOWN pressed';
  93.         WM_LBUTTONUP     : begin
  94.                              if MyGetPixel(pt.X, pt.Y, Pixel) then
  95.                                begin
  96.                                  Form1.Label3.Caption := Format('X: %d - Y: %d', [Pixel.X, Pixel.Y]);
  97.                                  Form1.Label4.Caption := Format('R: %d - G: %d - B: %d - Color: %d', [Pixel.R, Pixel.G, Pixel.B, Pixel.Color]);
  98.                                end;
  99.                              Form1.Label6.Caption := 'WM_LBUTTONUP pressed';
  100.                            end;
  101.         WM_MBUTTONDOWN   : Form1.Label6.Caption := 'WM_MBUTTONDOWN pressed';
  102.         WM_MBUTTONUP     : Form1.Label6.Caption := 'WM_MBUTTONUP pressed';
  103.         WM_RBUTTONDOWN   : Form1.Label6.Caption := 'WM_RBUTTONDOWN pressed';
  104.         WM_RBUTTONUP     : Form1.Label6.Caption := 'WM_RBUTTONUP pressed';
  105.         WM_MOUSEWHEEL    : if (SmallInt(HiWord(mouseData)) >= 0) then // positive = away from user, negativ = toward to user
  106.                              Form1.Label6.Caption := 'WM_MOUSEWHEEL (up) triggered'
  107.                              else
  108.                              Form1.Label6.Caption := 'WM_MOUSEWHEEL (down) triggered';
  109.         WM_XBUTTONDOWN   : if (HiWord(mouseData) = 1) then // 1 = xbutton1, 2 = xbutton2
  110.                              Form1.Label6.Caption := 'WM_XBUTTONDOWN (down) pressed'
  111.                              else
  112.                              Form1.Label6.Caption := 'WM_XBUTTONDOWN (up) pressed';
  113.         WM_XBUTTONUP     : if (HiWord(mouseData) = 1) then // 1 = xbutton1, 2 = xbutton2
  114.                              Form1.Label6.Caption := 'WM_XBUTTONUP (down) pressed'
  115.                              else
  116.                              Form1.Label6.Caption := 'WM_XBUTTONUP (up) pressed';
  117.         else
  118.           Form1.Label6.Caption := 'Unknown mouse event! (' + IntToStr(wParam) + ')'; // here you can identify more stuff
  119.       end;
  120.     end;
  121. end;
  122.  
  123. function MyGetPixel(const X, Y: LongInt; var MyPixel: TMyPixel): Boolean;
  124. var
  125.   DC : HDC;
  126. begin
  127.   DC            := Windows.CreateDCW(PWideChar('DISPLAY'), nil, nil, nil);
  128.   if ((DC = 0) or (DC = INVALID_HANDLE_VALUE)) then
  129.     Exit(False);
  130.   MyPixel.X     := X;
  131.   MyPixel.Y     := Y;
  132.   MyPixel.Color := Windows.GetPixel(DC, X, Y);
  133.   MyPixel.R     := MyPixel.Color and $000000FF;
  134.   MyPixel.G     := (MyPixel.Color shr 8) and $000000FF;
  135.   MyPixel.B     := (MyPixel.Color shr 16) and $000000FF;
  136.   Result        := Windows.DeleteDC(DC);
  137. end;
  138.  
  139. { TForm1 }
  140.  
  141. procedure TForm1.FormCreate(Sender: TObject);
  142. const
  143.   LWH_MOUSE_LL = LongInt(14); // 14 = low level mouse messages
  144. begin
  145.   // setup hook
  146.   mHook := SetWindowsHookExW(LWH_MOUSE_LL, @LowLevelMouseProc, hInstance, 0);
  147.   if ((mHook = 0) or (mHook = INVALID_HANDLE_VALUE)) then
  148.     ShowMessage('Problem during Hook install!' + sLineBreak +
  149.                 'Error: ' + SysErrorMessage(GetLastError));
  150. end;
  151.  
  152. procedure TForm1.FormDestroy(Sender: TObject);
  153. begin
  154.   // release hook
  155.   if ((mHook <> 0) and (mHook <> INVALID_HANDLE_VALUE)) then
  156.     if (not UnhookWindowsHookEx(mHook)) then
  157.       ShowMessage('Problem during Hook uninstall!' + sLineBreak +
  158.                   'Error: ' + SysErrorMessage(GetLastError));
  159. end;
  160.  
  161. end.

Enjoy!
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1398
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #1 on: December 14, 2022, 10:05:26 am »
Small update:

Code: Pascal  [Select][+][-]
  1.         WM_XBUTTONDOWN   : case HiWord(mouseData) of
  2.                              1: Form1.Label6.Caption := 'WM_XBUTTONDOWN (down) pressed';
  3.                              2: Form1.Label6.Caption := 'WM_XBUTTONDOWN (up) pressed';
  4.                              else
  5.                                Form1.Label6.Caption := 'WM_XBUTTONDOWN (' + IntToStr(HiWord(mouseData)) + ') pressed';
  6.                            end;
  7.         WM_XBUTTONUP     : case HiWord(mouseData) of
  8.                              1: Form1.Label6.Caption := 'WM_XBUTTONUP (down) pressed';
  9.                              2: Form1.Label6.Caption := 'WM_XBUTTONUP (up) pressed';
  10.                              else
  11.                                Form1.Label6.Caption := 'WM_XBUTTONUP (' + IntToStr(HiWord(mouseData)) + ') pressed';
  12.                            end;
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

fabiopesaju

  • Jr. Member
  • **
  • Posts: 89
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #2 on: December 14, 2022, 02:31:41 pm »
this works on linux?

Handoko

  • Hero Member
  • *****
  • Posts: 4833
  • My goal: build my own game engine using Lazarus
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #3 on: December 14, 2022, 02:33:59 pm »
No. It has Windows in the uses clause. See the code in the first post, line #24.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1398
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #4 on: December 14, 2022, 03:21:43 pm »
this works on linux?
Maybe compiling for Windows OS and running on Linux Wine will work, total untested.

No. It has Windows in the uses clause. See the code in the first post, line #24.
I also was thinking that my first lines speak for themself, I am referring to Microsoft Windows Api pages  ::)

If someone has code for other OS, please feel free to add your project in here  :-*
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #5 on: December 14, 2022, 04:56:29 pm »
Hi!

This is the simple way that works with all OS:

* Get the screen coordinates:  MyPoint := Mouse.CursorPos
* take a screenshot and load it into a TBitmap
* Get the color from MyBitmap.canvas.pixels[x,y]
* free the bitmap

Done

Winni


KodeZwerg

  • Hero Member
  • *****
  • Posts: 1398
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Extended Mouse Hook Demo by KodeZwerg
« Reply #6 on: December 15, 2022, 01:48:55 am »
Hi!

This is the simple way that works with all OS:
Hello Winni!
I am excited to see a simple "how"  8)
* Get the screen coordinates:  MyPoint := Mouse.CursorPos
Ugh... before I "get" a screen coordinate I need an Event, like "left mouse button was clicked inside/outside of my app"
Where is the "simple way" that works with all OS please?
* take a screenshot and load it into a TBitmap
* Get the color from MyBitmap.canvas.pixels[x,y]
* free the bitmap

Done

Winni
Thanks for sharing your wisdom but it covers 0% about my threads topic "Extended Mouse Hook"  :o

Please update your suggestion with an easy on all OS detecting mouse events code  :-*
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

 

TinyPortal © 2005-2018