在 MFC 中创建 HeaderBar 控件
在 Windows CE 的 MFC 中创建和使用头栏控件。
引言
继我上一篇关于创建头栏控件的文章之后,我决定在 MFC 中提供一个实现,该实现应具有 MFC 类库中标准通用控件所具有的质量和支持级别。开发人员将能够像使用独立类一样使用该类。
背景
头栏控件类有三个基本设计目标:
- 集成并使用 MFC 类库。
- 该类不应要求开发人员使用任何钩子或回调,也不需要他们做任何特殊的事情来使用该类。
- 代码应尽可能轻量级,并尽可能在更多 Windows CE 变体中工作。
简而言之,头栏控件应该能够在主窗口的左侧和/或右侧添加一个按钮或下拉按钮。然后,此按钮应向主框架窗口发送一个命令,该命令将被路由到当前视图或文档,就像 MFC 中的任何普通消息一样。
在Inbox应用程序中,头栏控件是一个工具栏通用控件,因此现在可以选择是派生自CToolbarCtrl
还是从CWnd
派生。经过决定,新控件将派生自CWnd
,原因如下。首先,工具栏包含与头栏控件无关的大量功能。其次,如果使用工具栏控件,则需要将基类设为私有或受保护,这在 MFC 中难以使用和解释。最后,我认为该控件应该是一个轻量级的包装器,围绕一个工具栏窗口,而工具栏控件具有过多的开销,这掩盖了我试图做的事情。
为此,复制了工具栏控件的代码,并删除了所有与头栏控件无关的函数。然后提供了用于在左侧和右侧添加按钮的公共函数。
有一个警告,为了与 MFC 窗口的样式保持一致,create 函数将样式参数作为第一个参数,因此无法默认此参数。在HeaderBar.h文件的顶部有一个定义HEADERBAR_DEFSTYLE
,其中包含推荐的默认样式。内部唯一强制的样式是CCS_NODIVIDER
和TBSTYLE_CUSTOMERASE
。
提供了AddLeftButton
和AddRightButton
函数,用于在头栏的左侧和/或右侧添加按钮。这隐含地假定按钮 ID 永远不会为零,因为此 ID 保留给分隔符按钮,此外,用户只会向左侧和/或右侧添加一个按钮,因此头栏控件中最多会有三个按钮。如果这些条件中的任何一个不满足,则会触发断言。
当在左侧或右侧添加按钮时,使用AdjustSeperatorButtonSize
函数重新计算分隔符按钮的大小。
将按钮添加到工具栏的实际代码与添加普通工具栏按钮的代码完全相同,因此此处未作详细说明。
开发的下一个阶段是处理分隔条的自定义绘制,以便下拉按钮显示为主下拉按钮的一部分,而不是由分隔条分隔。将自定义绘制链接到控件的最简单方法是使用消息反射。这在 MFC for Win32 随附的 Win32 文档中已有所介绍,在 technote 62 中。
我们使用ON_NOTIFY_REFLECT
宏在控件内部处理NM_CUSTOMDRAW
消息。MFC 允许我们的控件首先处理通知宏,然后再将其传递给父窗口,在本例中是框架窗口。然后,自定义绘制消息会告诉通用控件库绘制工具栏中的每个项(CDDS_PREPAINT
阶段返回CDRF_NOTIFYITEMDRAW
)。然后,当调用CDDS_ITEMPREPAINT
阶段时,它会返回CDRF_NOVERTBAR
。这告诉通用控件库不要为工具栏中的下拉按钮绘制分隔条。
开发的最后阶段是确保头栏控件能够成功地与 MFC 中的文档视图体系结构共存。当 Windows 需要调整主框架大小时,它会调用RecalcLayout
函数,该函数随后使用名称毫不意外的RepositionBars
函数重新定位控件条。然后,此调用会获取不在默认范围 0 和 0xFFFF 之间的子控件所占用的矩形,方法是向窗口发送WM_SIZEPARENT
消息。这还为控件提供了正确重新定位自己的机会。然后,框架中剩余的空间将被分配给视图。
因此,头栏的实现已经完成。只需要将两个文件添加到项目中。第一个是HeaderBar.h,它是控件的头文件;第二个是HeaderBar.cpp,它是实现文件。实际上,这里的一些单行辅助函数应该放在它们自己的.inl文件中,但这尚未完成,主要是因为它会分散对代码的注意力。头文件已使用 doxygen 格式布局。实现文件中包含许多注释和断言,这些注释和断言应能突出显示任何问题或回答有关代码功能的疑问。
使用代码
使用CHeaderBarCtrl
是一项相当简单的练习。通常,该栏将在主框架窗口的OnCreate
函数中创建。在CMainFrame
类中为CHeaderBarCtrl
类创建一个成员变量,然后在OnCreate
函数中创建一个新的窗口实例,记住要设置样式,因为它不是自动设置的。(您可以使用HEADERBAR_DEFSTYLE
定义作为默认值)接下来,如果使用位图和任何字符串,请添加它们,最后将左侧和右侧按钮添加到头控件并设置所有者。创建和设置控件就是这样。
接下来,使用AddLeftButton
和AddRightButton
命令添加左侧和右侧按钮。
所需的最后一步是添加命令处理程序,用于处理按钮按下时的操作。这些可以在文档或视图中完成。我个人更喜欢在视图中执行此操作,并且实现中也是如此。
在提供的示例中,右侧有一个下拉按钮,左侧有一个树形视图。该示例几乎与 Win32 实现随附的原始示例相同,只是它已被修改为真正的 MFC 端口,现在关闭树形控件的唯一方法是单击左侧按钮。
关注点
如果您想放置一个窗口以便与框架中的视图共享空间并共存,那么WM_SIZEPARENT
函数很有用。
如果您想将通知方法封装在自己的类中,而不是必须将代码粘贴到父类的处理程序中,那么ON_NOTIFY_REFLECT
宏非常有用。
历史
目前还没有。