是否可以拥有列表视图的整个列标题部分? (包括列标题右侧的区域)? ListView位于详细信息视图中。

这里的答案表明剩余空间可以与最后一个列标题一起绘制: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

但它似乎根本不起作用 - 在标题区域之外没有任何内容。

建议的解决方案基于在通过的边界之外绘图:

if (e.ColumnIndex == 3) //last column index
{
    Rectangle rc = new Rectangle(e.Bounds.Right, //Right instead of Left - offsets the rectangle
            e.Bounds.Top, 
            e.Bounds.Width, 
            e.Bounds.Height);

    e.Graphics.FillRectangle(Brushes.Red, rc);
}

可用Graphics实例的ClipBounds属性表示未绑定区域(从大负数到大正数)。但是在最后一列的列标题区域之外没有任何内容。

有人有解决方案吗?

有帮助吗?

解决方案

我对Jeffery Tan在那篇文章中的回答感到惊讶。他的解决方案无法工作,因为代码试图在标题控件客户区之外绘制。自定义绘图(因此所有者绘图)中使用的 hDC 用于控件的客户区域,因此不能用于在非客户区域中绘制。标头控件中最右列右侧的区域位于非客户区域中。所以你需要一个不同的解决方案。

可能的解决方案

  1. 高科技,部分有效
  2. 您可以使用 GetDC() WinAPI调用在客户区外启用绘图:

    [System.Runtime.InteropServices.DllImport("user32")]
    private static extern IntPtr GetDC(IntPtr hwnd);
    [System.Runtime.InteropServices.DllImport("user32")]
    private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
    
    public static IntPtr GetHeaderControl(ListView list) {
        const int LVM_GETHEADER = 0x1000 + 31;
        return SendMessage(list.Handle, LVM_GETHEADER, 0, 0);
    }
    

    在您的列绘制事件处理程序中,您将需要以下内容:

    if (e.ColumnIndex == 3) //last column index
    {
      ListView lv = e.Header.ListView;
      IntPtr headerControl = NativeMethods.GetHeaderControl(lv);
      IntPtr hdc = GetDC(headerControl);
      Graphics g = Graphics.FromHdc(hdc);
    
      // Do your extra drawing here
      Rectangle rc = new Rectangle(e.Bounds.Right, //Right instead of Left - offsets the rectangle
                e.Bounds.Top, 
                e.Bounds.Width, 
                e.Bounds.Height);
    
        e.Graphics.FillRectangle(Brushes.Red, rc);
    
      g.Dispose();
      ReleaseDC(headerControl, hdc);
    }
    

    但问题在于,由于您的绘图位于客户区之外,因此Windows并不总是知道何时应该绘制它。因此它有时会消失,然后在Windows认为标题需要重新绘制时重新绘制。

    1. 低技术但丑陋
    2. 为您的控件添加一个额外的空列,所有者绘制它看起来你想要的,使它非常宽,并关闭水平滚动(可选)。

      我知道这太可怕了,但你正在寻找建议:)

      1. 最有效,但仍然不完美
      2. 使用 ObjectListView 。 .NET ListView的这个包装器允许您在列表中添加叠加层 - 叠加层可以在ListView中的任何位置绘制,包括标题。 [声明:我是ObjectListView的作者,但我仍然认为这是最好的解决方案]

        public class HeaderOverlay : AbstractOverlay
        {
            public override void Draw(ObjectListView olv, Graphics g, Rectangle r) {
                if (olv.View != System.Windows.Forms.View.Details)
                    return;
        
                Point sides = NativeMethods.GetColumnSides(olv, olv.Columns.Count-1);
                if (sides.X == -1)
                    return;
        
                RectangleF headerBounds = new RectangleF(sides.Y, 0, r.Right - sides.Y, 20);
                g.FillRectangle(Brushes.Red, headerBounds);
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;
                g.DrawString("In non-client area!", new Font("Tahoma", 9), Brushes.Black, headerBounds, sf);
            }
        }
        

        这给出了这个:

        [阅读这个答案,我认为这是一个太努力的例子:)希望你能在这里找到有用的东西。]

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top