MFC——5.菜單

Lesson5:菜單

 

菜單是用戶交互界面中一個重要的角色,本文主要講解了菜單的使用方法,包括解析MFC的Frame,App,Doc,View類對菜單的響應順序,菜單的基本操作和右鍵彈出菜單。

1.    MFC的類對菜單命令響應順序

在MFC的資源裏面有一個菜單項,可以在這裏添加菜單。菜單設置裏Pop-up類型的菜單成爲彈出式菜單,這種菜單不能響應命令,一般默認頂層菜單都是彈出式菜單,它們會有子菜單,子菜單可以響應命令。當我們添加了菜單按鈕並給了標識IDM_TEST後,在嚮導裏的命令裏選擇與這個ID對應的命令消息,然後編輯代碼。這裏通過產生消息框進行測試。

void CMenuView::OnTest()

{

         //TODO:  在此添加命令處理程序代碼

         AfxMessageBox("ViewClicked!");

}

上面的測試是在View類裏的,那麼對於同一個菜單,當在MFC的Frame,App,Doc,View類裏分別添加函數後,事實上響應的先後順序是View,Doc,Frame,App。我們看看MFC的消息分類。

 

【消息的分類】

標準消息:除WM_COMMAND之外,所有以WM_開頭的消息(窗口重繪的WM_PAINT消息,窗口創建的WM_CREATE,鍵盤按鍵WM_CHAR消息等)。從CWnd派生的類,都可以接收到這類消息。

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

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

從從CWnd派生的類,可以接收標準消息、命令消息、通告消息。從CCmdTarget派生的類,可以接收命令消息、通告消息。

 

菜單命令消息的路由過程】 當點擊菜單項時,框架類首先接收到這個消息,並把消息交給它的子窗口,view類,由視類進行處理。view類首先查看自己是否有成員函數處理此消息,如果能處理,就由調用相應的響應函數來處理,如果沒有,由view類交給doc類處理,doc查找自己能否處理,如果能處理,就由調用相應的響應函數來處理,如果沒有,就交還給view類,view類又交還給frame類。這時frame類查看自己能否處理此消息,如果能則處理,不能則交給應用App程序類來處理。

 

2.    菜單相關操作

對菜單進行修改是在frame框架類窗口的OnCreate函數裏進行的。下面是一系列的菜單操作。

int CMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct)

{

         if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

                   return-1;

 

         if(!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP |CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

                   !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

         {

                   TRACE0("未能創建工具欄\n");

                   return-1;      // 未能創建

         }

         if(!m_wndStatusBar.Create(this))

         {

                   TRACE0("未能創建狀態欄\n");

                   return-1;      // 未能創建

         }

         m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));

 

         //TODO:  如果不需要可停靠工具欄,則刪除這三行

         m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

         EnableDocking(CBRS_ALIGN_ANY);

         DockControlBar(&m_wndToolBar);

 

         /*************1.標記菜單*****************/

       GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);         //逐層次訪問子菜單(文件 0)的菜單項(新建 0)

         //GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);  //以命令ID訪問

 

 

         /****************        2.創建默認菜單*******************/

         //對於一個菜單的默認菜單,只能有一個,當設置多個的時候就只有一個生效

         GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);    //設置默認的菜單項(表現爲加粗)。第一個參數是依賴於第二個參數,如果第二個參數是false,第一個參數用命令的ID,如果第二個參數是true,則第一個參數是位置索引,分割欄也佔一個索引

         //GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,FALSE);   //其中,false是默認的,可以不寫

         //GetMenu()->GetSubMenu(0)->SetDefaultItem(5,TRUE);    //設置默認的菜單項時,如果用索引號,注意分欄也佔一個號

        

         /*******************3.創建圖形標記菜單************/

         CStringstr;      //以下三行是爲了獲得系統圖標的大小,然後調整圖標大小,使圖標顯示適當

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

         MessageBox(str);          //標記的大小  

        //CBitmap m_bitmap 作爲一個成員函數,寫在成員變量裏,不在這

         m_bitmap.LoadBitmap(IDB_BITMAP1);              //下載一副自己製作的位圖

         GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION, &m_bitmap, &m_bitmap);   //將位圖設置在菜單項前

 

         /**********************4.禁用菜單******************/

         GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED|MY_GRAYED);       //(不能用時自動變灰)在設置同時,需要在frame的構造函數中m_bAutoMenuEnable = FALSE;

 

         /*以下是移除一個菜單後加載一個菜單*/

         //SetMenu(NULL);                    //當參數爲NULL時,菜單被移除

 

         //CMenumenu;                          //定義一個菜單,如果用一個局部變量menu,可以用SetMenu設置菜單,但後面用要menu.Detach

         //menu.LoadMenuA(IDR_MAINFRAME);            //加載一個菜單

         //SetMenu(&menu);                                                //設置一個菜單   調用setmenu後一定要緊接着用菜單對象的detach將菜單句柄與菜單對象分開

         //menu.Detach();                     //將菜單句柄和c++對象斷開,防止窗口重繪時候發生錯誤,menu對象析構時不會銷燬菜單

         return0;

}

 

3.    右鍵彈出菜單

在資源中增加一個menu,並對菜單的每一個子菜單設置caption 和ID號。

增加鼠標右鍵點擊的消息響應OnRButtonDown。

對子菜單編寫命令處理函數,。

void CMenuView::OnRButtonDown(UINT nFlags,CPoint point)

{

         //TODO:  在此添加消息處理程序代碼和/或調用默認值

         CMenumenu;                                //定義一個菜單 

         menu.LoadMenu(IDR_MENU1);                  //加載一個菜單資源

         CMenu*pPopup = menu.GetSubMenu(0);        //獲取一個子菜單

         ClientToScreen(&point);                    //將客戶區座標轉換爲屏幕座標

 

         pPopup->TrackPopupMenu(TPM_LEFTALIGN| TPM_RIGHTBUTTON, point.x, point.y, this);     //顯示菜單

         //TrackPopupMenu第一個參數表示菜單顯示的位置,第二三參數表示鼠標點擊的位置,第四個表示菜單的擁有者,第五個是默認的,指示了一個區域,當點擊區域外面時,菜單無效

         //當地四個選項說明擁有者後,菜單的子菜單的擁有者也是它

          CView::OnRButtonDown(nFlags,point);

}

  

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