当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 利用钩子实现菜单阴影效果
利用钩子实现菜单阴影效果
static CMap m_WndMenuMap;static HHOOK m_hMenuHook; 被我们抓到的这些家伙肯定不止一个,我们需要一个映射模板类来保存它们的句柄和对应的CMenuWndHook 类对象的指针。m_hMenuHook则为我们将要创建的钩子的钩子句柄。再在CPP文件中初始化它们: CMap CMenuWndHook::m_WndMenuMap;HHOOK CMenuWndHook::m_hMenuHook = NULL;下面再添加两个函数来做安装与卸载hook之用, 它们都是静态函数: void CMenuWndHook::InstallHook(){ if (m_hMenuHook == NULL) { m_hMenuHook = ::SetWindowsHookEx(WH_CALLWNDPROC, WindowHook, AfxGetApp()->m_hInstance, ::GetCurrentThreadId()); }} Windows之下一般用上面的SetWindowsHookEx API函数来安装HOOK,它的函数原型如下:HHOOK SetWindowsHookEx(int idHook, //钩子的类型,即它处理的消息类型 HOOKPROC lpfn, //子函数的入口地址,当钩子钩到任何消息后先调用这个函数。 // (如果dwThreadId参数为0,或是一个由别的进程创建的线程的标识, //lpfn必须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进 //程的一段钩子子程代码) HINSTANCE hMod, //应用程序实例的句柄。标识包含lpfn所指的子程的DLL。 // 如果dwThreadId标识当前进程创建的一个线程, //而且子程代码位于当前进程,hMod必须为NULL。 //可以很简单的设定其为本应用程序的实例句柄。 DWORD dwThreadId //与安装的钩子子程相关联的线程的标识符。 //如果为0,钩子子程与所有的线程关联,即为全局钩子。 //但这时,你钩子只能是放在DLL中。 ); 函数成功则返回钩子子程的句柄,失败返回NULL。 我们用到的是WH_CALLWNDPROC类型的钩子,它使你可以监视发送到窗口过程的消息, 系统在消息发送到 接收窗口过程之前会调用你指定的WH_CALLWNDPROC Hook 子程,这样你就可以等它们自投罗网,然后就可以 对它们为所欲为了。 卸载钩子就简单多了,只需要调用UnhookWindowsHookEx即可,当然,我们还需要额外做一点清理工作: void CMenuWndHook::UnInstallHook(){ POSITION pos = m_WndMenuMap.GetStartPosition(); while (pos != NULL) { HWND hwnd; CMenuWndHook *pMenuWndHook; m_WndMenuMap.GetNextAssoc(pos, hwnd, pMenuWndHook); delete pMenuWndHook; pMenuWndHook= NULL; } m_WndMenuMap.RemoveAll(); if (m_hMenuHook != NULL) { ::UnhookWindowsHookEx(m_hMenuHook); } } 在介绍如何安装钩子时,提到要一个钩子子程,这个子程必须按下面的格式声明,否则不能使用:LRESULT CALLBACK WindowHook(int code, WPARAM wParam, LPARAM lParam); 函数名随意,同样把它声明为静态函数,下面各位注意了,我们的逮捕行动就是在这个函数中展开的: LRESULT CALLBACK CMenuWndHook::WindowHook(int code, WPARAM wParam, LPARAM lParam){ //如果你安装的是WH_CALLWNDPROC类型的钩子的话,系统就会传递一个这个家伙的指针: CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam; while (code == HC_ACTION) { HWND hWnd = pStruct-> |