I have a Graphics object and a Panel. The Graphics object is instantiated with a Handler from the Panel. Then, the Panel is updated with the Paint action. Inside the Paint action, the Graphics object is used to paint. Sometimes through out the code I use the Invalidate() to update the panel.
I want to save the content of the Graphics object or the content of the Panel into a file. Whenever I try to do it, the image file is created, but blank.
Here are some snippets of the code:
I initiate Graphics object as a class variable:
Graphics GD_LD;
Then in the constructor I use the following to instantiate the object using the panel handler:
GD_LD = Graphics.FromHwnd(panelDrawLD.Handle);
Then I have the drawing function that is used on the Paint action of the Panel, were I use the Graphics object to make the all the drawings:
private void panelDrawLD_Paint(object sender, PaintEventArgs e)
{
..... some code ....
//Code example
GD_LD.FillPolygon(blackBrush, getPoints(min, sizeGP, scaleX, scaleY));
GD_LD.FillPolygon(blackBrush, getPoints(max, sizeGP, scaleX, scaleY));
..... some code ....
}
The above works fine to draw in the Panel and keep it always with the drawing.
The issue is when trying to save the Panel to a Image file:
Bitmap I_LD = new Bitmap(panelDrawLD.Size.Width, panelDrawLD.Size.Height);
panelDrawLD.DrawToBitmap(I_LD, new Rectangle(0,0, panelDrawLD.Size.Width, panelDrawLD.Size.Height));
I_LD.Save(tempPath + "I_LD.bmp",ImageFormat.Bmp);
The image file is created but without content. Just blank.
I saw some threads about this subject, but I could not adapt it to my situation.
What am I doing wrong? What's a possible solution?
What you really should be doing, is refactoring your Paint event in to a subroutine that takes a Graphics
object as an argument called target
. Do all your drawing against target
. Then you can call that and pass e.Graphics
from panelDrawLD_Paint
, and call it from your other function with a Graphics
you create with Graphics.FromImage(I_LD)
.
Also, if you create a Graphics
(or any other GDI object), you MUST destroy it, or you will get a memory leak.
Like this:
private void panelDrawLD_Paint(object sender, PaintEventArgs e)
{
//e.Graphics does NOT need to be disposed of because *we* did not create it, it was passed to us by the control its self.
DrawStuff(e.Graphics);
}
private void Save()
{
// I_LD, and g are both GDI objects that *we* created in code, and must be disposed of. The "using" block will automatically call .Dispose() on the object when it goes out of scope.
using (Bitmap I_LD = new Bitmap(panelDrawLD.Size.Width, panelDrawLD.Size.Height))
{
using (Graphics g = Graphics.FromImage(I_LD))
{
DrawStuff(g);
}
I_LD.Save(tempPath + "I_LD.bmp", ImageFormat.Bmp);
}
}
private void DrawStuff(Graphics target)
{
//Code example
target.FillPolygon(blackBrush, getPoints(min, sizeGP, scaleX, scaleY));
target.FillPolygon(blackBrush, getPoints(max, sizeGP, scaleX, scaleY));
}