複製鏈接
請複製以下鏈接發送給好友

CMenu

鎖定
CMenu,是一個計算機用語。用於創建系統菜單。
中文名
CMenu
屬    性
計算機用語

目錄

CMenu定義

用資源編輯器創建菜單
用資源編輯器創建菜單(5張)
對於系統菜單,創建起來比較簡單,直接使用資源編輯器就能生成菜單,再通過ClassWizard創建菜單命令函數。在我的資源中上傳了一個工程,實現了一個右鍵彈出貼圖菜單。結合這個工程,介紹動態創建菜單、創建彈出式菜單和重繪菜單。
首先介紹基礎知識:

CMenu成員函數

1. CreateMenu()和CreatePopupMenu(),這兩個函數用來創建一個菜單實例,CreateMenu()創建的是普通的菜單實例,如果想創建彈出式菜單,就要用CreatePopupMenu()函數。
2. AppendMenu()向菜單中添加一個子項,這個函數有兩個主要的參數。第一個UINT nFlags,這個參數表明了該子項的屬性特徵,可以這樣説,這個參數規定了菜單的樣式和功能。後面會詳細講這個參數所能使用的值。第二個參數UINT_PTR nIDNewItem,根據nFlags使用不同的設置,該參數將標明菜單的資源ID或在這個菜單中的索引號。第三個參數可以省略,如果不省略,可以傳入一個字符串,這個字符串將顯示在菜單中(因為我準備用突破錶示菜單項,所以我的工程中省略了這個參數)。
3. DrawItem(),這是一個虛函數,如果菜單設置成可以自繪類型,則這個函數將在生成菜單、彈出菜單、選中菜單、點擊菜單等時由系統框架調用。因此,這個函數是一個很有用的函數,它可以幫你繪製出各種樣式的菜單。
4. MeasureItem()也是一個虛函數,當菜單被創建的時候由系統框架調用。這個函數用來設置菜單的大小。

CMenu説明

