很都知道,如果要在系统范围内屏蔽键盘上的任何键,则需要使用全局键盘钩子。然而,像win键这样的“顽固”键是普通键盘钩子无法处理的。这里我提供了一种使用底部键盘钩子屏蔽任意键(包括win键)的方法,使其成为.dll的动态链接库,方便以后使用。 Hooks 是一种相对复杂的技术,通常用于监控系统中的某些类型的事件。这些事件可以与一个线程(线程钩子)或系统中的所有线程(全局钩子)相关。关于hook的理论,我不想说的太多,也不能说的太多,因为几句话说不清楚。
本文的重点是底层键盘钩子的应用。前几天有人问怎么在CSDN的VB版中屏蔽win键。说实话这个东西用VB也可以做,但是全局hook的hook函数必须写在标准dll中,VB只能通过灵活的方法制作标准dll,有点麻烦,所以我干脆用VC写了一个dll,这样就可以调用VC、VB或者Delphi等了,而且我也预留了足够的接口,我们后面会看到。
必须说明一点。底部键盘挂钩有一个半致命的缺点,就是只能在NT及以上系统使用,还好用2000、XP和2003的人肯定不在少数。使用 LongHorn 的人可能是不可或缺的,所以不要太担心这个。 :)
好了,废话少说,源代码如下:
DLL头文件(在VC中使用这个DLL中的函数时,需要包含这个头文件,就像用API包含windows.h一样):
/**************************************************** **************************/
/*文件名:MaskKey.h*/
/**/
/*Function:标准DLL导出函数头文件,在使用DLL的程序中包含该文件*/
/**/
/*作者:卢佩佩(goodname008) 时间:2004.8.21*/
/**/
/* 博客:*/
/**************************************************** **************************/
DECLSPEC_IMPORT
布尔
WINAPI
StartMaskKey(
LPDWORD lpdwVirtualKey,
intnLength,
BOOL bDisableKeyboard = FALSE
);
DECLSPEC_IMPORT
布尔
WINAPI
StopMaskKey();
DLL 主文件:
/**************************************************** **************************/
/*文件名:MaskKey.cpp */
/**/
/*功能:标准DLL ----使用底部键盘钩子实现对键盘任意键的屏蔽*/
/**/
/*作者:卢佩佩(goodname008) 时间:2004.8.21*/
/**/
/* 博客:*/
/**************************************************** **************************/
//导出函数列表
// StartMaskKey
// StopMaskKey
#define_WIN32_WINNT0x0500//设置系统版本,保证底部键盘钩子可以使用
#include“ windows.h”
//全局变量
LPDWORDg_lpdwVirtualKey = NULL;// 指向 Keycode 数组的指针
intg_nLength = 0; // Keycode数组的大小
BOOLg_bDisableKeyboard = FALSE;//是否屏蔽整个键盘
HINSTANCEg_hInstance = NULL;//模块实例句柄
HHOOKg_hHook = NULL;//钩子句柄
// DLL进入功能
BOOL APIENTRY DllMain(HANDLE hModule, DWORDul_reason_for_call, LPVOID lpReserved)
{
//保存模块实例句柄
g_hInstance = (HINSTANCE)hModule;
//在进程结束或线程结束时卸载钩子
开关(ul_reason_for_call)
{
caseDLL_PROCESS_ATTACH:
中断;
caseDLL_THREAD_ATTACH:
中断;
caseDLL_PROCESS_DETACH:
caseDLL_THREAD_DETACH:
deleteg_lpdwVirtualKey;
if(g_hHook != NULL) UnhookWindowsHookEx(g_hHook);
中断;
}
returnTRUE;
}
//低级键盘钩子函数
LRESULT 回调 LowLevelKeyboardProc(intnCode, WPARAM wParam, LPARAM lParam)
{
//禁用键盘的一个键,如果g_bDisableKeyboard为TRUE,则禁用整个键盘
if(nCode == HC_ACTION)
{
if(g_bDisableKeyboard)returnTRUE;
KBDLLHOOKSTRUCT* pStruct = (KBDLLHOOKSTRUCT*)lParam;
LPDWORD tmpVirtualKey = g_lpdwVirtualKey;
for(inti = 0; i
{
if(pStruct->vkCode == *tmpVirtualKey++)
returnTRUE;
}
}
//传递到系统中的下一个钩子
returnCallNextHookEx(g_hHook, nCode, wParam, lParam);
}

/**************************************************** **************************/
/*开始屏蔽键盘按键*/
/**/
/*参数:*/
/*指向lpdwVirtualKey键码数组的指针*/
/*nLengthKeycode 数组大小*/
/*bDisableKeyboard 是否屏蔽整个键盘*/
/**/
/*返回值:TRUE成功,FALSE失败*/
/**************************************************** ********************** /
BOOL WINAPI StartMaskKey(LPDWORD lpdwVirtualKey,intnLength, BOOL bDisableKeyboard = FALSE)
{
//如果键盘钩子已经安装,返回FALSE
if(g_hHook != NULL)returnFALSE;
//将用户传入的keycode数组保存在一个全局变量中
g_lpdwVirtualKey = (LPDWORD)malloc(sizeof(DWORD) * nLength);
LPDWORD tmpVirtualKey = g_lpdwVirtualKey;
for(inti = 0; i
{
*tmpVirtualKey++ = *lpdwVirtualKey++;
}
g_nLength = nLength;
g_bDisableKeyboard = bDisableKeyboard;
//安装底部键盘挂钩
g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, NULL);
if(g_hHook == NULL)returnFALSE;
returnTRUE;
}
/**************************************************** **************************/
/*停止屏蔽键盘按键*/
/**/
/*参数:(无)*/
/**/
/*返回值:TRUE成功,FALSE失败*/
/**************************************************** **************************/
BOOL WINAPI StopMaskKey()
{
//卸载钩子
if(UnhookWindowsHookEx(g_hHook) == 0)returnFALSE;
g_hHook = NULL;
returnTRUE;
}
DEF 文件 (MaskKey.def):
出口
StartMaskKey@1
StopMaskKey@2
以上是DLL工程中的三个主要文件,工程类型为Win32 Dynamic-Link Library。从DEF文件可以看出,DLL有两个导出函数:StartMaskKey和StopMaskKey。
StartMaskKey 有三个参数,lpdwVirtualKey 是一个指向 DWORD 数组的指针,DWORD 数组用于存储虚拟键代码,nLength 是数组的大小,bDisableKeyboard 是一个逻辑值,如果为 TRUE 表示禁用整个键盘,默认为 FALSE。使用正确的参数调用 StartMaskKey。 DLL可以使DWORD数组中的每个虚拟键代码免受键盘上相应键的影响。按下这些键将完全没有反应(包括 win 键)。其实虚拟键码只能用一个字节来表示,但是KBDLLHOOKSTRUCT结构中的vkCode是DWORD类型的,所以我也统一用了4个字节(DWORD)。即便如此,微软在MSDN中也强调过,虚拟键码的值必须是1到254之间的值,这一点一定要注意。
StopMaskKey 没有参数,表示停止屏蔽键盘按键。如果在程序中没有调用StopMaskKey停止屏蔽键盘按键,则在进程或线程退出时会自动停止屏蔽,并恢复到原来的状态。当然,进程和线程必须正常退出。如果其他程序使用 TerminateProcess 或 TerminateThread 以微软不推荐使用的残酷手段终止进程或线程,则不好处理。 :(
以下是VC中调用的例子:(两个Dialog成员函数,对应两个按钮)
voidCMaskKeyAppDlg::OnStartmaskkey()
{
///盾A,B,C,上,下,左,右和两个胜利键
DWORD dwVK[] = {'A','B','C', VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_LWIN, VK_RWIN};
intnLength =sizeof(dwVK) /sizeof(DWORD);
StartMaskKey(dwVK, nLength);
}
voidCMaskKeyAppDlg::OnStopmaskkey()
{
StopMaskKey();
}
以下是在VB中调用的例子:(在窗体上添加2个CommandButtons并重命名为cmdStartMask和cmdStopMask)
选项显式
私有声明函数StartMaskKeyLib"MaskKey" (lpdwVirtualKeyAs Long,ByValnLengthAs Long,Optional ByValbDisableKeyboardAs Boolean=False)As Long
私有声明函数StopMaskKeyLib"MaskKey"()As Long
私有 SubcmdStartMask_Click()
'屏蔽A、B、C、上、下、左、右两个胜利键
Dimkey(8)As Long
key(0) = vbKeyA
key(1) = vbKeyB
key(2) = vbKeyC
key(3) = vbKeyLeft
key(4) = vbKeyRight
key(5) = vbKeyUp
key(6) = vbKeyDown
key(7) = &H5B'左边的win键
key(8) = &H5C'右边的win键
StartMaskKey key(0),UBound(key) + 1
结束子
私人SubcmdStopMask_Click()
StopMaskKey
结束子
对于VB,如果在VB IDE环境下按F5启动程序,必须调用StopMaskKey才能恢复键盘状态。如果没有,DLL 将在您退出 VB IDE 环境时恢复键盘状态。对于编译后独立执行的VB程序,与VC编译的程序是一样的。无论是否调用StopMaskKey,DLL都会在程序退出时自动卸载该钩子并恢复键盘状态。
实际上,hook 并不是一种非常深奥的技术。写这个DLL的目的也是为了我们以后使用的时候实现“用法”。
DLL源码及VC、VB调用例程下载地址:
*-------------------------------------------* >
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-378898-1.html