关于标头控件

标头控件是一个窗口,通常位于文本或数字列的上方。 它包含每列的标题,可以分为多个部分。 用户可以拖动分隔符,分隔各个部分以设置每列的宽度。 下图显示一个已标记列的标头控件,用于提供有关目录中文件的详细信息。

screen shot of a dialog box with a three-column header control

可以使用 CreateWindowEx 函数并指定 WC_HEADER 窗口类和适当的标题控件样式来创建标头控件。 加载公共控件 DLL 时,会注册此窗口类。 要确保此 DLL 已加载,请使用 InitCommonControlsEx 函数。 创建标头控件后,可以将其分为各个部分,设置每个部分中的文本,并使用标头窗口消息控制窗口的外观。

可以将标头控件创建为另一个控件的子窗口,例如列表框。 但是,父控件不知道标头控件,并且不允许标头占用空间,列表项将在标头后面显示结果。 如果要使用列表框中的标头控件或其他控件,父控件必须是所有者绘制的控件,以便所有项都显示在正确的位置。

列表视图控件已具有标头控件。 使用 LVM_GETHEADERListView_GetHeader 检索现有控件,而不是为列表视图控件创建标头控件。

标头控件大小和位置

通常,必须设置标头控件的大小和位置,以适应特定矩形的边界,例如窗口的工作区。 通过使用 HDM_LAYOUT 消息,可以从标头控件中检索适当的大小和位置值。

发送 HDM_LAYOUT 时,指定 HDLAYOUT 结构的地址,该结构包含标头控件要占用的矩形的坐标,并提供指向 WINDOWPOS 结构的指针。 该控件填充 WINDOWPOS 结构,其大小和位置值适合将控件定位到指定矩形的顶部。 高度值是控件的设备上下文中控件的水平边框高度和当前所选字体中字符的平均高度的总和。

如果要使用 HDM_LAYOUT 设置标头控件的初始大小和位置,请设置控件的初始可见性状态,使其隐藏。 发送 HDM_LAYOUT 以检索大小和位置值后,可以使用 SetWindowPos 函数设置新的大小、位置和可见性状态。

标头控件通常有多个标头项,用于定义控件的列。 通过向标头控件发送 HDM_INSERTITEM 消息,可以将项添加到该控件。 该消息包括 HDITEM 结构的地址。 此结构定义标头项的属性,其中包括字符串、位图图像、初始大小和应用程序定义的 LPARAM 值。

项的 HDITEM 结构的 fmt 成员可以包含 HDF_STRINGHDF_BITMAP 标志,以指示控件是显示项的字符串还是位图。 如果要同时显示字符串和位图,请通过设置 fmt 成员以包含 HDF_OWNERDRAW 标志来创建所有者绘制的项。 HDITEM 结构还指定格式标志,用于指示控件是居中、左对齐还是右对齐项矩形中的字符串或位图。

HDM_INSERTITEM 返回新添加的项的索引。 可以使用其他消息中的索引来设置属性或检索有关该项的信息。 可以使用 HDM_DELETEITEM 消息指定要删除的项的索引来删除项。

可以使用 HDM_SETITEM 消息设置现有标头项的属性,使用 HDM_GETITEM 消息检索项的当前属性。 若要检索标头控件中项的计数,请使用 HDM_GETITEMCOUNT 消息。

所有者绘制的标头控件

可以将标头控件的各个项定义为所有者绘制的项。 使用此技术可以更好地控制标头项的外观。

可以使用 HDM_INSERTITEM 消息将所有者绘制的新项插入标头控件或使用 HDM_SETITEM 消息将现有项更改为所有者绘制的项。 这两条消息都包含 HDITEM 结构的地址,该结构应将 fmt 成员设置为 HDF_OWNERDRAW 值。

当标头控件必须绘制所有者绘制的项时,会将 WM_DRAWITEM 消息发送到父窗口。 消息的 wParam 参数是标头控件的子窗口标识符,lParam 参数是 DRAWITEMSTRUCT 结构的地址。 父窗口使用结构中的信息来绘制项。 对于标头控件中的所有者绘制的项, DRAWITEMSTRUCT 结构包含以下信息。

成员 说明
CtlType ODT_HEADER 所有者绘制的控件类型。
CtlID 标头控件的子窗口标识符。
itemID 要绘制的项的索引。
itemAction ODA_DRAWENTIRE 绘制操作标志。
ItemState 如果光标位于项上,并且鼠标按钮已关闭,则显示 ODS_SELECTED 绘制操作标志。 否则,此成员为零。
hwndItem 标头控件的句柄。
hDC 标头控件的设备上下文的句柄。
rcItem 要绘制的标头项的坐标。 坐标相对于标头控件的左上角。
itemData 与项关联的应用程序定义的 32 位值。

 

标头控件筛选器

通过为标头控件指定 HDS_FILTERBAR 窗口样式,可以启用列标头下筛选器编辑框的放置。 编辑框旁边会显示一个筛选器按钮。 可以通过响应 HDN_BEGINFILTEREDITHDN_ENDFILTEREDITHDN_FILTERBTNCLICKHDN_FILTERCHANGE 通知代码来实现筛选。

默认情况下,编辑框包含用户输入文本的提示。 可以使用 Header_ClearFilterHeader_ClearAllFilters 将编辑框还原为此默认状态。

下面的代码示例演示如何从列表视图控件中检索标头控件并添加筛选器栏。

// hList is the HWND of the list-view control.
HWND hHeader = ListView_GetHeader(hList);
LONG_PTR styles = GetWindowLongPtr(hHeader, GWL_STYLE);
SetWindowLongPtr(g_hHeader, GWL_STYLE, styles | HDS_FILTERBAR);

默认标头控件消息处理

本部分介绍由 WC_HEADER 窗口类的窗口过程处理的窗口消息。

Message 已执行的处理
WM_CREATE 初始化标头控件。
WM_DESTROY 取消初始化标头控件。
WM_ERASEBKGND 使用控件的当前背景色填充标头控件的背景。
WM_GETDLGCODE 返回 DLGC_WANTTABDLGC_WANTARROWS 值的组合。
WM_GETFONT 返回当前字体的句柄,标头控件使用该句柄绘制其文本。
WM_LBUTTONDBLCLK 捕获鼠标输入。 如果鼠标光标位于分隔符上,控件将发送 HDN_BEGINTRACK 通知代码并开始拖动分隔符。 如果光标位于某个项上,则该项以按下状态显示。
WM_LBUTTONDOWN WM_LBUTTONDBLCLK 消息相同。
WM_LBUTTONUP 释放鼠标捕获。 如果控件跟踪鼠标移动,将发送 HDN_ENDTRACK 通知代码并重新绘制标头控件。 否则,该控件将发送 HDN_ITEMCLICK 通知代码,并重新绘制已单击的标头项。
WM_MOUSEMOVE 如果拖动分隔线,控件将发送 HDN_TRACK 通知代码,并在新位置显示该项。 如果鼠标左键按下且光标位于某个项上,则该项以按下状态显示。
WM_NCCREATE 分配并初始化内部数据结构。
WM_NCDESTROY 在取消初始化标头控件后释放标头控件分配的资源。
WM_PAINT 绘制标头控件的无效区域。 如果 wParam 参数为非 NULL,则控件假定该值为 HDC,并使用该设备上下文进行绘制。
WM_SETCURSOR 设置光标形状,具体取决于光标是位于分隔线还是标头项上。
WM_SETFONT 在标头控件的设备上下文中选择新的字体句柄。