只有當nFlags設置成MF_OWNERDRAW的時候,系統框架才會重繪菜單。
MF_CHECKED:命令旁顯示默認複選標誌
MF_UNCHECKED:清除命令旁的複選標誌
MF_DISABLED:禁止此菜單命令,但是不變灰顯示
MF_ENABLED:允許此菜單命令,恢復到正常狀態
MF_GRAYED:禁止此菜單命令,變灰顯示
MF_MENUBARBREAK:對於靜態菜單,放到新行;對於彈出菜單,放到新欄 中,欄間有分隔線
MF_MENUBREAK:對於靜態菜單,放到新行;對於彈出菜單,放到新欄,欄間無分隔線
MF_OWNERDRAW:指定該命令是自畫式菜單命令
MF_POPUP:指定該菜單命令有一個關聯的彈出式菜單
MF_SEPARATOR:畫一條水平分隔線,只用於彈出式菜單
MF_STRING:指定此菜單命令是一個字符串
CMenu類從CObject類派生而來。為什麼要使用CMenu類呢?AppWzard不是把菜 單做好了嗎?在資源編輯器上修改菜單不是很方便嗎?
感覺學vc++稍微深入一點好,至少要能搞清楚AppWizard在背後都幹了些什麼東西。
事實上mfc就是用CMenu類來生成菜單的。讓我們就從CMenu開始吧。
CMenu生成的菜單有兩種:Popup類型和非Popup類型。這兩種方法裏又可以分
成使用資源編輯器生成的菜單資源和不使用這個資源。對於非Popup類型的菜單,
必須在創建出來後把它張貼到某個窗口上,它才會顯示出來,從而才有用處。Po
pup的菜單卻不能張貼到窗口上。
説明之前,先定義幾個常量:
#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
一。創建非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()使菜單和My
Menu對象脱離關係,因為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);
}三。如果使用資源的話,創建菜單確實非常簡單了,只須在窗口類的OnCreate()
函數里加幾句話就行了:
int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
CMenu MyMenu3;
MyMenu3.LoadMenu(IDR_MENU1);//IDR_MENU1是你的菜單的資源ID。
this->SetMenu(&MyMenu3);
MyMenu3.Detach();
return 0;
}
CMenu類還有很多成員函數,使你可以在運行中對菜單進行裁剪,比如加上幾
項或減去幾項等等,使用非常方便。大家可以去看msdn。
如果要實驗以上的菜單創建方法的話,可以用一個非常簡單的mfc程序來搞:
//這是一個非常簡單的mfc程序,必要的函數自己去加吧。
#include
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
};
class CMyWnd : public CWnd
{
public:
DECLARE_MESSAGE_MAP()
};
CMyApp MyApp;
BEGIN_MESSAGE_MAP(CMyWnd,CWnd)
END_MESSAGE_MAP()
BOOL CMyApp::InitInstance()
{
RECT rect={30,30,400,300};
CMyWnd* pCWindow=new CMyWnd;
pCWindow->CreateEx
(
NULL,
AfxRegisterWndClass(NULL,0,(HBRUSH)::GetStockObject(WHITE_BRU
SH),0),
"實驗程序",
WS_OVERLAPPEDWINDOW,
rect,NULL,NULL,NULL
);
m_pMainWnd = pCWindow;
pCWindow->ShowWindow(m_nCmdShow);
pCWindow->UpdateWindow();
return TRUE;
CMenu類為Windows HMENU的封裝類。它提供了成員函數以用於創建、追蹤、更新及銷燬菜單。
在本地的堆棧框架中創建一個CMenu對象,然後調用CMenu的成員函數來操縱所需的新菜單。接着,調用CWnd::SetMenu函數為窗口設置菜單。然後立即調用CMenu對象的Detach成員函數。CWnd::SetMenu成員函數將窗口的菜單設置為新菜單,這將導致在窗口刷新後將影響菜單的改變,同時也將菜單的擁有者傳遞給窗口。調用Detach函數將把HMENU從CMenu對象中分離出來,以便當本地的CMenu變量超出範圍後,CMenu對象的構造函數將不會銷燬不再擁有的菜單。當窗口銷燬後,菜單自動銷燬。
可以調用LoadMenuIndirect成員函數在內存中創建來自模板的菜單,不過通過調用LoadMenu創建的菜單更容易維護。並且這種菜單資源本身也可以由菜單編輯器創建或修改。
#include <afxwin.h>
CMenu類的成員
數據成員
m_hMenu
指定附加給CMenu對象的窗口菜單的句柄
構造函數
CMenu
構造一個CMenu對象
初始化
Attach
附加一個Windows菜單句柄給CMenu對象
Detach
從CMenu對象中分離Windows菜單的句柄,並返回該句柄
FromHandle
返回一個指向給定Windows菜單句柄的CMenu對象的指針
GetSafeHmenu
返回由CMenu對象包含的m_hMenu值
DeleteTempMap
刪除由FromHandle成員函數創建的所有臨時CMenu對象
CreateMenu
創建一個空菜單,並將其附加給CMenu對象
CreatePopupMenu
創建一個空的彈出菜單,並將其附加給CMenu對象
LoadMenu
從可執行文件中裝載菜單資源,並將其附加給CMenu對象LoadMenuIndirect從內存的菜單模板中裝載菜單,並將其附加給CMenu對象
DestroyMenu
銷燬附加給CMenu對象的菜單,並釋放菜單佔用的內存
菜單操作
DeleteMenu
從菜單中刪除指定的項。如果菜單項與彈出菜單相關聯,那麼將銷燬彈出菜單的句柄,並釋放它佔用的內存
TrackPopupMenu
在指定的位置顯示浮動菜單,並跟蹤彈出菜單的選擇項
菜單項操作
AppendMenu
在該菜單末尾添加新的菜單項
CheckMenuItem
在彈出菜單的菜單項中放置或刪除檢測標記
CheckMenuRadioItem
將單選鈕放置在菜單項之前,或從組中所有的其它菜單項中刪除單選鈕
SetDefaultItem
為指定的菜單設置缺省的菜單項GetDefaultItem獲取指定的菜單缺省的菜單項
EnableMenuItem
使菜單項有效、無效或變灰GetMenuItemCount決定彈出菜單或頂層菜單的項數
GetMenuItemID
獲取位於指定位置菜單項的菜單項標識
GetMenuState
返回指定菜單項的狀態或彈出菜單的項數
GetMenuString
獲取指定菜單項的標籤GetMenuItemInfo獲取有關菜單項的信息
GetSubMenu
獲取指向彈出菜單的指針
InsertMenu
在指定位置插入新菜單項,並順次下移其它菜單項
ModifyMenu
改變指定位置的已存在的菜單項
RemoveMenu
從指定的菜單中刪除與彈出菜單相關聯的菜單項
SetMenuItemBitmaps
將指定檢測標記的位圖與菜單項關聯
GetMenuCountextHelpID
獲取與菜單關聯的幫助文本的ID號
SetMenuCountextHelpID
設置與菜單關聯的幫助文本的ID號
可覆蓋的函數
DrawItem
通過框架來調用,其發生於擁有者菜單的可視部分有所改變
MeasureItem
通過框架來調用,用於決定當創建了擁有者菜單時的菜單維數