【问题标题】:Bug or am I doing something wrong? Usercontrol Painting错误还是我做错了什么?用户控制绘画
【发布时间】:2011-05-17 13:18:45
【问题描述】:
private void UserControl1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawEllipse(Pens.Black, new Rectangle(-200, -500, this.Width + 400, this.Height + 420));
}

将以上代码粘贴到用户控件中。将用户控件拖放到窗体上并将其锚定到所有 4 个点。

在设计器中(在 Visual Studio 2010 下)它可以完美呈现(即使您调整大小)。运行它并尝试调整表单的大小,椭圆变得倾斜。

这里有两个示例调整大小后第一个在运行时,第二个在设计器中。

显然,设计器中的行为不能总是被认为是相同的(尽管它会很好),但我的理解是上面的代码是完全合法的。我错了吗?

【问题讨论】:

    标签: c# .net winforms windows-forms-designer paint


    【解决方案1】:

    Stecya has posted“修复”,但省略了详细说明为什么有效或为什么您看到设计器中的行为与运行应用程序。在我看来,这使得答案的用处很小,所以我想我会尝试解释一下。

    您已经知道调用Invalidate method 是解决方案。它的作用是告诉 Windows,下次绘制窗口时需要重新绘制控件的整个表面区域。很简单,但您为什么不必在设计器中执行此操作?

    答案在于您正在运行启用了 Windows Aero 主题的程序。 Aero 使用基于合成的全新窗口管理器Desktop Window Manager(或简称 DWM)。每个窗口都是双缓冲的,这意味着它的图形在屏幕外渲染成一个临时位图,然后才被传送到屏幕上。这允许用户现在似乎喜欢的各种很酷的效果和花哨的过渡。

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

    在设计器之外,启用 Aero 合成后,仅重绘控件的新暴露部分(其余部分仍在缓冲区中),因此形状不对。旧形状的一部分仍然存在,而新形状的一部分刚刚被绘制出来。调用Invalidate 告诉Windows“这个控件的图形表面已经改变;忘记你认为你知道的一切,然后从头开始重新绘制它时间”。因此 Windows 尽职尽责,从屏幕外缓冲区中丢弃该部分并从头开始重新绘制它,从而生成正确渲染、平滑平滑的路径。

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

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

    【讨论】:

      【解决方案2】:

      您可以在调整大小时手动使控件无效

      private void Form1_Resize(object sender, EventArgs e)
      {
          userControl11.Invalidate();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-04
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多