如何enable/disable菜单项

这个问题在以前的知识库中出现过多次,许多人问及在MFC应用程序中enable或disable菜单的问题,在主菜单中调用 CMenu::EnableMenuItem不起作用......如何disable菜单项? 

根据以往的经验,要解决这种问题,似乎应该有一个象EnableMenuItem之类的API函数,它的功能就是enable或disable菜单项。Windows中确实有这样的函数-但不是在MFC的应用中。实际上,在MFC里enable或disable菜单项是通过使用ON_ UPDATE_COMMAND_UI实现的。首先让我解释一下为什么MFC的实现方法不同于标准的C和Windows API,以及MFC的实现方法的好处。 

一般情况下,用户界面的状态指的是按钮,状态格,菜单项等任何反映程序状态的东西。例如,如果程序处于只读模式,那么编辑(Edit)命令应该是disable的,并且在程序的某个地方可能有一个小指示器向用户提示这个状态。另一个例子是如果剪贴板没有内容(一种状态),那么菜单中的粘贴(Paste)命令应该是disable的。所以说通常的用户界面(UI)指的就是程序表现的状态,同时,程序状态的改变应该在程序的菜单中反映出来。 

如何随时获得反映程序状态的用户界面呢?我自己的方法有两种: 

第一种是神经过敏型,也就是说无论何时只要程序状态改变,都不要忘记同时更新用户界面,如果用户调用只读模式命令,这个命令要disable所由编辑控制。同样,如果用户调用Cut或者Copy,处理器立刻enable Paste命令。在程序的任何地方对程序状态的任何改变,都必须要更新相应的UI。 

第二种方法是放松型,也就是说,不要试图去维护所有的状态信息,只根据需要更新用户界面。对于菜单来说,不用保持菜单的状态的更新,只在显示的时候进行更新。

这个方法较容易,也十分简单。更重要的是,它使数据从用户界面中分离出来。每个对象只存储它自己的状态-例如,文档知道什么时候处于只读模式。UI能解释出现的各种状态,你不想低级对象调用类似EnableMenu的UI函数!MFC提供一个UI更新机制来实现后一种方法,详细的方法描述因为内容太多,将在另文中讨论,其基本思路是这样的:当用户调用一个菜单的时候,Windows发送一个WM_INITMENUPOPUP消息。MFC创建一个暂时的CCmdUI对象处理这个消息,为每一个菜单项做连续初始化并将它传递到应用程序中的对象。MFC为此调用ON_UPDATE_COMMAND_UI消息处理器更新用户界面: 

ON_UPDATE_COMMAND_UI(ID_FOO, OnUpdateFoo) 

只要用户进入包含Foo的菜单项,MFC就会调用OnUpdateFoo函数。你不必担心必须调用::EnableMenuItem(第一种方法)的所有地方;要做的只是从程序状态确定菜单状态。典型的处理方法如下: 

void CMainFrame::OnUpdateFoo(CCmdUI* pCmdUI)
{
  
    pCmdUI->Enable(pObj->GetFoo());
}

GetFoo()是个假设的函数,它获得某个对象的foo状态-例如,m_pDocument->GetReadOnly()。可能有20函数来修改foo状态(自然是通过方法SetFoo),但更新菜单的地方只有一处。当然有可能是更复杂的情形,如: 

pCmdUI->Enable(m_bFoo &&

(GetStatusX(...) || GetStatusY(...)));

在Paste菜单的情形中,你必须检查剪贴板是否有粘贴的内容,内容有可能是文本或图形,这里关键是在需要的时候决定菜单的状态,菜单更新代码被单独放在一个函数中-远离潜在的对象-替代了遍及所有对象的洒水式EnableMenuItem调用。 

MFC使用CCmdUI和ON_UPDATE_COMMAND_UI来调整按钮、状态条窗格和菜单项的状态,并且你可以自己扩展其它的UI项目。例如,当用户点击下拉箭头时,你可以根据程序的状态调整组合框或列表框的内容。CCmdUI::Enable是个虚拟函数,在对于菜单项的操作当中,它变成了::EnableMenuItem。 

在前面的例子中,我们讨论的UI处理是在CMainFrame中实现的,但你也能将这种处理放在框架,视图,文档,应用(派生于CWinApp)或任何其它类中,命令通过CCmdTarget::OnCmdMsg发送。如果MFC找不到特定菜单的ON_UPDATE_COMMAND_UI,它用以下的规则自动做enable或disable: 

