C#) How to keep drawing graphics by GDI

C

cty0000

I have some quiestion...

I want to draw line,point,rectangles and etc... on the from
So I code like this..

public update()
{
g = this.CreateGraphics();
g.FillRectangle(Brushes.White, x1, y1, x2, y2);
}

But the rectangle is removed after window update (minimizer or overrap
by other window)
How can I keep my drawing??

Someone recommand to draw somethins in paint event but I have
question...

My question is... do I need to keep all draw information at some class
or variable to use by paint event???
For example..
If I draw 10 rectangles by using x1,x2, y1,y2, does paint event need
all 10 datas when redraw??

What I want to do is ...
1. A class send position data to B class
2. when B class receive data, B class draw on form by GDI
3. A glass update position data (goto 1)

looping like 1-2-3- 1-2-3- 1-2-3 about 1000 more times

in this case do I also need to draw something at paint event?
and does B class need to keep all data to use at redraw time??

please help me..
 
E

eusebiu

To get redraw the rectangles or whatever your doing, you have to call
Invalidate() method. For minimizing or overrap... use the bellow
method.

protected override void DefWndProc(ref Message m)
{
if (m.Msg == 0x47)//WM_WINDOWPOSCHANGED
{
this.Invalidate();
}

base.DefWndProc(ref m);
}


As you've heard, you should paint on the Paint event. ( you'll have
the graphics into PaintEventArgs e properties). And maybe instead of a
form you should use a UserControl... :)\
Hope this helps
 
C

cty0000

To get redraw the rectangles or whatever your doing, you have to call
Invalidate() method. For minimizing or overrap... use the bellow
method.

protected override void DefWndProc(ref Message m)
{
if (m.Msg == 0x47)//WM_WINDOWPOSCHANGED
{
this.Invalidate();
}

base.DefWndProc(ref m);
}

As you've heard, you should paint on the Paint event. ( you'll have
the graphics into PaintEventArgs e properties). And maybe instead of a
form you should use a UserControl... :)\
Hope this helps

Thanks for your reply..
Now I'm using UserControl to draw something...
but....
What I really really wonder is.... look at the below code..

namespace testWindow
{
public partial class UserControl1 : UserControl
{
public int x, y;
public UserControl1()
{
InitializeComponent();
x = 10;
y = 10;
}

public void update()
{
x = x + 2;
y = y + 2;
Invalidate();
}

private void UserControl1_Paint(object sender, PaintEventArgs
e)
{
Graphics g = e.Graphics;

Pen p = new Pen(Color.Black, 3);
g.DrawRectangle(p, x, y, x, y);
}
}
}

namespace testWindow
{
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
userControl11.update();
}
}
}

according to above code...
if user click button on form, user control draw rectangle in
10,10,10,10
if user click more more... then rectangle is change size (+2, +2,
+2....)
at this time, user control is draw only last one because Paint event
draw only one rectangles..

This is not what I wants..
I need all rectangles, so I draw on other function not paint event.
If user click button 4 times, the function draw 4 rectangles... that
good for me.
But.. the problem is that when window is updated (size change,
minimizer and etc...) the drawing is not all recovered

So I wonder that user control need to keep all data to redraw at
somewhere.. (maybe array list or some...)
But this also impossible because the drawing data is too much to keep
in my case..

Is there any good idea or solution?
 
G

Guest

Why bother with class B, since class A has its position data, and presumably
knows what to draw, give it a Draw routine that takes a Graphics object as an
argument and draws what is required at the correct position. Make a
collection of the class A objects and in the forms Paint event handler
iterate through the collection calling the Draw routines and passing the
forms Graphics object to draw on.
 
E

eusebiu

the usercontrol :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class UserControl1 : UserControl
{
public int x, y;

List<Rectangle> _MyRectangleList = new List<Rectangle>();

public UserControl1()
{
InitializeComponent();

this.Paint+=new PaintEventHandler(UserControl1_Paint);
x = 10;
y = 10;

Rectangle r = new Rectangle(x, y, x, y);
this._MyRectangleList.Add(r);
}


public void update()
{
x = x + 2;
y = y + 2;

Rectangle r = new Rectangle(x, y, x, y);
this._MyRectangleList.Add(r);
this.Invalidate();
}

private void UserControl1_Paint(object sender, PaintEventArgs
e)
{
Graphics g = e.Graphics;

Pen p = new Pen(Color.Black, 3);
g.DrawRectangles(p, _MyRectangleList.ToArray());
}
}
}

the form is unchanged.
 
K

Kevin Spencer

So I wonder that user control need to keep all data to redraw at
somewhere.. (maybe array list or some...)
But this also impossible because the drawing data is too much to keep
in my case..

Use an in-memory Bitmap in the Control. When you call the Update method,
draw on the internal Bitmap. When the Paint event handler is called, draw
the Bitmap to the Graphics context.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
FTP Client Classes, Enhanced Data Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
 
B

Ben Voigt [C++ MVP]

Kevin Spencer said:
Use an in-memory Bitmap in the Control. When you call the Update method,
draw on the internal Bitmap. When the Paint event handler is called, draw
the Bitmap to the Graphics context.

Or just enable double-buffering, which does all the above for you, saving
your painting in memory and restoring the screen as needed.
 
P

Peter Duniho

Or just enable double-buffering, which does all the above for you, saving
your painting in memory and restoring the screen as needed.

Not really. With double-buffering, one is required to always be ready to
redraw the entire image at any moment. It's just like handling the Paint
event, except that the drawing is done off-screen first.

