使用钩子函数屏蔽键盘或鼠标

来源:互联网 发布:国际淘宝 编辑:程序博客网 时间:2024/04/29 10:05

首先简单说一下钩子方面的知识:

       钩子又分为系统钩子和进程钩子,其中又分有好多种类型的钩子,比如键盘钩子、鼠标钩、调试钩子等。钩子函数又属于回调函数,但是,一般能使用SetWindowsHookEx函数设置挂钩的回调函数,就叫做钩子函数。

    系统有一个钩子链表,每当我们使用SetWindowsHookEx函数设置了一个钩子时,系统就会把我们的钩子放在链表的开头,系统调用钩子是安后设置先调用的规定进行的。当安装了钩子后,每当有与安装钩子的类型匹配的事件产生时,钩子函数首先捕获,捕获后可以对其进行处理,比如修改、屏蔽等,或者不处理。除了屏蔽之外,都要使用CallNextHookEx函数,否则其它在安装了同一类的钩子就不能捕获对应事件的产生。当自己定的义的钩子不用时候,就要销毁掉,特别是全局的钩子,使用UnhookWindowsHookEx函数,否则就会严重影响系统的性能。

下边介绍一下钩子相关的主要函数:

1、

HHOOK SetWindowsHookEx(

int idHook,//这个主钩子的类型,比如WH_CBT、WH_DEBUG、WH_KEYBOARD_LL等

HOOKPROC lpfn,//这个是我们自己定义的回调函数

HINSTANCE hMod,//这个是实例的句柄,当然也可以用GeModuleHandle函数反回

DWORD dwThreadId//这个是线程的ID,如果值为0,则监视所有的程序线程,否则只监视指定ID的线程

说一下lpfn这个参数,这是一个指向我们自己定义的回调函数的指针,这个回调函数必须符合下面的签名格式:

LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam);

当然,这里的函数名HookProc可以是自己任意定的,随你的喜欢。

这里也说一下,在32位系中,如果是安装全局钩子的话,要把安装的钩子写在DLL文件里,

2、CallNextHookEx(

HHOOK hhk,//指向当前钩子的句柄,即SetWindowsHookEx函数的返回值

int nCode,//和HookProc中的nCode一样

WPARAM wParam,//和HookProc中的一样

LPARAMA lParam//和HookProc中的一样

)

这个函数是把事业消息传递到下一个相同的钩子子程,注意,有我们定义的钩子子程中,如果nCode的值小于0,则应该要调用该函数,使我们的钩子子程返回它的返回值。

3、

UnhookWindowsEx(

HHOOK hkk//SetWindowsHookEx的返回值

)

该函数是销毁钩子,使其从系统钩子链表中移除

好,通过上边的简单的介绍,我们基本知道钩子是怎么的一回事,下边我们通过具体的例子说明怎么使用。

该例子的功能是根据不同的函数参数,使屏蔽键盘还是鼠标或者是两者都屏蔽。

预设了底层键盘钩子和鼠标钩子,根据参数的选择进行安装

这里只写了DLL文件,在CPP文件或者其他文件中进行调用,就可以使用

程序清单如下:

#define _WIN32_WINNT 0X0500//在windows NT/2000/XP上,所以这样定义一个宏,要d在#include<windows.h>前
#include<windows.h>
extern "C"__declspec(dllexport) void setHook(int flag,WORD mykey);//导出函数

extern "C"__declspec(dllexport) void stopHook();//导出函数

HHOOK Mousehook=NULL;//鼠标钩子句柄
HINSTANCE Mousehinstance=NULL;
HHOOK Boardhook=NULL;//键盘钩子句柄
HINSTANCE Boardhinstance=NULL;
WORD key=VK_RETURN;//默认,当键盘和鼠标都锁定时,只有按下回车键才能解锁。可以设置

