天天看點

菜單

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-&gt;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(&amp;point)使用該函數進行轉化)

pWnd:指定快捷菜單的擁有者。

lpRect:指定一塊矩形區域。滑鼠點選其他處該快捷菜單也不會消失。

(2)差別

pPopup -&gt;TrackPopupMenu(TPM_RIGHTBUTTON|TPM_LEFTALIGN,point.x,point.y,this);

pPopup -&gt;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,如需轉載請自行聯系原作者