65.9K
CodeProject 正在变化。 阅读更多。
Home

MFC 更新命令 UI 机制的端口

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.21/5 (6投票s)

2005年9月14日

2分钟阅读

viewsIcon

30515

downloadIcon

306

使用事件驱动架构替代 CUpdateUI。

动机

WTLCUpdateUI 违反了 ATL 的策略。BEGIN_MSG_MAP 是一组函数调用,但 WTLBEGIN_UPDATE_UI_MAP 是一组数据。这使得你的程序变得不可控,尤其是在 MDI 应用程序的情况下。参见 WTL 的示例,MDIDocVw。这是不可能理解的。因此,应该替换 CUpdateUI

所以,Ketchup.CmdUI 提供了 MFC 更新命令 UI 机制的端口,这是 MFC 仅剩的优点。

要求

快速开始

  1. 包含头文件
    #include "ketchup/cmd_ui.hpp"
  2. 定义 CmdUI 处理程序
    void OnUpdateViewStatusBar(ketchup::cmd_ui& ui)
    {
      ui.set_check(::IsWindowVisible(m_hWndStatusBar));
    }
  3. 将处理程序添加到消息映射
    BEGIN_MSG_MAP(CMDIFrame)
      // ...
      KETCHUP_CMD_UI_HANDLER(ID_VIEW_STATUS_BAR, 
                               OnUpdateViewStatusBar)
    END_MSG_MAP()
  4. 添加 CmdUI 生成器
    virtual BOOL OnIdle()
    {
      ketchup::update_toolbar_cmd_ui(m_hWnd, m_ToolBar);
      return FALSE;
    }
    BEGIN_MSG_MAP(CMDIFrame)
      // ...
      KETCHUP_UPDATE_MENU_CMD_UI()
    END_MSG_MAP()

Ketchup.CmdUI 是一种事件驱动架构。您可以使用代码而不是数据来确定 UI 的状态。首先,CUpdateUI 与 Win32 不一致。

基本概念

  • CmdUI

    CmdUI 是一个派生自 ketchup::cmd_ui 的对象。

  • CmdUI 生成器

    CmdUI 生成器是生成 CmdUI 并将其发送到处理它的窗口的任何东西。

  • 依赖的 CmdUI

    依赖的 CmdUI 是任何没有自己 ID 的 CmdUIis_dependent 代表依赖关系。

ketchup::cmd_ui

这个类是 MFC 的 CCmdUI 的端口

struct cmd_ui
{
  UINT get_id() const;
  void set_handled(bool on);
  bool is_handled() const;

  virtual void enable(bool on);
  virtual void set_check(int state);
  virtual void set_radio(bool on);
  virtual void set_text(LPCTSTR pszText);
  virtual void set_default(bool on);
  virtual bool is_dependent();
};

成员的语义与 CCmdUI 的语义相同,但拒绝使用默认参数。

预定义的 CmdUI 生成器

KETCHUP_UPDATE_MENU_CMD_UI

这是 BEGIN_MSG_MAP 的一个入口,它从菜单项创建 CmdUI

ketchup::update_toolbar_cmd_ui

这从工具栏按钮项创建 CmdUI

嵌套弹出菜单

从弹出菜单生成的 CmdUI 是依赖 CmdUI 的模型。弹出菜单不能有自己的 ID,因此它依赖于第一个菜单项。参见 MFC 的文档 嵌套弹出菜单。MFC 的语法有些笨拙。ketchup::cmd_ui 提供了一个名为 is_dependent 的成员

void OnUpdatePopupSubmenu(ketchup::cmd_ui& ui)
{
  if (ui.is_dependent())
    ui.enable(m_popup_enabled);
}

请注意,如果您使用 WTL::CCommandBarCtrl 的 chevron 菜单,所有顶级菜单项(如文件、编辑等)都可以设置为依赖项。

CmdUI 链

提供了 KETCHUP_CHAIN_CLIENT_CMD_UIKETCHUP_CHAIN_MDI_CHILD_CMD_UI。作用与 WTLCHAIN_CLIENT_COMMANDSCHAIN_MDI_CHILD_COMMANDS 相同。

自动禁用

每个 MDI 子窗口都有不同的命令集。MDI 框架提供动态菜单,但您将如何处理工具栏?如果您想在 MDI 子窗口之间共享菜单,该怎么办?因此,KETCHUP_ENABLE_CMD_UI_IF_HANDLED_BY_MDI_CHILD 会自动链接和禁用 CmdUI

typedef ketchup::idset<
  ID_BLACK, ID_RED, ID_GREEN, ID_BLUE, ID_WHITE,
  ID_CUSTOM, ID_SPEED_SLOW, ID_SPEED_FAST
> child_cmd_ids;

BEGIN_MSG_MAP(CMDIFrame)
  // ...
  KETCHUP_ENABLE_CMD_UI_IF_HANDLED_BY_MDI_CHILD(child_cmd_ids)
END_MSG_MAP()

MFC 可以根据是否处理 WM_COMMAND 来禁用 CCmdUI,但 WTL 不行。因此,Ketchup.CmdUI 会根据是否处理 CmdUI 来禁用 CmdUI,也就是说,一个 MDI 子窗口是否有 KETCHUP_CMD_UI_HANDLER 入口。请注意,您应该使用 ketchup::idset 指定目标命令集。

参考文献

© . All rights reserved.