菜单栏编程

一:设置复选标记 *******   CheckMenuItem()
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++学习


CMainFrame->Add Windows Message Handle->选中菜单项ID->
->选择UPDATE_COMMAND_UI
 
菜单栏编程 - andylanzhiyong - C++学习
例如:
 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++学习
顶级菜单不显示,文本随便写。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++学习

 编辑器把我们新添加的几个菜单命令的响应函数都放在注释宏AFX_MSG之间了,
把它们拿出来放在释宏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);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值