Use the underlying keyboard hook to block any button (callback version)

xiaoxiao2021-03-06  39

I have written a "using the underlying keyboard hook shielding any button" and put it on my blog. The "shield" is changed to "interception" in the topic of this article, which is obviously stronger than the previous version. For the previously written DLL, there is a place that is not ideal, it can only be shielded. If you want to add some "little actions" before shield, you can only modify the DLL, add code to the LowlevelKeyboardProc function, implement new features. But this is obviously not flexible enough, and such a DLL does not have a generality. So I naturally thought of the callback, there's a lot of APIs that need a callback function in Windows, and we can certainly write such an API. The advantage of doing this is to leave enough interfaces to the DLL call program. At this time, the DLL is like a valve. We don't care about the button, just intercept the button message we care, and then further process, and these processing code writes in the callback function of the DLL call program. This is the most ideal.

Relative to the previous version, the modified DLL source code is as follows:

/ ************************************************** ****************** /

/ * File name: Maskkey.cpp * /

/ * * /

/ * Function: Standard DLL ---- Using the underlying keyboard hook to implement intercept keyboard any button * /

/ * * /

/ * Author: Lu Peipei (goodname008) Time: 2005.1.18 * /

/ * * /

/ * Blog: http://blog.9cbs.net/goodname008 * /

/ ************************************************** ****************** /

// Export function list

// StartmaskKey

// stopmaskkey

#define _win32_winnt 0x0500 // Set the system version, make sure you can use the underlying keyboard hook

#include "windows.h"

// Tune function pointer

Typedef Bool (Callback * lpfnkeyboardproc) (WPARAM, KBDLLHOOKSTRUCT *);

// Global variable

LPDWORD G_LPDWVIRTUALKEY = NULL; / / KeyCode array pointer

INT g_nlength = 0; // KeyCode array size

BOOL g_bdisablekeyboard = false; // Whether to block the entire keyboard

Hinstance g_hinstance = null; // module instance handle

HHOOK G_HHOOK = NULL; // Hook handle

LPFNKEYBOARDPROC G_LPFNKEYBOARDPROC; // Keyboard hook callback function pointer // DLL entry function

Bool Apientry Dllmain (Handle Hmodule, DWORD UL_REASON_FOR_CALL, LPVOID LPRESERVED)

{

/ / Save Module Instance Handle

G_HINSTANCE = (hinstance) hmodule;

/ / Unload hook at the end of the process or thread

Switch (ul_reason_for_call)

{

Case DLL_Process_attach:

Break;

Case DLL_THREAD_ATTACH:

Break;

Case DLL_PROCESS_DETACH:

Case DLL_THREAD_DETACH:

Free (g_lpdwvirtualkey);

IF (g_hhook! = null) UnHookWindowsHookex (g_hhook);

Break;

}

Return True;

}

// Bottom keyboard hook function

LResult Callback LowlevelKeyboardProc (int Ncode, WPARAM WPARAM, LPARAM LPARAM)

