我创建了一个自定义面板,用于绘制边框(包含两个矩形)。问题是,如果我调整窗口大小,仍然会有残留物……很像 Windows XP 的纸牌动画。请参阅下面的屏幕截图。我向右调整了窗口的大小。
出了什么问题,我该如何解决?
protected override void OnPaint(PaintEventArgs e)
{
var outer = ClientRectangle;
outer.Width -= 1;
outer.Height -= 1;
var inner = outer;
inner.X++;
inner.Y++;
inner.Width -= 2;
inner.Height -= 2;
e.Graphics.DrawRectangle(DarkPen, outer);
e.Graphics.DrawRectangle(WhitePen, inner);
base.OnPaint(e);
}
Run Code Online (Sandbox Code Playgroud)
更新
一开始我以为是因为我没有删除之前绘制的矩形。于是我打电话FillRectangle删除里面。
var contentArea = inner;
contentArea.X++;
contentArea.Y++;
contentArea.Width -= 2;
contentArea.Height -= 2;
e.Graphics.FillRectangle(SystemBrushes.Control, contentArea);
Run Code Online (Sandbox Code Playgroud)
但它也不起作用。似乎控件只绘制新扩展的部分,而不是整个区域。
Form 类被优化为一个容器控件。容器通常只需要绘制背景颜色。所以,正如您所注意到的,确实“只绘制新扩展的部分”。或者更准确地说,它不会覆盖之前的像素,很容易从产生的涂抹效果中识别出来。当您调整窗口大小时,使 Winforms 设计更加生动是一种有点微弱的尝试,当表单具有很多控件时,绘画会成为一个瓶颈,这非常明显。
您必须将其 ResizeRedraw 属性设置为 true,以便在必要时重绘其整个表面。当绘图代码变得复杂并且您开始注意到闪烁时,将 DoubleBuffered 属性设置为 true 也可能不会受到影响。
所以,大致:
public Form1() {
InitializeComponent();
this.ResizeRedraw = true;
this.DoubleBuffered = true;
}
Run Code Online (Sandbox Code Playgroud)
优化 OnPaint() 通常不是一个有回报的策略,Windows 本身已经剪辑了您针对脏区域绘制的内容。