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

WTL 助手

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (114投票s)

2004 年 11 月 24 日

13分钟阅读

viewsIcon

772582

downloadIcon

8841

Microsoft VC++.NET 2003 的一个插件,用于帮助 WTL 插入消息处理程序。

引言

当我开始使用 WTL 时,我发现没有工具可以帮助我像类向导那样添加消息处理程序。因此,我决定开发自己的 Microsoft Visual Studio (MS VS) 插件来完成这项工作。抱歉我的英语不好,我不太会说。

使用加载项

首先,您应该下载 WTL Helper Setup 并运行它来安装插件。该插件会自动注册快捷键 CTRL+ALT+W 来调用对话框。但是,如果您使用预定义的键盘映射方案之一,则快捷键注册会失败。相反,您应该创建当前键盘映射方案的副本。为此,请转到菜单 Tools->Options。在 Environment 部分,选择 Keyboard,按下 Save As 按钮并为新的键盘方案选择一个名称。然后,您可以手动设置 WTL Helper 的快捷键(其完整名称为 WtlHelper.Connect.WtlHelper)。

消息映射

如果插件安装正确,WTL Helper 子菜单将出现在 Tools 菜单中。单击 WTL Helper,您将看到上面显示的对话框。左侧 TreeView 面板的结构在 WTL 文件中进行了描述。如果使用安装程序,这些 WTL 文件将被解压到 {installation_path}\Messages 目录,或者它们位于源代码存档的 \wtl 子目录中。这些文件的描述如下。我已按类别对这些消息进行了分组,以便更快地搜索。如果您认为此顺序不方便,可以修改 WTL 文件以拥有自己的消息树视图。

DDX 映射

在对话框的左侧面板中,您可以看到所选对话框的控件 ID。默认情况下,组合框中只有对话框类。在右侧面板中,是与这些 ID 控件相对应的变量。

选项

其他菜单项 Options 允许您选择以下选项:

消息选项

  1. 消息处理程序的默认样式(新或旧)
  2. 消息处理程序的排序(开/关)
  3. 函数处理程序(内联或在 CPP 中)
  4. 将使用哪个 CRectCPointCSize 类:WTL 或 ATL
  5. 处理程序颜色

DDX 选项

  1. DDX 变量的默认保护级别
  2. Variables 选项卡上仅显示对话框类还是所有类
  3. 对 DDX 变量使用类型前缀

更多关于这些选项的解释将在下面给出。

消息选项讨论

  1. WTL 3.1 及更高版本有一个名为 atlcrack.h 的文件。在此文件中,有许多消息处理程序可以解包(crack)wParamlParam。因此,消息处理程序函数变得更加简洁。但是,存在一些问题,因为 cracking 必须与以 BEGIN_MSG_MAP_EX 而不是 BEGIN_MSG_MAP 开头的消息映射一起使用。BEGIN_MSG_MAP 宏和 cracked handlers 仅适用于 ATL 7.0 及更高版本,并且仅适用于继承自 CWindowImlCDialogImpl 的类。
  2. 您可以使用消息处理程序的排序,该排序默认启用。排序意味着消息映射中的所有新消息处理程序将按以下顺序插入:
    1. Windows 消息处理程序,如 WM_CREATEWM_DESTROY
    2. 命令消息处理程序:WM_COMMAND 消息的一部分
    3. 通知消息处理程序:WM_NOTIFY 消息的一部分
    4. 其他消息处理程序(用户定义的消息)
    5. CHAIN_MSG_MAP
  3. 如果为 true,则函数插入到头文件中。否则,函数插入到 CPP 文件中。
  4. ATL 7.0 及更高版本有一个名为 atltypes.h 的文件。在此文件中,声明了 CRectCPointCSize 等类。您也可以使用 WTL 类 CRectCPointCSize。如果勾选此选项,您将使用 WTL 类。否则,您将使用 ATL 类。如果您选择 WTL 类,则文件 <atlmisc.h> 将包含在每个声明使用 CRectCPointCSize 的消息处理程序的头文件中。如果您选择 ATL 类,则文件 <atltypes.h> 将以相同方式包含。
  5. 从 0.9.9.0 版本开始,您还可以设置处理程序的突出显示颜色。只需按下按钮,您就会看到类似的对话框。

    Screenshot - colorsetup.PNG

    选择您最喜欢的颜色,处理程序将以该方式突出显示。

