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