{

// Intercept some buttons of the keyboard, if g_bdisablekeyboard is true, intercept the entire keyboard button

IF (ncode> = hc_action)

{

KBDLLHOOKSTRUCT * PSTRUCT = (KBDLLHOKSTRUCT *) LPARAM;

IF (g_bdisableKeyboard)

IF (g_lpfnkeyboardproc (wparam, pstruct))

Return CallNexthookex (G_HHHOOK, NCODE, WPARAM, LPARAM);

Else

Return True;

LPDWORD TMPVIRTUALKEY = G_LPDWVIRTUALKEY;

For (int i = 0; i

{

IF (pstruct-> vkcode == * tmpvirtualkey )

IF (g_lpfnkeyboardproc (wparam, pstruct))

Return CallNexthookex (G_HHHOOK, NCODE, WPARAM, LPARAM);

Else

Return True;

}

}

// Call the next hook in the system

Return CallNexthookex (G_HHHOOK, NCODE, WPARAM, LPARAM);

}

/ ************************************************** ****************** /

/ * Start blocking keyboard button * /

/ * * /

/ * Parameters: * /

/ * LPDWVIRTUALKEY KeyCode array pointer * /

/ * NLENGTH Keycode array size * /

/ * BDISABLEKEYBOARD is intercepted for the entire keyboard * /

/ * * // * Return value: true success, FALSE failed * /

/ ************************************************** ****************** /

Bool WinApi StartmaskKey (LPDWORD LPDWVIRTUALKEY, INT NLENGTH,

LPFNKEYBOARDPROC LPFNKEYBOARDPROC, BOOL BDISABLEKEYBOARD = FALSE

{

// Return False if the keyboard hook has been installed

IF (g_hhook! = null || NLENGTH == 0) Return False;

// Save the keycode array from the user in the global variable

g_lpdwvirtualkey = (lpdword) Malloc (Sizeof (DWORD) * NLENGTH);

LPDWORD TMPVIRTUALKEY = G_LPDWVIRTUALKEY;

For (int i = 0; i

{

* TMPVIRTUALKEY = * LPDWVIRTUALKEY ;

}

g_nlength = NLENGTH;

g_bdisableKeyboard = bdisableKeyboard;

g_lpfnkeyboardproc = lpfnkeyboardproc;

/ / Install the underlying keyboard hook

g_hook = setwindowshookex (wh_keyboard_ll, loewlerybookardproc, g_hinstance, null);

IF (g_hhook == null) Return False;

Return True;

}

/ ************************************************** ****************** /

/ * Stop blocking keyboard button * /

/ * * /

/ * Parameters: (none) * /

/ * * /

/ * Return value: true success, False failed * /

/ ************************************************** ****************** /

Bool WinApi StopmaskKey ()

{

// Uninstall the hook

IF (unhookwindowshookex (g_hhook) == 0) Return False;

g_hook = NULL;

Return True;

}

Of course, the maskkey.h header is also added:

// Tune function pointer

Typedef Bool (Callback * lpfnkeyboardproc) (WPARAM, KBDLLHOOKSTRUCT *);

The following is an example in which the call is called: (two Dialog member functions, corresponding two buttons, plus a callback function) // Global keyboard hook callback function

// Parameter: Action identifies the keyboard message (press, bounce), Keystruct contains button information

Bool Callback KeyboardProc (WParam Action, KBDLLHOOKSTRUCT * PKEYSTRUCT)

{

// Judgment button action

Switch (action)

{

Case WM_KeyDown:

Break;

Case WM_KEYUP:

Break;

Case WM_SYSKEYDOWN:

Break;

Case WM_SYSKEYUP:

Break;

}

/ / Return true to continue to pass the button message

/ / Return false indicates the end button message delivery

Return False;

}

Void CMaskKeyAppdlg :: onstartmaskKey ()

{

// Shield a, b, c, upper, lower left, left, right and two WIN keys

DWORD DWVK [] = {'A', 'B', 'C', VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_LWIN, VK_RWIN};

INT NLENGTH = SIZEOF (DWVK) / SizeOf (DWORD);

StartmaskKey (DWVK, NLENGTH, KeyboardProc);

}

Void CMaskKeyAppdlg :: onstopmaskKey ()

{

STOPMASKKEY ();

}

Oh, is this exciting to see you here? ! StartmaskKey adds a parameter, a function pointer, which is our very familiar callback function. The StartmaskKey function in the DLL is saved in the G_LPFNKEYBOARDPROC variable, and once the button to be intercepted in LowlevelKeyboardProc, the callback function is transferred through the function pointer, and the control is completely returned to the DLL call program. Further processing by the callback function keyboardProc (play a small piece of music, or do something interesting program, or restart the shutdown. Hey, with you.: D), the Action parameter is used to identify keyboard messages (press) Or bounce down), the pkeystruct parameter contains rich buttons, in fact, the system is transmitted to LowlevelKeyboardProc, and I passed it to KeyboardProc, huh, huh. The most important thing is the return value of the callback function, which will determine the fate of this button. From the process of the LowlevelKeyboardProc function in the DLL, if the return value of the callback function KeyboardProc is true, the button message continues to pass to the next hook in the system; if false is the passage of the button message, this The effect of the interception button will be blocked.

People with VB may be a bit impatient, don't worry, the last article gives the VB called routine, which certain cannot be lacking. Here is an example in which you call in VB: (2 CommandButton added on the form, and renamed cmdstartmask and cmdstopmask, respectively)

Option expedition

Private Declare Function StartMaskKey Lib "MaskKey" (lpdwVirtualKey As Long, ByVal nLength As Long, ByVal lpfnKeyboarProc As Long, Optional ByVal bDisableKeyboard As Boolean = False) As LongPrivate Declare Function StopMaskKey Lib "MaskKey" () As Long

Private sub cmdstartmask_click ()

'Shield a, b, c, upper, bottom, left, right and two WIN keys

DIM Key (8) as long

Key (0) = VBKEYA

Key (1) = VBKEYB

Key (2) = VBEYC

Key (3) = VBEYLEFT

Key (4) = VBEYRIGHT

Key (5) = VBEYUP

Key (6) = VBKEYDOWN

Key (7) = & H5B 'left WIN button

Key (8) = & h

5C

'WIN button on the right

StartmaskKey Key (0), Ubound (Key) 1, Addressof KeyboardProc

End Sub

Private sub cmdstopmask_click ()

StopmaskKey

End Sub

The code of the form module is almost the same as the previous routine, just adding a parameter when calling the StartmaskKey function: Addressof keyboardproc. People who have used the callback function in VB will never be unfamiliar with this thing, and addressof is a one-dimensional operator, and then a function name, its function is a pointer to the specified function. However, it must be noted that the reconvection function (KEYBOARDPROC in this case) must be written in the standard module of the VB, as follows:

Option expedition

Private const wm_keydown = & h100

Private const wm_keyup = & h101

Private const wm_syskeydown = & h104

Private const wm_syskeyup = & h105

Public Type KBDLLHOOKSTRUCT

Vkcode as long 'virtual button (1--254)

Scancode as long 'hardware button scan code

Flags as long 'Flags

Time as long 'message timestamp

DWEXTRAINFO AS long 'extra information

End Type

Public enum keyaction

Action_keydown = WM_KeyDown

Action_keyup = WM_Keyup

Action_syskeydown = WM_SYSKEYDOWN

Action_syskeyup = WM_SYSKEYUP

END ENUM

'Global keyboard hook callback function

'Parameters: Action identifies the keyboard message (press, bounce up), Keystruct contains button information

Public Function KeyboardProc (Byval Action As KeyAction, Keystruct As Kbdllhookstruct) AS Booleanselect Case Action

Case action_keydown

Debug.print Keystruct.vkcode, "Press the keyboard button"

CASE ACTION_KEYUP

Debug.print Keystruct.vkcode, "Bounce Keyboard Buttons"

Case action_syskeydown

Case action_syskeyup

End SELECT

'Return true indicates that the button message continues to pass

'Return False indicates the end button message delivery

KeyboardProc = FALSE

END FUNCTION

And the VC version of the call routine is similar, just translate syntax into VB, this VB standard module is the taste of the MFC message mapping function? ! : D To note that the VB's callback function must be written in a standard module. The careful person may also find that I made a small hand feet on the Action parameters, it was changed to an enumeration type, which is mainly for easy understanding. OK, it's going to write so much, about the content of the global keyboard hook, I also want to tell a paragraph. With VC written DLL, VB can also easily implement global keyboard hooks. Of course, this is not limited to the keyboard hook, which can achieve any type of hook using this method. Download address of DLL source code and VC and VB call routines: http://9cbsgoodname008.51.net/maskkeycb.zip

* ------------------------------------------- *

* Please inform the author and indicate the source, 9CBS welcomes you! *

* Author: Lu Peipei (goodname008) *

* Email: GoodName008@163.com *

* Column: http://blog.9cbs.net/goodname008 *

* ------------------------------------------- *

转载请注明原文地址:https://www.9cbs.com/read-67443.html

New Post(0)