473,320 Members | 1,846 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

using GDI+ Graphics object and getting confused, help!

Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter
Jan 21 '06 #1
7 2550
Peter,

In order to get custom painting to work, you have to handle the painting
in your Paint event handler (or override of the OnPaint method).

This is the case because of how windows programs work. Basically, you
have a loop which processes windows messages. Every so often, a message is
sent to the window saying "paint yourself".

So, your controls go and paint themselves.

Now, when you call your method and paint, you are painting, but if a
message comes in to the window to repaint itself, the device context (the
surface you are painting on) doesn't remember what was there. Also, because
you don't have the code in your paint method (event or OnPaint override), it
just paints itself, most likely clearing out whatever you did before.

So, this is why you have to place the code to paint in your paint
handler.

Now, what you are probably wondering is how do you handle changes in
what you want to display in your control. I'm sure you would rather just
call a method to do the painting, and then be done with it.

Unfortunately, because of the way the painting works, that's not
possible.

What you have to do is set variables/state that the paint method/handler
has access to, which will let that implementation of the method know how to
paint itself appropriately.

So this will set the state of what to show. For example, perhaps you
have changed text in a textbox and want it to be painted in your control
after you click a button. On the event handler for the button, you set a
string on the class level to the text in the textbox (or not at all, since
the textbox is on the same level, but it's the same concept).

At that point, you have to get your paint method/handler called.
Intuition tells you that you can just call it, but unfortunately, that will
just cause it to get wiped out again, since your graphics context will be
wiped out the next time your control needs redrawing (a process called
invalidation).

What you do at this point is tell windows that your window is
invalidated, and you need to be repainted. That is what the Invalidate
method is for on the Control class. Call that after you set your state, and
your paint handler/method will get called (with the right Graphics instance
to paint on, btw), and your changes will be persisted.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter Row" <fu******@spammers.com> wrote in message
news:el**************@TK2MSFTNGP14.phx.gbl...
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter

Jan 21 '06 #2
Hi,

Thanks for the reply, I knew about the whole Invalidate() method bit and
how that causes the Paint event to be fired.

However that still leaves one of my questions unanswered.
What is the point of the .CreateGraphics( ) method if you can't use the
Graphics object it returns to paint on your control?

I understand what you're saying about how by using it that it is actually
painting but it gets wiped out when the control gets told to paint itself.
But then as above what is the point of having that method at all.

It seems to be there as a tease. You could see where someone like myself
who is a software developer (MCP on exam 70-316, Win Apps in C#)
just I haven't done/needed to do any owner draw stuff before might get
misled. There is a method that creates a graphics object that references the
drawing surface of your control. So in my eyes it is not unreasonable to
expect that using the graphics object it gives to actually be able to see
some
visible results.

Again, thanks for the reply. I have started on a Paint event handler now
it's just annoying knowing something is there but can't be used.

Regards,
Peter

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:uF****************@TK2MSFTNGP12.phx.gbl...
Peter,

In order to get custom painting to work, you have to handle the
painting in your Paint event handler (or override of the OnPaint method).

This is the case because of how windows programs work. Basically, you
have a loop which processes windows messages. Every so often, a message
is sent to the window saying "paint yourself".

So, your controls go and paint themselves.

Now, when you call your method and paint, you are painting, but if a
message comes in to the window to repaint itself, the device context (the
surface you are painting on) doesn't remember what was there. Also,
because you don't have the code in your paint method (event or OnPaint
override), it just paints itself, most likely clearing out whatever you
did before.

So, this is why you have to place the code to paint in your paint
handler.

Now, what you are probably wondering is how do you handle changes in
what you want to display in your control. I'm sure you would rather just
call a method to do the painting, and then be done with it.

Unfortunately, because of the way the painting works, that's not
possible.

What you have to do is set variables/state that the paint
method/handler has access to, which will let that implementation of the
method know how to paint itself appropriately.

So this will set the state of what to show. For example, perhaps you
have changed text in a textbox and want it to be painted in your control
after you click a button. On the event handler for the button, you set a
string on the class level to the text in the textbox (or not at all, since
the textbox is on the same level, but it's the same concept).

At that point, you have to get your paint method/handler called.
Intuition tells you that you can just call it, but unfortunately, that
will just cause it to get wiped out again, since your graphics context
will be wiped out the next time your control needs redrawing (a process
called invalidation).

What you do at this point is tell windows that your window is
invalidated, and you need to be repainted. That is what the Invalidate
method is for on the Control class. Call that after you set your state,
and your paint handler/method will get called (with the right Graphics
instance to paint on, btw), and your changes will be persisted.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter Row" <fu******@spammers.com> wrote in message
news:el**************@TK2MSFTNGP14.phx.gbl...
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a
simple
test but I cannot get it to work at all unless I handle my custom
controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter


Jan 22 '06 #3
On Sat, 21 Jan 2006 18:33:20 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter


One way of working is to use a separate graphics buffer. Start by
copying the original of your control into the buffer and make all your
changes to the buffer. All you have to do in the Paint event is to
tell it to copy the buffer to the control. If you want something to
display immediately then just call myControl.Refresh() when you are
finished updating the buffer.

One advantage of this technique is that it can reduce screen flicker
when you are doing a lot of changes since changes to the buffer do not
appear on screen until they are copied to the control.

rossum

--

The ultimate truth is that there is no ultimate truth
Jan 22 '06 #4
Hi,

How do I get access to "the buffer"?

Are you refering to a reference to a graphics object?

Wouldn't it be bad practice to keep a graphics object handing around
after your finished with it? Everything I've read says to dispose of it as
soon as you're done with it.

Regards,
Peter
"rossum" <ro******@coldmail.com> wrote in message
news:rg********************************@4ax.com...
On Sat, 21 Jan 2006 18:33:20 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter


One way of working is to use a separate graphics buffer. Start by
copying the original of your control into the buffer and make all your
changes to the buffer. All you have to do in the Paint event is to
tell it to copy the buffer to the control. If you want something to
display immediately then just call myControl.Refresh() when you are
finished updating the buffer.

One advantage of this technique is that it can reduce screen flicker
when you are doing a lot of changes since changes to the buffer do not
appear on screen until they are copied to the control.

rossum

--

The ultimate truth is that there is no ultimate truth

Jan 22 '06 #5
Check out the information in the GDI+ FAQ.

Also, the beginners guide to GDI+ has some great info for you.
http://www.bobpowell.net/beginnersgdi.htm

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"Peter Row" <fu******@spammers.com> wrote in message
news:el**************@TK2MSFTNGP14.phx.gbl...
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter

Jan 23 '06 #6
On Sun, 22 Jan 2006 22:15:05 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

How do I get access to "the buffer"? You have to create it yourself. Googling <GDI+ double buffering>
should help if needed.

Are you refering to a reference to a graphics object? It is a reference in the sense that is is not a value type, but it
does not refer to the Graphics object currently being displayed on the
screen. It starts as a cloned copy of that object and you then modify
it before copying it back to the control.

Wouldn't it be bad practice to keep a graphics object handing around
after your finished with it? Everything I've read says to dispose of it as
soon as you're done with it. Yes, you only need it while you are drawing. If you are drawing at
multiple points in your application then you may need to keep it
around a bit longer but this will depend on the speed of response you
require, memory available and so on.

The buffer will need to be available to both the method(s) that draw
the graphics and to the MyControl_Paint().

rossum

Regards,
Peter
"rossum" <ro******@coldmail.com> wrote in message
news:rg********************************@4ax.com.. .
On Sat, 21 Jan 2006 18:33:20 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter


One way of working is to use a separate graphics buffer. Start by
copying the original of your control into the buffer and make all your
changes to the buffer. All you have to do in the Paint event is to
tell it to copy the buffer to the control. If you want something to
display immediately then just call myControl.Refresh() when you are
finished updating the buffer.

One advantage of this technique is that it can reduce screen flicker
when you are doing a lot of changes since changes to the buffer do not
appear on screen until they are copied to the control.

rossum

--

The ultimate truth is that there is no ultimate truth


--

The ultimate truth is that there is no ultimate truth
Jan 23 '06 #7
On Sun, 22 Jan 2006 22:15:05 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

How do I get access to "the buffer"? You have to create it yourself. Googling <GDI+ double buffering>
should help if needed.

Are you refering to a reference to a graphics object? It is a reference in the sense that is is not a value type, but it
does not refer to the Graphics object currently being displayed on the
screen. It starts as a cloned copy of that object and you then modify
it before copying it back to the control.

Wouldn't it be bad practice to keep a graphics object handing around
after your finished with it? Everything I've read says to dispose of it as
soon as you're done with it. Yes, you only need it while you are drawing. If you are drawing at
multiple points in your application then you may need to keep it
around a bit longer but this will depend on the speed of response you
require, memory available and so on.

The buffer will need to be available to both the method(s) that draw
the graphics and to the MyControl_Paint().

rossum

Regards,
Peter
"rossum" <ro******@coldmail.com> wrote in message
news:rg********************************@4ax.com.. .
On Sat, 21 Jan 2006 18:33:20 -0000, "Peter Row"
<fu******@spammers.com> wrote:
Hi,

I've started work on my own control some parts of which use standard
controls, others I need to draw on my controls surface to get the display
output I require, however....

I seem to be stupid or missing the point. I used DrawString( ) as a simple
test but I cannot get it to work at all unless I handle my custom controls
Paint event.

So for example if I say in the Paint event handler:
e.Graphics.DrawString("2006", this.Font, Brushes.Black, 50 , 2);

Then I see the text "2006" painted at coordinates 50, 2 on my control
as I'd expect.

HOWEVER....
If I simply have a method which says:

private void MyTestMethod( )
{
using (Graphics g = this.CreateGraphics( ))
{
g.DrawString("2006, this.Font, Brushes.Black, 50, 2);
}
}

I call the method and get absolutely nothing output, which is not what I
expect.
What the hell is going on?
What is the point of having a method on a control called CreateGraphics()
when you seemly can't use the object it returns to draw anything with it?

I am obviously missing something but I just can't see what that is, I
looked
at a few examples of DrawString() on the net and they also seem to do it
within the confines of a Paint() event handler.

I probably could do what I need to do for my control in the Paint() event
handler but this is bugging me now and I have to know what I am doing
wrong or what I am misunderstanding.

Thanks for any help given,
Peter


One way of working is to use a separate graphics buffer. Start by
copying the original of your control into the buffer and make all your
changes to the buffer. All you have to do in the Paint event is to
tell it to copy the buffer to the control. If you want something to
display immediately then just call myControl.Refresh() when you are
finished updating the buffer.

One advantage of this technique is that it can reduce screen flicker
when you are doing a lot of changes since changes to the buffer do not
appear on screen until they are copied to the control.

rossum

--

The ultimate truth is that there is no ultimate truth


--

The ultimate truth is that there is no ultimate truth
Jan 23 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: anonymous | last post by:
I'm writing a program that deals extensively with the printer. For the most part my application runs fine, but occasionally I run into some Exceptions. The most common exceptions I run into are...
3
by: Richard | last post by:
I have a requirement to put a GDI style circle or rectangle border around the selected row of a datagrid/ It will overlap into the row above and below the selected row. Doing this in a the OnPaint...
6
by: johannblake | last post by:
I am wondering whether it is easy to setup a coordinate system for drawing (using GDI+) that uses meters (or any custom scaling for that matter). Currently, I need to convert from pixels to meters...
5
by: Bonj | last post by:
How can GDI+ be used from C++?? I tried the following methods, but all failed with about 100 different errors relating to stuff that was not in any file I created. The file <gdiplus.h> only exists...
15
by: David Lozzi | last post by:
Howdy, I have a function that uploads an image and that works great. I love ..Nets built in upload, so much easier than 3rd party uploaders! Now I am making a public function that will take the...
0
by: Lloyd Dupont | last post by:
In the same OnPaint() method I could mix GDI+ and GDI drawing. I have some hard to track nasty bug that appears sometimes (mainly when I print) and I wonder if any of the things I do are not...
3
by: jm | last post by:
>From a C. Petzold book I have Programming Windows C#. It's a little old now, but anyway, it has on page 71 (shortened): form.Paint += new PaintEventHandler(MyPaintHandler); static void...
1
by: JP2006 | last post by:
I'm trying to write a control that will take a screen capture of a particular website when a user submits a form in a web application; one of the form fields is for a URL - the control needs to get...
7
by: j4richard | last post by:
Help please, I am getting this "Unhandled Exception has occurred in your application" " A Generic error occurred in GDI+" See the end of this message for details on...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.