错误或我做错了什么?Usercontrol绘画

Max*_*ich 6 .net c# paint windows-forms-designer winforms

private void UserControl1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawEllipse(Pens.Black, new Rectangle(-200, -500, this.Width + 400, this.Height + 420));
}
Run Code Online (Sandbox Code Playgroud)

将上面的代码粘贴到usercontrol中.将usercontrol放到表单上并将其锚定到所有4个点.

在设计器(在Visual Studio 2010下),它呈现完美(即使您调整大小).运行它并尝试调整窗体大小,椭圆变得倾斜.

以下是运行时第一个调整大小后的两个示例,设计器中的第二个调整大小.

调整后运行 设计师调整大小后

显然,设计师的行为并不总是被认为是相同的(虽然它会很好)但我的理解是上面的代码是完全合法的.我错了吗?

Cod*_*ray 7

Stecya发布了"修复",但省略了一个解释,详细说明了为什么有效,或者为什么你看到设计师和正在运行的应用程序中的行为之间存在差异.在我看来,这使答案只有最低限度的用处,所以我想我会试图解释一下.

您已经知道调用该Invalidate方法是解决方案.这样做是告诉Windows,下次窗口被绘制时需要重新绘制控件的整个表面区域.很简单,但为什么你不必在设计师那里做到这一点?

答案在于您在启用Windows Aero主题的情况下运行程序.Aero使用一种全新的窗口管理器,称为桌面窗口管理器(简称DWM),基于组合.每个窗口都是双缓冲的,这意味着它的图形会在屏幕外呈现为临时位图,然后才会显示在屏幕上.这允许用户现在喜欢的各种酷炫效果和花哨的过渡.

但是,当然,这意味着已经绘制的部分不会被删除和重绘,除非您明确指示Windows需要这样做.这对于设计器内部的表单来说不是问题,因为在那里,Aero的DWM组合未启用.当窗口调整大小时,它会自动重绘,你的旋风看起来很平滑和正确.

设计器之外,启用Aero合成后,只会重新绘制控件的新曝光部分(其余部分仍在缓冲区中),因此形状错误.旧形状的一部分仍然存在,新形状的一部分刚刚被绘制出来.调用Invalidate告诉Windows"这个控件的图形表面已经改变;忘记你认为你知道的一切,并在下次从头开始重绘".因此,Windows尽职尽责地从其屏幕外缓冲区中丢弃该部分并从头开始重绘,从而生成正确渲染,平滑的路径.

您可以以另一种更优雅的方式实现相同的更改:告诉控件每次调整大小时需要重绘自己.将以下代码插入控件的构造方法中:

public MyUserControl()
{
    // Force the control to redraw itself each time it is resized
    this.SetStyle(ControlStyles.ResizeRedraw);
}
Run Code Online (Sandbox Code Playgroud)