DrawToBitmap返回空白图像 [英] DrawToBitmap returning blank image

查看:418
本文介绍了DrawToBitmap返回空白图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在用Winform应用程序创建位图图像时遇到问题.

情况:

我有一个名为"CanvasControl"的UserControl,它接受OnPaint方法作为Draw Pad应用程序的画布.在此用户控件内部,我有一个函数"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()"功能.

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

到目前为止我尝试过的事情:

为了测试这不是语法问题,我尝试将PrintCanvas()函数转换为我的主要形式,但令人惊讶的是,我在文件中得到了整个主要形式的图像,但UserControl在此处不可见./p>

我还有其他设置无法使winform UserControl可打印吗?

更新:(常规程序)

  1. 充当画布的用户控件-在此处编码

解决方案

问题中的代码给出了第一个提示,但链接中的代码显示了问题的根源:您使用了绘图对象:

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图形中最常见的错误之一! 请勿使用CreateGraphics!在Paint或DrawXXX事件中,您始终应使用Graphics对象绘制到控制表面上..这些事件具有参数e.Graphics,这是唯一可以绘制持久性图形的参数.

永久意味着它将始终在必要时刷新,而不仅仅是在触发时刷新.这是一个令人讨厌的错误,因为在您遇到外部事件需要重绘的情况下,一切似乎都可以正常工作

  • 最小化然后最大化表单
  • 将其移出屏幕,然后再次返回
  • 致电DrawToBitmap
  • ...

请注意,只有使用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对象!您可以将其传递给子例程以使代码更结构化,但不要尝试对其进行缓存;它必须是最新的!

I have a problem on creating bitmap image out of my winform application.

Situation:

I have a UserControl named as "CanvasControl" that accepts OnPaint method acting as canvas for my Draw Pad application. Inside this user control I have a function "PrintCanvas()" that will create a screenshot image of the UserControl into PNG file. Below is the PrintCanvas() function:

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();
}

This user control (CanvasControl) is called out inside my main form where user will draw something and have an option to save afterwards using a save button. The save button will call out the "PrintCanvas()" function of the UserControl.

I get the output image file as expected, but the problem is it was a blank image.

What I have tried so far:

To test that it is not a syntax issue, I tried to transfer the PrintCanvas() function into my main form and surprisingly I get an image of the whole main form on file but the UserControl is not visible there.

Is there any other setup i missed out to make a winform UserControl printable?

UPDATE: (DRAWING ROUTINES)

  1. User control acting as canvas - code here

解决方案

The code in the question gave a first hint but the code in the link showed the source of the problem: You use a 'wrong' instance of the Graphics object for drawing:

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();
  ..

This is one of the most common mistakes with winforms graphics! Never use CreateGraphics ! You always should draw onto the control surface with the Graphics object in a Paint or DrawXXX event. These events have a parameter e.Graphics which is the only one that can draw persistent graphics.

Persistent means that it will always be refreshed when necessary, not just when you trigger it. This is a nasty error because everything seems to work until you come upon a situation when an outside event makes redrawing necessary:

  • Minimizing and then maximizing the form
  • Moving it off the screen and back again
  • Calling DrawToBitmap
  • ...

Note that all will only really work if you use the valid and current Graphics object from the PaintEventArgs e parameter.

So, the solution is simple:

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();  // << === !!
  ..

But what is the CreateGraphics good for? It is only good for luring newbies into that error??

Not quite; here are some uses for it:

  • Drawing non-persistent graphics like a rubber-band rectangle or a special mouse cursor
  • Measuring text sizes without actually drawing it with a TextRenderer or the MeasureString method
  • Querying the screen or Bitmap resolution with Graphics.DpiX/Y

and probably some others I can't think of at the moment..

So for normal drawing onto controls always use the e.Grapahics object! You can pass it on to subroutines to make the code more structured, but do not try to cache it; it needs to be current!

这篇关于DrawToBitmap返回空白图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