DDX 选项讨论

  1. 当对话框要求新 DDX 条目的参数时,变量的默认保护类型。
  2. 如果选中此选项,则在 Variables 选项卡上仅显示基于对话框的类。在其他情况下,将显示所有类。
  3. 如果设置此标志,则所有自动生成的变量名都将带有类型前缀,例如 im_iVar1)或 strm_strVar2)。

上下文菜单

从 0.9.9.0 版本开始,我添加了一些上下文菜单处理程序,以方便调用 WTL Helper。在 Visual Studio 2003 中,上下文菜单是 MS Office 命令栏。因此,我需要知道它们的名称来添加我的菜单项。以下是命令栏名称及其调用位置:

  • 类视图项:类视图窗口
  • 资源编辑器:除菜单编辑器外的所有资源编辑器
  • 菜单设计器:菜单编辑器

加载插件后,我的菜单项会出现在这些上下文菜单中。

类视图

Screenshot - classsview_context.PNG

我添加了两个菜单项,用于显示 WTL Helper 的主窗口。唯一的区别是第一个将处理程序/函数页面设置为默认值,第二个将 DDX 变量页面设置为默认值。

资源编辑器

Screenshot - res_context.PNG

对于快捷键或工具栏按钮,您可以直接添加命令处理程序。

Screenshot - dialog_context.PNG

在上图中,您可以看到对话框的上下文菜单。前两项与类视图的相同。要使用最后一项,您需要拥有 WTL Wizards 至少 1.1 版本。WTL Wizards 是一组用于添加 WTL 类的对话框。

Screenshot - control_context.PNG

您无需显示 WTL Helper 的主窗口,就可以直接为控件添加处理程序或变量。

菜单编辑器

Screenshot - menu_context.PNG

与快捷键或工具栏按钮相同,您可以直接为菜单项添加命令处理程序。

对话框资源视图

Screenshot - resdialog_context.PNG

对话框编辑器也是如此。

获取选定的资源项

当我尝试获取当前资源 ID 和选定的资源项时遇到了一些麻烦。Visual Studio 插件框架没有记录在案的方法来获取此类信息。最困难的是确定当前正在编辑的资源及其 ID。我不是以正确的方式完成的(我不知道正确的方式),但我找到了一种解决方法。您可以看到,资源编辑窗口的标题由资源文件名、当前正在编辑资源的 ID 和资源类型组成。因此,我使用此标题来获取我需要的所有信息。

下一个问题是如何检索当前正在编辑的资源项(菜单项、对话框控件等)的 ID。您可以从 EnvDTE::SelectedItems 对象获取 EnvDTE::SelectionContainer 对象,然后可以获取选定项的对象。但是,对于资源项,没有这样的文档。这些对象定义在 ResEditPKGLib 中。要使用它们,您应该像这样导入具有 GUID {7365C6FE-4191-476B-A3FE-1CB6A7B1C119} 的 TLB:

#import "libid:7365C6FE-4191-476B-A3FE-1CB6A7B1C119" 
    version("7.1") lcid("0") no_implementation

每个资源项对象都有一个 ID 属性,但这些对象没有通用接口。因此,我使用 IDispatch 接口的 Invoke 方法来检索当前资源项 ID。

重写函数

Screenshot - specfunc.PNG

从 0.9.9.0 版本开始,我添加了重写父类某些函数的功能。在上图所示的菜单中,可以看到 CScrollWindowImpl 类的子类的菜单。前两个函数适用于除对话框类之外的所有类。其他函数仅适用于指定类。例如,DoScrollDoPaint 仅适用于 CScrollImpl 的子类。

处理 EnvDTE 时遇到的问题

问题在于没有精确的映射定义。我认为在 Microsoft 中,映射被称为从预定义宏之一开始的对象,例如 BEGIN_MSG_MAPBEGIN_MESSAGE_MAP 等。这在使用 EnvDTE 的此对象时会产生一些问题。

BEGIN_MSG_MAP_EX 不被识别为映射的开始;它被识别为一个函数。类声明中使用的所有宏也被识别为函数。但这并不是主要问题。主要问题是,当您使用 BEGIN_MSG_MAP_EX 或其他映射(如 DDX 映射)创建消息映射并尝试将函数插入源文档时,会返回错误。

