【vc】6_菜 單

一、菜單命令響應函數:

  提示:MFC都是採用大寫字母來標識資源ID號的;爲了區分資源類型,通常遵循這樣一個原則:在「ID」字符串後加上一個標識資源類型的字母。例:菜單資源(Menu):ID_Mxxx;光標資源(Cursor):ID_Cxxx;圖標資源(Icon):ID_Ixxx等;編程

 

二、菜單命令的路由:

  程序類對菜單命令的響應順序:視類、文檔類、框架類、應用程序類框架

    xxxView --> xxxDoc --> xxxFrame --> xxxApp(能夠經過調試驗證,注意:CxxxApp類 和 CxxxDoc類 都不是從CWnd類派生的,故都沒有MessageBox成員函數,因此要使用全局的MessageBox函數,或者使用應用程序框架的函數:AfxMessageBox)ide

int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );

 

  Windows消息的分類函數

    ·標準消息 除WM_COMMAND以外,全部以WM_開頭的消息。 從CWnd派生的類,均可以接收到這類消息。工具

    ·命令消息 來自菜單、加速鍵或工具欄按鈕的消息。這類消息都以WM_COMMAND呈現。在MFC中,經過菜單項的標識(ID)來區分不一樣的命令消息;在SDK中,經過消息的wParam參數識別。 從CCmdTarget派生的類,均可以接收到這類消息。this

    ·通告消息 由控件產生的消息,例如,按鈕的單擊,列表框的選擇等均產生此類消息,爲的是向其父窗口(一般是對話框)通知事件的發生。這類消息也是以WM_COMMAND形式呈現。 從CCmdTarget派生的類,均可以接收到這類消息。spa

  CWnd類派生於 CCmdTarget類;即:凡是從CWnd派生的類,他們既能夠接收標準消息,也能夠接收命令消息和通告消息。而對於那些從CCmdTarget派生的類,則只能接收命令消息和通告消息,不能接收標準消息。(文檔類、視圖類 派生於 CCmdTarget類)操作系統

 

  **菜單命令的路由3d

    菜單命令消息響應函數的映射與「4_簡單繪圖」中介紹的標準消息的映射是同樣的,只是消息命令使用的是ON_COMMAND宏。可是:命令消息和標準消息的路由過程仍是有區別的。指針

 

提示:WindowProc函數是CWnd類的一個成員函數。

 

3菜單的結構

  整個樓房對應於程序中的菜單欄,樓房的每一層對應於菜單欄上的子菜單(如:文件、編輯、查看、幫助等菜單對象),而房間對應於菜單項。

  注意:分隔欄在(子)菜單中是佔據索引位置的。

 

  程序的主菜單屬於框架窗口,因此須要在框架類窗口建立完成以後再去訪問菜單對象。能夠在框架類(CMainFrame類)的OnCreate函數的最後(return以前)添加對菜單功能操做的代碼。

//CWnd::GetMenu
CMenu* GetMenu( ) const; 

 

  ·功能:在框架窗口中得到指向菜單欄的指針;CMenu類是一個MFC類,是Windows菜單句柄HMENU的一個封裝,提供一些與菜單操做有關的成員函數,例如:菜單的建立、更新和銷燬等,還能夠得到一個菜單的子菜單,以下:

//CMenu::GetSubMenu 
CMenu* GetSubMenu( int nPos ) const;

  ·功能:獲取一個菜單的子菜單;

  ·nPos:指定子菜單的索引號;

  ·返回一個指向CMenu對象的指針,該函數返回值所指向的對象與CWnd類的GetMenu函數的返回值所指向的對象不同;GetMenu函數返回的是指向程序菜單欄對象的指針,而GetSubMenu成員函數返回的是由參數nPos指定的子菜單的指針。

  

  注意:GetMenu函數是CWnd類的成員函數,而GetSubMenu函數是CMenu的成員函數。

 

//CMenu::CheckMenuItem
UINT CheckMenuItem( UINT nIDCheckItem, UINT nCheck ); 

  ·功能:爲菜單項添加一個標記,或者移除菜單項的標記;

  ·nIDCheckItem:指定須要處理的菜單項,它的取值由第二個參數決定。

  ·nCheck:指定怎樣設置菜單項,以及如何定位該菜單項的位置;取值能夠是:MFCHECKED 或 MF_UNCHECKED 與 MF_POSITION 或 MF_BYCOMMAND的組合;

如: GetMenu()->GetSubMenu(0)->ChechMenuItem(0, MF_BYPOSITION | MF_COMMOD); 此爲位置訪問菜單項,也可用菜單標識訪問。

 

