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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (25投票s)

2002 年 11 月 25 日

3分钟阅读

viewsIcon

322122

展示了一种快速简便的方法来自动调整 ListView 控件的最后一列的大小。

Sample Image - ListViewAutoSize.jpg

引言

我一直很不喜欢网格或列表控件不自动调整其列大小以适应控件画布。你们中的一些人可能还记得早期的 OCX 和 ActiveX 控件,它们实现了自动调整最后一列大小的属性来解决这个问题。本质上,网格或列表视图中的最后一列会自动扩展以占用任何可用空间。当调整表单大小,或者用户在运行时调整列宽时,最后一列的大小会自动增加或减小,以使该列与控件的右边缘对齐。

我喜欢 Windows 资源管理器的外观,也喜欢 ListView 控件的功能和外观 - 我们只需要对最后一列做一些处理!在互联网上搜寻寻找示例或线索后,最终结果是,找到解决方案证明很困难,但实现解决方案实际上非常简单。

设置列大小

实际上,ListView 类确实提供了一个 ColumnHeader.Width 属性。 MSDN 文档描述了与自动调整列大小相关的两个特殊值,如下所示:“要调整列中最长项目的大小的宽度,请将 Width 属性设置为 -1。要自动调整到列标题的宽度,请将 Width 属性设置为 -2”。

Width 设置为 -2 的一个特殊功能是,它自动将最后一列扩展到控件的右边缘。这似乎解决了问题,但它只执行一次自动调整大小,如果用户在运行时调整任何列宽,或者将 ListView 控件设置为随表单调整大小,则不会保留该自动调整大小。

响应更改

当我第一次处理这个问题时,我认为答案在于响应用户调整列大小或控件调整大小时的某些事件,或者对 ListView 进行子类化以访问某些受保护的接口。 实际上,用于提供 ListView.Columns 成员实现的 ColumnHeaderCollectionColumnHeader 类完全埋在父控件内部。

我的下一个方法是查看 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 ) ;
}
© . All rights reserved.