局部钩子只能挂钩自己进程的事件。现在编写一个实例来感受一下。
1.安装鼠标钩子
如果想监视鼠标消息,首先就需要定义相应的鼠标钩子过程,该钩子过程的定义形式如下所示:
LRESULT CALLBACK MouseProc( int nCode , WPARAM wParam , LPARAM lParam ) ;
(1)参数nCode :确定钩子如何处理当前消息。这个值可以取HC_ACTION HC_NOREMOVE,具体参照MSDN。
(2)参数wParam :指示鼠标消息的标示
(3)lParam :指向MOUSEHOOKSTRUCT结构体指针。这个参数并不重要,因此不必厢述。
在钩子过程中对信息的处理完成后,如果想要把西悉尼继续传递到下一个钩子过程,可以调用CallNextHookEx函数来实现。该函数的功能是把钩子信息传递给钩子链中下一个等到接受信息的钩子过程。该函数的声明如下:
LRESULT CallNextHoohEx( HHook hhk , int nCode , WPARAM wParam , LPARAM lParam ) ;
参数hhk指示当前钩子过程句柄,就是调用SetWindowsHookEx函数后得到的返回值,其他3个参数跟MouseProc函数的参数相同。
如果钩子函数的返回值非0,表示已经对当前的消息进行了处理。这样,系统就不再将这个消息传递到目的窗口过程了。因此如果钩子过程对当前消息进行了处理则应返回一个非0值,以避免系统再次将此消息传递给目标窗口过程;否则建议调用CallNextHookEx并返回该函数的返回值,以便安装了WH_MOUSE类型钩子过程的应用程序获得相应上网钩子通知。
实例编写:
我们的程序将使用MFC编写一个基于对话框的Application。
首先我们实现一个鼠标钩子过程:
LRESULT CALLBACK MouseProc( int nCode , WPARAM wParam , LPARAM lparam )
{
return 1 ;
}
HHOOK g_hMouse = NULL ;
g_hMouse = SetWindowsHookEx( WH_MOUSE , MouseProc , NULL , GetCurrentThreadId() ) ;
第三个参数因为这里创建的钩子过程是和当前进程中的当前线程,即主线程相关的,所以将此参数设置为NULL;对于第四个参数,既然钩子过程与当前线程相关,所以就应该床底当前线程的ID,这个ID可以通过GetCurrentThreadId来获得。
当我们运行程序会发现我们的鼠标已经不起作用了。
2.安装键盘钩子
为了给程序安装键盘钩子,首先需要定义键盘钩子过程。
LRESULT CALLBACK KeyboardProc( int nCode , WPARAM wParam , LPARAM lparam )
{
return 1 ;
}
因为在函数体里直接返回了1,那么就屏蔽了所有的键盘消息
设置键盘钩子与上面设置鼠标钩子大同小异,区别有几点:
(1)钩子的类型不同,鼠标钩子类型为WH_MOUSE ,键盘为WH_KEYBOARD 。
当我们指向屏蔽某写键盘的按键时,就需要另外处理了。不过首先我们来看看键盘钩子过程的参数:
参数wParam 是产生当前按键消息的键盘按键的虚拟,码,这是windows定义域设备无关的,键盘按键的代码。当按下键盘上的按键时,它实际上发送的是脉冲信号,windows定义了一些虚拟键代码来表示这些信号,并由键盘设备驱动程序负责解释。因此在键盘钩子过程中就可以通过参数wParam来判断按下的是哪一个键
LRESULT CALLBACK KeyboardProc( int nCode , WPARAM wparam , lParam )
{
if( VK_SPACE == wParam )
{
return 1 ;
}
else
{
return CallNextHookEx( g_Keyboard , nCode , wParam , lParam ) ;
}
}
当然了,程序中是很有必要加上UnhookWindowsHookEx来解除hook的。