private void UserControl1_Paint(object sender,PaintEventArgs e) { e.Graphics.DrawEllipse(Pens.Black,new Rectangle(-200,-500,this.Width + 400,this.Height + 420)); }
将上面的代码粘贴到usercontrol中.将usercontrol放到表单上并将其锚定到所有4个点.
在设计器(在Visual Studio 2010下),它呈现完美(即使您调整大小).运行它并尝试调整窗体大小,椭圆变得倾斜.
以下是运行时第一个调整大小后的两个示例,设计器中的第二个调整大小.
显然,设计师的行为并不总是被认为是相同的(虽然它会很好)但我的理解是上面的代码是完全合法的.我错了吗?
解决方法
您已经知道调用Invalidate
method是解决方案.这样做是告诉Windows,下次窗口被绘制时需要重新绘制控件的整个表面区域.很简单,但你为什么不在设计师那里做到这一点?
答案在于您在启用Windows Aero主题的情况下运行程序. Aero使用一个全新的窗口管理器,基于组合称为Desktop Window Manager(或简称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); }