孙鑫VC++深入详解:Lesson6 Part2 -- MFC菜单更新机制 用该机制实现 Enable or Disable MenuItem
2013-07-05 12:22
483 查看
MFC菜单命令更新机制---用该机制实现 Enable or Disable MenuItem
方法:
1)用资源中的菜单项"剪切"的ClassWizard添加一个UPDATE_COMMAND_UI消息响应函数
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
同时发现MFC在MainFrm.cpp的消息映射代码处添加了一个宏:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) //关联CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 的宏
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
MFC就是由消息映射表中的宏来调用关联的消息响应函数,对消息做出响应.
2) 在消息响应函数OnUpdateEditCut(CCmdUI* pCmdUI)中:
pCmdUI->Enable(true); //就可以Enable "剪切",由灰色变成激活了.
//
//---
因为工具栏上的剪刀图标的index并不等于2,工具栏这个横条是一个整体,剪刀的index=4
------> 0,1,2(保存),3(分隔条),4(剪刀)
//---
//---
//---
菜单和工具栏图标都激活: 最简单就是不要用if()判断,直接Enable
pCmdUI->Enable(true);
//--- 代码都是在CMainFrame的MainFrm.cpp中干活,为什么不在CMenuVie类,CMenuDoc类中干活? 其实都可以.
OnTest中实验COMMAND的响应顺序是CMenuView--->CMenuDoc--->CMainFrame--->CMenuApp..
在这里做了个实验:
(1)如果CMenuDoc中添加了void CMenuDoc::OnUpdateEditCut(CCmdUI* pCmdUI) ,虽然CMainFrame也有void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
但是后者不会被调用了.
(2) CMenuDoc::OnUpdateEditCut是被调用的消息处理函数,但是它没有 pCmdUI->Enable(true),因此"剪切"子菜单项还是个灰色的.
void CMenuDoc::OnUpdateEditCut(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
方法:
1)用资源中的菜单项"剪切"的ClassWizard添加一个UPDATE_COMMAND_UI消息响应函数
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
同时发现MFC在MainFrm.cpp的消息映射代码处添加了一个宏:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) //关联CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 的宏
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
MFC就是由消息映射表中的宏来调用关联的消息响应函数,对消息做出响应.
2) 在消息响应函数OnUpdateEditCut(CCmdUI* pCmdUI)中:
pCmdUI->Enable(true); //就可以Enable "剪切",由灰色变成激活了.
//
//---
因为工具栏上的剪刀图标的index并不等于2,工具栏这个横条是一个整体,剪刀的index=4
------> 0,1,2(保存),3(分隔条),4(剪刀)
//---
//---
//---
菜单和工具栏图标都激活: 最简单就是不要用if()判断,直接Enable
pCmdUI->Enable(true);
//--- 代码都是在CMainFrame的MainFrm.cpp中干活,为什么不在CMenuVie类,CMenuDoc类中干活? 其实都可以.
OnTest中实验COMMAND的响应顺序是CMenuView--->CMenuDoc--->CMainFrame--->CMenuApp..
在这里做了个实验:
(1)如果CMenuDoc中添加了void CMenuDoc::OnUpdateEditCut(CCmdUI* pCmdUI) ,虽然CMainFrame也有void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
但是后者不会被调用了.
(2) CMenuDoc::OnUpdateEditCut是被调用的消息处理函数,但是它没有 pCmdUI->Enable(true),因此"剪切"子菜单项还是个灰色的.
void CMenuDoc::OnUpdateEditCut(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
// MainFrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "Menu.h" #include "MainFrm.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMainFrame IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) //关联CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 的宏 //}}AFX_MSG_MAP END_MESSAGE_MAP() static UINT indicators[] = { ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, }; ///////////////////////////////////////////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { // TODO: add member initialization code here // m_bAutoMenuEnable =false; //改回false. 下面用MFC菜单命令更新机制来处理菜单. } CMainFrame::~CMainFrame() { } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); //------ 子菜单项勾选函数CheckMenuItem //MenuItem:菜单项就是子菜单下面的各个选项,如"新建","打开","保存"等等. // GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);////通过索引0访问"新建"菜单项MenuItem // GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED);//通过命令ID访问"新建"菜单项MenuItem //------ 子菜单项设置为默认函数SetDefaultItem // GetMenu()->GetSubMenu(0)->SetDefaultItem(0,true);//第二个参数是true,则第一个参数用索引 // GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_NEW);//第二个参数默认是false,则第一个参数ID // GetMenu()->GetSubMenu(0)->SetDefaultItem(5,true); //"打印"是5不是4,因为分隔栏是要占索引的, 另外只能有一个缺省菜单项 //------ 子菜单项上添加位图(文字左边) SetMenuItemBitmaps CString str; str.Format("x=%d, y=%d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK)); //MessageBox(str);//x=13,y=13 系统子菜单项位图大小必须是13*13 m_bitmap.LoadBitmap(IDB_BITMAP1); GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,NULL); //要注意修改位图的底色,白色就看不见了. //------ 禁用子菜单项 // m_bAutoMenuEnable 在CMainFrame()构造函数中设置其为m_bAutoMenuEnable =false 关闭MFC自动更新菜单的机制 GetMenu()->GetSubMenu(0)->EnableMenuItem(ID_FILE_OPEN,MF_DISABLED|MF_GRAYED);//禁用"打开"子菜单项 //GetMenu()->GetSubMenu(0)->EnableMenuItem(0,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);//或者这样用子菜单项索引 //------ 删除整个菜单,和加载菜单 // SetMenu(NULL); // 填参数NULL 就删除了整个菜单 //------加载菜单,可以加载自定义菜单资源 /* CMenu menu; // 这里有个隐藏的问题 就是menu是个局部变量,解决办法是(1)把他放到CMainFrame中作为成员变量 //(2) 就是下面的加上:menu.Detach(); menu.LoadMenu(IDR_MAINFRAME); //菜单资源ID SetMenu(&menu); menu.Detach();//将菜单句柄与CMenud对象menu脱离,这样局部变量menu析构是就不会这个菜单资源(因菜单资源已经不属于它了,析构不到) */ return 0; } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CMainFrame diagnostics #ifdef _DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMainFrame message handlers //DEL void CMainFrame::OnTest() //DEL { //DEL // TODO: Add your command handler code here //DEL MessageBox("MainFrame clicked"); //DEL //DEL } void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here // if(pCmdUI->m_nID == ID_EDIT_CUT)这个判断是多余的,因为pCmdUI的成员m_nID传入进来是必定是ID_EDIT_CUT //因为这个消息响应函数是与菜单项关联了的. //------通过菜单项的ID "ID_EDIT_CUT",这样能保证菜单项"剪切"和工具栏那个剪刀都Enable /* if(pCmdUI->m_nID == ID_EDIT_CUT) //多余的 pCmdUI->Enable(true); */ //------通过索引m_nIndex: 这样的缺点工具栏中的剪刀图标没有激活,仅激活了子菜单项"剪切" //因为工具栏上的剪刀图标的index并不等于2,工具栏这个横条是一个整体,剪刀的index=4 /* if(pCmdUI->m_nIndex == 2) pCmdUI->Enable(); */ //------菜单和工具栏图标都激活: 最简单就是不要用if()判断,直接Enable pCmdUI->Enable(true); }
相关文章推荐
- MFC菜单命令更新机制
- MFC---如何利用菜单更新机制动态更新菜单
- MFC菜单更新机制
- MFC菜单命令更新机制
- MFC菜单的命令更新机制
- AppWidget实现机制分析--应用更新时更新AppWidget深入分析
- MFC Ribbon UI 弹出菜单实现分析
- Log4j2中RollingFile的文件滚动更新机制 一、什么是RollingFile RollingFileAppender是Log4j2中的一种能够实现日志文件滚动更新(rollover)的
- 在MFC对话框中使用ON_UPDATE_COMMAND_UI更新菜单
- MFC中复选菜单的更新策略
- Android自定义TabActivity(实现仿新浪微博底部菜单更新UI)
- 菜单命令更新机制
- 如何实现缓存系统的更新机制
- MFC下托盘图标的实现和托盘菜单
- quick-cocos2d-x的热更新机制实现<四>update包(lua)(中)
- 用MFC “菜单响应事件” 实现绘图
- 使用.net反射机制实现 “热”更新动态库(dll文件)
- MFC实现菜单弹出对话框,并在对话框中实现控件触发
- quick-cocos2d-x的热更新机制实现
- MFC中菜单图标的实现