CMenu類從CObject類派生而來。為什么要使用CMenu類呢?AppWzard不是把菜單做好了嗎?在資源編輯器上修改菜單不是很方便嗎?我是個vc++初學者,自從當斑竹以來,天天看貼子,也學到了不少東西。感覺學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);
}
三。使用資源編輯器做好的菜單,只能做非POPUP類型菜單。
如果使用資源的話,創建菜單確實非常簡單了,只須在窗口類的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;
}