Window 拖过 UserControl 后 GDI+ 中的拖尾现象
Smearing Phenomenon in GDI+ After a Window is Dragged Over the UserControl
我正在创建一个 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
}
边框画的很好,但是自从我加上了,问题就来了:
每当我将其他一些 window 拖到该用户控件上时,我会在用户控件上出现 "leftover" 污迹..
看看它的样子:
覆盖 OnPaint() 之前:
覆盖 OnPaint() 后:
为什么会这样?
根据我的实验,
尝试启用 DubbleBuffering 在这里没有帮助.. 涂抹仍然存在..
此外,如果我禁用 ControlPaint.DrawBorder()
行,
并将其替换为 e.Graphics.DrawRectangle()
,
然后问题就消失了..
所以这意味着问题不一定在于覆盖 OnPaint()
或类似的东西,而是 ControlPaint.DrawBorder()
.
ControlPaint
class在它提供的其他绘图操作中是否有问题?
是否有解决办法,或者由于这个错误应该避免它?
看来你是用cliprect画边框的,意思就是只重绘控件的部分。使用控件dimensions/coordinates绘制边框
你误解了e.ClipRectangle
的作用。它与你的window内容无关,它只是告诉你你的window的哪一部分需要重新绘制。您代码中的错误仅在 XP 上非常明显,在使用 Aero 的较新 Windows 版本上更不明显。
当您将另一个 window 拖过您的 OS 时,OS 会告诉您只需要重绘 window 移动时显示的部分。只是一条细长条,如果您水平拖动,那么它的宽度只会与自上次您绘制后用户移动 window 的宽度一样宽。 e.ClipRectangle
包含该条子。
旨在帮助您优化您的绘画代码。由于您只需绘制那条条子,因此您可以跳过在它之外绘制的任何代码。优化您的绘画代码可能很重要,如果它太慢,那么用户可以看到条子的未绘画部分,并产生类似于您在启用鼠标轨迹时看到的视觉效果。然而,Windows 本身已经优化以在内部观察 ClipRectangle。您仍然进行 Graphics 方法调用,但它们什么都不做。或者只做你要求他们做的工作的一部分,与 ClipRectangle 相交的部分。因此,实际上很少需要编写代码并针对矩形进行测试。
您的错误在 Aero 上不太明显,它 double-buffers 内存中的 window 表面。更接近于许多程序员认为绘画应该起作用的方式。它可以非常快速地从表面副本中重新绘制条子,而无需您提供帮助。但是,当您将 window 拖出屏幕并返回时,它仍然会发生,double-buffered 表面不包括不在屏幕上的 window 部分。
我正在创建一个 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
}
边框画的很好,但是自从我加上了,问题就来了:
每当我将其他一些 window 拖到该用户控件上时,我会在用户控件上出现 "leftover" 污迹..
看看它的样子:
覆盖 OnPaint() 之前:
覆盖 OnPaint() 后:
为什么会这样?
根据我的实验,
尝试启用 DubbleBuffering 在这里没有帮助.. 涂抹仍然存在..
此外,如果我禁用 ControlPaint.DrawBorder()
行,
并将其替换为 e.Graphics.DrawRectangle()
,
然后问题就消失了..
所以这意味着问题不一定在于覆盖 OnPaint()
或类似的东西,而是 ControlPaint.DrawBorder()
.
ControlPaint
class在它提供的其他绘图操作中是否有问题?
是否有解决办法,或者由于这个错误应该避免它?
看来你是用cliprect画边框的,意思就是只重绘控件的部分。使用控件dimensions/coordinates绘制边框
你误解了e.ClipRectangle
的作用。它与你的window内容无关,它只是告诉你你的window的哪一部分需要重新绘制。您代码中的错误仅在 XP 上非常明显,在使用 Aero 的较新 Windows 版本上更不明显。
当您将另一个 window 拖过您的 OS 时,OS 会告诉您只需要重绘 window 移动时显示的部分。只是一条细长条,如果您水平拖动,那么它的宽度只会与自上次您绘制后用户移动 window 的宽度一样宽。 e.ClipRectangle
包含该条子。
旨在帮助您优化您的绘画代码。由于您只需绘制那条条子,因此您可以跳过在它之外绘制的任何代码。优化您的绘画代码可能很重要,如果它太慢,那么用户可以看到条子的未绘画部分,并产生类似于您在启用鼠标轨迹时看到的视觉效果。然而,Windows 本身已经优化以在内部观察 ClipRectangle。您仍然进行 Graphics 方法调用,但它们什么都不做。或者只做你要求他们做的工作的一部分,与 ClipRectangle 相交的部分。因此,实际上很少需要编写代码并针对矩形进行测试。
您的错误在 Aero 上不太明显,它 double-buffers 内存中的 window 表面。更接近于许多程序员认为绘画应该起作用的方式。它可以非常快速地从表面副本中重新绘制条子,而无需您提供帮助。但是,当您将 window 拖出屏幕并返回时,它仍然会发生,double-buffered 表面不包括不在屏幕上的 window 部分。