第二个问题是某些映射条目和映射结束的识别。例如:

CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(CMessageFilter)
CHAIN_MSG_MAP(CIdleHandler<CMainFrame>)

...被识别为

CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
CHAIN_MSG_MAP(CMessageFilter)
CHAIN_MSG_MAP(CIdleHandler<CMainFrame>)

当我试图理解这种行为时,我发现第二个 CHAIN_MSG_MAP 带有参数模板化类(在示例中为 CUpdateUI<CMainFrame>)未被识别。但是,如果第二个 CHAIN_MSG_MAPCMessageFilter,第三个是 CUpdateUI<CMainFrame>,那么 CMessageFilter 可以正确识别,但 CUpdateUI<CMainFrame> 无法识别。

当某些映射条目在映射 EnvDTE 中未被识别时,映射的结束也不会被识别。BEGIN_MSG_MAP_EX 还有另一个问题。如果映射以 BEGIN_MSG_MAP_EX 开头,以 END_MSG_MAP 结尾,那么 EnvDTE 无法识别映射之后的任何 CodeElement。我通过以下方式解决了这个问题:我在 stdafx.h 中添加了一个宏。

#define END_MSG_MAP_EX END_MSG_MAP

当我在与映射相同的头文件中添加此宏时,结果与没有宏时相同。但是,它在 stdafx.h 中运行良好。

Using the Code

主要功能位于文件 VSElements.hVSElements.cpp 中。这是我对 EnvDTE 关于 CodeElement 接口的封装。有一些类包装了函数、变量、映射、类和函数的参数。

这些包装器中最重要的是映射包装器 VSMap。我重写了这个类来获取映射条目,因为使用 EnvDTE::CodeElement(种类为 EnvDTE::vsCMElementMap)或 VCCodeModelLibrary::VCCodeMap 无法获得我们想要的精确结果。这些问题已在上面描述。

我创建了一个名为 VSMessageMap 的特殊类用于消息映射。我很抱歉文件中存在俄语注释,但没有足够的时间添加英文注释。您在工作时看到的所有对话框都在 \dialog 子目录中。用于解析资源的类在 \resources 子目录中。

结论

WTL Helper 的最新版本在此处:here您可以帮助我使 WTL Helper 更好。我需要有人为我绘制工具栏和图标,因为我认为它们现在不太好。

