【问题标题】:Why can't I disable/gray out menuitem? (MFC)为什么我不能禁用/灰显 menuitem? (MFC)
【发布时间】:2015-01-19 14:17:28
【问题描述】:

我正在尝试使用 CMenu::EnableMenuItem() 方法禁用/灰显菜单项。

我有一个CMenu* 变量pMenu,它引用了对话框的顶部菜单。我可以使用pMenu->GetSubMenu(int)submenu->GetMenuStringA() 获取子菜单,验证我返回的子菜单/菜单项的名称。我在使用EnableMenuItem() 方法时遇到了问题。假设有一个File 菜单。其中有NewOpen 弹出菜单和ImportCloseClose All 菜单项。 NewOpen 有子菜单项。 (例如New->Document)使用submenu->EnableMenuItem([position of submenu/menuitem], MF_BYPOSITION | MF_GRAYED); 我可以禁用NewOpen,但是对于ImportCloseClose All 以及所有带有New 的菜单项和Open.

注意:当我说EnableMenuItem() 失败时,我并不是说它返回-1。它返回之前的状态,但菜单不会被禁用或变灰。

EnableMenuItem():http://msdn.microsoft.com/en-us/library/h62wh3y1.aspx 的 MSDN 文档中,它声称这适用于弹出菜单项和标准菜单项。不过,它似乎只适用于弹出式广告。

【问题讨论】:

    标签: c++ mfc cmenu


    【解决方案1】:

    MFC 有另一个用于启用/禁用菜单项的方案,该方案正在撤消您正在执行的操作。要在 MFC 方案中工作,请添加消息处理程序 ON_UPDATE_CMD_UI,如下所述:

    http://msdn.microsoft.com/en-us/library/6kc4d8fh.aspx

    【讨论】:

    • 问题是,我从外部应用程序中完成了所有这些。我使用主窗口的句柄来获取它的菜单,然后我使用 GetSubMenu 来获取它的子菜单,我无权访问 CCmdUI 对象。
    • @Amre 那么你就被卡住了。您尝试控制的应用程序正在通过其自己的 CCmdUI 对象不断重置启用/禁用状态,您所做的任何更改都将在几毫秒内恢复。
    • 基本上我想要完成的是将 oncommand 消息发送到按钮。我正在尝试创建一个应用程序,可用于测试我的应用程序的安全性,以防止有人向控件发送 oncommand 或 bn_clicked 消息并访问他们不应该访问的内容。
    • 我意识到我从未真正对此进行过更新。最后,我没有费心尝试启用灰色按钮或菜单项,而是在它们被禁用时调用它们。我为这样的按钮做了这个: CWnd* selCWnd = //get CWnd reference ::SendMessage(selCWnd->m_hWnd, WM_LBUTTONDOWN, 0, 0); ::SendMessage(selCWnd->m_hWnd, WM_LBUTTONUP, 0, 0);所以我发现我可以只发送一个左键向下,然后是一个左键向上命令,模仿点击它就可以了!
    • 对于菜单项,我使用 PostMessage 并使用 id 将 WM_COMMAND 消息发送到菜单项。即:::PostMessage(m_HWNDSel, WM_COMMAND, MAKEWPARAM(id, 0), 0);其中 id 是菜单项 ID。我能够通过获取对引用菜单栏的 PMenu 的引用来获取这些 ID,然后我遍历所有子菜单并使用 pMenu->GetMenuItemID() 获取菜单项 ID
    【解决方案2】:

    ScottMcP-MVP MFC 声明在 ON_UPDATE_COMMAND_UI 处理程序中进行菜单配置:当您的应用程序的用户下拉菜单时,每个菜单项都需要知道它应该显示为启用还是禁用。菜单命令的目标通过实现 ON_UPDATE_COMMAND_UI 处理程序来提供此信息。对于应用程序中的每个命令用户界面对象,使用“属性”窗口为每个处理程序创建一个消息映射条目和函数原型。

    当下拉菜单时,框架会搜索并调用每个 ON_UPDATE_COMMAND_UI 处理程序,每个处理程序调用 CCmdUI 成员函数如 Enable 和 Check,然后框架会适当地显示每个菜单项。

    这意味着您必须在自己的类中存储可以选中/取消选中的菜单项的预期状态。您必须在ON_COMMAND 宏附近为每个菜单元素放置一个ON_UPDATE_COMMAND_UI 宏,该元素将引用一个接收CCmdUi 对象的函数,您可以根据需要对其进行修改。但是当您使用 MFC 时,您通常不会手动操作,而只需使用包含菜单的窗口的属性。

    【讨论】:

    • 我明白你在说什么,但这并不是我真正想要做的。我没有尝试使用应用程序启用/禁用项目。我在外部应用程序中调用所有这些方法。
    • 你绝对做不到!您应该改为向 MFC 应用程序发送自定义消息,告诉它某些菜单项应该变灰。然后在 MFC 应用程序中,您将能够使用 ON_UPDATE_COMMAND_UI 处理程序来启用/禁用它们。我无法想象 MFC 应用程序的另一种方式。
    • 如果我知道菜单项的 ID,有什么方法可以调用 oncommand 或 Bn_clicked 消息处理程序?我尝试使用 sendmessage 和 postmessage 传递主窗口的句柄以及 BN_CLICKED 和 WM_COMMAND 但这似乎不起作用。
    • @Amre 您无法从应用程序外部触发这些 MFC 事件,因为它们是由 MFC 框架生成的。
    • 我意识到我从未真正对此进行过更新。最后,我没有费心尝试启用灰色按钮或菜单项,而是在它们被禁用时调用它们。我为这样的按钮做了这个: CWnd* selCWnd = //get CWnd reference ::SendMessage(selCWnd->m_hWnd, WM_LBUTTONDOWN, 0, 0); ::SendMessage(selCWnd->m_hWnd, WM_LBUTTONUP, 0, 0);所以我发现我可以只发送一个左键向下,然后是一个左键向上命令,模仿点击它就可以了!
    猜你喜欢
    • 2016-09-01
    • 2012-03-27
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2013-10-17
    • 2010-10-11
    • 1970-01-01
    相关资源
    最近更新 更多