在绘制列表视图的列标题栏区域以外 [英] Drawing outside of column area in listview column header

查看:220
本文介绍了在绘制列表视图的列标题栏区域以外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能的OwnerDraw ListView的整列标题部分? (包括该地区的列标题的右侧)? ListView控件是详细信息视图。

Is it possible to ownerdraw the entire column header section of a listview? (including the region to the right of the column headers)? ListView is in Details View.

这是答案在这里表示余下的空间可以用最后一个栏标题一起得出:<一href=\"http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx\" rel=\"nofollow\">http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

An answer here indicates that the remaining space can be drawn along with the last column header: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic32927.aspx

但它似乎并没有在所有的工作 - 什么也不绘制头部区域之外

But it does not seem to work at all - nothing is drawn outside header area.

所提出的解决方案是基于绘制传递界以外

The proposed solution is based on drawing outside of the passed Bounds:

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区域之外。

The ClipBounds property of the available Graphics instance indicates an unbound area (from large negative numbers to large positive). But nothing is drawn outside the columnheader area of the last column.

是否有人有办法解决这个?

Does anybody have a solution for this?

推荐答案

我对杰弗里谭在该职位的回答感到惊讶。他的解决方案不能工作,因为code尝试将头控制客户区之外绘制。在的hDC 自定义中使用的图纸(因此车主图)是控制的客户区,所以不能用在非客户区进行绘制。到在报头控制最右列的右侧的区域是在非客户区。因此,你需要不同的解决方案。

I'm surprised by Jeffery Tan's answer in that post. His solution cannot work, since the code tries to draw outside of the header control client area. The hDC used within custom drawing (and hence owner drawing) is for the client area of the control, and so cannot be used to paint in the non-client area. The area to the right of the right most column in a header control is in non-client area. So you need a different solution.

可能的解决方案

Possible Solutions


  1. 高科技和部分有效

您可以启用使用客户端区域外绘制的GetDC() WinAPI的电话:

You can enable drawing outside the client area by using the GetDC() WinAPI call:

[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);
}

在您的专栏平局的事件处理程序,你需要这样的:

In your column draw event handler, you will need something like this:

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认为头需要重绘重绘。

But the problem with this is that since your drawing is outside the client area, Windows doesn't always know when it should be drawn. So it will disappear sometimes, and then be redrawn when Windows thinks the header needs repainting.


  1. 低技术,但丑

一个额外的空列添加到您的控制,所有者绘制但是你想它做一下,让它很宽,并关闭横向滚动(可选)。

Add an extra empty column to your control, owner draw it do look however you want, make it very wide, and turn off horizontal scrolling (optional).

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

I know this is horrible, but you're looking for suggestions :)


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

使用 ObjectListView 。围绕.NET的ListView此包装可以让你覆盖添加到您的列表 - 覆盖可以在ListView内的任何地方画画,包括头。 [声明:我ObjectListView的作者,但我仍然认为这是最好的解决方案]

Use ObjectListView. This wrapper around a .NET ListView allows you to add overlays to your list -- an overlay can draw anywhere within the ListView, including the header. [Declaration: I'm the author of ObjectListView, but I still think it is best solution]

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

这给出了这样的:

This gives this:

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

[Reading over this answer, I think this is an example of trying too hard :) Hope you find something here helpful.]

这篇关于在绘制列表视图的列标题栏区域以外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