MFC 菜單編程 -- 總結

菜單結構

  1. 一個菜單欄可以有若干個子菜單,而一個子菜單又可有若干個菜單項。
    對於菜單欄的子菜單,由左至右從0開始索引。
    對於特定的子菜單的菜單項,由上至下建立從0開始的索引。
    訪問子菜單和菜單項,均可通過其索引或標識進行。
  2. 對於在窗口客戶區右鍵彈出的菜單,如果彈出菜單歸屬View 類窗口,則菜單項只能響應View 和Doc 類消息點擊。
  3. 如果彈出菜單歸屬框架窗口,彈出菜單上的消息的路由遵循View -DOC-MainFrame-APP的響應順序 。

 

菜單的相關重要函數

  1. CMenu*    GetMenu( ) ;                  // 得到菜單指針
  2. CMenu*    GetSubMenu( ) ;           // 得到子菜單指針,也就是彈出菜單指針
  3. UINT CheckMenuItem( );              // 將菜單項加上或去掉√(對號)標記
    a.如果第一個參數是ID號,    第二個參數必須是MF_BYCOMMAND | MF_CHECKED的組合
    b.如果第一個參數是索引號, 第二個參數必須是MF_BYPOSITION   | MF_CHECKED的組合
  4. BOOL SetDefaultItem();                // 設置缺省菜單,也就是將菜單項粗體顯示
    a.如果第一個參數是索引號,第二個參數必須是true
    b.如果第一個參數是ID號,第二個參數必須是false
    *注 :一個子菜單最多只能有一個缺省菜單項
  5. BOOL SetMenuItemBitmaps( );      // 設置位圖標記,標記大小爲13*13像素
    a.如果第一個參數是ID號,第二個參數必須是MF_BYCOMMAND
    b.如果第一個參數是索引號,第二個參數必須是MF_BYPOSITION
    ,第三個參數是沒有選中時的位圖,第四個參數是標記時的位圖
  6. UINT EnableMenuItem();                //使菜單項有效,無效,或變灰
    a.如果第一個參數是ID號,第二個參數必須是MF_BYCOMMAND 和有效,無效,或變灰 的組合
    b.如果第一個參數是索引號,第二個參數必須是MF_BYPOSITION 和有效,無效,或變灰 的組合
    *注 :若讓此函數生效,必須在mainfrm構造函數中添加:m_bAutoMenuEnable =false,
    此時,其他變灰的菜單項也就恢復爲不變灰狀態了,會有副作用的
  7. BOOL SetMenu( CMenu* pMenu );  //在當前窗口上設置新菜單或移除菜單。
    如果參數爲0,則是移除菜單。
    自己創建菜單{CMenu menu;menu.LoadMenu(IDR_MENU1);
    SetMenu(&menu);menu.Detach();}
  8. HMENU Detach( );  // 如果將CMenu 對象設置爲局部對象,使用Detach()從menu對象中分離窗口菜單句柄,從而當menu對象析構的時候窗口菜單資源不隨之銷燬

 

菜單的相關操作的實現方法

a.添加對號標記:
方法一:   GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED );                          //通過索引
方法二:   GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED );     //通過ID

 

b.設置缺省菜單項:

每個子菜單最多只能有一個缺省菜單項
方法一: GetMenu()->GetSubMenu(0)->SetDefaultItem(1,true);                             //通過索引
方法二: GetMenu( )->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,false);     //通過ID

 

c.添加圖形標記:
方法一:通過ID
CBitmap bitmap;       //必須設置爲全局對象
bitmap.LoadBitmap(IDB_BITMAP1);
GetMenu( )->GetSubMenu(0)->SetMenuItemBitmaps(ID_FILE_NEW,MF_BYCOMMAND,&bitmap,&bitmap);

方法二:通過索引
CBitmap bitmap;       //必須設置爲全局對象
bitmap.LoadBitmap(IDB_BITMAP1);
GetMenu( )->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION ,&bitmap,&bitmap);


d.使菜單無效,變灰

//必須在構造函數中添加:   m_bAutoMenuEnable = false;
GetMenu( )->GetSubMenu(0)->EnableMenuItem(ID_FILE_OPEN,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);

 

e.移除菜單
SetMenu(0);

 

f.添加菜單
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
menu.Detach();

 

圖形標記大小

系統獲得位圖標記的大小:
CString str;
str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK));
MessageBox(str);

命令更新機制

菜單的UPDATE_COMMAND_UI消息響應

{
     pCmdUI->Enable(false);       // true和false 來設置能否使用或變灰
     pCmdUI->SetCheck(true);   // true和false 來設置標記
     pCmdUI->SetText(“cut”);    //改變菜單項文本內容

}

 

 

動態創建菜單

先定義幾個常量:
#define IDM_MENU0 0
#define IDM_MENU1 1
#define IDM_MENU2 2
#define IDM_MENU3 3
#define IDM_ITEM0 10
#define IDM_ITEM1 11
#define IDM_ITEM2 12
#define IDM_ITEM3 13
#define IDM_ITEM4 14
#define IDM_ITEM5 15
#define IDM_ITEM6 16

 