The OP wants to be able to draw and then just forget about everything he's
drawn, but keep the image that resulted. The basic idea behind Kevin's
suggestion is really the only way to accomplish this, because Windows
won't remember the graphics for you implicitly.

There are variations on the theme: drawing to a Metafile instead of a
Bitmap; using the Bitmap as the background image for the Form, or in a
PictureBox control; etc. But they all involve the shared general idea of
maintaining a description of the image itself somehow, and using *that* to
redraw the form or control when needed.

Note to the OP: no matter what, at some level you need to handle the Paint
event. You can do this by attaching your Image (Bitmap or Metafile) to
something that will draw for you, or you can draw the Image explicitly as
Kevin suggests. But the basic behavior is fundamental to Windows, and you
can't just draw something to a window (form) and have it stick around.
Windows just doesn't work that way.

Pete
 
P

Peter Duniho

[...]
So I wonder that user control need to keep all data to redraw at
somewhere.. (maybe array list or some...)
But this also impossible because the drawing data is too much to keep
in my case..

I do question your statement that "the drawing data is too much to keep in
my case". Most Windows applications do just that: keep all the drawing
data. In many cases, they are dealing with a very complex document,
whether text or graphics or some more abstract data that is reprented
on-screen by text or graphics (and admittedly, "text" is really just a
special-case of "graphics"). Every time the window needs to be redrawn,
they go through all the relevant data and redraw it.

It works fine. Now and then, an application will need to do some caching
of the results to improve performance, but this is generally limited to
specific aspects. And even in that case, the data required to draw
everything from scratch is generally maintained in memory; the caching is
with respect to the execution of the drawing commands, rather than
throwing out the source data altogether.

Pete
 
C

cty0000

[...]
So I wonder that user control need to keep all data to redraw at
somewhere.. (maybe array list or some...)
But this also impossible because the drawing data is too much to keep
in my case..

I do question your statement that "the drawing data is too much to keep in
my case". Most Windows applications do just that: keep all the drawing
data. In many cases, they are dealing with a very complex document,
whether text or graphics or some more abstract data that is reprented
on-screen by text or graphics (and admittedly, "text" is really just a
special-case of "graphics"). Every time the window needs to be redrawn,
they go through all the relevant data and redraw it.

It works fine. Now and then, an application will need to do some caching
of the results to improve performance, but this is generally limited to
specific aspects. And even in that case, the data required to draw
everything from scratch is generally maintained in memory; the caching is
with respect to the execution of the drawing commands, rather than
throwing out the source data altogether.

Pete

I read all you guys reply (Thanks..)
But I still dont know how to maintain something drawed.

What I'm doing is realtime updating which is updated in a unit of
every 0.5~1 secs and the updating is a lot...
It's possible to keep a lot drawing information in a array, but i
don't know performance.. (Actually I do not want to keep the data..)
After update something, I want to remove the information in every
class..
Somebody tell me the OS system or Video card remember drawing
information in a cache or somewhere, So I do not need to keep that but
I don't know how to do it...


Does any body show me the short sample code..
Please help me.... . ;;;;
 
P

Peter Duniho

I read all you guys reply (Thanks..)
But I still dont know how to maintain something drawed.

I'm not clear on why not, as it seems to me that the question was answered
correctly and more than once.

That said...
What I'm doing is realtime updating which is updated in a unit of
every 0.5~1 secs and the updating is a lot...

Updating every half second to second is child's play for a modern
computer, even when including a _lot_ of information in the update.
It's possible to keep a lot drawing information in a array, but i
don't know performance.. (Actually I do not want to keep the data..)

If you do not want to keep the data, then why do you want to keep
displaying it?

Something to keep in mind: if it is taking you so long to draw everything
you want from scratch, then it is likely that you are drawing more
information to the screen than any human user will be able to comprehend..

Conversely, if you have a mechanism in mind for "aging" the information
and throwing out old information, then you can apply that to stored data
as well as you can to a cached bitmap (better than, actually).
After update something, I want to remove the information in every class..

So, do that. No one said you had to save ALL of the information you ever
receive. You just have to save the information that will be important the
next time Windows asks you to redraw your form.
Somebody tell me the OS system or Video card remember drawing
information in a cache or somewhere, So I do not need to keep that but
I don't know how to do it...

Somebody tell you? If anyone told you that what you draw once is
automatically saved for you, they were wrong. That's just not part of the
standard Windows screen updating paradigm (nor of most other GUI operating
systems for that matter).
Does any body show me the short sample code.
Please help me.... . ;;;;

Here is some short code that should give you the idea:

private Bitmap _bmpCache;

void UpdatedData()
{
Graphics gfx = Graphics.FromImage(_bmpCache);

// use gfx Graphics instance to draw whatever you want to draw
}

protected override void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_bmpCache, 0, 0);
}

You need to make sure that _bmpCache is initialized to a Bitmap the
correct size for your form (or at least, the size you expect to draw to)..
You will need to clear the bitmap manually any time you think that is
appropriate, because everything you draw will just keep piling up in the
bitmap otherwise.

Hope that helps.

Pete
 
P

Peter Duniho

void UpdatedData()
{
Graphics gfx = Graphics.FromImage(_bmpCache);

// use gfx Graphics instance to draw whatever you want to draw
}

And yes, I'm playing the "this is just demo code" card. You should, of
course, make sure to dispose the Graphics object once done with it, either
explicitly, or implicitly with a "using" statement.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top