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
可打印?
更新:(绘图程序)
- 用户控件充当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
优点是什么? 引诱新手进入那个错误只会有好处吗?
不完全的; 这里有一些用途:
- 绘制非持久性图形,如橡皮筋矩形或特殊鼠标光标
- 测量文本大小而不使用
TextRenderer
或MeasureString
方法实际绘制它 - 使用
Graphics.DpiX/Y
查询屏幕或Bitmap
分辨率
可能还有其他一些我现在想不到的......
因此,对于正常绘制到控件上,请始终使用e.Grapahics
对象! 您可以将其传递给子例程以使代码更加结构化,但不要尝试缓存它; 它需要是最新的!