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