关于菜单的学习(VS2010)
来源:互联网 发布:重庆警方破获网络诈骗 编辑:程序博客网 时间:2024/06/13 21:47
1、菜单消息的分类
菜单消息一般分3类:
1.1标准消息
除WM_COMMAND之外,所有以WM_开头的消息都是标准消息。从CWnd派生的类,都可以接收这类消息。
1.2命令消息
都是来自菜单、加速键或工具栏按钮的消息,这类消息以WM_COMMAND形式呈现。在MFC中通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wPara参数识别。从CCmdTarget派生的类,都可以接收到这类额消息。
1.3通告消息
是由控件产生的消息,例如按钮的单机、列表框中选项的选择都会产生这类消息,目的是向父窗口(通常是对话框)通知事件的发生。这类消息会以WM_COMMAND形式呈现。从CCmdTarget派生的类,都会接收这类的消息。
2、菜单添加响应
2.1操作
资源视图中打开菜单,在需要添加的菜单项右击属性将Popup改为false,邮件添加响应函数,选择响应的类即可,编辑响应函数;
2.2菜单消息响应顺序
4个类的消息响应优先次序分别是:1.View;2.CDOC;3.CMainFrame.4.CWinAPP.
3、创建标记菜单
在CMainFrame::OnCreate函数下:
GetMenu(); CWnd的成员函数,返回整个菜单栏的指针。
GetMenu()->GetSubMenu(0); 获取子菜单,参数为子菜单索引,从0开始
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED); /通过位置索引设置标记
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED); //通过菜单项的ID进行索引设置标记
<注意>
在VS2010中,由于CMainFrame继承至CFrameWndEx会导致无法像VC6.0一样使用GetMenu()等函数,所以这时在建立工程的时候就应该选择为:第一步:项目标准: MFC标准视觉样式和颜色:windows 本机/默认第五步:命令栏:使用经典菜单这样就和VC6.0中的菜单一样了
4、创建缺省菜单项
CMenu::SetDefaultItem(UINT ,BOOL); //bool为false则UINT为ID表示,true为地址索引表示。
GetMenu()->GetSubMenu(0)->SetDefaultItem(1,true);将文件-打开设置为缺省项。
<注意>
确定菜单的索引号,注意从0开始,分隔符也算数。
一个子菜单只能有一个缺省菜单。
5、创建图形标记菜单
CMenu::SetMenuItemBitmaps(UINT nposition, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked);
nFlags: MF_BYPOSITION 和MF_BYCOMMAND位置索引和ID索引。
pBmpUnchecked: 没有选中时的位图
pBmpChecked: 选中时的位图
<具体操作>
先通过GetSystemMetrics()函数获取菜单图标大小,按这个大小制作位图:
CString str;
str.Format(_T("x=%d,y=%d"),GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK));
MessageBox(str); //显示出来宽高,13*13的,然后制作13*13的位图
然后CMainFrame中添加成员变量:m_bitmap
m_bitmap.LoadBitmapW (IDB_BITMAP1);
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);
6、屏蔽菜单项
CMenu::EnableMenuItem(UINT nIDEnableItem, UINT nEnable);
<具体操作>
在CMainFrame构造函数中设置m_bAutoMenuEnable=false;从而EnableMenuItem可以起作用,然后在OnCreate函数中:
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED|MF_GRAYED); //屏蔽打开菜单项并使其变灰
7、取消菜单
CMenu::SetMenu(CMenu* pMenu); //pMenu为NULL时为当前菜单被移走
取消并重新加载菜单,可用于更换菜单
SetMenu(NULL); //取消当前菜单
CMenu menu; //定义成成员变量,或紧接着Detach函数
menu.LoadMenuW(IDR_MAINFRAME); //重新加载菜单
SetMenu(&menu);
menu.Detach();
8、命令更新
在CMainFrame构造函数中取消设置m_bAutoMenuEnable=false;选择采用命令更新机制。可以看到编辑子菜单下的撤销、剪切、复制、粘贴等菜单项都不能使用了。
添加时间处理函数,其中消息类型选择UPDATE_COMMAND_UI,创建相应函数:
void CMainFrame::OnUpdateEditCut(CCmdUI *pCmdUI)
该函数传递了一个CCmdUI类的指针。在该相应函数中:
pCmdUI->Enable(); //这样剪切键就可以使用了, Enable的默认参数为true
pCmdUI->Enable(FALSE); //使菜单项无法使用
在执行Enable函数之前可以先进行判断,判断pCmdUI是否指向当前菜单项:
if(2==pCmdUI->m_nIndex) //通过地址判断,这是菜单项的剪切可用,工具栏中剪切依然不可用
pCmdUI->Enable();
或通过ID号索引:
if(ID_Edit_Cut==pCmdUI->m_nID) //通过ID号索引,菜单项和工具栏中的都可用
pCmdUI->Enable();
9、增加PopupMenu菜单
Project->Add to Project->component and controls在vs2010中找不到,手动创建。
<具体操作>
资源中新建一个菜单
CMenuView类中添加右键响应函数OnRButtonDown
CMenu menu;
menu.LoadMenu(IDR_Popup);
CMenu *pPopup=menu.GetSubMenu(0); //获取子菜单,只有一个子菜单
ClientToScreen(&point);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,this); //point是屏幕坐标,要先ClientToScreen将客户区坐标转换为屏幕坐标
由于TrackPopupMenu调用的是this指针,因此弹出菜单中的菜单项的响应只能由view执行,框架类不能响应,为了使框架类也能指向响应操作,需将this换为其父窗口的指针GetParent()。
10、动态添加菜单
<函数的使用>
10.1 函数原型:
BOOL AppendMenu(hMenu hMenu,UINT uFlags,UINT uIDNewltem,LPCTSTR lpNewltem);
将被修改的菜单条、下拉式菜单、子菜单、或快捷菜单的句柄。
控制新菜单项的外观和性能的标志。此参数可以是备注里所列值的组合。
指定新菜单项的标识符,或者当uFlags设置为MF_POPUP时,表示下拉式菜单或子菜单的句柄。
指定新菜单项的内容。此参数的含义取决于参数uFlags是否包含MF_BITMAP, MF_OWNERDRAW或MF_STRING标志,如下所示:
含有位图句柄。MF_STRING:以`\O’结束的字符串的指针。
含有被应用程序应用的32位值,可以保留与菜单项有关的附加数据。当菜单被创建或其外观被修改时,此值在消息WM_MEASURE或WM_DRAWITEM的参数IParam指向的 结构,成员itemData里。
返回值:如果函数调用成功,返回非零值;如果函数调用失败,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。
<备注>
一旦菜单被修改,无论它是否在显示窗口里,应用程序必须调用函数DrawMenuBar。
为了使键盘加速键能控制位留或自己绘制的菜单项,菜单的拥有者必须处理WM_MENUCHAR消息。
参见自绘制菜单和WM_MENUCHAR消息。
10.2函数原型:
HMENU CreatePopupMenu(VOID)
<函数功能>
该函数创建一个下拉式菜单、子菜单或快捷菜单。此菜单最初是空的,但可用函数InsertMenultem来插入或追加菜单项。也可用函数InsertMenu来插人菜单项,用AppendMenu来追加菜单项。
参数:无。
返回值:如果函数调用成功,返回值是新创建菜单的句柄。如果函数调用失败,返回值是NULL。若想获得更多的错误信息,请调用GetLastError函数。
10.3函数原型
BOOL InsertMenu(HMENU hMenu,UINt uPosition,UINT uFlags,UINT uIDNewltem,LPCTSTR lpNewltem)
<具体操作>
CMenu menu;
menu.CreatePopupMenu();
// GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,_T("WinSun")); //增加菜单,在最后
GetMenu()->InsertMenu(2,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu, _T("WinSun")); //插入菜单
menu.AppendMenu(MF_STRING,111,_T("Hello")); //插入菜单项
menu.AppendMenu(MF_STRING,112,_T("Weixin"));
menu.AppendMenu(MF_STRING,113,_T("Mybole"));
menu.Detach();
GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome"); //在文件子菜单下加菜单项
GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
MF_BYCOMMAND | MF_STRING,115, "维新"); //在新建和打开之间插入菜单项
// GetMenu()->DeleteMenu(1,MF_BYPOSITION); //删除菜单
// GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION); //删除打开菜单项
11、 为动态创建的菜单增加消息响应的步骤
a.在resource.h中增加#define IDM_HELLO 123
b.在MainFrm.h中加入afx_msg void OnHello();
c.MainFrm.cpp中加入ON_COMMAND(IDM_HELLO,OnHello)
d.最后加入
void CMainFrame::OnHello()
{
MessageBox("Hello!");
}
12、动态增加电话号码本步骤
12.1 view类中处理WM_Char消息。
void CMenu2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(0x0d==nChar) //回车
{
if(0==++m_nIndex) //如果第一次按回车,则创建菜单
{
m_menu.CreatePopupMenu ();
GetParent()->GetMenu()->AppendMenuW(MF_POPUP, (UINT)m_menu.m_hMenu, _T("PhoneBook"));
//菜单属于框架类所以要GetParent()->GetMenu()来获取
GetParent()->DrawMenuBar();
//重绘菜单,否则不显示,又因为菜单属于框架类所以要GetParent()->
}
m_menu.AppendMenuW (MF_STRING, IDM_PHONE1+m_nIndex, m_strLine.Left (m_strLine.Find (' '))); //以字符串空格前的字符为名创建菜单项
m_strArray.Add (m_strLine); //m_strArray为CstringArray类型的成员变量,存储CString
m_strLine.Empty (); //清空字符串
Invalidate(); //窗口背景被擦除
}
else
{
m_strLine+=char(nChar);
dc.TextOut(0,0,m_strLine);
}
CView::OnChar(nChar, nRepCnt, nFlags);
}
12.2 添加菜单项的消息处理函数
Menu2View.h 中加入:
afx_msg void OnPhone1();
afx_msg void OnPhone2();
afx_msg void OnPhone3();
Menu2View.cpp中加入:
ON_COMMAND(IDM_PHONE1, &CMenu2View::OnPhone1)
ON_COMMAND(IDM_PHONE2, &CMenu2View::OnPhone2)
ON_COMMAND(IDM_PHONE3, &CMenu2View::OnPhone3)
void CMenu2View::OnPhone1()
{
CClientDC dc(this);
dc.TextOutW (0,0,m_strArray.GetAt (0)); //取出m_strArray中数据
}
12、在CMainFrame类中截获消息处理函数
CMainFrame中增加虚函数:
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和或调用基类
int MenuCmdId=LOWORD(wParam);
CMenu2View *pView=(CMenu2View*)GetActiveView();
// GetActiveView()为CMainFrame类的成员函数,获取view类指针
if(MenuCmdId>=IDM_PHONE1&&MenuCmdId<IDM_PHONE1+pView->m_strArray.GetSize())
{
//MessageBox(_T("test"));
CClientDC dc(pView); //用View类指针创建dc
dc.TextOutW (0,0,pView->m_strArray .GetAt (MenuCmdId-IDM_PHONE1));
return true;
}
return CFrameWnd::OnCommand(wParam, lParam);
}
注意要增加两个头文件:
#include "Menu2Doc.h"
#include "Menu2View.h"
可学习看“WM_COMMAND消息路由”。
- 关于菜单的学习(VS2010)
- 关于VS2010 MFC菜单替换的问题??
- VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)
- VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)
- VS2010关于C#代码混淆和程序打包的学习
- 如何用VS2010学习孙鑫视频的第6课菜单
- VS2010 菜单字体模糊的解决方案
- 基于VS2010的MFC动态菜单
- VS2010中没有Virtualddk菜单的解决办法
- VS2010中右键菜单的添加
- VS2010的MFC动态创建菜单
- 基于VS2010的MFC动态菜单
- Qt学习(八) 关于托盘菜单不消失的问题
- 小菜学习日记—关于下拉导航菜单闪烁(hover、mouseover 与 mouseenter的区别)
- 关于菜单的api
- MFC(VS2010)对话框菜单添加及菜单响应
- 关于vs2010 内存不足的问题
- 关于VS2010 的command arguments
- inline-block的几个问题(还没解决)
- Unity_混合树实现三种动画的混合_070
- MyBatis (一)基本步骤
- package-cleanup
- Algorithms 练习1.1.15
- 关于菜单的学习(VS2010)
- scikit-learn实现线性回归之Lassolars模型
- RQNOJ 169 最小乘车费用
- java每日一练
- Java上传Excel文件导入数据
- 单片机处理用串口接收频次较高的数据方式
- Linux中常用Makefile隐含规则
- CentOS命令行使用shadowsocks代理的方法
- webgl学习笔记一-绘图单点