DrawToBitmap返回空白图像

我在winform应用程序中创建位图图像时遇到问题。

情况:

我有一个名为“ CanvasControl ”的UserControl ,它接受OnPaint方法作为我的Draw Pad应用程序的canvas。 在这个用户控件中,我有一个函数“ PrintCanvas() ”,它将创建UserControl到PNG文件的屏幕截图。 下面是PrintCanvas()函数:

 public void PrintCanvas(string filename = "sample.png") { Graphics g = this.CreateGraphics(); //new bitmap object to save the image Bitmap bmp = new Bitmap(this.Width, this.Height); //Drawing control to the bitmap this.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height)); bmp.Save(Application.StartupPath + @"\ExperimentFiles\Experiment1" + filename, ImageFormat.Png); bmp.Dispose(); } 

这个用户控件( CanvasControl )在我的主窗体中被调出,用户将在其中绘制一些东西,并且可以选择使用保存按钮进行保存。 保存按钮将调出UserControl的“ PrintCanvas() ”function。

我得到了预期的输出图像文件,但问题是它是一个空白图像。

到目前为止我尝试了什么:

为了测试它不是语法问题,我尝试将PrintCanvas()函数转移到我的主窗体中,令人惊讶的是我得到了整个主窗体的图像,但是UserControl在那里看不到。

有没有其他设置我错过了使winform UserControl可打印?

更新:(绘图程序)

  1. 用户控件充当canvas – 代码在这里

问题中的代码给出了第一个提示,但链接中的代码显示了问题的根源:使用Graphics对象的“错误”实例进行绘制:

 protected override void OnPaint(PaintEventArgs e) { // If there is an image and it has a location, // paint it when the Form is repainted. Graphics graphics = this.CreateGraphics(); .. 

这是winforms图形最常见的错误之一! 永远不要使用CreateGrphics! 您总是应该在Paint或DrawXXX事件中使用Graphics对象绘制到控制界面上。 这些事件有一个参数e.Graphics ,它是唯一可以绘制持久图形的参数。

持久意味着它将在必要时始终刷新,而不仅仅是在您触发它时。 这是一个令人讨厌的错误,因为一切似乎都有效,直到您遇到外部事件需要重绘的情况:

  • 最小化然后最大化forms
  • 将其从屏幕上移开并再次返回
  • 调用DrawToBitmap

..all仅在您使用PaintEventArgs e参数中的有效和当前 Graphics对象时才有效

所以,解决方案很简单:

  protected override void OnPaint(PaintEventArgs e) { // If there is an image and it has a location, // paint it when the Form is repainted. Graphics graphics = e.Graphics(); // << === !! .. 

CreateGraphics优点是什么? 引诱新手进入那个错误只会有好处吗?

不完全的; 这里有一些用途:

  • 绘制非持久性图形,如橡皮筋矩形或特殊鼠标光标
  • 测量文本大小而不使用TextRendererMeasureString方法实际绘制它
  • 使用Graphics.DpiX/Y查询屏幕或Bitmap分辨率

可能还有其他一些我现在想不到的......

因此,对于正常绘制到控件上,请始终使用e.Grapahics对象! 您可以将其传递给子例程以使代码更加结构化,但不要尝试缓存它; 它需要是最新的!