【问题标题】:Draw an ellipse without OnPaint method不使用 OnPaint 方法绘制椭圆
【发布时间】:2012-07-03 21:46:36
【问题描述】:

我正在寻找一些 GDI 教程,但到目前为止我发现的所有内容都适用于 OnPaint 方法,该方法将 Paintarguments 传递给 Graphics。我还没有找到如何从头开始,我的意思是如何使用 Graphics 类本身? 这是我已经完成但对我不起作用的全部代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Pen pen= new Pen(Color.Red, 3);
            Graphics g;
            g = this.CreateGraphics();
    g.DrawEllipse(pen, 150, 150, 100, 100);
        }
    }
}

它只是没有做任何事情。我尝试了新的形式,没有。

提前谢谢你!

【问题讨论】:

  • 调用 CreateGraphics 时,必须手动处置已创建的对象,即在完成后调用 g.Dispose ()。

标签: c# winforms gdi+


【解决方案1】:

代码可能没问题,它正在绘制您希望的椭圆。但是,在 Load 事件之后,将有一个 PaintBackground 事件和一个 PaintEvent 作为显示表单。默认情况下,PaintBackground 将擦除控件的内容,从而有效地删除您刚刚绘制的椭圆。

绘画是一个两阶段的过程:

for each (region in set of regions that need updating)
{
  PaintBackground (region)
  Paint (region)
}

窗口管理器只重绘控件中需要更新的部分,如果控件的内容没有改变或者没有用户操作改变了控件的可见性,则不进行绘制。

那么,为什么要在Load方法中画椭圆呢?通常,您只想在需要绘制某些东西时绘制一些东西,并在 PaintBackgroundPaint 事件中告知您的表单何时需要绘制。

您担心闪烁吗?还是速度问题?椭圆可以快速绘制。然而,闪烁更难修复。您需要在 Paint 事件期间创建一个位图,绘制到该位图并将该位图传送到控件。另外,让PaintBackground 事件不执行任何操作 - 不擦除控件,是擦除导致闪烁。

编辑:一个例子,我在这里使用 DevStudio 2005。

  1. 创建一个新的 C# winform 应用程序。
  2. 在 Form1.cs 中添加以下内容:

    protected override void OnPaintBackground (PaintEventArgs e)
    {
      // do nothing! prevents flicker
    }
    
    protected override void OnPaint (PaintEventArgs e)
    {
      e.Graphics.FillRectangle (new SolidBrush (BackColor), e.ClipRectangle);
    
      Point
        mouse = PointToClient (MousePosition);
    
      e.Graphics.DrawEllipse (new Pen (ForeColor), new Rectangle (mouse.X - 20, mouse.Y - 10, 40, 20));
    }
    
    protected override void OnMouseMove (MouseEventArgs e)
    {
      base.OnMouseMove (e);
      Invalidate ();
    }
    
  3. 编译并运行。

【讨论】:

  • 如果我总是需要使用输入参数重绘一些特殊对象怎么办?我的表单正在跟随鼠标。
  • 跟随鼠标,处理鼠标移动事件并使表单无效,这将导致控件在鼠标移动事件上重绘。