網(wǎng)站建設(shè)是指使用標(biāo)識語言(markup language),通過一系列設(shè)計、建模、和執(zhí)行的過程將電子格式的信息通過互聯(lián)網(wǎng)傳輸,最終以圖形用戶界面(GUI)的形式被用戶所瀏覽。簡單來說,網(wǎng)頁設(shè)計的目的就是產(chǎn)生網(wǎng)站。簡單的信息如文字,圖片(GIF,JPEG,PNG)和表格,都可以通過使超文件標(biāo)示語言、可擴(kuò)展超文本標(biāo)記語言等標(biāo)示語言放置到網(wǎng)站頁面上。 現(xiàn)在許多用戶界面都使用工具欄制作菜單條,小弟最近對此感興趣,便從網(wǎng)上求助,可是得到的幫助大多是BCGControlBar的源代碼或者是SizableRebar的源代碼,對于只希望是自己的界面具有該功能的朋友來說,這也許是不錯的選擇,只要看一下demo,然后直接調(diào)用別人的類庫就可以了,但對于我等對此話題感興趣,希望弄懂其來龍去脈的讀者來說,直接看這些沒有詳細(xì)解釋的源代碼,要從中弄出個所以然來,實不是件容易的是,至少對于像我這樣的菜鳥來說是這樣的,本文出于此種原因,希望對還在尋求此幫助的讀者能提供一些幫助。
下面我們邊看邊侃:
在接收到toolbarbutton按下消息時,我們一般使用TrackPopupMenuEx彈出菜單,問題的關(guān)鍵是,在菜單未關(guān)閉時,TrackPopupMenuEx并不返回,并攔截鼠標(biāo)和鍵盤消息,使用spy可以看到,此時的工具欄收不到任何消息,當(dāng)然無從改變熱點,這就需要我們自己探測鼠標(biāo)位置并在鼠標(biāo)移動到下一個熱點時關(guān)閉上一個菜單并顯示下一個菜單。這里我們使用鉤子函數(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ù)檢查消息,如果是來自菜單,則將消息傳遞給函數(shù)HookMessageProc處理,我們所要做的就是在該函數(shù)中檢測消息WM_MOUSEMOVE,并測試鼠標(biāo)位置,如果鼠標(biāo)已經(jīng)移動到另一個按鈕上,則關(guān)閉菜單并顯示下一個菜單,關(guān)閉菜單使用消息WM_CANCELMODE,當(dāng)菜單關(guān)閉后,我們要釋放鉤子,在下一個菜單彈出時重新安裝鉤子,彈出菜單示例代碼如下:
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; //下一個彈出項,若為負(fù),則退出 } SendMessage(hWndToolBar,TB_SETHOTITEM,-1,0);
}
(經(jīng)驗與建議:如果button使用樣式TBSTYLE_DROPDOWN,請不要在消息TBN_DROPDOWN中直接調(diào)用該函數(shù),應(yīng)使用中間消息,然后使用PostMessa個發(fā)送該消息,以使TBN_DROPDOWN可以直接返回,否則消除第一個高亮熱點是很麻煩的事。)iPopup為當(dāng)前彈出項,iNextPop為下一個彈出項,這些變量需要在函數(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)驗與建議:不要試圖在此處調(diào)用TrackPopup,我曾試圖取消該函數(shù)內(nèi)的while循環(huán),直接在此調(diào)用該函數(shù),結(jié)果是在TrackPopupMenuEx未返回之前,該函數(shù)已被調(diào)用)
這里,僅僅處理了鼠標(biāo)移動消息,真正的菜單還應(yīng)處理鍵盤導(dǎo)航消息,詳細(xì)的代碼可以參考 BCGControlBar(http://www.vckbase.com/code/downcode.asp?id=1382) 或SizableRebar(http://www.codeproject.com/docking/sizablerebar/SizableRebar_demo.zip )
有了這底層框架,這些處理過程應(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 95090Toolbar制作菜單條過程詳解xmlscript.src="http://guide.pconline.com.cn/comment/commentService_js.jsp?"+(new Date()); (出處:CSDN)大多數(shù)人在上網(wǎng)的時候,都會瀏覽網(wǎng)頁提供給我們的信息。
|