在列表视图上绘画会禁用列表视图项目的重绘

发布于 2024-08-09 10:02:22 字数 912 浏览 1 评论 0原文

这是什么原因呢?

我重写 OnPaintBackground 并绘制一个字符串。直到我在构造函数中调用它之后它才会显示:

this.SetStyle ( ControlStyles.UserPaint, true );

但是我在列表视图中看不到这些项目。

为什么以及如何解决这个问题?

编辑:代码

    protected override void OnPaintBackground ( PaintEventArgs pevent )
    {
        base.OnPaintBackground ( pevent );

        // Create string to draw.
        String drawString = "76";

        // Create font and brush.
        Font drawFont = new Font ( "Arial", 36 );
        SolidBrush drawBrush = new SolidBrush ( Color.Blue );

        // Create point for upper-left corner of drawing.
        PointF drawPoint = new PointF ( 150.0F, 150.0F );

        // Draw string to screen.
        pevent.Graphics.DrawString ( drawString, drawFont, drawBrush, drawPoint );

        //pevent.Graphics.FillRectangle ( drawBrush, this.ClientRectangle );
    }`enter code here`

What's the reason for this?

I override OnPaintBackground and draw a string. It doesn't show up until I call this in the constructor:

this.SetStyle ( ControlStyles.UserPaint, true );

But then I don't see the items in the listview.

Why and how to solve this?

EDIT: code

    protected override void OnPaintBackground ( PaintEventArgs pevent )
    {
        base.OnPaintBackground ( pevent );

        // Create string to draw.
        String drawString = "76";

        // Create font and brush.
        Font drawFont = new Font ( "Arial", 36 );
        SolidBrush drawBrush = new SolidBrush ( Color.Blue );

        // Create point for upper-left corner of drawing.
        PointF drawPoint = new PointF ( 150.0F, 150.0F );

        // Draw string to screen.
        pevent.Graphics.DrawString ( drawString, drawFont, drawBrush, drawPoint );

        //pevent.Graphics.FillRectangle ( drawBrush, this.ClientRectangle );
    }`enter code here`

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

层林尽染 2024-08-16 10:02:22

正如我在关于该主题的上一篇文章中所说,OnPaint()UserPaint 不适用于 ListView。该绘画由底层控件处理,不能以这种方式拦截。这与其他控件不同

,因此,当 ControlStyles.UserPainttrue 时,不会告诉底层控件重绘自身。相反,所有绘图都会路由到 OnPaintBackground()OnPaint() 方法,正如您所发现的那样,它们什么也不做。

有两种方法可以满足您的要求(第二种比第一种更好):

第一种方法:拦截WM_PAINT,进行基本处理,然后绘制到列表视图上。像这样的事情:

public class MyListView : ListView
{
    protected override void WndProc(ref Message m) {
        switch (m.Msg) {
            case 0x0F: // WM_PAINT
                this.HandlePaint(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }

    protected virtual void HandlePaint(ref Message m) {
        base.WndProc(ref m);

        using (Graphics g = this.CreateGraphics()) {
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            sf.Trimming = StringTrimming.EllipsisCharacter;
            g.DrawString("Some text", new Font("Tahoma", 13),
                SystemBrushes.ControlDark, this.ClientRectangle, sf);
        }
    }
}

但是,当您绘制的内容位于列表视图认为包含控件内容的区域之外时,这会带来重绘问题 - 它不会触发绘制事件。

第二种方式:拦截CustomDraw通知(这与OwnerDraw不同),并监听CDDS_POSTPAINT阶段。在该阶段,您可以安全地在列表视图上绘图。您可以查看 ObjectListView 的代码来了解它是如何完成的。

您也可以直接使用 ObjectListView 来省去很多麻烦:)

As I said in the last thread about this subject, OnPaint() and UserPaint don't work with ListView. The painting is handled by the underlying control and cannot be intercepted in that fashion. This is different to other Controls

So, when ControlStyles.UserPaint is true, the underlying control is not told to redraw itself. Instead, all drawing is routed to the OnPaintBackground() and OnPaint() methods, which -- as you have found -- do nothing.

There are two ways to do what you asked (the second is better than the first):

First way: Intercept the WM_PAINT, do the base processing, and then draw onto the listview. Something like this:

public class MyListView : ListView
{
    protected override void WndProc(ref Message m) {
        switch (m.Msg) {
            case 0x0F: // WM_PAINT
                this.HandlePaint(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }

    protected virtual void HandlePaint(ref Message m) {
        base.WndProc(ref m);

        using (Graphics g = this.CreateGraphics()) {
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            sf.Trimming = StringTrimming.EllipsisCharacter;
            g.DrawString("Some text", new Font("Tahoma", 13),
                SystemBrushes.ControlDark, this.ClientRectangle, sf);
        }
    }
}

But this gives repaint problems when what you draw is outside the area that the listview thinks holds the control's contents -- it doesn't trigger paint events.

Second manner: Intercept the CustomDraw notification (this is not the same as OwnerDraw), and listen for the CDDS_POSTPAINT stage. In that stage you can safely draw onto the list view. You can look at the code of ObjectListView to see how it is done.

You could also just save yourself a lot of bother and use an ObjectListView directly :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文