CreateGraphics on a System.Image
-
Hi. So far my app runs great. Apart from some slow performance, but that's not too important. using System.Drawing I'm making use of a Panel control and drawing using .CreateGraphics() What I'd like to know is, is there any way of getting a System.Graphics object for an Image or a Bitmap, so that I can draw to the bitmap in memory (using FillRectangle, etc.) and then dump the Bitmap onto the Panel control when the paint event comes a-knocking? Basically, what's the equivalent of Control.CreateGraphics() for a Bitmap? Cheers, Ninja
Ninja (the Nerd)
Confused? You will be... -
Hi. So far my app runs great. Apart from some slow performance, but that's not too important. using System.Drawing I'm making use of a Panel control and drawing using .CreateGraphics() What I'd like to know is, is there any way of getting a System.Graphics object for an Image or a Bitmap, so that I can draw to the bitmap in memory (using FillRectangle, etc.) and then dump the Bitmap onto the Panel control when the paint event comes a-knocking? Basically, what's the equivalent of Control.CreateGraphics() for a Bitmap? Cheers, Ninja
Ninja (the Nerd)
Confused? You will be...Ninja-the-Nerd wrote:
drawing using .CreateGraphics()
Never do this. Open your app. Open Calculator. Drag calculator over your app. See how your painting all disappears ? That's because you used CreateGraphics. Handle the paint event of your control instead.
Ninja-the-Nerd wrote:
What I'd like to know is, is there any way of getting a System.Graphics object for an Image or a Bitmap,
Graphics.FromImage
Ninja-the-Nerd wrote:
when the paint event comes a-knocking?
You call CreateGraphics in a paint event ? Why ?
Christian Graus - Microsoft MVP - C++ "also I don't think "TranslateOneToTwoBillion OneHundredAndFortySevenMillion FourHundredAndEightyThreeThousand SixHundredAndFortySeven()" is a very good choice for a function name" - SpacixOne ( offering help to someone who really needed it ) ( spaces added for the benefit of people running at < 1280x1024 )
-
Ninja-the-Nerd wrote:
drawing using .CreateGraphics()
Never do this. Open your app. Open Calculator. Drag calculator over your app. See how your painting all disappears ? That's because you used CreateGraphics. Handle the paint event of your control instead.
Ninja-the-Nerd wrote:
What I'd like to know is, is there any way of getting a System.Graphics object for an Image or a Bitmap,
Graphics.FromImage
Ninja-the-Nerd wrote:
when the paint event comes a-knocking?
You call CreateGraphics in a paint event ? Why ?
Christian Graus - Microsoft MVP - C++ "also I don't think "TranslateOneToTwoBillion OneHundredAndFortySevenMillion FourHundredAndEightyThreeThousand SixHundredAndFortySeven()" is a very good choice for a function name" - SpacixOne ( offering help to someone who really needed it ) ( spaces added for the benefit of people running at < 1280x1024 )
"You call CreateGraphics in a paint event ? Why ?" I don't. I assure you, even 3 years of VB.NET didn't make me THAT bad. What the app does is create an instance of a class which contains a whole lot of drawing code and pass it a reference to the control it draws to. Then it adds its own handlers for the Resize & Paint events of the control, and updates the Graphics object accordingly. The paint event calls the drawDisplay() event, which uses the Graphics object to draw (fill) rectangles and text to the control. The resize event is the only thing that ever calls CreateGraphics(). What I want to do is to be able to store a copy of the Image last drawn, and only necessitate that the image be redrawn when the display is scrolled. Otherwise, the paint event will simply draw the last image drawn. I did have a Image lastImage for this, but using displayPanel.DrawToBitmap doubled my draw time and would only draw the control as a background colour. "Graphics.FromImage" So if I set my Graphics object like this I'll be able to use DrawString & FillRectangle to draw directly to the Bitmap in memory, then draw said Bitmap to the control using e.Graphics.DrawImage() ? *realises how badly explained it was first time*
Ninja (the Nerd)
Confused? You will be... -
"You call CreateGraphics in a paint event ? Why ?" I don't. I assure you, even 3 years of VB.NET didn't make me THAT bad. What the app does is create an instance of a class which contains a whole lot of drawing code and pass it a reference to the control it draws to. Then it adds its own handlers for the Resize & Paint events of the control, and updates the Graphics object accordingly. The paint event calls the drawDisplay() event, which uses the Graphics object to draw (fill) rectangles and text to the control. The resize event is the only thing that ever calls CreateGraphics(). What I want to do is to be able to store a copy of the Image last drawn, and only necessitate that the image be redrawn when the display is scrolled. Otherwise, the paint event will simply draw the last image drawn. I did have a Image lastImage for this, but using displayPanel.DrawToBitmap doubled my draw time and would only draw the control as a background colour. "Graphics.FromImage" So if I set my Graphics object like this I'll be able to use DrawString & FillRectangle to draw directly to the Bitmap in memory, then draw said Bitmap to the control using e.Graphics.DrawImage() ? *realises how badly explained it was first time*
Ninja (the Nerd)
Confused? You will be...Ninja-the-Nerd wrote:
So if I set my Graphics object like this I'll be able to use DrawString & FillRectangle to draw directly to the Bitmap in memory, then draw said Bitmap to the control using e.Graphics.DrawImage() ?
Correct.
Christian Graus - Microsoft MVP - C++ "also I don't think "TranslateOneToTwoBillion OneHundredAndFortySevenMillion FourHundredAndEightyThreeThousand SixHundredAndFortySeven()" is a very good choice for a function name" - SpacixOne ( offering help to someone who really needed it ) ( spaces added for the benefit of people running at < 1280x1024 )
-
Ninja-the-Nerd wrote:
So if I set my Graphics object like this I'll be able to use DrawString & FillRectangle to draw directly to the Bitmap in memory, then draw said Bitmap to the control using e.Graphics.DrawImage() ?
Correct.
Christian Graus - Microsoft MVP - C++ "also I don't think "TranslateOneToTwoBillion OneHundredAndFortySevenMillion FourHundredAndEightyThreeThousand SixHundredAndFortySeven()" is a very good choice for a function name" - SpacixOne ( offering help to someone who really needed it ) ( spaces added for the benefit of people running at < 1280x1024 )
Excellent. Just starting to wrestle with the limits of Image and Bitmap being different, and wondering why new Bitmap(1, 1) can be assigned to an Image. Either way, a couple of method changes ought to have the app working great. And now, I can get on with reality (or, pseudo-reality at least). Thanks for your help.
Ninja (the Nerd)
Confused? You will be... -
Hi. So far my app runs great. Apart from some slow performance, but that's not too important. using System.Drawing I'm making use of a Panel control and drawing using .CreateGraphics() What I'd like to know is, is there any way of getting a System.Graphics object for an Image or a Bitmap, so that I can draw to the bitmap in memory (using FillRectangle, etc.) and then dump the Bitmap onto the Panel control when the paint event comes a-knocking? Basically, what's the equivalent of Control.CreateGraphics() for a Bitmap? Cheers, Ninja
Ninja (the Nerd)
Confused? You will be...Hi, FYI: if you want to paint to the screen, do it in the Paint handler, without CreateGraphics, as Christian said. if you want to paint into a Bitmap, use
Graphics.FromImage()
and don't forget to dispose of the Graphics as soon as you're done painting in it. :)Luc Pattyn [Forum Guidelines] [My Articles]
this months tips: - use PRE tags to preserve formatting when showing multi-line code snippets - before you ask a question here, search CodeProject, then Google
-
Hi, FYI: if you want to paint to the screen, do it in the Paint handler, without CreateGraphics, as Christian said. if you want to paint into a Bitmap, use
Graphics.FromImage()
and don't forget to dispose of the Graphics as soon as you're done painting in it. :)Luc Pattyn [Forum Guidelines] [My Articles]
this months tips: - use PRE tags to preserve formatting when showing multi-line code snippets - before you ask a question here, search CodeProject, then Google
What's the hurry with disposing it? I'd rather keep it and use it later (memory is no object, I have something like 500MB spare on my target machine). OK, if Graphics leaks then it'll become a problem, the app will be running for 2-2.5 hours, but CreateGraphics is only called upon creation, and resizing, which will typically be done once.
Ninja (the Nerd)
Confused? You will be... -
What's the hurry with disposing it? I'd rather keep it and use it later (memory is no object, I have something like 500MB spare on my target machine). OK, if Graphics leaks then it'll become a problem, the app will be running for 2-2.5 hours, but CreateGraphics is only called upon creation, and resizing, which will typically be done once.
Ninja (the Nerd)
Confused? You will be...Ninja-the-Nerd wrote:
What's the hurry with disposing it? I'd rather keep it and use it later
There is no point in keeping the Graphics, it is only valid for the one Bitmap from which it got created; if you get another Bitmap, same or diferent size, you would need another Graphics object. And Graphics objects are expensive, they take lots of memory and occupy some system resources that may be expensive, meaning your system may slow down significantly or hang completely when they run low. so by definition "once you are done painting in it" as I put it, you should dispose of it; later on, you can save the image to disk, or paint it to the screen, or whatever, but for these operations the Graphics you've got from FromImage is no longer useful. :)
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips: - use PRE tags to preserve formatting when showing multi-line code snippets - before you ask a question here, search CodeProject, then Google
-
Ninja-the-Nerd wrote:
What's the hurry with disposing it? I'd rather keep it and use it later
There is no point in keeping the Graphics, it is only valid for the one Bitmap from which it got created; if you get another Bitmap, same or diferent size, you would need another Graphics object. And Graphics objects are expensive, they take lots of memory and occupy some system resources that may be expensive, meaning your system may slow down significantly or hang completely when they run low. so by definition "once you are done painting in it" as I put it, you should dispose of it; later on, you can save the image to disk, or paint it to the screen, or whatever, but for these operations the Graphics you've got from FromImage is no longer useful. :)
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips: - use PRE tags to preserve formatting when showing multi-line code snippets - before you ask a question here, search CodeProject, then Google
Hmm. Well, being a noob with GDI (or anything more complicated than FillRectangle)...I really shouldn't argue a point, but... If I keep it; I get to use it during the search method which scans a text source for a result and then draws a message to the screen. I get to update the image at will, without needing to re-get the Graphics object. I mean, it's based on the same Image which is updated on the resize event, but the Graphics object is recreated just after that for the new Image. Like I said, I have typically, 1GB of RAM spare on my dev machine and almost 600MB, I think, on the target machine. A few Graphics objects won't kill the system. OK, if the core part of Windows runs out of memory then, oops, but I haven't hit that eventuality yet. As for slowing down, my dev machine, 2.6GHz Core2Duo Intel with a Radeon 2600 Pro, draws a typical screen (measured inaccurately using Environment.TickCount) in 31 or 46 "Ticks". Slow code, eh. My 2GHz AMD Athlon which is about 4 years old, has DDR and not DDR2 RAM, and a Radeon 9200 using AGP and not PCI-E...can draw exactly the same screen completing in either 0 or 15 "ticks". :wtf::confused: Pretty new system, compared with 4 year old technology that sits in a cold room for weeks at a time. The only thing I can think of is the old machine has very little more than XP, .NET 2, and DirectX. The new machine has a fair bit more on it but not enough for a 3x slowdown.
Ninja (the Nerd)
Confused? You will be... -
Hmm. Well, being a noob with GDI (or anything more complicated than FillRectangle)...I really shouldn't argue a point, but... If I keep it; I get to use it during the search method which scans a text source for a result and then draws a message to the screen. I get to update the image at will, without needing to re-get the Graphics object. I mean, it's based on the same Image which is updated on the resize event, but the Graphics object is recreated just after that for the new Image. Like I said, I have typically, 1GB of RAM spare on my dev machine and almost 600MB, I think, on the target machine. A few Graphics objects won't kill the system. OK, if the core part of Windows runs out of memory then, oops, but I haven't hit that eventuality yet. As for slowing down, my dev machine, 2.6GHz Core2Duo Intel with a Radeon 2600 Pro, draws a typical screen (measured inaccurately using Environment.TickCount) in 31 or 46 "Ticks". Slow code, eh. My 2GHz AMD Athlon which is about 4 years old, has DDR and not DDR2 RAM, and a Radeon 9200 using AGP and not PCI-E...can draw exactly the same screen completing in either 0 or 15 "ticks". :wtf::confused: Pretty new system, compared with 4 year old technology that sits in a cold room for weeks at a time. The only thing I can think of is the old machine has very little more than XP, .NET 2, and DirectX. The new machine has a fair bit more on it but not enough for a 3x slowdown.
Ninja (the Nerd)
Confused? You will be...X|
Luc Pattyn [Forum Guidelines] [My Articles]
this months tips: - use PRE tags to preserve formatting when showing multi-line code snippets - before you ask a question here, search CodeProject, then Google