VC++学习(6):菜单编程
1.?????? MFC中的頂層菜單默認(rèn)為彈出菜單(Pop-up),它是不能用來(lái)作命令響應(yīng)的,當(dāng)取消Pop-up選項(xiàng)后可接受命令響應(yīng)。
2.?????? 消息的分類(lèi):標(biāo)準(zhǔn)消息,命令消息,通告消息。
[標(biāo)準(zhǔn)消息]:除WM_COMMAND之外,所有以WM_開(kāi)頭的消息。從CWnd類(lèi)派生的類(lèi)都可以接收到這一消息;
[命令消息]:來(lái)自菜單、加速鍵或工具欄按鈕的消息。這類(lèi)消息都以WM_COMMAND呈現(xiàn)。在MFC中,通過(guò)菜單項(xiàng)的標(biāo)識(shí)(ID)來(lái)區(qū)分不同的命令消息;在SDK中,通過(guò)消息的wParam參數(shù)識(shí)別。從CCmdTarget(CWnd的父類(lèi))派生的類(lèi)都可以接收到這一類(lèi)消息;
[通告消息]:由控件產(chǎn)生的消息,例如,按鈕的單擊,列表框的選擇等均產(chǎn)生此類(lèi)消息,為的是向其父窗口(通常是對(duì)話(huà)框)通知事件的發(fā)生。這類(lèi)消息也是以WM_COMMAND形式呈現(xiàn)。從CCmdTarget(CWnd的父類(lèi))派生的類(lèi)都可以接收到這一類(lèi)消息
總結(jié):
凡是從CWnd派生的類(lèi),既可以接收標(biāo)準(zhǔn)消息,也要以接收命令消息和通告消息。
而對(duì)于那些從CCmdTarget派生的類(lèi),則只能接收命令消息和通告消息,不能接收標(biāo)準(zhǔn)消息。
3.?????? MFC中菜單項(xiàng)消息如果利用ClassWizard來(lái)對(duì)菜單項(xiàng)消息分別在上述四個(gè)類(lèi)中進(jìn)行響應(yīng),則菜單消息傳遞順序:View類(lèi)--Doc類(lèi)--CMainFrame類(lèi)--App類(lèi)。菜單消息一旦在其中一個(gè)類(lèi)中響應(yīng)則不再在其它類(lèi)中查找響應(yīng)函數(shù)。
菜單消息與前面介紹的標(biāo)準(zhǔn)消息的實(shí)現(xiàn)機(jī)制是相類(lèi)似的,都是在消息響應(yīng)函數(shù)原型(頭文件),消息映射宏(源文件)和消息函數(shù)實(shí)現(xiàn)(源文件)中添加代碼。注意:文檔類(lèi)與應(yīng)用程序類(lèi)都是由CCmndTarget類(lèi)派生,所以可以接收菜單命令消息,但不能接收標(biāo)準(zhǔn)消息(只能由CWnd類(lèi)派生才可以)。
具體消息路由過(guò)程:
當(dāng)點(diǎn)擊一個(gè)菜單項(xiàng)的時(shí)候,最先接受到菜單項(xiàng)消息的是CMainFrame框架類(lèi),CMainFrame框架類(lèi)將會(huì)把菜單項(xiàng)消息交給它的子窗口View類(lèi),由View類(lèi)首先進(jìn)行處理;如果View類(lèi)檢測(cè)到?jīng)]對(duì)該菜單項(xiàng)消息做響應(yīng),則View類(lèi)把菜單項(xiàng)消息交由文檔類(lèi)Doc類(lèi)進(jìn)行處理;如果Doc類(lèi)檢測(cè)到Doc類(lèi)中也沒(méi)對(duì)該菜單項(xiàng)消息做響應(yīng),則Doc類(lèi)又把該菜單項(xiàng)消息交還給View類(lèi),由View類(lèi)再交還給CMainFrame類(lèi)處理。如果CMainFrame類(lèi)查看到CMainFrame類(lèi)中也沒(méi)對(duì)該消息做響應(yīng),則最終交給App類(lèi)進(jìn)行處理。
4.?????? 一個(gè)菜單欄可以有若干個(gè)子菜單,一個(gè)子菜單又可以有若干個(gè)菜單項(xiàng)等。對(duì)菜單欄的子菜單由左至右建立從0開(kāi)始的索引。對(duì)特定子菜單的菜單項(xiàng)由上至下建立了從0開(kāi)始的索引。訪(fǎng)問(wèn)子菜單和菜單項(xiàng)均可以通過(guò)其索引或標(biāo)識(shí)(如果有標(biāo)識(shí)的話(huà))進(jìn)行。
相關(guān)重要函數(shù):
CMenu* GetMenu( ) ;//CWnd::GetMenu得到窗口菜單欄對(duì)象指針。
CMenu* GetSubMenu(?) ;//CMenu::GetSubMenu獲得指向彈出菜單對(duì)象指針
UINT CheckMenuItem( );//CMenu::CheckMenuItem 添加選中標(biāo)識(shí)
BOOL SetDefaultItem();//CMenu::SetDefaultItem 為指定菜單設(shè)置缺省菜單項(xiàng)(唯一)
BOOL SetMenuItemBitmaps( );//CMenu::SetMenuItemBitmaps 設(shè)置位圖標(biāo)題菜單。
UINT EnableMenuItem();//CMenu::EnableMenuItem使菜單項(xiàng)有效,無(wú)效,或變灰。
BOOL SetMenu( CMenu* pMenu );//CWnd::SetMenu在當(dāng)前窗口上設(shè)置新菜單或移除菜單。
HMENU Detach( );//CMenu::Detach;斷開(kāi)一個(gè)菜單資源與相關(guān)的類(lèi)對(duì)象句柄關(guān)聯(lián),可以定義局部對(duì)象,在使用完后調(diào)用Detach函數(shù),則不會(huì)因?yàn)榫植繉?duì)象影響使用
說(shuō)明:
1)在計(jì)算子菜單菜單項(xiàng)的索引的時(shí)候,分隔欄符也算索引的。
2)int GetSystemMetrics()獲取系統(tǒng)信息度量。可以用它來(lái)獲取菜單標(biāo)題的尺寸(后面還會(huì)使用到獲取屏目尺寸)從而設(shè)置位圖標(biāo)題菜單中位圖的大小。
3)在MFC中MFC為我們提供了一套命令更新機(jī)制,所有菜單項(xiàng)的更新都是由這套機(jī)制來(lái)完成的。所以要想利用CMenu::EnableMenuItem來(lái)自己控制菜單使用或不使用變灰等,必須要在CMainFrame的構(gòu)造函數(shù)中將變量m_bAutoMenuEnable設(shè)置為FALSE。
EXAMPLE:
CMenu menu;//定義為局部對(duì)象
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
menu.Detach();// 這里menu對(duì)象作為一個(gè)局部對(duì)象。使用Detach()從menu對(duì)象中分離窗口菜單句柄,從而當(dāng)menu對(duì)象析構(gòu)的時(shí)候窗口菜單資源不隨之銷(xiāo)毀。
5.?????? 命令更新機(jī)制:
菜單項(xiàng)狀態(tài)的維護(hù)是依賴(lài)于CN_UPDATE_COMMAND_UI消息,誰(shuí)捕獲CN_UPDATE_COMMAND_UI消息,MFC就在其中創(chuàng)建一個(gè)CCmdUI對(duì)象。
在后臺(tái)操作系統(tǒng)發(fā)出WM_INITMENUPOPUP消息,然后由MFC的基類(lèi)如CFrameWnd接管并創(chuàng)建一個(gè)CCmdUI對(duì)象和第一個(gè)菜單項(xiàng)相關(guān)聯(lián),調(diào)用對(duì)象成員函數(shù)DoUpdate()(注:這個(gè)函數(shù)在MSDN中沒(méi)有找到說(shuō)明)發(fā)出CN_UPDATE_COMMAND_UI消息,這條消息帶有指向CCmdUI對(duì)象的指針。此后同一個(gè)CCmdUI對(duì)象又設(shè)置為與第二個(gè)菜單項(xiàng)相關(guān)聯(lián),這樣順序進(jìn)行,直到完成所有菜單項(xiàng)。
更新命令UI處理程序僅應(yīng)用于彈出式菜單項(xiàng)上的項(xiàng)目,不能應(yīng)用于永久顯示的頂級(jí)菜單項(xiàng)目。
說(shuō)明:可以手工或用ClassWizard來(lái)給菜單項(xiàng)添加UPDATE_COMMAND_UI消息響應(yīng),利用響應(yīng)函數(shù)中傳進(jìn)來(lái)的CCmdUI對(duì)象指針可完成設(shè)置菜單項(xiàng)可使用,不可使用,變灰,設(shè)置標(biāo)記菜單等操作。
6,如果要想讓工具欄上的某個(gè)圖標(biāo)與菜單項(xiàng)的某個(gè)菜單相關(guān)聯(lián),只需要將圖標(biāo)的ID設(shè)置為該菜單項(xiàng)的ID。
工具欄圖標(biāo)的索引記數(shù)順序是:從左至右從0開(kāi)始,分隔符也算索引號(hào)。
?
7,利用向項(xiàng)目中添加VC的POPMENU控件:Project->Add to Project->Components and Controls..
系統(tǒng)增加的內(nèi)容:A,一個(gè)菜單資源;B,在派生View類(lèi)中增加了OnContextMenu()函數(shù)
說(shuō)明:
1)CWnd::OnContextMenu Called by the framework when the user has clicked the right mouse button (right clicked) in the window. You can process this message by displaying a context menu using the TrackPopupMenu.
2)BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL );
//CMenu::TrackPopupMenu Displays a floating pop-up menu at the specified location and tracks the selection of items on the pop-up menu. A floating pop-up menu can appear anywhere on the screen.
?
8,利用調(diào)用TrackPopupMenu函數(shù),手工添加彈出菜單:
1)用資源管理器添加一個(gè)菜單資源
2)在鼠標(biāo)右鍵消息響應(yīng)函數(shù)中,加載菜單資源,并獲得要顯示的子菜單指針,并用該指針調(diào)用TrackPopupMenu函數(shù)便完成任務(wù)(但要注意:鼠標(biāo)響應(yīng)函數(shù)傳進(jìn)來(lái)的坐標(biāo)是客戶(hù)區(qū)坐標(biāo),而TrackPopupMenu函數(shù)中使用的是屏幕坐標(biāo),在調(diào)用TrackPopupMenu前要調(diào)用ClientToScreen客戶(hù)區(qū)坐標(biāo)到屏幕坐標(biāo)的轉(zhuǎn)換)
事例代碼:
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *pPopup=menu.GetSubMenu(0);
ClientToScreen(&point);????????????????? //坐標(biāo)轉(zhuǎn)換
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,this);
說(shuō)明:
CWnd::ClientToScreen(..);//將一個(gè)坐標(biāo)點(diǎn)或一個(gè)矩形區(qū)域坐標(biāo)轉(zhuǎn)換成屏幕坐標(biāo)。
CMenu::TrackPopupMenu(..);//在指定位置以指定的方式顯示彈出菜單。
?
9,當(dāng)彈出菜單屬于框架窗口的時(shí)候(可在TrackPopupMenu函數(shù)參數(shù)中設(shè)置),彈出菜單上的消息,在路由的時(shí)候,仍然遵循View-DOC-MainFrame-APP的響應(yīng)順序。
10,動(dòng)態(tài)菜單編程:
所有的資源對(duì)象都有一個(gè)數(shù)據(jù)成員保存了資源的句柄。
下面的函數(shù)可以操作子菜單(Popup菜單)或者菜單項(xiàng);
CMenu::AppendMenu //Appends a new item to the end of a menu.
CMenu::CreatePopupMenu //Creates an empty pop-up menu and attaches it to a CMenu object.
CMenu::InsertMenu
//Inserts a new menu item at the position specified by nPosition and moves other items down the menu.
CMenu::GetSubMenu //Retrieves a pointer to a pop-up menu.
CWnd::GetMenu //Retrieves a pointer to the menu for this window.
CMenu::DeleteMenu //Deletes an item from the menu.
?
11,手動(dòng)給動(dòng)態(tài)菜單項(xiàng)添加響應(yīng)函數(shù):
在Resource.h中可以添加資源的ID
在頭文件中寫(xiě)消息函數(shù)原型
在代碼文件中添加消息映射和添加消息響應(yīng)函數(shù)
說(shuō)明:
可以先創(chuàng)建一個(gè)臨時(shí)的菜單項(xiàng),設(shè)置它的ID和動(dòng)態(tài)菜單項(xiàng)的一致,然后對(duì)它用向?qū)нM(jìn)行消息響應(yīng),然后刪除臨時(shí)菜單。
再在代碼文件中把消息映射放到宏外(注意一定要放到宏外面,因?yàn)?/span>CLASSWIZARD發(fā)現(xiàn)菜單刪除了,同時(shí)要把其宏對(duì)里的消息映射也刪除掉的)
?
12,CWnd::DrawMenuBar?? 重畫(huà)菜單欄
//Redraws the menu bar. If a menu bar is changed after Windows has created the window, call this function to draw the changed menu bar
?
CWnd::GetParent //get a pointer to a child window’s parent window (if any).
CWnd::Invalidate //注意其參數(shù)的作用,使窗口區(qū)域無(wú)效,重畫(huà)時(shí)擦出原來(lái)的背景(也可以有效)
?
13,集合類(lèi):
CStringArray,CStringArray,CDWordArray,CPtrArray,CStringArray,CUIntArray,CWordArray
其中成員函數(shù):
CArray::GetAt
CArray::Add
?
14,命令消息是到OnCommand函數(shù)的時(shí)候完成路由的。
由于CWnd::OnCommand 是個(gè)虛函數(shù),可以在框架類(lèi)中重寫(xiě)OnCommand函數(shù),從而可以截獲菜單消息使它不再往下(VIEW類(lèi))路由。
例:
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
?// TODO: Add your specialized code here and/or call the base class
?int MenuCmdId=LOWORD(wParam);//取命令ID
?CMenu2View *pView=(CMenu2View*)GetActiveView();//獲取當(dāng)前VIEW類(lèi)指針
?if(MenuCmdId>=IDM_PHONE1 && MenuCmdId<IDM_PHONE1+pView->m_strArray.GetSize())//消息范圍判斷
?{
?CClientDC dc(pView);
?dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdId-IDM_PHONE1));
?return TRUE;
?? //函數(shù)返回,避免調(diào)用CFrameWnd::OnCommand函數(shù),在CFrameWnd::OnCommand中截獲的消息會(huì)交由VIEW類(lèi)處理
?}
?return CFrameWnd::OnCommand(wParam, lParam);
?//調(diào)用基類(lèi)OnCommand函數(shù),在CFrameWnd::OnCommand中截獲的消息會(huì)交由VIEW類(lèi)處理
}
?
15,LOWORD與HIWORD宏
WORD LOWORD(
?DWORD dwValue?// value from which low-order word is retrieved
);
WORD HIWORD(
?DWORD dwValue?// value from which high-order word is retrieved
);
?
//The LOWORD macro retrieves the low-order word from the given 32-bit value.
//The HIWORD macro retrieves the high-order word from the given 32-bit value.
?
16,CFrameWnd::GetActiveView
CView* GetActiveView( ) const;//獲取當(dāng)前視窗口指針(單文檔框架中)
源文件是單獨(dú)參與編譯的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/forlina/archive/2011/07/28/2119751.html
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的VC++学习(6):菜单编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: nmap扫描ipv6端口_Flan Sc
- 下一篇: 市面上有哪几种门_目前市面上木门的几种分