孙鑫VC++视频学习笔记(第六课 菜单的工作原理及编写控件)
来源:互联网 发布:单片机仿真器 编辑:程序博客网 时间:2024/06/06 17:33
消息分类
1.标准消息:
除WM_COMMAND之外,所有以 WM_ 开头的消息。
从CWnd派生的类,都可以接收到这类消息
2.命令消息
来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中通过消息的wParam参数识别
从CCmdTarget派生的类,都可以接收到这类消息。
3通告消息
由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是想器父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现
从CCmdTarget派生的类,都可以接收到这类消息
MFC类的结构层次图
菜单的索引是从0开始,子菜单中的菜单项之间的分割符也算一位。
CWnd::GetMenu()
CMenu* GetMenu() const; 获得菜单栏的指针
CMenu::GetSubMenu() 获得一个菜单项的指针
CMenu* GetSubMenu(int nPos) const
CMenu::CheckMenuItem() 在一个菜单项打一个标记
UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck);
当 nCheck=MF_BYCOMMAND
第一个参数代表的是菜单项的ID号(ID_
当 nCheck=MF_BYPOSITION
第一个参数代表的是菜单项的索引号(0,1,2...)
示例程序
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);获得一个子菜单指针,再获取索引号为0的菜单项指针 ,标记索引号为0 (ID号为ID_FILE_NEW)的菜单项
GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);//第二参数缺省值为FALSECMenu::SetMenuItemBitmapsBOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags,//这两个参数与前面的一样 const CBitmap* pBmpUnchecked,//没有选中用这个位图 const CBitmap* pBmpChecked //选中就用这个位图);创建一个图形标识菜单,在资源视图中添加一个位图(IDB_BITMAP)
示例程序
CBitmap m_bitmap;//用建立类向导ClassWizard添加类的成员变量m_bitmap.LoadBitmap(IDB_BITMAP);GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);//当背景色为白色的位图可能看不到效果,位图尺寸太大无法显示完整
可用
CString str;str.Format("x=%d,y=%d",::GetSystemMetrics(SM_CXMENUCHECK),::GetSystemMetrics(SM_CYMENUCHECK);获得缺省的标识位图的尺寸大小(单位:像素)
将禁用某一个菜单项项,使其变灰
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_POSITION | MF_DISABLED | MF_GRAYED);//程序效果无效,结果还是可以打开该菜单项
查看MSDN
// The code fragment below shows how to disable (and gray out) the File\New menu item.//NOTE: m_bAutoMenuEnable is set to FALSE in the constructor of CMainFrame so no ON_UPDATE_COMMAND_UI or ON_COMMAND handlers are needed, and CMenu::EnableMenuItem() will work as expected.
在类的构造函数中可以将m_bAutoMenuEnable=FALSE
加载自己的菜单资源
SetMenu(NULL);CMenu menu;menu.LoadMenu(IDR_MAINFRAME);SetMenu(&menu);menu.Detach();//当menu为类的成员变量时可不用,当为本地变量时要调用,不然会发生错误
命令更新
菜单项状态的维护是依赖与CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。我们通过手工或利用建立类向导ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来不活CN_UPDATE_COMMAND_UI消息。
在后台所做的工作是:操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类CFrameWnd接管。它创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个成员函数DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息指向CCmdUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。
更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用与永久显示的顶级菜单项目
添加右键弹出菜单功能
VC6编辑器
工程-》添加到工程-》Components and Controls Gallery-》Visual C++ Components-》Pop-up Menu
提示增加到哪个类当中,不要选择框架类,框架类接受不到鼠标消息,可以增加到View类当中!
MFC会在我们的工程当中增加一个菜单资源,和View类中添加一个OnContextMenu函数
手动添加
调用TrackPopupMenu
CMenu::TrackPopupMenu
BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = 0);示例代码
利用ClassWizard添加右键鼠标消息
void CMenu1View::OnRButtonDown(UINT nFlags, CPoint point) {// TODO: Add your message handler code here and/or call defaultCMenu menu;menu.LoadMenu(IDR_MENU1);//加载自定义的菜单资源CMenu *pPopup=menu.GetSubMenu(0); //获得菜单项指针ClientToScreen(&point);//转换point坐标,将客户区坐标转换为屏幕坐标pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,GetParent()/*this*/);//如果为this就表示该弹出窗口拥有者为View类,因此只能是View类为我们的弹出菜单中的菜单项进行命令响应//如果想要框架类也能为该弹出猜中的菜单项进行命令响应,可以将最后一个参数this改为GetParent()获得框架类的指针CView::OnRButtonDown(nFlags, point);}动态添加菜单
CMenu::CreatePopupMenu 创建一个空的弹出菜单CMenu::AppendMenu 添加一个新的菜单项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("My"));menu.Detach();GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,_T("WELCOM"));GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,MF_BYCOMMAND | MF_STRING,115,_T("小豆"));//插入GetMenu()->DeleteMenu(1,MF_BYPOSITION);//删除GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);我们可以手动添加对菜单项的响应,一可以通过ClassWizard来添加。
课程实验设计 -------电话本程序
CString m_strLine;
int m_nIndex;
CStringArray m_strArray;
CMenu m_menu;
void CMenu2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {// TODO: Add your message handler code here and/or call defaultCClientDC dc(this);if(0x0d==nChar){if(0==++m_nIndex){m_menu.CreatePopupMenu();GetParent()->GetMenu()->AppendMenu(MF_POPUP,(UINT)m_menu.m_hMenu,_T("PhonBook"));//在View类中获得框架类的指针使用GetParentGetParent()->DrawMenuBar();//马上更新菜单栏}m_menu.AppendMenu(MF_STRING,IDM_PHONE1+m_nIndex,m_strLine.Left(m_strLine.Find(' ')));m_strArray.Add(m_strLine);m_strLine.Empty();Invalidate();//缺省为TRUE,客户区更新}else{m_strLine+=nChar;dc.TextOut(0,0,m_strLine);}CView::OnChar(nChar, nRepCnt, nFlags);}
在在框架类CMainFrame中利用ClassWizard添加虚函数OnCommand()来截获消息并处理BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) {// TODO: Add your specialized code here and/or call the base classint MenuCmdID=LOWORD(wParam); //获得低字节CMenu2View *pView=(CMenu2View*)GetActiveView();//获得当前视类的指针,从得到我们所需要的其中的m_strArray数据if(MenuCmdID>=IDM_PHONE1 && MenuCmdID<=IDM_PHONE1+pView->m_strArray.GetSize());{//MessageBox("xiaodou");CClientDC dc(pView);dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdID-IDM_PHONE1));return TRUE;}return CFrameWnd::OnCommand(wParam, lParam);}详细程序略
- 孙鑫VC++视频学习笔记(第六课 菜单的工作原理及编写控件)
- 孙鑫vc++ 第六课 笔记 菜单的工作原理及编写应用
- 孙鑫VC学习笔记:第六讲 菜单
- 孙鑫VC学习笔记:第六讲 菜单
- 孙鑫VC学习笔记:第六讲 菜单
- 孙鑫VC++学习笔记(第六讲 ——菜单)
- (孙鑫)菜单的原理及编写
- 孙鑫vc第六课,菜单
- 孙鑫VC视频教程笔记之第六课“菜单”
- 分析集线器的工作原理--视频学习笔记
- 《VC++深入详解》学习笔记 第六章 菜单
- 孙鑫VC++视频学习笔记之5: VC菜单相关编程
- 孙鑫VC++视频学习笔记之5: VC菜单相关编程
- 孙鑫VC视频学习笔记
- 孙鑫VC++视频学习笔记
- 《VC++深入详解》学习笔记----Lesson1: Windows程序运行原理及程序编写流程
- 孙鑫VC学习笔记:第六讲
- VC++编写ActiveX控件(转载学习)
- 软件实现的施密特触发器
- 2011-11-28星星
- xml 类
- 不要保留最近打开文档的记录
- 主题:四,android四大组件基础介绍及打电话,发短信简单应用 &单元测试
- 孙鑫VC++视频学习笔记(第六课 菜单的工作原理及编写控件)
- 设计模式——序
- 深入剖析WTL框架(一)
- Linux 内核/sys 文件系统介绍
- 完全背包问题、、、
- Android 日历方式显示的日期选择组件
- 深入剖析WTL框架(二)
- 数据挖掘从业人员工作分析
- 块设备驱动注册和注销、加载与卸载、块设备驱动的I/O请求