windows 编程钩子技术初尝(hook)

最近在研究hook这个东西,作为一个windows菜鸟,研究这个还真花了点时间,下面分享下今天按照别人代码写出的两个鼠标钩子实例。

第一个是针对线程的钩子

几点需要说明的地方:
  (1) 如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。
  (2) 对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
  (3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。

第一个程序,用一个文档显示当前鼠标的位置,我们知道鼠标的位置信息是,移动鼠标形成鼠标中断--OS发送中断调用驱动--驱动将鼠标的移动信息发给OS--OS进行计算处理得到当前坐标--OS将坐标发给图形界面系统

那么我们的钩子就是在最后OS将坐标发给gwes.exe(也就是图形系统进程的时候),先截取消息,处理完后再发给gwes.exe。

首先我们新建工程MFC  基于单文档的exe

编写钩子程序的步骤分为三步:定义钩子函数安装钩子卸载钩子

1.定义钩子

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

我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。

LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )

参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。 
当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。

 

2.安装钩子
在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。
其函数原型为: 
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) 
      参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。
  Lpfn是钩子函数的地址。
  HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。
  dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。
  SetWindowsHookEx返回所安装的钩子句柄。
  
 3.卸载钩子

当不再使用钩子时,必须及时卸载。简单地调用函数 BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。

 

代码:

HHOOK hHook;//鼠标钩子句柄
CPoint point;//鼠标位置信息
CChildView *pView;//实例化

CChildView::CChildView()
{
 pView=this;//获得输出窗口指针
 hHook=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());

}//在构造函数中创建一个钩子函数

 

CChildView::~CChildView()
{
 if(hHook)
 UnhookWindowsHookEx(hHook);

}//析构函数中释放钩子函数

 

//下面是获取消息后的处理函数

LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{//是鼠标移动消息
 if((wParam == WM_MOUSEMOVE)||(wParam == WM_NCMOUSEMOVE))
 {
  point=((MOUSEHOOKSTRUCT *)lParam)->pt;
  //取鼠标信息
  pView->Invalidate(); //窗口重画
 }
 return CallNextHookEx(hHook,nCode,wParam,lParam);
 //传递钩子信息 ,如果直接return true 那么消息就不会往下继续发送
}

 

这样一个简单的针对线程的钩子应用就OK,移动鼠标就可以看见鼠标的坐标参数。

 

下面是针对系统的hook应用了:

 这时必须用扩展DLL的方式来实现,为什么呢,因为要对整个系统起作用,要对系统的每个进程起作用,就必须修改他们公用的库,

而这个动态库是可以扩展的,我们可以把钩子的处理通过DLL加入进去。这样,鼠标的信息不管在哪都会通过扩展DLL截下来

然后通过调用该扩展DLL来进行消息的处理。

 

mark 一下,未完待续

 

首先建立DLL工程:

建立时选择 共享DLL

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2012-08-22 12:24  嵌入式·李  阅读(2014)  评论(0编辑  收藏  举报