gpt4 book ai didi

c# - 在 ListView 列标题中的列区域之外绘制

转载 作者:太空狗 更新时间:2023-10-30 01:12:02 25 4
gpt4 key购买 nike

是否可以自己绘制 ListView 的整个列标题部分? (包括列标题右侧的区域)? ListView 处于详细信息 View 中。

此处的答案表明剩余空间可以与最后一列标题一起绘制: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 属性指示未绑定(bind)区域(从大负数到大正数)。但在最后一列的列标题区域之外没有绘制任何内容。

有人对此有解决方案吗?

最佳答案

我对 Jeffery Tan 在那篇帖子中的回答感到惊讶。他的解决方案行不通,因为代码试图在标题控件客户区之外绘制。在自定义绘图(以及所有者绘图)中使用的 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);
}
}

这给出了这个: alt text

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

关于c# - 在 ListView 列标题中的列区域之外绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1433292/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com