Last night, a friend told me that he wanted to block the win key of the keyboard and asked me if I had a simple solution. When I came back, I made a simple example.
A low-level keyboard hook is used in this example. It is introduced from Windows2000, so it must be supported in Win2000 or later versions, in addition, the section about low-level keyboard Hooks is not introduced in Delphi. Therefore, compare the C language data to convert it to the Delphi format. Below is a constant and a data structure declared in the Delphi format:
Const wh_keyboard_ll = 13;
Type
Pbdllhookstruct = ^ tbdllhookstruct;
Tbdllhookstruct = record
Vkcode: DWORD;
Scancode: DWORD;
Flags: DWORD;
Time: DWORD;
Dwextrainfo: DWORD;
End;
The usage of the hook is not described in detail here. As long as you search for it online, there are a lot of materials in this regard! Here is a brief introduction to the basic principles of HOOK: since Windows is a message-based operating system, we and the system (including hardware and operating systems or other software) basically, messages are used. There are many more messages, including hardware messages (such as keyboard-press messages and mouse messages), software messages (many windows-defined notification messages or custom messages), and many more, I will not list them here! In message processing, we use system functions such as getmessage or other functions provided by windows. In fact, these functions are not only used to represent their names, they can also use interruptions to enter the system space for further processing (for example, if the getmessage function call finds that no message is sent to the thread message queue, the system will schedule it, this thread will be suspended until the next scheduling occurs. If a message is sent to the queue, the CPU time will be re-obtained.) Here, the system will process a lot, this includes hook processing. If a user registers a hook at this time (all the hooks registered by the user are saved in a linked list of data structures ), then, the function calls the callback function of the hook before returning the result. If the callback returns true, it indicates that the callback function has processed the message event and requires the system not to send the message event again, at this time, the function will wait for the arrival of the next message event and will not return (BLOCKED), so our userProgramWill not be notified of this message event, and this will not achieve the goal of filtering?
Okay. I have a brief understanding of the hook principle. Let's talk about the process below:
1. Install the hook first:
Hhook setwindowshookex (INT idhook, hookproc lpfn, hinstance hmod, DWORD dwthreadid );
This function is used to install hooks. The idhook parameter indicates the type of hooks you want to install (the hook type is pre-defined by the system, and the system can only process known hook types ); lpfn indicates your callback process. If a message event of your installation type occurs, Windows will call your function based on the registered function address, the structure returned by the function determines whether to filter or continue to be handed over to the user for processing. If we want to install a filter function for all programs, we can map this function to the address space of all programs for use, this task can be completed only by the DLL file. This is why the global hook function must be placed in the DLL. If it is placed in the EXE file, only the message events of our own EXE can be filtered; the hmod parameter is the module handle that contains the hook function. dwthreadid indicates the ID of the thread to be monitored. If it is determined, the hook is only valid for a single thread (note: the message queue is a thread, rather than a window or process, although many threads do not use a queue at all). If this parameter is set to 0, all threads are used, at this time, the hook function should be placed in the DLL, otherwise it will be invalid!
2. Define the hook function: (this step should be at the beginning. In order to better organize the function, put the 2nd rows ^_^)
Function procname (ncode: integer; wparam: integer; lparam: integer): lresult; stdcall;
The above is the prototype of the hook function. Here we should pay attention to the returned value. If we are sure to filter, We can exit the function by returning 1. If we are not interested, the returned value cannot be determined. It should be handed over to the system. The system will look for other registered hook functions, and the returned values will be determined by them. Therefore, the returned values can be determined by calling the callnexthookex function.
3. Uninstall the HOOK:
Longbool unhookwindowshookex (INT idhook );
If we want to exit hook filtering, we call this function, which will delete the corresponding hooks in the hook chain in windows.
The following is the Delphi method for implementing a low-level keyboard hook.CodeBecause it is a low-level hook (with the highest processing priority), it has a feature that does not need to put the hook function in the DLL, as long as our processes are running (not necessarily active), Windows will always be able to get the entry to our callback function (I guess there is a task switch internally, finally, we will switch to our process for processing. This switching process can achieve the same effect of using DLL to map the callback function to the address space of other processes! If our process is disabled, even if our hook is not uninstalled normally, the hook will not work immediately because the system cannot find the callback function entry address, even if it does not use javas_^ for task switching, this example is very simple. It only shields the win key (there are two win keys on the keyboard ).
Unit unit1;
Interface
Uses
Windows, messages, sysutils, variants, classes, graphics, controls, forms,
Dialogs, stdctrls;
Const wh_keyboard_ll = 13;
Type
Pbdllhookstruct = ^ tbdllhookstruct;
Tbdllhookstruct = record
Vkcode: DWORD;
Scancode: DWORD;
Flags: DWORD;
Time: DWORD;
Dwextrainfo: DWORD;
End;
Tform1 = Class (tform)
Button1: tbutton;
Button2: tbutton;
Procedure button1click (Sender: tobject );
Procedure button2click (Sender: tobject );
Procedure formclose (Sender: tobject; var action: tcloseaction );
Private
{Private Declarations}
Public
{Public declarations}
End;
Function keyboardproc (ncode: integer; wparam: integer; lparam: integer): lresult; stdcall;
VaR
Form1: tform1;
HOOK: hhook = 0;
Implementation
{$ R *. DFM}
Function keyboardproc (ncode: integer; wparam: integer; lparam: integer): lresult;
Begin
If (ncode = hc_action) then
Begin
Case wparam
Wm_keydown, wm_syskeydown,
Wm_keyup, wm_syskeyup:
Begin
If (pbdllhookstruct (lparam) ^. vkcode = vk_lwin) or
(Pbdllhookstruct (lparam) ^. vkcode = vk_rwin) then
Begin
Result: = 1;
Exit;
End;
End;
End;
End;
Result: = callnexthookex (0, ncode, wparam, lparam );
End;
Procedure tform1.button1click (Sender: tobject );
Begin
HOOK: = setwindowshookex (wh_keyboard_ll, keyboardproc, hinstance, 0 );
End;
Procedure tform1.button2click (Sender: tobject );
Begin
If Hook 0 then
Unhookwindowshookex (Hook );
End;
Procedure tform1.formclose (Sender: tobject; var action: tcloseaction );
Begin
Button2click (NiL );
End;
End.