孫鑫VC學習筆記:第六講 菜單

 

CMenuApp 並不是從CWnd派生出來的,所以不能使用MessageBox函數。
           但可以使用全局的MessageBox函數:AfxMessageBox函數
           int AfxMessageBox(LPCTSTR lpszText,UINT nType,UINT nIDHelp);
          
           對菜單項Test響應的順序:           View-Doc-MainFrame-App
          
                          消息的分類
          
標準消息      除WM_COMMAND之外,所有以WM_開頭的消息。從CWnd派生的類,都可以接收到這類消息。

命令消息      來自菜單、加速鍵或工具欄按鈕的消息。這類消息都以WM_COMMAND呈現。
              在MFC中,通過菜單項的標識(ID)來區分不同的命令消息;
              在SDK中,通過消息的wParam參數識別。從CCmdTarget派生的類,都可以接收到這類消息。
            
通告消息      由控件產生的消息,例如,按鈕的單擊,列表框的選擇等均產生此類消息,
              爲的是向其父窗口(通常是對話框)通知事件的發生。
              這類消息也是以WM_COMMAND形式呈現。從CCmdTarget派生的類,都可以接收到這類消息。

CWnd是由CCmdTarget派生


CWnd::GetMenu
CMenu* GetMenu()const;

CMenu封裝了一些和菜單有關的操作,封裝了windows的HMENU(菜單句柄)

CMenu::GetSubMenu
   CMenu* GetSubMenu( int nPos) const; //獲取子菜單
  
CMenu::CheckMenuItem
   UINT CheckMenuItem( UINT nIDCheckItem, UINT nCheck);// Return the previous state of the item  
  
CMenu::SetDefaultIte
   //BOOL SetDefaultItem( UINT uItem, BOOL fByPos=FALSE) //設置缺省的菜單項
    指定的缺省菜單項將會被加黑顯示
   
CAUTION! 一個子菜單中,只能有一個缺省菜單項

CMenu::SetMenuItemBitmaps
//BOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags,
                             const CBitmaps* pBmpUnchecked, const CBitmaps* pBmpChecked)
創建圖形標記菜單
獲取圖形標記菜單位圖的大小:
    int GetSystemMetrics( int nIndex)
    nIndex: //system metric or configuration setting
     SM_CXMENUCHECK //缺省的菜單標記位圖的高度
      SM_CYMENUCHECK //缺省的菜單標記位圖的寬度
     
     
CString str;

str.Format("x=%d, y=%d",GetSystemMetrics(SM_CXMENUCHECK),
                        GetSystemMetrics(SM_CYMENUCHECK));
MessageBox(str);

//改變菜單項的狀態
CMenu::EnableMenuItem
UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );

CAUTION! 只有在CMainFrame的構造函數中將變量 m_bAutoMenuEnable=FALSE時,
           EnableMenuItem函數纔會起作用
           m_bAutoMenuEnable=FALSE時MFC就不會使用他的命令更新機制去判斷哪個菜單項能使用
           哪個菜單項不能使用,此時這些操作都要由我們自己去完成

如何將整個菜單取消:
CWnd::SetMenu
   //BOOL SetMenu( CMenu* pMenu);
   SetMenu( NULL); //移走當前菜單
  
重新加載菜單:
CMenu menu; // 不能是局部對象
menu.LoadMenu( IDM_MAINFRAME /×菜單ID*/)//動態的更換菜單
SetMenu(&menu);
menu.Detach();//如果menu是局部對象,一定要調用Detach()函數,它將菜單的句柄和我們的C++對象斷開,
                  這樣當局部對象CMenu析構時,不會銷燬我們的菜單

  
MFC對菜單項採用的命令更新機制:01:18:00

                              命令更新

菜單項狀態的維護是依賴於CN_UPDATE_COMMAND_UI消息,誰捕獲CN_UPDATE_COMMAND_UI消息,
MFC就在其中創建一個CCmdUI對象。我們可以通過手工或利用ClassWizard在消息映射中添加
ON_UPDATE_COMMAND_UI宏來捕獲CN_UPDATE_COMMAND_UI消息。

在後臺所做的工作是:操作系統發出WM_INITMENUPOPUP消息,然後由MFC的基類如CFrameWnd接管。
它創建一個CCmdUI對象,並與第一個菜單項相關聯,調用對象的一個成員函數DoUpdate()。
這個函數發出CN_UPDATE_COMMAND_UI消息,這條消息帶有指向CCmdUI對象的指針。同一個
CCmdUI對象就設置爲與第二個菜單項相關聯,這樣順序進行,直到完成所有菜單項。

更新命令UI處理程序僅應用於彈出式菜單項上的項目,不能應用於永久顯示的頂級菜單項目。

void CMainFrame::OnUpdateEditCut( CCmdUI* pCmdUI)
{
pCmdUI->Enable();//Enable()函數的缺省參數爲 BOOL類型TRUE
}

工具欄上的圖標,和它所對應的菜單項的ID號是一樣的。所以當對菜單項DISABLE或者ENABLE時能夠相應
的在工具欄上顯現出來。
CAYTION!:如果在改變菜單項狀態的過程中是用的菜單項ID號,則菜單項狀態的改變能在工具欄上相應的
         圖標上顯現出來,但如果使用的是菜單項的位置索引,則相應的狀態不會在工具欄上顯現出來。
         這是因爲工具欄上的圖標和相應菜單項具有相同的ID號,但位置索引是不相同的。
        
實現右鍵彈出菜單的功能:
   Project->Add To Project->Components and Controls->Visual C++ Components->Pop-up Menu
  
