Toolbar制作菜單條過(guò)程詳解
現(xiàn)在許多用戶界面都使用工具欄制作菜單條,小弟最近對(duì)此感興趣,便從網(wǎng)上求助,可是得到的幫助大多是BCGControlBar的源代碼或者是SizableRebar的源代碼,對(duì)于只希望是自己的界面具有該功能的朋友來(lái)說(shuō),這也許是不錯(cuò)的選擇,只要看一下demo,然后直接調(diào)用別人的類(lèi)庫(kù)就可以了,但對(duì)于我等對(duì)此話題感興趣,希望弄懂其來(lái)龍去脈的讀者來(lái)說(shuō),直接看這些沒(méi)有詳細(xì)解釋的源代碼,要從中弄出個(gè)所以然來(lái),實(shí)不是件容易的是,至少對(duì)于像我這樣的菜鳥(niǎo)來(lái)說(shuō)是這樣的,本文出于此種原因,希望對(duì)還在尋求此幫助的讀者能提供一些幫助。
下面我們邊看邊侃:
在接收到toolbarbutton按下消息時(shí),我們一般使用TrackPopupMenuEx彈出菜單,問(wèn)題的關(guān)鍵是,在菜單未關(guān)閉時(shí),TrackPopupMenuEx并不返回,并攔截鼠標(biāo)和鍵盤(pán)消息,使用spy可以看到,此時(shí)的工具欄收不到任何消息,當(dāng)然無(wú)從改變熱點(diǎn),這就需要我們自己探測(cè)鼠標(biāo)位置并在鼠標(biāo)移動(dòng)到下一個(gè)熱點(diǎn)時(shí)關(guān)閉上一個(gè)菜單并顯示下一個(gè)菜單。這里我們使用鉤子函數(shù)SetWindowsHookEx在調(diào)用TrackPupupMenuEx前安裝WH_MSGFILTER鉤子,代碼如下:
m_hMsgHook = SetWindowsHookEx( WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId() );
MssageProc是鉤子函數(shù),代碼如下:
LRESULT CALLBACK MessageProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code == MSGF_MENU)
{
HookMessageProc(lParam);
}
return CallNextHookEx(m_hMsgHook, code, wParam, lParam);
}
函數(shù)檢查消息,如果是來(lái)自菜單,則將消息傳遞給函數(shù)HookMessageProc處理,我們所要做的就是在該函數(shù)中檢測(cè)消息WM_MOUSEMOVE,并測(cè)試鼠標(biāo)位置,如果鼠標(biāo)已經(jīng)移動(dòng)到另一個(gè)按鈕上,則關(guān)閉菜單并顯示下一個(gè)菜單,關(guān)閉菜單使用消息WM_CANCELMODE,當(dāng)菜單關(guān)閉后,我們要釋放鉤子,在下一個(gè)菜單彈出時(shí)重新安裝鉤子,彈出菜單示例代碼如下:
void TrackPopup(HWND hWndToolBar, int iButton)
{
while (iButton >= 0)
{
SendMessage(hWndToolBar,TB_SETHOTITEM,iButton,0);
iPopup = iButton;
//安裝鉤子
g_hMsgHook = SetWindowsHookEx(WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId());
//彈出菜單
TrackPopupMenuEx(…);
//卸載鉤子
UnhookWindowsHookEx(g_hMsgHook);
iButton = iNextPop; //下一個(gè)彈出項(xiàng),若為負(fù),則退出
}
SendMessage(hWndToolBar,TB_SETHOTITEM,-1,0);
}
(經(jīng)驗(yàn)與建議:如果button使用樣式TBSTYLE_DROPDOWN,請(qǐng)不要在消息TBN_DROPDOWN中直接調(diào)用該函數(shù),應(yīng)使用中間消息,然后使用PostMessa個(gè)發(fā)送該消息,以使TBN_DROPDOWN可以直接返回,否則消除第一個(gè)高亮熱點(diǎn)是很麻煩的事。)
iPopup為當(dāng)前彈出項(xiàng),iNextPop為下一個(gè)彈出項(xiàng),這些變量需要在函數(shù)HookMessageProc中處理,示例代碼如下:
void HookMessageProc(MSG * pMsg)
{
if (pMsg->message == WM_MOUSEMOVE)
{
int iButton, iCount;
POINT pt = { LOWORD(pMsg->lParam), HIWORD(pMsg->lParam) };
ScreenToClient(hWndToolbar, &pt);
iButton = SendMessage(hWndToolbar, TB_HITTEST, 0, &pt);
iCount = SendMessage(hWndToolbar, TB_BUTTONCOUNT, 0, 0);
if (iPopup != iButton && iButton < iCount && iButton >= 0)
{
iNextPop = iButton;
SendMessage(hWndMain, WM_CANCELMODE, 0, 0);
}
else
{
iNextPop = -1;
}
}
}
?。ń?jīng)驗(yàn)與建議:不要試圖在此處調(diào)用TrackPopup,我曾試圖取消該函數(shù)內(nèi)的while循環(huán),直接在此調(diào)用該函數(shù),結(jié)果是在TrackPopupMenuEx未返回之前,該函數(shù)已被調(diào)用)
這里,僅僅處理了鼠標(biāo)移動(dòng)消息,真正的菜單還應(yīng)處理鍵盤(pán)導(dǎo)航消息,詳細(xì)的代碼可以參考
BCGControlBar(http://www.vckbase.com/code/downcode.asp?id=1382)
或SizableRebar(http://www.codeproject.com/docking/sizablerebar/SizableRebar_demo.zip
)
有了這底層框架,這些處理過(guò)程應(yīng)該不再困難,文章所涉及到的一些API函數(shù)可以參考msdn。
Msdn上相關(guān)資料:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/faq/iemenubar.asp
http://www.microsoft.com/msj/0199/c/c0199.aspx
- 微軟IE Developer Toolbar安裝使用簡(jiǎn)要圖文說(shuō)明
- jquery toolbar與網(wǎng)頁(yè)浮動(dòng)工具條具體實(shí)現(xiàn)代碼
- Java Swing中的工具欄(JToolBar)和分割面版(JSplitPane)組件使用案例
- iOS應(yīng)用中使用Toolbar工具欄方式切換視圖的方法詳解
- iOS中的導(dǎo)航欄UINavigationBar與工具欄UIToolBar要點(diǎn)解析
- Android5.0+ CollapsingToolbarLayout使用詳解
- Android自定義ActionProvider ToolBar實(shí)現(xiàn)Menu小紅點(diǎn)
- Android自定義Toolbar使用方法詳解
- 分別用ToolBar和自定義導(dǎo)航欄實(shí)現(xiàn)沉浸式狀態(tài)欄
- 深入理解Android 5.0中的Toolbar
相關(guān)文章
java(swing)+ mysql實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)源碼
這篇文章主要分享了java mysql實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)的源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11spring-mybatis與原生mybatis使用對(duì)比分析
這篇文章主要介紹了spring-mybatis與原生mybatis使用對(duì)比分析,需要的朋友可以參考下2017-11-11java實(shí)現(xiàn)/創(chuàng)建線程的幾種方式小結(jié)
在JAVA中,用Thread類(lèi)代表線程,所有線程對(duì)象都必須是Thread類(lèi)或者Thread類(lèi)子類(lèi)的實(shí)例,下面這篇文章主要介紹了java實(shí)現(xiàn)/創(chuàng)建線程的幾種方式,需要的朋友可以參考下2021-08-08解決IDEA右鍵沒(méi)有創(chuàng)建新的package選項(xiàng)的情況
這篇文章主要介紹了解決IDEA右鍵沒(méi)有創(chuàng)建新的package選項(xiàng)的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02將對(duì)象轉(zhuǎn)化為字符串的java實(shí)例
這篇文章主要介紹了將對(duì)象轉(zhuǎn)化為字符串的java實(shí)例,有需要的朋友可以參考一下2013-12-12IntelliJ IDEA 15款超級(jí)牛逼插件推薦(自用,超級(jí)牛逼)
這篇文章主要給大家推薦介紹了IntelliJ IDEA 15款超級(jí)牛逼插件,這15款插件都是自用的,真的非常推薦,需要的朋友可以參考下2020-11-11