// 在最後一個菜單項後面添加菜單項
BOOL AppendMenu ( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
BOOL AppendMenu ( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

// 插入菜單項
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

// 移除菜單項
BOOL RemoveMenu( UINT nPosition, UINT nFlags );

// 刪除菜單項
BOOL DeleteMenu( UINT nPosition, UINT nFlags );

一 、創建非Popup類型菜單,不使用資源。
(一)創建非下拉菜單。
1。在窗口類的OnCreate函數裏創建CMenu對象。如果是創建運用程序主框架窗口
的話,也可以在InitInstance()函數裏。
2。聲明一個CMenu對象:CMenu MyMenu;
3。調用MyMenu.CreateMenu()或MyMenu.LoadMenu()
4。調用若干次MyMenu.AppendMenu()或MyMenu.InsertMenu(),每調用一次創建一
個菜單項。
5。調用MyMneu.SetMenu()將菜單Attach到窗口上。
6。調用MyMenu.Detach()。

例子:
int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
     CMenu MyMenu;
     MyMenu.CreateMenu();
     MyMenu.AppendMenu(MF_STRING,IDM_MENU0,"文件");
     MyMenu.AppendMenu(MF_STRING,IDM_MENU1,"編輯");
     MyMenu.AppendMenu(MF_STRING,IDM_MENU2,"查看");
     MyMenu.AppendMenu(MF_STRING,IDM_MENU3,"幫助");
     MyMenu.InsertMenu(IDM_MENU2,MF_BYCOMMAND,IDM_ITEM0,"有關");
     this->SetMenu(&MyMenu);
     MyMenu.Detach();
     return 0;
}//各個函數的細節就不講解了,看聯機幫助是最好的。
這個方法是先把菜單創建好後再貼到窗口上去,然後用Detach()使菜單和MyMenu對象脫離關係,因爲MyMenu對象馬上就要超出作用域了,這一步是必須的。


(二)創建下拉菜單,不使用資源。
    這種菜單當鼠標移動到菜單條目上面點擊時不是去執行某段程序,而是彈出
一個下拉菜單。這需要用前面的方法創建兩個菜單。第一個是鼠標未點擊時看到
的那個菜單,另一個就是扮演下拉菜單的菜單。例子:
int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
        CMenu MyMenu0,MyMenu1;
        //下面這幾條創建下拉菜單
        MyMenu1.CreateMenu();
        MyMenu1.AppendMenu(MF_STRING,IDM_ITEM0,"拷貝");
        MyMenu1.AppendMenu(MF_STRING,IDM_ITEM1,"剪切");
        MyMenu1.AppendMenu(MF_STRING,IDM_ITEM2,"粘貼");
        MyMenu1.AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
        MyMenu1.AppendMenu(MF_STRING,IDM_ITEM4,"全選");
        MyMenu1.AppendMenu(MF_SEPARATOR,IDM_ITEM5,"");
        MyMenu1.AppendMenu(MF_STRING,IDM_ITEM6,"刪除");
        //下面這兩條創建鼠標未點擊時看到的那個菜單
        //其中第二句將下拉菜單張貼到第一個菜單上。
        MyMenu0.CreateMenu();
        MyMenu0.AppendMenu(MF_POPUP,(UINT)MyMenu1.m_hMenu,"編輯");

        this->SetMenu(&MyMenu0);//將菜單張貼到窗口上
        MyMenu0.Detach();//必須有
        MyMenu1.Detach();//必須有
        return 0;
}

二、創建Popup類型的菜單,也不用資源。
    很多程序裏,只要用鼠標右鍵點一下窗口客戶區,就會在鼠標的位置彈出一
個菜單,這叫右鍵菜單。我們可以用CMenu類來製作。
    製作這種菜單比製作第一類菜單稍微複雜點。首先要在窗口類里加個成員變
量:CMenu *MyMenu2;
    然後在窗口類的構造函數裏(或OnCreate()函數裏)加上創建菜單的語句,再
在析構函數里加上銷燬菜單的語句,最後在OnRButtonDown()函數里加上顯示菜單
的語句。
    創建菜單時,CMenu類對象應該用new來分配。
    例子:

CMyWnd::CMyWnd()
{
     //CMyWnd是從CWnd派生來的。
     //先把菜單創建起來。
     MyMenu2=new CMenu;
     MyMenu2->CreatePopupMenu();
     MyMenu2->AppendMenu(MF_STRING,IDM_ITEM0,"拷貝");
     MyMenu2->AppendMenu(MF_STRING,IDM_ITEM1,"剪切");
     MyMenu2->AppendMenu(MF_STRING,IDM_ITEM2,"粘貼");
MyMenu2->AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
     MyMenu2->AppendMenu(MF_STRING,IDM_ITEM4,"全選");
     MyMenu2->AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
     MyMenu2->AppendMenu(MF_STRING,IDM_ITEM5,"刪除");

}
CMyWnd::~CMyWnd()
{
     MyMenu2->DestroyMenu();//銷燬菜單所佔用的系統資源
     delete MyMenu2;//銷燬菜單類對象
}
void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point)
{
     RECT rect;
     GetWindowRect(&rect);
     //顯示菜單
     MyMenu2->TrackPopupMenu(TPM_RIGHTALIGN,point.x+rect.left,point.y+
rect.top,this,NULL);
}

 

 

 

 

 

 

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