注意:應該把菜單加入CMenuView類

此時,會在CMenuView類中加入一個函數OnContextMenu( CWnd* , CPoint)
//CWnd::OnContextMenu
//afx_msg void OnContextMenu( CWnd* pWnd,CPoint pos)
//Called by 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(用來顯示彈出菜單)
CMenu:: TrackPopupMenu
//BOOL TrackPopupMenu( UINT nFlags, //彈出菜單相對於x的位置
                         int x, int y, //鼠標點擊的位置座標,注意這個位置座標是相對於屏幕座標
                                       //而不是客戶區座標,使用是需要進行座標轉換
                         CWnd* pWnd,   //菜單的擁有者
                         LPCRECT lpRect=NULL //指定一個矩形,當鼠標在矩形外點擊時,菜單消失
                                             //在矩形內點擊時,彈出菜單不消失
                       );
                      
                      
座標轉換:
CWnd::ClientToScreen
    void ClientToScreen( LPPOINT lpPoint) const;
    void ClientToScreen( LPRECT lpRect) const;
   
爲彈出菜單的“顯示”菜單項,在CMenuView和CMainFrame類中分別加入命令捕獲OnShow函數

選中“顯示”項,發現只有CMenuView類對菜單命令進行捕獲,原因是用TrackPopupMenu顯示彈出
菜單時,指定了彈出菜單的擁有者窗口指針
即使將指針設置爲父窗口指針,子窗口依然最先響應菜單命令,只有當子窗口不響應時,才交由父窗口響應

通過代碼來動態添加菜單
CMenu::AppendMenu
//BOOL AppendMenu( UINT nFlags, UINT nIDNewItem=0, LPCTSTR lpszNewItem=NULL);
//BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp);
//可以將一個菜單或者一個菜單項添加到現有菜單的末尾
//nFlags: MF_STRING MF_POPUP MF_SEPARATOR
//nIDNewItem:當nFlags=MF_POPUP,則nIDNewItem爲POPUP菜單的句柄
               //當nFlags=MF_SEPARATOR,則nIDNewItem被Ignored
              
CMenu::CreatePopupMenu
//Creates an empty pop-up menu and attaches it to a CMenu object
//BOOL CreatePopupMenu()

插入菜單
CMenu::InsertMenu
   //BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem=0,LPCTSTR lpszNewItem);
    //BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem,const CBitmap* pBmp);
    //nPosition的取值由nFlags來確定,如果nFlags=MF_BYPOSITION,則nPosition爲位置所以號
                                   //如果nFlags=MF_BYCOMMAND,則nPosition爲菜單項ID號
    //nIDNewItem:當nFlags=MF_POPUP,則nIDNewItem爲POPUP菜單的句柄
               //當nFlags=MF_SEPARATOR,則nIDNewItem被Ignored
刪除子菜單
CMenu::DeleteMenu()
   //BOOL DeleteMenu( UINT nPosition, UINT Flags); //刪除一個指定的菜單項或彈出菜單
  
對動態創建的菜單項進行命令響應
    頭文件Resource.h定義了資源的ID
    做一個菜單命令的命令響應函數,它的添加和消息響應函數時一樣的,一共有三個步驟:
    step1:首先在頭文件中做命令響應函數的原型
               //MainFrm.h
               //protected:
               //afx_msg void OnHello();
    step2: 消息映射                       //使用教程中的方法時,消息映射一定要放到註釋宏的外面
          //MainFrm.cpp  
          BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        //{{AFX_MSG_MAP(CMainFrame)
          // NOTE - the ClassWizard will add and remove mapping macros here.
          //    DO NOT EDIT what you see in these blocks of generated code !
         ON_WM_CREATE()
        //}}AFX_MSG_MAP
        ON_COMMAND(IDM_HELLO/*ID號*/,OnHello/*命令響應函數*/)   //注意!不要加任何的標點符號
      END_MESSAGE_MAP()
    step3:命令響應函數的實現
             //MainFrm.cpp
             void CMainFrame::OnHello()
             {
          MessageBox("Hello!");
        }

編寫電話本程序

注:菜單欄是屬於框架窗口的,在view類中調用GetMenu()是無法獲得指向菜單的指針的,因爲view窗口根本
    沒有菜單
   
對菜單欄進行重繪
    CWnd::DrawMenuBar
     void DrawMenuBar()
     //Redraw the menu bar .If a menu bar is changed after windows has created the window,
     //cal the function to draw the changed menu bar.
     利用父窗口(框架窗口)調用DrawMenuBar

對窗口進行重繪
    CWnd::Invalidate
    //void Invalidate( BOOL bErase=TRUE)
   
CString的查找功能
    CString::Find
      int Find( TCHAR ch)const;
      int Find( LPCTSTR lpszSub)const;
      int Find( TCHAR ch, int nStart)const;
      int Find( LPCTSTR pstr, int nStart)const;
    Return Value
      返回基於0的第一個匹配的字符(串)索引,如果找不到,返回-1

存儲字符串集合類 CStringArray     
     
CWnd::OnCommand
//virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam) 虛函數
//The framework calls this member function when the user selects an item from a menu,when a
//child control sends a notification message(通告消息),or when an accelerator keystroke is
//translated
//OnCommand 處理消息映射

如何得到框架窗口下的視圖窗口的指針:
CFrameWnd::GetActiveView
   CView* GetActiveView() const;
Return Value
   A point to the current CView.If there is no current view, returns NULL.
   //獲取當前視類的指針


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/huahuamoon/archive/2008/01/02/2010258.aspx


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章