如果命令有一个处理器(ON_COMMAND),MFC enable菜单项;否则,MFC disable菜单项。你可以设置CFrameWnd::m_bAutoMenuEnable = FALSE重载这个行为,这样的话,所有菜单项都将被enable-不管有没有处理器。 

所以,在MFC应用程序中,不要用EnableMenuItem来enable或disable菜单,而要使用ON_UPDATE_COMMAND_UI处理器来实现菜单的enable或disable。

时间: 2024-11-10 00:19:42

如何enable/disable菜单项的相关文章

手机开发-Android 模拟器中按菜单Menu键弹出菜单项MenuItem,点击菜单项中的菜单项没反应!!!

问题描述 Android 模拟器中按菜单Menu键弹出菜单项MenuItem,点击菜单项中的菜单项没反应!!! public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.main,menu); return true; } public boolean onOptionsItemSeleted(MenuItem item){ switch(item.getItemId()) { case R.i

使用xml作为数据源,让asp:Menu类自由扩展菜单项

先新建一个名为menu的xml文件,内容如下: <?xml version="1.0" encoding="utf-8" ?><menu>  <menuItem url="~/Default.aspx" title="首页"  description=""/>  <menuItem url="~/News.aspx" title="新闻

如何在IE右键菜单中添加菜单项

菜单|右键 如果使用过Netants的朋友可能都知道,NetAnts在IE中添加了右键菜单功能,只要在页面的一个链接或者图片上点击右键后在菜单中选择 Down By Netants 就可以调用Netants下载该链接指向的文件.在本文中作者将介绍如何通过VB来实现这样的功能. 要实现在IE右键菜单中添加菜单项的功能,要依次实现以下步骤: 1.在注册表HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt项下建立一个新项,项的名

在Excel中建立自定义菜单项

excel|菜单 演练:在Excel中建立自定义菜单项 Brian A. Randell MCW Technologies, LLC September 2003 Applies to: Microsoft Visual Studio Tools for the Microsoft Office System Microsoft Office Excel 2003 Microsoft Visual Studio .NET 2003 概述:Office CommandBar对象提供了增加菜单项和工

WiX安装选项---开始菜单项

参考文档: How To: Create a Shortcut on the Start Menu,How To: Create an Uninstall Shortcut 制作的安装程序安装后,都要在开始菜单上生成一个应用程序的菜单,通常包括调用应用程序的快速入口和卸载应用程序项.下面取一个例子来看: <?xml version="1.0" encoding="utf-8"?> <Wix xmlns="http://schemas.mi

delphi7.0 intraweb 5.3 菜单为什么不能显示子菜单项

问题描述 delphi7.0 intraweb 5.3 菜单为什么不能显示子菜单项 delphi7.0 intraweb 5.3 菜单为什么不能显示子菜单项 我在页面上添加的IWmenu 和,Tmainmenu.设置好,运行,结果,子菜单不显示 只显示顶级的.网上查好多资料,没有解决,路过的大师指点一下,谢谢.小弟头一次使用intraweb. 解决方案 整治了一天,终于搞定的,原因是版本太低.

如何用c++编写一个菜单项啊?

问题描述 如何用c++编写一个菜单项啊? 在系统盘里点击鼠标右键会出现删除,剪切之类的操作,请问如何用c++编写一个菜单项程序呢. 解决方案 你说的不清楚.你的问题有4种理解 (1)系统菜单,控制菜单项添加项http://www.knowsky.com/394853.html (2)系统托盘添加菜单http://blog.csdn.net/cliviajin/article/details/1890828 (3)Shell上下文菜单http://www.cnblogs.com/fangkm/ar

插件开发,扩展了popMenus,开始右键不出现扩展的菜单项

问题描述 plugin.xml中代码片段如下:<extensionpoint="org.eclipse.ui.popupMenus"><objectContributionadaptable="true"id="test.objectContribution1"objectClass="nc.uap.studio.mde.ext.navigator.adapters.BComponent"><ac

eclipsercp-EclipseRCP 向原有插件添加新菜单项

问题描述 EclipseRCP 向原有插件添加新菜单项 point="org.eclipse.ui.popupMenus"> objectClass="org.eclipse.ui.IEditorInput" nameFilter = "*.*" id="zzzz.contribution1"> label="New menu" path="additions" id=&qu