绘制在列表视图列标题栏区的外(Drawing outside of column area in l

2019-07-18 05:05发布

是否有可能的OwnerDraw ListView的整列标题部分? (包括该区域的列标题的右侧)? 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);
}

可用图形实例的ClipBounds属性指示未绑定的区域(从大的负数到大正)。 但没有什么是绘制的最后一列的columnHeader区域之外。

没有任何人有一个解决方案?

Answer 1:

我被杰弗里谭在该职位的答案感到惊讶。 他的溶液不能工作,因为代码试图标题控制客户区之外绘制。 所述hDC自定义绘制(因此所有者绘图)是用于控制的客户区中使用,因此不能用在非客户区作画。 到在报头控制最右边的列右侧的区域是在非客户区。 因此,你需要不同的解决方案。

可能的解决方案

  1. 高科技和部分有效

您可以启用通过客户端区域外绘制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. 技术含量低,但丑

一个额外的空列添加到您的控制,所有者绘制但是你想它不看,使它非常广泛,并关闭水平滚动(可选)。

我知道这是可怕的,但你要找的建议:)

  1. 最有效的,但还不够完善

使用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);
    }
}

这给了这一点:

[读了这个答案,我认为这是过于卖力的例子:)希望你找到的东西在这里帮助。]



文章来源: Drawing outside of column area in listview column header