一:设置复选标记 ******* CheckMenuItem()
例如:
动态添加菜单示例
编辑器把我们新添加的几个菜单命令的响应函数都放在注释宏AFX_MSG之间了,
1:按索引
//获得菜单栏->获得子菜单->获得子菜单的菜单项(索引0,按索引并复选)
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);
2:按ID
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);
二、设置默认菜单项(粗体显示) ******** SetDefaultItem()
注意:一个子菜单只能有一个默认菜单项
1:按索引
GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);
2:按ID(参数2有默认值FALSE)
GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN)
三、设置位图标记菜单项 ******** SetMenuItemBitmaps()
注意:若要完整显示位图,图片大小不要超过13*13
//加载位图
m_bitmap1.LoadBitmap(IDB_BITMAP1);
m_bitmap2.LoadBitmap(IDB_BITMAP2);
//按索引(可按ID)设置位图标记菜单项,选中菜单项显示m_bitmap1,否则显示m_bitmap2
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap1,&m_bitmap2);
四、设置菜单项禁用(或可用) ********** EnableMenuItem()
注意:若要使用此函数,需在MainFrame构造函数中设置
m_bAutoMenuEnable=FALSE;
//按索引设置禁用
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
//按ID设置可用
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_ENABLED);
对菜单项的更改还可以通过来消息ON_UPDATE_COMMAND_UI实现
![菜单栏编程 - andylanzhiyong - C++学习 菜单栏编程 - andylanzhiyong - C++学习](http://img1.ph.126.net/RuRvyynBLp8SM8rQFysOYw==/6631889100888547423.jpg)
CMainFrame->Add Windows Message Handle->选中菜单项ID->
->选择UPDATE_COMMAND_UI
![菜单栏编程 - andylanzhiyong - C++学习 菜单栏编程 - andylanzhiyong - C++学习](http://img0.ph.126.net/Cv1uSeexVNStKWQ4V7qeVw==/6632051828609456598.jpg)
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
if(2==pCmdUI->m_nIndex)
//if(ID_EDIT_CUT==pCmdUI->m_nID)
pCmdUI->Enable();
//设置可用
}
************************************************************************
注意:工具栏上的按钮ID一般与对应菜单项的ID一致,
更改菜单项禁用(可用)时,若按ID禁用,则工具栏跟着改为禁用
若按索引禁用,对应的工具栏按钮索引可能与菜单项索引不一致,则不跟着改变
*****************************************************************************************
void CMainFrame::OnUpdateFileNew(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
//
if(ID_FILE_NEW==pCmdUI->m_nID)
if(0==pCmdUI->m_nIndex)
pCmdUI->Enable(FALSE);
//设置禁用
}
五:移除整个菜单*******SetMenu(NULL)
六:加载菜单资源
CMenu menu;
//创建菜单
menu.LoadMenu(IDR_MAINFRAME);
//加载菜单
SetMenu(&menu);
//设置为本窗口的菜单
//将局部的菜单对象与句柄断开联系
//menu设置为static或Frame的成员变量时,不需调用此函数
menu.Detach();
右键菜单编程
在资源编辑器中创建一个菜单资源:如图
![菜单栏编程 - andylanzhiyong - C++学习 菜单栏编程 - andylanzhiyong - C++学习](http://img0.ph.126.net/srlXvG2xgrzu3ZgdZWsDQQ==/6632572997118352095.jpg)
顶级菜单不显示,文本随便写。pop_up属性要选中
设置菜单项ID及文本
添加鼠标右键按下响应函数:
void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CMenu menu;
menu.LoadMenu(IDR_MENU1);
//加载快捷菜单
CMenu *pPopup=menu.GetSubMenu(0);
//获得给菜单
ClientToScreen(&point);
//客户坐标转换为屏幕坐标
//显示右键菜单
//参数1:显示样式:鼠标左对齐(菜单在鼠标右边)。多种可选
//参数2、3:右键菜单左上角坐标
//参数4:父窗口
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x, point.y,this);
CView::OnRButtonDown(nFlags, point);
}
CMenu menu;
menu.CreatePopupMenu();
//创建一个弹出式子菜单
//获得系统菜单后,在菜单栏最后添加一个弹出式子菜单
GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
//插入一个弹出式子菜单
GetMenu()->InsertMenu(2,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
//弹出式子菜单添加菜单项,(
IDM_HELLO,112,113为各菜单项ID)
//menu.AppendMenu(MF_STRING,111,"Hello");
//可在Resourse.h中为ID"111"创建一个资源ID"IDM_HELLO"
//eg: #define IDM_HELLO 111
menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello");
menu.AppendMenu(MF_STRING,112,"Weixin");
menu.AppendMenu(MF_STRING,113,"Mybole");
menu.Detach();
//断开联系
//系统菜单第一个子菜单末尾添加一个菜单项
GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");
//系统菜单第一个子菜单插入一个菜单项
GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
MF_BYCOMMAND | MF_STRING,115,"维新");
//删除系统菜单第2个子菜单
GetMenu()->DeleteMenu(1,MF_BYPOSITION);
//删除系统菜单第一个子菜单第三个菜单项
GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);
若要为ID为IDM_HELLO的菜单项添加消息响应函数
由于它在资源视图不可见,用ClassWizad实现不了
只能手动添加(可模仿,用
ClassWizad
添加一个类似的再删除掉)
第一步:在CMainFrame头文件中声明命令响应函数原型
例如:(红色代码部分)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
afx_msg void OnHello();
DECLARE_MESSAGE_MAP()
第二步:在CMainFrame源文件中添加消息映射
例如:(红色代码部分,注意格式)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_COMMAND(IDM_HELLO,OnHello)
END_MESSAGE_MAP()
第三步:在CMainFrame源文件中定义该响应函数
例如:
void CMainFrame::OnHello()
{
MessageBox("Hello!");
}
下面做一个电话本示例:
在View中输入名字+空格+号码,第一次按回车后添加一个子菜单,
并在子菜单添加一个菜单项,菜单项文本为刚输入的名字。
以后再输入名字+空格+号码按回车后,继续增加菜单项。
添加完后点击菜单项按钮时,在View输出对应的名字和号码
首先在View中定义几个变量:
public:
//设置公有
CStringArray m_strArray;
//用户电话号码集合
private:
CString m_strLine;
//保存用户输入字符
CMenu m_menu;
//创建的菜单
int m_nIndex;
//第几次按回车键
添加OnChar()响应函数
void CMenu2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if(0x0d==nChar)
//如果按下回车键
{
if(0==++m_nIndex)
//如果第一次按下回车键
{
m_menu.CreatePopupMenu();
//创建弹出式子菜单
//子菜单添加到系统菜单项末尾
GetParent()->GetMenu()->AppendMenu(MF_POPUP,
(UINT)m_menu.m_hMenu,"PhoneBook");
//重画菜单栏
GetParent()->DrawMenuBar();
}
//为新添加子菜单添加菜单项,文本为姓名
//m_strLine.Find(' ')查找第一个空格的索引
//m_strLine.Left(m_strLine.Find(' ')) 取出空格左边的字符
//IDM_PHONE1+m_nIndex 菜单项动态增长
m_menu.AppendMenu(MF_STRING,IDM_PHONE1+m_nIndex,m_strLine.Left(m_strLine.Find(' ')));
//把输入姓名电话添加到集合中
m_strArray.Add(m_strLine);
//按回车清空之前输入字符串
m_strLine.Empty();
//擦除背景
Invalidate();
}
else
{
m_strLine+=nChar;
//输入字符增长
dc.TextOut(0,0,m_strLine);
}
CView::OnChar(nChar, nRepCnt, nFlags);
}
接下来添加菜单项响应函数
![菜单栏编程 - andylanzhiyong - C++学习 菜单栏编程 - andylanzhiyong - C++学习](http://img0.ph.126.net/BWy6GYaZrQ13QC_DYp641A==/6632128794423402243.jpg)
![菜单栏编程 - andylanzhiyong - C++学习 菜单栏编程 - andylanzhiyong - C++学习](http://img2.ph.126.net/skcisAWRatTj6BkWD_GgDg==/6632177172935025302.jpg)
把它们拿出来放在释宏AFX_MSG之后,以区分自添加。如:(红色部分已挪出来)
//{{AFX_MSG(CMenu2View)
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
afx_msg void OnPhone1();
afx_msg void OnPhone2();
afx_msg void OnPhone3();
afx_msg void OnPhone4();
同样,消息映射也放到注释宏之后。必须拿出来。
BEGIN_MESSAGE_MAP(CMenu2View, CView)
//{{AFX_MSG_MAP(CMenu2View)
ON_WM_CHAR()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(IDM_PHONE1, OnPhone1)
ON_COMMAND(IDM_PHONE2, OnPhone2)
ON_COMMAND(IDM_PHONE3, OnPhone3)
ON_COMMAND(IDM_PHONE4, OnPhone4)
END_MESSAGE_MAP()
经过以上几步,View类就有了几个菜单项的命令响应函数
void CMenu2View::OnPhone1()
{
// TODO: Add your command handler code here
CClientDC dc(this);
dc.TextOut(0,0,m_strArray.GetAt(0));
}
void CMenu2View::OnPhone2()
{
// TODO: Add your command handler code here
CClientDC dc(this);
dc.TextOut(0,0,m_strArray.GetAt(1));
}
void CMenu2View::OnPhone3()
{
// TODO: Add your command handler code here
CClientDC dc(this);
dc.TextOut(0,0,m_strArray.GetAt(2));
}
void CMenu2View::OnPhone4()
{
// TODO: Add your command handler code here
CClientDC dc(this);
dc.TextOut(0,0,m_strArray.GetAt(3));
}
以上菜单项单击响应函数由View处理,也可以由CMainFrame的OnCommand()截获处理
用类向导添加CMainFrame的虚函数OnCommand(),重写它
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
//wParam的低字节区保存了命令按钮的ID
int MenuCmdId=LOWORD(wParam);
//
获得当前的View视图
CMenu2View *pView=(CMenu2View*)GetActiveView();
if(MenuCmdId>=IDM_PHONE1 && MenuCmdId<IDM_PHONE1+pView->m_strArray.GetSize())
{
CClientDC dc(pView);
dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdId-IDM_PHONE1));
return TRUE;
}
return CFrameWnd::OnCommand(wParam, lParam);
}