C# ListView所有者图形和列自动调整大小

C# ListView所有者图形和列自动调整大小,c#,listview,autoresize,C#,Listview,Autoresize,我有一个正在使用所有者图纸为一些子项绘制附加内容的项目 我发现,由于这些额外的内容占用了一些额外的空间,列表视图现在错误地计算了列“自动调整大小”的宽度,因此当有人自动调整某些列的大小时(例如,双击列调整大小手柄),列的大小会调整得太小,该列表视图中的文本在末尾以parenthases(…)呈现 是否有一种方法可以提示列表视图在自动调整大小时询问列的大小?您可以在以下两个场景中手动执行此操作: 如果要修复最小宽度和最大宽度, 在列表视图的列宽更改事件中使用此选项: 如果要修复列表视图列

我有一个正在使用所有者图纸为一些子项绘制附加内容的项目

我发现,由于这些额外的内容占用了一些额外的空间,列表视图现在错误地计算了列“自动调整大小”的宽度,因此当有人自动调整某些列的大小时(例如,双击列调整大小手柄),列的大小会调整得太小,该列表视图中的文本在末尾以parenthases(…)呈现

是否有一种方法可以提示列表视图在自动调整大小时询问列的大小?

您可以在以下两个场景中手动执行此操作:


  • 如果要修复
    最小宽度
    最大宽度

    列表视图的
    列宽更改
    事件中使用此选项:


  • 如果要修复
    列表视图列
    列宽
    ,请设置 所需的
    列宽度

    列表视图的
    列宽更改
    事件中使用此选项:


没有一条消息会告诉您何时要自动调整列的大小。但正如您所提到的,用户只有两种方式可以触发该操作:双击分隔符和
Ctrl-Shift-+
。你可以截取这两个,然后做任何你喜欢的事情

步骤#1:要拦截双击,您需要将
ListView
子类化,并侦听
HDN\u DIVIDERDBLCLICK
通知:

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case 0x4E: // WM_NOTIFY
            if (!this.HandleNotify(ref m))
                base.WndProc(ref m);
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}

protected bool HandleNotify(ref Message m) {

    const int HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25);

    NativeMethods.NMHEADER nmheader = (NativeMethods.NMHEADER)m.GetLParam(typeof(NativeMethods.NMHEADER));

    switch (nmheader.nhdr.code) {

        case HDN_DIVIDERDBLCLICKW:
            if (nmheader.iItem >= 0 && nmheader.iItem < this.Columns.Count) {
                this.AutoResizeColumn(nmheader.iItem);
                m.Result = (IntPtr)1; // prevent the change from happening
                return true;
            }
            break;

        default:
            break;
    }

    return false;
}
受保护的覆盖无效WndProc(参考消息m){
开关(m.Msg){
案例0x4E://WM\u NOTIFY
如果(!本手册通知(参考m))
基准WndProc(参考m);
打破
违约:
基准WndProc(参考m);
打破
}
}
受保护的bool HandleNotify(参考消息m){
const int HDN_DIVIDERDBLCLICKW=(HDN_FIRST-25);
NativeMethods.NMHEADER NMHEADER=(NativeMethods.NMHEADER)m.GetLParam(typeof(NativeMethods.NMHEADER));
开关(nmheader.nhdr.code){
案例HDN\U分区BLCLICKW:
如果(nmheader.iItem>=0&&nmheader.iItem
当然,您必须实现
AutoResizeColumn()
,才能执行您想要的操作

第二步。要截取Ctrl-Shift-+,需要覆盖
ProcessKeyPreview
。我会告诉你怎么做。在覆盖中,您将为每个列调用
AutoResizeColumn()

替代方法
如果将
ListViewItems
构造为每个子项都是一个“W”字符串,长度与要绘制的数据相同,则控件将使用这些字符串自动计算此列。这可能是一种更简单的方法。

这实际上与自动调整大小功能不同。“自动调整大小功能将在双击拆分器时调整列的大小。”我说的对吗?是的-列会自动调整为内容的正确宽度-这不是您在上述两种情况下所做的操作。在我所做的操作中,列会调整为固定宽度[之前设置]!这不是自动调整大小功能所做的。当用户双击列的调整大小手柄(或使用Ctrl+Shift+
+
键盘快捷键)时,自动调整大小功能仅将列调整为合适的值(基于内容)。列的大小不是固定的,但是,用户仍然可以自由地将列的大小调整为他们想要的任何宽度。
   ListView ColumnList = sender as ListView;
   e.Cancel = true;
   e.NewWidth = ColumnList.Columns[e.ColumnIndex].Width;
protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case 0x4E: // WM_NOTIFY
            if (!this.HandleNotify(ref m))
                base.WndProc(ref m);
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}

protected bool HandleNotify(ref Message m) {

    const int HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25);

    NativeMethods.NMHEADER nmheader = (NativeMethods.NMHEADER)m.GetLParam(typeof(NativeMethods.NMHEADER));

    switch (nmheader.nhdr.code) {

        case HDN_DIVIDERDBLCLICKW:
            if (nmheader.iItem >= 0 && nmheader.iItem < this.Columns.Count) {
                this.AutoResizeColumn(nmheader.iItem);
                m.Result = (IntPtr)1; // prevent the change from happening
                return true;
            }
            break;

        default:
            break;
    }

    return false;
}