日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转载】CMenu自绘---钩子---去除边框

發(fā)布時間:2024/4/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转载】CMenu自绘---钩子---去除边框 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? ?使用默認的CMenu菜單類或者繼承CMenu實現(xiàn)的菜單擴展類,在顯示的時候最外層都會有邊框出現(xiàn),或者說是具有3D外觀(菜單陰影不算),當改變菜單背景色或者需要加個邊框線時就會看上去很不美觀。看過很多菜單的自定義實現(xiàn)類,一般可以有兩種方式來實現(xiàn)外框的移除。
???????第一種方法就是:自定義窗口,完全模擬菜單的實現(xiàn),自給自足,倒是能夠完全滿足開發(fā)需要,不過實現(xiàn)的復雜讓人頭痛,此處略過不提。

?????? 下面介紹第二種比較簡單直接的方法:安裝鉤子,在菜單創(chuàng)建時就改變其窗口屬性。其實菜單應該也算是一個窗口類,不過實在是無從得知到底在哪創(chuàng)建的窗口,所以下下鉤子,過程倒是明了許多。
?實現(xiàn)如下:

先在cpp前面申明一下:

??????? static HHOOK g_hook=NULL;?// 全局鉤子
??????? static LRESULT WINAPI CallWndProc(int, WPARAM, LPARAM);?// 安裝的鉤子的窗口過程
??????? static LRESULT WINAPI MenuWndProc(HWND, UINT, WPARAM, LPARAM); // 用來處理菜單的窗口過程

然后是鉤子的實現(xiàn):

/
// 如果需要去除菜單的外部邊框,需要通過安裝鉤子,設置外框?qū)傩圆⒏淖儾藛未笮?br />WNDPROC oldWndProc = NULL; // 用來保存被替換的窗口過程
LRESULT WINAPI CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
?CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;
?while (code == HC_ACTION)
?{
??HWND hWnd = pStruct->hwnd;
??// 捕捉創(chuàng)建消息WM_CREATE,后面篩選為是否是菜單的創(chuàng)建
??if ( pStruct->message != WM_CREATE)
???break;
??TCHAR sClassName[10];
??int Count = ::GetClassName(hWnd, sClassName, sizeof(sClassName)/sizeof(sClassName[0]));
??// 檢查是否菜單窗口,#32768為菜單類名
??if ( Count != 6 ||? _tcscmp(sClassName, _T("#32768")) != 0 )???
???break;
??
??WNDPROC lastWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);???
??if (lastWndProc != MenuWndProc)???
??{???
???// 替換菜單窗口過程??
???SetWindowLong(hWnd, GWL_WNDPROC, (long)MenuWndProc);???
???// 保留原有的窗口過程???
???oldWndProc = lastWndProc;???
??}
??break;???
?}

?return CallNextHookEx((HHOOK)WH_CALLWNDPROC, code, wParam, lParam);?
}

// 處理菜單的窗口過程
LRESULT WINAPI MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{???
?LRESULT lResult;
?switch (message)???
?{??????
?case WM_CREATE:
??{???
???// 首先要去掉菜單窗口的一些擴展風格
???// 包括:WS_BORDER、WS_EX_DLGMODALFRAME、WS_EX_WINDOWEDGE
???lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);???
???DWORD dwStyle = ::GetWindowLong(hWnd,?? GWL_STYLE);???
???DWORD dwNewStyle = (dwStyle & ~WS_BORDER);
???::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);???
???DWORD dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
???DWORD dwNewExStyle = (dwExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE));???
???::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewExStyle);???
???return lResult;?
??}???
?case?? WM_PRINT: // 此處阻止非客戶區(qū)地繪制
???return CallWindowProc( oldWndProc, hWnd, WM_PRINTCLIENT, wParam, lParam);

?case?? WM_WINDOWPOSCHANGING:???
??{???
???// 最后,由于我們在MeasureItem里指定了菜單大小,而系統(tǒng)會自動替菜單加邊框,
???// 因此必須去掉此部分額外地尺寸,將菜單大小改小
???LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam;???
???lpPos->cx -= 2*GetSystemMetrics(SM_CXBORDER)+4;???
???lpPos->cy -= 2*GetSystemMetrics(SM_CYBORDER)+4;
???lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);??
???return 0;
??}???
?case?? WM_GETICON:
??return 0;????
?default:???
??return? CallWindowProc( oldWndProc, hWnd, message, wParam, lParam);???
?}???
}??

/

最后是調(diào)用:
下鉤子需要調(diào)用SetWindowsHookEx,參數(shù)包括主窗口的實例句柄theApp.m_hInstance,可以在調(diào)用時作為參數(shù)傳入,同時也設一個參數(shù)作為是否安裝鉤子的標識,以便在退出時判斷是否需要卸載鉤子(UnhookWindowsHookEx(g_hook))。示例如下:

void CSkinMenu::RemoveMenuBorder(HINSTANCE hInst, BOOL bRemove /* = TRUE */)
{
?m_bRemoveBorder = bRemove; // 標識

?// 需要移除邊框時,要安裝鉤子
?if (m_bRemoveBorder)
?{
??DWORD id = ::GetCurrentThreadId();?// 獲取當前線程的ID
??g_hook = SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,hInst,id);
?}
}


?這樣子,就搞定菜單的邊框了,最后要記得,如果安裝了鉤子,需要卸載掉。

轉(zhuǎn)載于:https://www.cnblogs.com/doudongchun/p/3699700.html

總結(jié)

以上是生活随笔為你收集整理的【转载】CMenu自绘---钩子---去除边框的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。