在用户控件上拖动窗口后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
类在其提供的其他绘图操作中是否存在问题
有没有修复方法,或者由于这个错误应该避免?
似乎您使用clirect来绘制边界,这意味着只有控件中应该重新绘制的部分。使用控制尺寸/坐标绘制边界。
您误解了e.ClipRectangle
的作用。它与您的窗口内容无关,它只是告诉您的窗口需要重新绘制的部分。代码中的错误仅在XP上非常明显,在使用Aero的较新Windows版本上更不明显。
当你拖动另一个窗口穿过你的窗口时,操作系统告诉你只需要重新绘制移动显示的窗口部分。如果水平拖动,那么它的宽度将仅与用户自上次绘制以来移动窗口的量一样宽。e.ClipRectangle
包含该条带。
它旨在帮助您优化绘画代码。由于你只需要画那一条,你可以跳过任何在它之外绘制的代码。优化你的绘制代码可能很重要,如果速度太慢,用户可以看到那一条未绘制的部分,这会产生一种视觉效果,就像你启用鼠标轨迹时看到的一样。然而,Windows本身已经进行了优化,可以在内部观察ClipRectangle。您仍然可以调用Graphics方法,但它们什么都不做。或者只做你要求他们做的工作的一部分,与ClipRectangle相交的部分。因此,真正需要编写代码并针对矩形进行测试的情况非常罕见。
你的bug在Aero上不太明显,它在内存中对窗口表面进行了双重缓冲。更接近于许多程序员认为绘画应该起作用的方式。它可以非常快速地从表面副本重新绘制银条,而无需您的帮助。然而,当您将窗口拖离屏幕并返回时,这种情况仍然会发生,双缓冲曲面不包括不在屏幕上的窗口部分。