//CMenu::SetDefaultItem
BOOL SetDefaultItem( UINT uItem, BOOL fByPos = FALSE );

  ·做用:設置默認菜單項;

  ·uItem:取值由第二個參數決定;能夠是新的默認喜好單項的表示或位置索引,值爲-1,代表沒有默認菜單項。

  ·fByPos:值爲FALSE,代表第一個參數是菜單項標識,不然是菜單項位置索引;

  ·一個子菜單隻有一個默認菜單項;

 

 圖形標記菜單:

//CMenu::SetMenuItemBitmaps 
BOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked );

  ·做用:將指定的位圖與菜單項關聯起來(菜單項前面有小圖標);

  ·第一個參數(nPosition)的取值也是由第二個參數(nFlags)的值決定;

  ·第三個參數:指定當取消菜單項選中狀態時的位圖,

  ·第四個參數:指定選中菜單項時顯示的位圖(固然能夠都指定同一個位圖,也能夠指定不一樣的位圖);

  注意:bitmap是全局變量仍是局部變量這很關鍵,它們的做用週期不一樣,會致使不同的結果。

 

int GetSystemMetrics(
  int nIndex   // system metric or configuration setting
);
View Code

 

   ·做用:用來指定但願獲取那部分系統信息;

  ·nIndex:當值爲SM_CXMENUCHECK或SM_CYMENUCHECK時,該函數將獲取標記菜單項上標記圖形的默認尺寸,前者是得到標記圖形的寬度,後者是得到標記圖形的高度(還有不少其餘的取值,參見MSND)。

 

禁用菜單項:

//CMenu::EnableMenuItem 
UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );
// NOTE: m_bAutoMenuEnable is set to FALSE in the constructor of 
// CMainFrame so no ON_UPDATE_COMMAND_UI or ON_COMMAND handlers are 
// needed, and CMenu::EnableMenuItem() will work as expected. 

 

   ·做用:設置菜單項的狀態:可以使用、禁用或變灰顯示。

  ·第一個參數有第二個參數決定。後者能夠是MF_DISABLED, MF_ENABLED 或 MF_GRAYED 與 MF_BYCOMMAND(指定第一個參數是菜單項的標識ID) 或 MF_BYPOSITION(指定第一個參數是菜單項的位置索引) 的組合。

  ·提示信息:一旦在CMainFrame類的構造函數中把成員變量m_bAutoMenuEnable設置爲FALSE後,就不須要對ON_UPDATE_COMMAND_UI 或 ON_COMMAND 消息進行響應處理了,CMenu類的EnableMenuItem函數將可以正常工做。(默認狀況下,全部菜單項的更新都是由MFC的命令更新機制完成的。若是咱們想本身更改菜單項的狀態,那就必須先把 m_bAutoMenuEnable 變量設置爲FALSE,以後,咱們本身對相愛但想的狀態更新才能起做用)

   CMainFrame::CMainFrame()
  {

    //TODO:ADD menber initialization code here
    m_bAutoMenuEnable = FALSE;
  }

 
View Code

 

  ·將m_bAutoMenuEnable設置爲FALSE後,MFC就再也不利用它的菜單命令更新機制去判斷哪一個菜單可使用,那個菜單不可以使用,因此其也就不能根據菜單項的狀態以不一樣的外觀來顯示;而菜單可否使用這些判斷操做,就須要咱們本身去完成了。

 

移除和裝載菜單:

//CWnd::SetMenu
BOOL SetMenu( CMenu* pMenu );

  ·pMenu:指向一個新菜單對象。值爲NULL,則當前菜單就被移除了。

  

  在編程中,除了使用MFC自動建立的IDR_MAINFRAME菜單之外,還能夠本身建立一個菜單資源並加載,而後調用SetMenu函數,從而使程序的菜單編程本身定義的這個菜單;經過這種方式,能夠實現動態更換程序菜單的功能

 

  提示:在設置窗口菜單是,若是定義的是局部菜單對象,則必定要在調用SetMenu函數設置窗口菜單以後,當即調用菜單對象的Detach函數將菜單句柄與菜單對象分離。

//CMenu::Detach 
HMENU Detach( );

  ·功能:把菜單句柄與這個菜單對象(局部變量)分離。在「SetMenu(xxx);」 後使用;(SetMenu函數會把窗口的菜單設置爲器參數指定的新菜單,到時窗口重繪,以反映菜單的這種變化,同時也將該菜單對象的全部權交由給窗口對象。而稅後的Detach函數會把菜單句柄與這個菜單對象分離,這樣當這個局部菜單對象的聲明週期結束時,它不會去銷燬一個它再也不具備擁有權的菜單)

 

