1、MFC類層次結構圖:
CxxxApp類和CxxxDoc類不是CWnd派生,是以沒有成員函數MessageBox,可以使用應用程式架構的函數:AfxMessageBox()代替,原型如下:
Int AfxMessageBox(LPCTSTR lpszText,UINT nType=MB_OK,UINT nIDHelp=0);
2、程式類對菜單指令的響應順序:
視類、文檔類、架構類、應用程式類。
3、windows消息分類
(1)标準消息
以WM_開頭。
(2)指令消息
來自菜單、加速鍵或工具欄按鈕的消息。都以WM_COMMAND形式呈現。MFC中,通過菜單項的辨別(ID)識别;SDK中通過消息的wParam參數識别。
(3)通告消息
由控件産生,例如:按鈕的單擊、清單框的選擇等都會産生這類消息,目的是為了向其父視窗(通常是對話框)通知事件的發生。
結論:
從CWnd派生的類均可繼承以上三種消息。
從CCmdTarget派生的類隻能接收指令消息和通告消息。
4、菜單指令路由通經
4、基本菜單操作
(1)獲得程式的菜單欄,CWnd::GetMenu()函數,原型如下:
CMenu * GetMenu() const;
傳回的是一個CMenu對象指針,可以進行菜單的建立、更新、銷毀以及調用其子菜單GetSubMenu函數,原型如下:
CMenu * GetSubMenu(int nPos) const; //子菜單的索引号
(2)為菜單項添加或移除标記,CMenu::CheckMenuItem()函數,原型如下:
UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck);
參數含義:指定處理的菜單項,如何處置(MF_CHECKED,MF_UNCHECKED,MF_BYPOSITION,MF_BYCOMMAND)
(3)例如:(紅字部配置設定對使用)
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_SAVE,MF_BYCOMMAND|MF_CHECKED);
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);
6、預設菜單項(黑體字辨別)
設定預設菜單項,CMenu::SetDefaultItem()函數,原型如下:
BOOL SetDefaultItem(UINT uItem,BOOL fByPos=FALSE);
參數含義:若為false,第一個參數表示菜單項辨別,否則為菜單項位置索引。
(1)一個子菜單隻能有一個預設菜單項。
(2)分隔欄在菜單項中占據索引位置。
7、圖形标記菜單
實作圖形标記菜單利用CMenu::SetMenuItemBitmaps(),作用是将指定位圖與菜單項關聯,原型如下:
BOOL SetMenuItemBitmaps(UINT nPosition,UINT nFlags,const CBitMap * pBmpUnChecked,const * CBitMap pBmpChecked);
參數描述:菜單項辨別|菜單項位置索引,MF_BYCOMMAND,未選中狀态位圖,選中狀态位圖。
m_bitmap.LoadBitmap(IDB_BITMAP1); //m_bitmap為全局變量
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION|MF_CHECKED,&m_bitmap,&m_bitmap);
//擷取标記菜單項上标記圖形的預設尺寸:标記寬度,标記高度
GetSystemMetrics(SM_CXMENUCHECK);
8、禁用菜單項
設定菜單項的狀态:能夠使用、禁用或變灰顯示。CMenu::EnableMenuItem(),原型如下:
UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);
注意:
//需将CMainFrame類的構造函數中成員變量m_bAutoMenuEnable設定為false。
9、移除和裝載菜單
CWnd::SetMenu(),函數原型如下:
BOOL SetMenu(CMenu * pMenu);
例如:
(1)SetMenu(NULL); //移除
(2)CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
//将菜單句柄和菜單對象分離
menu.Detach(); //以防程式出現問題 因為此時的menu為一個局部變量
10、MFC菜單指令更新機制
(1)當要顯示菜單時,作業系統發出WM_INITMENUPOPUP消息,然後由應用程式視窗的基類如CFrameWnd接管,它會創造一個CCmdUI對象,并與程式的第一個菜單項相關聯,調用該對象的一個成員函數DoUpdate(),該函數發出ON_UPDATE_COMMAND_UI消息,這條消息帶有一個指向CCmdUI對象的指針。系統判斷是否存在一個ON_UPDATE_COMMAND_UI的宏,如果存在就調用相應的函數處理,在該函數中,可以利用傳遞過來的CCmdUI對象去調用,使用某個菜單項或禁用某個菜單項。更新完第一個菜單後,同一個CCmdUI對象就設定為第二個菜單項相關聯,依次進行,直到完成所有菜單項的處理。
<a target="_blank" href="http://blog.51cto.com/attachment/201101/105900875.jpg"></a>
(2)CCmdUI類成員變量m_nID,用于儲存目前菜單項、工具欄按鈕,或者其他由CCmdUI對象表示的UI對象的辨別。
(3)CCmdUI類成員變量m_nIndex,用于儲存目前菜單項的位置索引。
8、快捷菜單
(1)
void CMenuView::OnContextMenu(CWnd*, CPoint point)
{
CMenu* pPopup = menu.GetSubMenu(0);
。。。。
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
pWndPopupOwner);
}
其中TrackPopupMenu原型如下:
BOOL TrackPopupMenu(UINT nFlags,int x,int y,CWnd * pWnd,LPCRECT lpRect=NULL)
nFlags:指定菜單在螢幕上顯示的位置。
x,y:指快捷菜單顯示位置處的x,y坐标。相對于螢幕坐标而不是客戶區坐标(ClientToScreen(&point)使用該函數進行轉化)
pWnd:指定快捷菜單的擁有者。
lpRect:指定一塊矩形區域。滑鼠點選其他處該快捷菜單也不會消失。
(2)差別
pPopup ->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_LEFTALIGN,point.x,point.y,this);
pPopup ->TrackPopupMenu(TPM_RIGHTBUTTON|TPM_LEFTALIGN,point.x,point.y,Get Parent());//這種方法好像不對,編譯不通過
9、動态菜單操作(針對彈出式菜單動态操作、針對菜單項的動态操作)
(1)動态的添加菜單項目,CMenu::AppendMenu函數原型如下:
BOOL AppendMenu(UINT nFlags,UINT_PTR nIDNewItem=0,LPCTSTR lpszNewItem=NULL); 末尾添加
nFlags:新添加菜單項目的狀态資訊。(禁用加灰菜單、移除對号标記菜單等)
nIDNewItem:如果第一個參數為MF_POPUP,則為頂層菜單句柄;否為新菜單項的指令ID。
如果第一個參數為MF_SEPARATOR,nIDNewItem值忽略。
lpszNewItem:如果第一個參數為MF_STRING,則指向新添加菜單項目的文本的指針。
如果第一個參數為MF_OWNERDRAW,則指向該菜單項目一個附加資料指針。
如果第一個參數為MF_SEPARATOR,lpszNewItem值忽略。
(2)CMenu::CreatePopupMenu,作用:建立一個彈出菜單并關聯菜單對象。
(3)插入菜單項:(在兩個子菜單項中添加,在兩個菜單項中添加)CMenu::InsertMenu()
BOOL InsertMenu(UINT nPosition,UINT nFlags,UINT_PTR nIDNewItem=0,LPCTSTR lpszNewItem=NULL); 根據具體位置添加
參數含義同AppendMenu函數,但nFlags會多幾個組合MF_BYPOSITION和MF_BYCOMMAND.
(4)删除菜單項CMenu::DeleteMenu(),原型如下:
BOOL DeleteMenu (UINT nPosition,UINT nFlags);
13、動态添加菜單項的指令響應:
(1)Resource.h 中添加預定義内容 #define IDM_HELLO 111
(2)menu.AppendMenu(MF_STRING,IDM_HELLO,"hello");
(3)MainFrm.h檔案中 AFX_MSG之後,DECLARE_MESSAGE_MAP之前添加:afx_msg void OnHello();
(4)MainFrm.cpp檔案中BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之間添加:
ON_COMMAND(IDM_HELLO,OnHello)不加分号。
(5)MainFrm.cpp檔案中實作函數OnHello的實體
void CMainFrame::OnHello()
MessageBox("hello");
14、架構類視窗截獲菜單指令消息(不用在視類中處理)
方法是:在架構類中添加OnCommand虛函數. return TRUE;//中斷消息路由路徑。
(1)架構類擷取視類的成員變量
CMainFrame::GetActiveView成員函數,擷取與架構類相關聯的目前視類的指針。原型如下:CView * GetActiveView()const; // 傳回的是CView,如果不是使用者所需還需類型轉換。
例如:CTelNoteView * pView=(CTelNoteView *)GetActiveView(); //擷取目前視類指針。
(2)m_bAutoMenuEnable=FALSE;
本文轉自 韬光星夜 51CTO部落格,原文連結:http://blog.51cto.com/xfqxj/476997,如需轉載請自行聯系原作者