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

使用 Win32 在 Windows CE 中创建标题栏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.24/5 (14投票s)

2003年8月31日

CPOL

7分钟阅读

viewsIcon

83432

downloadIcon

484

在 Windows CE 中创建和使用标题栏样式的控件。

引言

本文展示了如何使用简单的 Common Control 库调用和消息创建 Microsoft 风格的标题栏和状态栏控件。不需要 GDI 绘图代码,因为所有这些功能都已内置到通用控件库中。

背景

对于最近的一个项目,我想创建一个类似 Microsoft 在 Pocket PC 平台上大多数应用程序中使用的标题栏。但是,我不想使用 MFC,部分原因是其大小。

下面的对话框来自 Pocket PC 2002 上的收件箱应用程序。我已屏蔽了不感兴趣的区域,因此您可以看到主应用程序窗口上的标题栏控件和状态栏控件。

WinCE_HeaderBarControl/ppc_inbox.gif

图片上有两个有趣的特征。第一个特征是顶部的标题控件。它有一个下拉组合框,允许用户在右侧选择排序选项,并在左侧选择相关的文件夹和邮件存储。为了保持 Windows UI 的外观和感觉,如果用户点击下拉菜单,则只有下拉菜单会突出显示。如果用户点击按钮上的任何位置,则整个按钮都会突出显示。

第二个特征是使用底部的“状态栏”向用户显示有关当前文件夹状态的信息,但稍后会详细介绍。

对于标题控制栏,我的第一个想法是使用标题通用控件来创建图片中的效果。然而,事实证明这是误导性的,我在使用 Remote Spy++ 进行了一些工作后才发现。原来被认为是标题控件的实际上是工具栏控件。

现在,既然已经确定标题栏控件实际上不是标题控件,而是工具栏,那么问题就变成了:它是如何实现的?

查看通用控件库会发现,工具栏控件确实支持下拉按钮,但当实现它们时,组合框下拉按钮有一个难看的右侧边框,以及左侧边框和文本之间的间隙。

解决第二个问题很简单,当添加工具栏按钮时,我们只想显示空白,而不是空白位图。为了纠正这一点,您需要指定要使用的位图是 I_IMAGENONE(相当于 -2),而不是 -1(表示只显示一个空位图)。

第一个问题更麻烦。如何从组合框中删除分隔线?最初,我以为我需要完全重写绘图代码才能使其工作。幸运的是,在通用控件头文件中有一个未文档化的宏 CDRF_NOVERTBAR。在工具栏控件重绘时,将其作为自定义绘图阶段的一部分使用,可以删除分隔线。

以上是一个经过修正的标题栏控件,分隔线和空白图标已移除。据我所知,这段代码现在反映了标准 Windows 应用程序中控件的功能。

以下是 WM_NOTIFY 消息处理程序中 NM_CUSTOMDRAW 函数的代码摘录。请注意,如何告知通用控件模块的通知处理程序,当工具栏中的项目需要重新绘制时,每个项目都需要重新绘制。然后,当一个项目即将重新绘制时,返回 CDRF_NOVERTBAR 代码,通知通用控件模块当前正在绘制的项目应不带垂直分隔线绘制。当然,也可以通过检查 NMCUSTOMDRAW 结构中的 dwItemSpeclItemlParam 部分中的项目,逐项执行此操作。

case NM_CUSTOMDRAW:
    {
        LPNMCUSTOMDRAW  lpnmcd = (LPNMCUSTOMDRAW)lParam;
        switch(lpnmcd->dwDrawStage)
        {
            case CDDS_PREPAINT
                return CDRF_NOTIFYITEMDRAW;
            case CDDS_ITEMPREPAINT:
                return CDRF_NOVERTBAR
        }
    }

最后一部分是处理工具栏按钮被点击时的命令。工具栏按钮由两部分组成,因为该按钮是下拉式按钮。当按下下拉菜单时,需要模拟相应按钮被按下的情况。为此,需要处理 TBN_DROPDOWN 通知命令,并根据所选的命令向主窗口发布 WM_COMMAND 消息。当点击与按钮关联的命令时,消息会路由到父窗口,在那里它像按下工具栏按钮时正常的 WM_COMMAND 处理程序中处理。

作为所提供示例的一部分,它加载了一个菜单资源并使用 TrackPopupMenu 显示它。您还可以构建和显示树视图或类似的东西。实际上,zip 文件中包含的示例源代码正是这样做的,用于左侧的下拉按钮,但我在此处没有详细说明代码。

处理状态栏时,它有点简单,因为创建状态栏时,状态栏成功创建,但它不会出现在屏幕上。问题在于控件设置为与屏幕底部对齐而不是菜单栏顶部对齐,因此当菜单栏在屏幕底部创建时,它实际上会遮挡状态栏,因此状态栏看起来是隐形的,但实际上隐藏在菜单栏后面。

为了解决这个问题,只需在创建控件时使用 CCS_NOPARENTALIGN 窗口样式,这样控件就不会与任何客户端区域对齐。当然,您还需要手动重新对齐其周围的控件,以适应菜单栏和主窗口上其余控件之间的状态栏。您还会看到,状态栏最初显示时,它带有一个边框和创建窗口时默认的文本。我们只需使用 SB_SETTEXT 消息在窗口中设置文本。

使用代码

Win32 示例中的代码只是一个基本的 Pocket PC 2002 应用程序,带有“Hello World”默认实现。

这被扩展为在窗口顶部创建一个新的工具栏窗口。要了解菜单栏控件是如何创建的,请查看名为 CreateHeaderBar 的函数。

这里需要注意的主要几点是,工具栏窗口已使用 TBSTYLE_CUSTOMERASETBSTYLE_FLATTBSTYLE_LIST 创建。最重要的是 TBSTYLE_CUSTOMERASE。这将允许拦截绘制阶段并替换为新的自定义绘制处理程序绘制阶段,从而允许移除下拉按钮上的垂直条。

工具栏成功创建后,可以将两个按钮添加到控件中。实际上有三个按钮,中间按钮的宽度是扣除左右按钮大小后剩余的宽度计算出来的,只是一个不可按压的标准按钮。

此代码位于辅助函数 CreateHeaderRowButtons 中。该函数将允许一个左按钮和/或一个右按钮,但至少必须存在一个。传递 TBBUTTON 结构的原因是它允许程序员最大程度地配置按钮的外观和感觉。

需要注意的一点是,在获取按钮宽度时,您需要调用 TB_GETITEMRECT 而不是 TB_GETBUTTONFINO,因为前者可以获取自动调整大小按钮的正确宽度,而后者则不能。

状态栏的使用更像是一个疏忽而不是其他。它实际上很容易纠正,因为它只需要将样式从隐式的 CCS_ALIGNBOTTOM 更改为 CCS_NOPARENTALIGN,然后程序员就可以控制状态栏在屏幕上的大小和位置。

下拉控件的处理在 WM_NOTIFY 命令处理程序中的 TBN_DROPDOWN 子命令中完成。这只是发布与按钮关联的命令的 WM_COMMAND 消息。

关注点

如果 Microsoft 也能为 CE 提供关于自定义绘制功能的示例和文档,并记录 CDRF_NOVERTBAR 样式,那就太好了。

历史

修复了下载示例问题

© . All rights reserved.