資源描述:
《利用鉤子實(shí)現(xiàn)菜單陰影效果》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在學(xué)術(shù)論文-天天文庫(kù)。
1、利用鉤子實(shí)現(xiàn)菜單陰影效果程序運(yùn)行效果截圖: 也許有很多人曾和我一樣,對(duì)OfficeXP里面的菜單的陰影效果羨慕不已,它不需要在WindowsXP中就可以在菜單后面顯示陰影,當(dāng)然在WindowsXP中,已經(jīng)完全支持菜單陰影了。雖然我們不一定很有必要自己來(lái)實(shí)現(xiàn)這個(gè)較難實(shí)現(xiàn)的效果。但是正如有很多人想實(shí)現(xiàn)那種IE風(fēng)格的菜單欄一樣,盡管它們并不能為我們帶來(lái)更多實(shí)用的功能,卻可以使我們的程序看起來(lái)與眾不同。:)??菜單也是一個(gè)窗口,假如我們能得到它的窗口的句柄,要實(shí)現(xiàn)像添加陰影這樣的效果,就不會(huì)很難了。可惜我們根本找不到這個(gè)窗口是在哪里被創(chuàng)建的,也沒(méi)辦法很容易地取得它的窗口句柄,甚至幾乎難以相信它是
2、一個(gè)窗口,因?yàn)槲覍?shí)在找不到它的窗口句柄啊。經(jīng)過(guò)對(duì)許多別人已經(jīng)做好的類(lèi)的源代碼的"研究",我終于找到了一個(gè)方法。那就是萬(wàn)能的鉤子,如果說(shuō)在Windows里面抓"人",連鉤子也辦不到的話,那我就不知道該用什么方法實(shí)現(xiàn)了,呵呵。??下面我就一起來(lái)看看如何抓到這些"可惡"的家伙吧。為了便于移植,我們就寫(xiě)一個(gè)專(zhuān)用的類(lèi)吧,就取名為CMenuWndHook。添加兩個(gè)靜態(tài)成員先:staticCMapm_WndMenuMap;staticHHOOKm_hMenuHook;?被我們抓到的這些家伙肯定不止一個(gè),我們需要一個(gè)映射模板類(lèi)來(lái)保存它們的句柄和對(duì)應(yīng)的CMenuWndHook類(lèi)對(duì)象的指針。m_hMenuHo
3、ok則為我們將要?jiǎng)?chuàng)建的鉤子的鉤子句柄。再在CPP文件中初始化它們:CMapCMenuWndHook::m_WndMenuMap;HHOOKCMenuWndHook::m_hMenuHook=NULL;下面再添加兩個(gè)函數(shù)來(lái)做安裝與卸載hook之用,它們都是靜態(tài)函數(shù):voidCMenuWndHook::InstallHook(){??if(m_hMenuHook==NULL)??{??m_hMenuHook=::SetWindowsHookEx(WH_CALLWNDPROC,???????????????????WindowHook,??AfxGetApp()->m_hInstance,???
4、???????????????::GetCurrentThreadId());??}}Windows之下一般用上面的SetWindowsHookExAPI函數(shù)來(lái)安裝HOOK,它的函數(shù)原型如下:HHOOKSetWindowsHookEx(intidHook,//鉤子的類(lèi)型,即它處理的消息類(lèi)型 HOOKPROClpfn,?//子函數(shù)的入口地址,當(dāng)鉤子鉤到任何消息后先調(diào)用這個(gè)函數(shù)。??//(如果dwThreadId參數(shù)為0,或是一個(gè)由別的進(jìn)程創(chuàng)建的線程的標(biāo)識(shí),?//lpfn必須指向DLL中的鉤子子程。除此以外,lpfn可以指向當(dāng)前進(jìn)?//程的一段鉤子子程代碼) HINSTANCE
5、hMod,//應(yīng)用程序?qū)嵗木浔?。?biāo)識(shí)包含lpfn所指的子程的DLL。??//如果dwThreadId標(biāo)識(shí)當(dāng)前進(jìn)程創(chuàng)建的一個(gè)線程,?//而且子程代碼位于當(dāng)前進(jìn)程,hMod必須為NULL。?//可以很簡(jiǎn)單的設(shè)定其為本應(yīng)用程序的實(shí)例句柄?! WORDdwThreadId//與安裝的鉤子子程相關(guān)聯(lián)的線程的標(biāo)識(shí)符。?//如果為0,鉤子子程與所有的線程關(guān)聯(lián),即為全局鉤子。?//但這時(shí),你鉤子只能是放在DLL中。?????? );??函數(shù)成功則返回鉤子子程的句柄,失敗返回NULL。我們用到的是WH_CALLWNDPROC類(lèi)型的鉤子,它使你可以監(jiān)視發(fā)送到窗口過(guò)程的消息,系統(tǒng)在消息發(fā)送到接
6、收窗口過(guò)程之前會(huì)調(diào)用你指定的WH_CALLWNDPROCHook子程,這樣你就可以等它們自投羅網(wǎng),然后就可以對(duì)它們?yōu)樗麨榱?。卸載鉤子就簡(jiǎn)單多了,只需要調(diào)用UnhookWindowsHookEx即可,當(dāng)然,我們還需要額外做一點(diǎn)清理工作:voidCMenuWndHook::UnInstallHook(){??POSITIONpos=m_WndMenuMap.GetStartPosition();while(pos!=NULL)??{????HWNDhwnd;????CMenuWndHook*pMenuWndHook;?m_WndMenuMap.GetNextAssoc(pos,hwnd,?p
7、MenuWndHook);?deletepMenuWndHook;?pMenuWndHook=NULL;}m_WndMenuMap.RemoveAll();if(m_hMenuHook!=NULL){?::UnhookWindowsHookEx(m_hMenuHook);}?}??在介紹如何安裝鉤子時(shí),提到要一個(gè)鉤子子程,這個(gè)子程必須按下面的格式聲明,否則不能使用:LRESULTCALLBACKWindowHook(in