Vc下钩子
最近在一个单文档应用程序的View的非客户区实现一个鼠标点击的功能时,发现了一个怪异的现象:在win7系统上,非客户区会响应WM_NCLBUTTONDOWN消息,而在winxp上,却不响应该消息,原因是想不清楚,但是要实现这样的功能还是有办法的,那就是下鼠标钩子。
下钩子一般有三步:1、安装钩子;2、实现钩子函数;3、卸载钩子。下面我们结合代码来详细说明一下。
第一步:安装钩子
在安装钩子之前,我们需要定义一个全局的钩子句柄HHOOK,如:
HHOOK g_MouseHook = NULL;
然后在适当的时候,在我这个问题的解决中,我在CTestView的构造函数中来安装钩子。
if ( NULL == g_hMouseHook ) { //关于SetWindowsHookEx函数的函数可以去查看MSDN,第一个参数表明钩子类型,我们这里是WH_MOUSE表示是鼠标钩子,第二个参数后面要实现的钩子函数 g_hMouseHook = SetWindowsHookEx( WH_MOUSE, MouseProc, AfxGetApp()->m_hInstance, GetCurrentThreadId() ); }
第二步:实现钩子函数MouseProc,我们实现一个全局函数MouseProc,如:
LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lParam ) { //该函数中wParam表示消息类型,lParam根据钩子类型不同,表示的是不同类型的结构体,鼠标钩子中,它就是MOUSEHOOKSTRUCT,还有很多其他类型钩子的结构体可以参照msdn
BOOL bRet = FALSE; if ( wParam == WM_NCLBUTTONDOWN ) { MOUSEHOOKSTRUCT* pMouseHook = ( MOUSEHOOKSTRUCT* )lParam; if ( pMouseHook->hwnd == g_TestView->m_hWnd ) { //判断当前消息是否是发送给期待的窗口的,如果不想该消息继续传递下去,在此可以return } } //如果不是自己想截获的消息,或者不是发送给View窗口的消息,让该消息继续传递下去 return CallNextHookEx( g_hMouseHook, nCode, wParam, lParam ); }
第三步:卸载钩子,在适当的时候卸载钩子,在此例中,我们在TestView的析构函数中卸载钩子。
if ( NULL != g_hMouseHook ) { UnhookWindowsHookEx( g_hMouseHook ); }