MFC菜單命令的更新機制

  利用MFC編程時,菜單項狀態的維護依賴與CN_UPDATE_COMMAND_UI消息,誰捕獲CN_UPDATE_COMMAND_UI消息,MFC就在其中那個建立一個CCmdUI對象。(咱們能夠經過手工,或利用ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏來捕獲CN_UPDATE_COMMAND_UI消息)

                 圖示  爲剪切菜單項增長UPDATE_COMMAND_UI消息處理函數

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    ON_WM_CREATE()
    ON_COMMAND(IDM_TEST, OnTest)
    ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)//*消息映射機制自動添加的xxx宏*該宏是用來捕獲CN_UPDATE_COMMAND_UI消息的
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
View Code

 

 

當程序框架捕獲到了CN_UPDATE_COMMAND_UI消息後,最終仍是交由該消息的響應函數來處理,例如本例中的OnUpdateEditCut函數:

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
    
}
View Code

 

  ·CCmdUI指針類型的參數:利用CCmdUI類,能夠決定一個菜單項是否可使用、是否有標記,還能夠改變菜單項的文本。(UI(User Interface):用戶接口;菜單項 就是一個用戶接口)

  提示:CN_UPDATE_COMMAND_UI消息的響應只能應用於菜單項,不能應用與永久顯示的頂級菜單(即彈出式菜單)項目

 

MFC在後臺的所作的工做是:當要顯示菜單時,操做系統發出WM_INITMENUPOPUP消息,而後有程序窗口的基類如CFrameWnd接管。它會建立一個CCmdUI對象,並與程序的第一個菜單項相關聯,調用該對象的一個成員函數DoUpdate()。這個函數發出CN_UPDATE_COMMAND_UI消息,這條消息帶有一個指向CCmdUI對象的指針。這時,系統會判斷是否存在一個ON_UPDATE_COMMAND_UI宏去捕獲這個菜單項消息。若是找到這樣一個宏,就調用響應的消息響應函數進行處理,在這個函數中,能夠利用傳遞過來的CCmdUI對象去調用響應的函數,是該菜單項可使用,或禁用該菜單項。當更新完第一個菜單項後,同一個CCmdUI對象就設置爲與第二個菜單項相關聯,以此順序進行,知道完成全部菜單項的處理。這就是MFC命令更新機制

 

  利用MFC提供的命令更新機制,在程序中實現菜單項的可用或機制功能時就變得很簡單了。咱們只須要捕獲UPDATE_COMMAND_UI消息,在該消息的響應函數中調用CCmdUI對象的相應函數,如:Enable、SetCheck、或SetText函數,就能夠分別實現菜單項可用或禁用、設置標誌菜單,或者設置菜單項的文本這些功能。

//CCmdUI::xxx
virtual void Enable( BOOL bOn = TRUE );
virtual void SetCheck( int nCheck = 1 );
virtual void SetRadio( BOOL bOn = TRUE );
virtual void SetText( LPCTSTR lpszText );
void ContinueRouting( );
View Code

 

 

若是要把工具欄上的一個工具按鈕與菜單欄中的某個菜單項相關聯,只要將他們的ID設置爲同一個標識就能夠了。

計算菜單項索引時,必定要把分隔欄菜單項計算在內。

綜上:若是要在程序中設置某個菜單系那個的狀態,首先經過ClassWizard爲這個菜單項添加UPDATE_COMMAND_UI消息響應函數,而後在這個函數中進行狀態的設置便可。

 

快捷菜單:

//CMenu::TrackPopupMenu 
BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL );

  ·做用:顯示一個快捷菜單。

 

快捷菜單建立的步驟

  (1)爲Menu程序增長一個新的菜單資源(Menu1)。而後打開菜單資源添加菜單項。如:

  (2)給CMenuView類添加WM_RBUTTONDOWN消息響應函數。(若是是在鼠標右鍵單擊窗口時顯示快捷菜單,那麼就應該捕獲這個消息)

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CMenu menu;
    menu.LoadMenu (IDR_MENU1);
    CMenu* pPopup = menu.GetSubMenu(0);
    
        ClientToScreen(&point);//左邊轉換,把客戶區座標轉換爲屏幕座標
    pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);//注意:this的不一樣,就有不一樣的響應

    CView::OnRButtonDown(nFlags, point);
}
View Code

  (3)爲Menu程序添加快捷菜單上個菜單項命令的響應函數。

  提示:對於快捷菜單,若是將其擁有者窗口設置爲框架類窗口,則框架類窗口才能有機會得到對該快捷菜單中的菜單項的命令響應,不然,就只能有視類窗口作出響應。

 

動態菜單操做

  未完待續···

相關文章
相關標籤/搜索