LRESULT CALLBACK mouseHook(int nCode,WPARAM wparam,LPARAM lparam)//自己定义的鼠标钩子过程
{
if(nCode == HC_ACTION) //当nCode等于HC_ACTION时,要求得到处理

   if(wparam==WM_MOUSEWHEEL//屏蔽滑轮
    ||wparam==WM_RBUTTONDOWN//屏蔽鼠标右键按下
    ||wparam==WM_LBUTTONDOWN//屏蔽鼠标左键按下
    ||wparam==WM_RBUTTONUP//屏蔽鼠标右键弹起的消息
    ||wparam==WM_LBUTTONUP//屏蔽鼠标左键弹起的消息
    ||wparam==WM_MOUSEMOVE)//屏蔽鼠标的移动
   {
    return true;//如果是这些事件产生的话,就返回真,即屏蔽掉这些事件,也就是安装有同类型的其他钩子,捕获不到同样的事件
   }
}
return CallNextHookEx(Mousehook,nCode,wparam,lparam);//否则,如果返回给下一个钩子子程处理
}

LRESULT CALLBACK boardHook(int nCode,WPARAM wparam,LPARAM lparam)//定义自己的键盘钩子过程
{
if(nCode == HC_ACTION) //要求得到处理
{
   if(wparam==WM_KEYDOWN||wparam==WM_KEYUP)//当有键盘键按下或弹起时
   {
    KBDLLHOOKSTRUCT *lp=(KBDLLHOOKSTRUCT*)lparam;
    if(lp->vkCode==key)//检查是否是我们要销毁钩子的键
    {
     stopHook();//如果是的话,我们就销毁掉我们定义的所有钩子,使其从系统中删除
    }
    else
    {
     return true;//如果不是的话,屏蔽掉,让下一个同类的钩子得不到该信息
    }
   }
}
return CallNextHookEx(Boardhook,nCode,wparam,lparam);//否则返回给下一个钩子处理
}


void setHook(int flag,WORD mykey)//安装我们定义的钩子
{
if(mykey)//如果mykey为空的话,使用默认的回车键销毁钩子
   key=mykey;
if(flag==0)//如果flag为0,则只安装鼠标钩子
{
   if(Mousehook==NULL)
    Mousehook=SetWindowsHookEx(WH_MOUSE_LL,(HOOKPROC)mouseHook,Mousehinstance,0);
}
    else if(flag==1)//如果为1,只安装键盘钩子
{
   if(Boardhook==NULL)
    Boardhook=SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)boardHook,Boardhinstance,0);
}
else if(flag==2)//如果是2,则同时装两个钩子
{
   if(Mousehook==NULL)
    Mousehook=SetWindowsHookEx(WH_MOUSE_LL,(HOOKPROC)mouseHook,Mousehinstance,0);
   if(Boardhook==NULL)
    Boardhook=SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)boardHook,Boardhinstance,0);
}
}

void stopHook()//用来销毁定义的所有钩子
{
if(Mousehook!=NULL)
   UnhookWindowsHookEx(Mousehook);//鼠标钩子句柄不为空时销毁掉
Mousehook=NULL;
if(Boardhook!=NULL)
   UnhookWindowsHookEx(Boardhook);键盘钩子句不为空时销毁掉
Boardhook=NULL;

}


BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD ul_reason_for_call, 
                       LPVOID lpReserved
      )
{
if(DLL_PROCESS_ATTACH==ul_reason_for_call)//当进程一开如加载该DLL文时,首先获取其实例句柄
{
   Mousehinstance=(HINSTANCE)hModule;
   Boardhinstance=(HINSTANCE)hModule;
}
else if(DLL_PROCESS_DETACH==ul_reason_for_call)//当加载该DLL文件的进程退出时,释放定义的所有钩子,使其从系统钩子链表中删除
{
   stopHook();
}
    return TRUE;
}

OK!通过执行文件的调使,就可以使用了,注意,执行文件中必须有一个消息循环队列。

其它的钩子的使用也基本都与以上的类似,不同的钩子其中的比如WPARAM、LPARAM中的参数有所不同,读者可以参考MSDN以获得帮助。


原创粉丝点击