DrawToBitmap returning blank image

孤街醉人 提交于 2019-11-26 11:40:12

问题


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

回答1:


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!



来源:https://stackoverflow.com/questions/35544789/drawtobitmap-returning-blank-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!