为什么PaintEventArgs.Graphics的行为与Control.CreateGraphics不同?

时间:2011-11-26 00:21:26

标签: c# .net winforms

我编写了一个事件处理程序方法,并将其附加到Paint的{​​{1}}事件(只是主窗口)。此事件会发送一个Form,其中包含一个名为PaintEventArgs的属性,该属性是Graphics的一个实例。

以下是我正在使用的代码:

System.Drawing.Graphics

最后,我只是想更好地了解这里发生的事情,但具体来说我有三个问题:

  1. 为什么private void Form1_Paint(object sender, PaintEventArgs e) { Bitmap bm = new Bitmap("fruit-dealer-full.jpg"); Graphics g1 = this.CreateGraphics(); Graphics g2 = e.Graphics; // g1.DrawImage(bm, 0, 0, this.Width, this.Height); // g1.DrawRectangle( // Pens.White, 10.0f, 10.0f, this.Width - 200, this.Height - 200); g2.DrawImage(bm, 0, 0, this.Width, this.Height); g2.DrawRectangle( Pens.White, 10.0f, 10.0f, this.Width - 200, this.Height - 200); } 在整个窗口中重绘图像,而g1只绘制新部分,即使我在绘图前调用g2
  2. 为什么使用g2.Clear()个对象,只是在窗口大小增加时重绘图像,而不是在它变小时重绘?
  3. 如果Graphics可以(或不应该)用于绘图,它用于什么?我想,如果表单不需要重绘,它只会阻止你创建一个新的PaintEventArgs.Graphics实例;我还缺少哪些东西?

2 个答案:

答案 0 :(得分:3)

你的.NET WinForms孩子真的应该学习Win32 API。拿起一份Petzold吧!

  

为什么g1会在整个窗口中重绘图像,而g2只绘制新的部分,即使我在绘制之前调用g2.Clear()?

据推测,g2是从BeginPaint收到的设备上下文的包装器。我想WinForms会为你包裹PAINTSTRUCT::rcPaint - 这个变量描述了要绘制的区域。这是预期的行为 - 而不是燃烧CPU周期重新绘制整个窗口每次只有一个像素重叠它,你可以重绘...只有一个像素!

g2.Clear可能受rcPaint限制。

g1可能是窗口的GetDC - 它可以为您提供整个表面。

  

为什么使用Graphics对象时,图像只在窗口大小增加时重绘,而不是在缩小时重绘?

底层窗口类可能没有CS_HREDRAWCS_VREDRAW窗口样式。如果没有这些,没有理由要求您在窗口变小时请求重绘窗口的默认行为:Windows知道整个窗口的样子,它可以剪掉不需要的位。这与窗口变大时不同,它不知道在新区域中绘制什么。

  

如果PaintEventArgs.Graphics可以(或不应该)用于绘图,它用于什么?我想,如果表单不需要重绘,它只会阻止你创建一个新的Graphics实例;我还缺少哪些东西?

它用于绘图。除非您有一些复杂的绘图要求,否则您可以使用PaintEventArgs.Graphics最小化进入窗口的绘画量。 (如上所述 - 这是CPU周期的巨大节省,它可能是BeginPaintEndPaint的简单包装 - how drawing to the client area is meant to be done。)

答案 1 :(得分:1)

  1. 为什么g1会在整个窗口中重绘图像,而g2只绘制新部分,即使我在绘制之前调用g2.Clear()?
    我无法理解这一点,你在两种情况下都是完整的形式。所以两者都应该绘制整个表单,也许你在不同的代码中有这种行为

  2. 为什么使用Graphics对象时,只有当窗口大小增加时才重绘图像,而不是当它变小时? 因为您应该在Form.Resize事件中调用Invalidate()来启动重绘

  3. 如果PaintEventArgs.Graphics可以(或不应该)用于绘图,它用于什么?我想,如果表单不需要重绘,它只会阻止你创建一个新的Graphics实例;还有更多我失踪了吗? 它们不同,CreateGraphics是一个临时对象,应该在使用后立即处理(或在using块中使用),它用于不需要绘图的简单任务,如MeasureString或获取Context信息。对于绘图,你总是应该使用PaintEventArgs.Graphics。差异很明显的好方法是使用双缓冲时,如果使用CreateGraphics获取Graphics对象,您将获得控件的Graphics对象,而从PaintEventArgs获取它将获得缓冲位图。 < / LI>
相关问题