In this article we find out what the user is doing with his mouse, even outside of the program. Let’s conquer the whole system!
We have events on components, such as OnClick
, OnMouseDown
, OnScrollDown
etc. But unfortunately these events only work when the mouse is inside the form. But sometimes we need to get a view of what the user is doing on other programs or other windows (or in other words “System-wide”). These “System wide” events can be “caught” through a crazy thing called “hooks”.
A Hook is a function that you can tell Windows to run whenever something special happens. You can create a hook for keyboard to run it whenever a key is pressed. Then you can do something based on which key is pressed (in whichever window it is pressed). Today we are going to focus on mouse events. We will catch what the mouse is doing system wide. Wherever the mouse goes, we catch what the user is doing with it.
What we’ll do
We will catch when the left, middle and right mouse button is pressed, and additionally when the mouse wheel is scrolled up or down. These things are especially useful in cases like, to create such a program which can record a macro and repeat those tasks later, or create mouse gestures on touching the corner of the screen (like in Gnome 3), or maybe creating a form which acts like a menu so when the user clicks outside it closes… the possibilities are endless.
Any DLL need to be made?
Nope.
Some Delphi/Pascal codes found on the internet demand to create a DLL file. DLL files are a mess and don’t forget the DLL hell. In this article, the whole code is Lazarus based and resides in the single .exe file with no DLL involved. Cool, right!
Tutorial
Start Lazarus.
Create a new Application Project (Project -> New Project -> Application -> OK).
Draw a TLabel and a TMemo. Empty the Lines property and set the Scrollbars property to ssVertical of the Memo. Customize the form the way you like it.
Optionally, you can set the FormStyle to fsSystemStayOnTop. It will keep the form always on top and let you see the events even when you click outside of the form.
Switch to code view (F12). Now add windows
unit to uses
clause:
1 | uses |
Under the type
clause enter this:
1 | type |
Before the var
clause enter:
1 | ... |
This function will be our hook function. Windows will run it whenever there is a mouse event.
Under the var
clause declare a variable:
1 | var |
Now we enter code for our hook function. Under the implementation
clause enter:
1 | function LowLevelMouseHookProc(nCode, wParam, lParam : integer) : integer; stdcall; |
Switch to Form view (F12), then double click on the form, and enter:
1 | procedure TForm1.FormCreate(Sender: TObject); |
Switch to form view again (F12), then select the form, go to Object Inspector -> Events, then click OnDestroy
, then click the […] button beside it. Now enter:
1 | procedure TForm1.FormDestroy(Sender: TObject); |
Now run the project (F9 or Run -> Run).
Now, when you use this code on your project you will need to customize the LowLevelMouseHookProc()
function to suit your needs. Try things yourself. The sky is the limit here!
…And for the mouse position, it is better to use the Mouse.CursorPos.x or .y because the solution in this article sometimes begets negative values, which might not be what you would like. The code is kept just to show how it is done in the hooks style.
Ref:
https://www.experts-exchange.com/questions/21838717/Delphi-detect-a-left-right-mouse-click-anywhere-on-the-screen.html - thanks to ZhaawZ, his answer helped greatly
Downloads
You can download the source code for the tutorial project and executable/EXE files from the links below: