使用 WndProc 自动调整 ListView 控件的最后一列大小






4.59/5 (25投票s)
2002 年 11 月 25 日
3分钟阅读

322122
展示了一种快速简便的方法来自动调整 ListView 控件的最后一列的大小。
引言
我一直很不喜欢网格或列表控件不自动调整其列大小以适应控件画布。你们中的一些人可能还记得早期的 OCX 和 ActiveX 控件,它们实现了自动调整最后一列大小的属性来解决这个问题。本质上,网格或列表视图中的最后一列会自动扩展以占用任何可用空间。当调整表单大小,或者用户在运行时调整列宽时,最后一列的大小会自动增加或减小,以使该列与控件的右边缘对齐。
我喜欢 Windows 资源管理器的外观,也喜欢 ListView 控件的功能和外观 - 我们只需要对最后一列做一些处理!在互联网上搜寻寻找示例或线索后,最终结果是,找到解决方案证明很困难,但实现解决方案实际上非常简单。
设置列大小
实际上,ListView
类确实提供了一个 ColumnHeader.Width
属性。 MSDN 文档描述了与自动调整列大小相关的两个特殊值,如下所示:“要调整列中最长项目的大小的宽度,请将 Width
属性设置为 -1。要自动调整到列标题的宽度,请将 Width
属性设置为 -2”。
将 Width
设置为 -2 的一个特殊功能是,它还自动将最后一列扩展到控件的右边缘。这似乎解决了问题,但它只执行一次自动调整大小,如果用户在运行时调整任何列宽,或者将 ListView
控件设置为随表单调整大小,则不会保留该自动调整大小。
响应更改
当我第一次处理这个问题时,我认为答案在于响应用户调整列大小或控件调整大小时的某些事件,或者对 ListView
进行子类化以访问某些受保护的接口。 实际上,用于提供 ListView.Columns
成员实现的 ColumnHeaderCollection
和 ColumnHeader
类完全埋在父控件内部。
我的下一个方法是查看 Win32 API,但也面临同样的障碍。 我找不到任何直接访问 ListView 列标题的示例。
解决此类棘手问题的最后一步是查看 Window 消息循环。 .NET 控件的一个方便功能是它们公开了 WndProc
方法来处理控件接收到的消息。 通过分析在调整列宽时或调整控件大小时通过 ListView
控件泵送的消息,我发现隐藏的 ColumnHeader
类将 WM_PAINT
消息发送到父控件,以在调整列大小期间通知它,以及当用户完成调整列大小时作为最后一步。 WM_PAINT
方法也是用户调整 ListView
控件大小时处理的最后一条消息。
解决方案
要实现最后一列的自动调整大小,请对 ListView
控件进行子类化,并重写 WndProc
方法。
protected override void WndProc( ref Message message )
{
const int WM_PAINT = 0xf ;
// if the control is in details view mode and columns
// have been added, then intercept the WM_PAINT message
// and reset the last column width to fill the list view
switch ( message.Msg )
{
case WM_PAINT:
if ( this.View == View.Details && this.Columns.Count > 0 )
this.Columns[this.Columns.Count - 1].Width = -2 ;
break ;
}
// pass messages on to the base control for processing
base.WndProc( ref message ) ;
}