在用户控件上拖动窗口后GDI+中的涂抹现象

本文关键字:GDI+ 控件 用户 拖动 窗口 | 更新日期: 2023-09-27 18:28:31

我正在创建一个UserControl,我想通过ControlPaint.DrawBorder()为它添加一个边框
我为OnPaint()创建了一个覆盖,并将其放入其中:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    int     Border_Width    =1;
    Color   Border_Color    =Color.FromArgb(170,170,170);
    ControlPaint.DrawBorder(e.Graphics,e.ClipRectangle,
        Border_Color,Border_Width,ButtonBorderStyle.Solid,      //Left
        Border_Color,Border_Width,ButtonBorderStyle.Solid,      //Top
        Border_Color,Border_Width,ButtonBorderStyle.Solid,      //Right
        Border_Color,Border_Width,ButtonBorderStyle.Solid);     //Bottom
}

边界画得很好,但自从我添加后,一个问题就开始了:

每当我在该用户控件上拖动其他窗口时,我都会在用户控件上看到一个"剩余"的污点。。

看看它的样子:

覆盖OnPaint()之前:

覆盖OnPaint()后:

为什么会发生这种情况?

根据我的实验,
尝试启用DubleBuffering在此处没有帮助。。污点依然存在。。

此外,如果我禁用ControlPaint.DrawBorder()行,
并将其替换为e.Graphics.DrawRectangle()
那么问题就消失了。。

因此,这意味着问题不一定是覆盖OnPaint()或类似的东西,而是ControlPaint.DrawBorder()

ControlPaint类在其提供的其他绘图操作中是否存在问题
有没有修复方法,或者由于这个错误应该避免?

在用户控件上拖动窗口后GDI+中的涂抹现象

似乎您使用clirect来绘制边界,这意味着只有控件中应该重新绘制的部分。使用控制尺寸/坐标绘制边界。

您误解了e.ClipRectangle的作用。它与您的窗口内容无关,它只是告诉您的窗口需要重新绘制的部分。代码中的错误仅在XP上非常明显,在使用Aero的较新Windows版本上更不明显。

当你拖动另一个窗口穿过你的窗口时,操作系统告诉你只需要重新绘制移动显示的窗口部分。如果水平拖动,那么它的宽度将仅与用户自上次绘制以来移动窗口的量一样宽。e.ClipRectangle包含该条带。

它旨在帮助您优化绘画代码。由于你只需要画那一条,你可以跳过任何在它之外绘制的代码。优化你的绘制代码可能很重要,如果速度太慢,用户可以看到那一条未绘制的部分,这会产生一种视觉效果,就像你启用鼠标轨迹时看到的一样。然而,Windows本身已经进行了优化,可以在内部观察ClipRectangle。您仍然可以调用Graphics方法,但它们什么都不做。或者只做你要求他们做的工作的一部分,与ClipRectangle相交的部分。因此,真正需要编写代码并针对矩形进行测试的情况非常罕见。

你的bug在Aero上不太明显,它在内存中对窗口表面进行了双重缓冲。更接近于许多程序员认为绘画应该起作用的方式。它可以非常快速地从表面副本重新绘制银条,而无需您的帮助。然而,当您将窗口拖离屏幕并返回时,这种情况仍然会发生,双缓冲曲面不包括不在屏幕上的窗口部分。