历史

  • 2004 年 11 月 24 日:0.6
    • 首次发布
  • 2004 年 11 月 25 日:0.6.0.1
    • 修复了安装程序中的错误
    • 将 WTL 文件添加到安装程序中
  • 2004 年 12 月
    • 0.7.5.0 1
      • 将 COM 接口指针替换为 _com_ptr 对象
      • 修复了 dialogs.datCAxDialogImpl 的错误名称
      • 修复了 Alex Cherepanov 报告的错误
      • 添加了在添加类型为 CString 的 DDX 映射条目时选择包含哪个 CString(ATL 或 WTL)的选项
    • 0.7.5.1 2
      • 修复了映射条目没有参数的错误
      • 在安装程序中放置了正确版本的插件
    • 0.7.6.0 9
      • 为 DDX 添加了两个小型增强功能
  • 2004 年 12 月 21 日:0.8.0.0
    • 移除了在添加控件消息的 DDX 变量时,在对话框的 ComboBox 中添加菜单和快捷键 ID
    • DDX 的一些小修复
    • static 消息添加了 WTL 文件
    • 添加了对嵌套类和命名空间的支持
    • 重新构建了选项对话框
  • 2004 年 12 月 23 日:0.8.1.0
    • 在选项对话框中添加了 关于 页面
    • 修复了 DDX 中的一个小错误
  • 2005 年 1 月 11 日:0.8.2.0
    • 修复了消息排序中的错误
    • 现在在 关于 选项卡中显示版本号
    • 区分系统选项和用户选项
    • 添加了两个选项
      • 将使用哪个 CRectCPointCSize 类:WTL 或 ATL
      • Variables 选项卡上仅显示对话框类或所有类
  • 2005 年 2 月 7 日:0.9.0.0
    • 大量修复和优化
    • 添加了对 ALT_MSG_MAP 的支持
    • 添加了对 REFLECT_NOTIFICATIONSFORWARD_NOTIFICATIONS 的支持
    • 更改了界面,现在对话框具有可调整大小的边框
    • 添加了对 XXX_RANGE_XXX 处理程序的支持
    • Custom Window Message 添加了对 MESSAGE_HANDLER_EX 的支持
    • 为工具提示添加了 WTL 文件
  • 2005 年 2 月 11 日:0.9.0.1
    • 修复了工具栏错误
  • 2005 年 2 月 24 日:0.9.0.2
    • 提高了稳定性
    • 修复了一个小错误
  • 2005 年 2 月 25 日:0.9.0.3
    • 修复了 Ning 报告的错误
    • 添加了为处理程序选择函数的功能(仅适用于通知或命令消息)
  • 2005 年 2 月 28 日:0.9.0.4
    • 修复了在 MFC 或控制台项目中启动 WTL Helper 时的错误
  • 2005 年 3 月 10 日:0.9.0.5
    • 添加了为 Windows 消息处理程序选择函数的功能,并改进了通知和命令消息
    • 修复了尝试移至未插入的函数时发生的崩溃
    • 修复了 Apply 按钮错误
  • 2005 年 3 月 16 日:0.9.0.6
    • 修复了资源文件加载错误
    • 添加了对 XP 主题的支持
  • 2005 年 3 月 21 日:0.9.0.7
    • 修复了对话框类中没有 enum IDD 时发生的崩溃
  • 2005 年 3 月 29 日:0.9.1.0
    • 修复了添加 DDX 变量对话框中控件类型检测错误的 bug
    • 将 EDITBOX 的 DDX 变量的默认类型设置为 UINT,该 EDITBOX 具有 ES_NUMBER 样式而不是 CString
    • 为 DDX 变量添加了自动生成名称的功能
  • 2005 年 4 月 26 日:0.9.1.1
    • 添加了输入控件 ID 和函数名的非常长的名称的可能性
  • 2005 年 5 月 23 日:0.9.1.2
    • 修复了添加函数
  • 2005 年 10 月 17 日:0.9.9.0
    • 为处理程序添加了颜色高亮显示
    • 添加了重写父函数(非 virtual)的可能性
    • 将菜单项添加到上下文菜单
    • 增加了与 Visual Studio 2005 Beta 2 的兼容性
    • 修复了一些错误
  • 2005 年 10 月 28 日:0.9.9.1
    • 为资源视图中的对话框项添加了上下文菜单
  • 2005 年 11 月 10 日:1.0
    • 更改了图标
    • Help->About 中添加了 WTL Helper 的信息
    • 修复了与 Visual Studio 2005 的一些兼容性问题
  • 2005 年 11 月 14 日:1.0.2
    • 修复了分割器错误
    • 修复了 Visual Studio 2005 的一些错误
  • 2006 年 1 月 26 日:1.1
    • 增加了对扩展消息反射宏的支持(WTL 7.5 及以上版本)
    • 添加了“保存上次显示的页面”选项
    • 添加了 WTL 版本信息的功能
    • 添加了允许为对话框添加 PreTranslateMessage()OnIdle() 的选项
  • 2006 年 2 月 17 日:1.1.3
    • 修复了文件名处理错误
    • 修复了尝试为对话框插入 PreTranslateMessage()OnIdle() 函数时发生的崩溃
    • 修复了 Visual studio 2005 工具栏问题
    • 一些小的修复和改进
  • 2006 年 3 月 28 日:1.1.4
    • 修复了在解决方案未加载时调用 WTL Helper 时发生的崩溃
  • 2006 年 7 月 7 日:1.1.5
    • 修复了 Visual studio 2005 工具栏问题
  • 2006 年 11 月 14 日:1.1.6
    • 修复了工具栏重复问题
  • 2007 年 4 月 27 日:1.1.7
    • 再次修复 :) Visual Studio 2005 中的工具栏问题
  • 2007 年 8 月 27 日:1.1.8
    • 修复了旧样式通知处理程序问题
    • 添加了为当前解决方案保存旧样式或新样式处理程序的选项
© . All rights reserved.