Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / December 2007

Tip: Looking for answers? Try searching our database.

clear fillEllipse graphics

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Slickuser - 30 Nov 2007 06:35 GMT
I have this function that will fill the ellipse every 10 seconds with
specific x,y,w,h.

Now I want do the the reverse, to clear the ellipse with given x,y
using Timer at every 30s.
Or I have put these (x,y,w,h) to an array?
Later go back the array and fill ellipse with the same color as
background?

Is there an easy way?

Thanks..

//Sample code that draw with timer

       private void drawNote(int x, int y, int width, int height,
SolidBrush brush)
       {
           Graphics graphicGlobal = this.CreateGraphics();
           this.Show();

           graphicGlobal.FillEllipse(brush, x, y, width, height);

       }

       // Timer to draw
       private void timer_note_Tick(object sender, EventArgs e)
       {
           SolidBrush colorBrush = new SolidBrush(Color.Cyan);
           SolidBrush colorBrush2 = new SolidBrush(Color.Magenta);

           drawNote(x_global, y_global, width_global, height_global,
colorBrush);

           drawNote(x_global + 15, y_global + 15, width_global,
height_global, colorBrush2);

           x_global = x_global + 30;
           y_global = y_global + 30;
       }
Hilton - 30 Nov 2007 07:02 GMT
I think you need to dispose of graphicGlobal.

>I have this function that will fill the ellipse every 10 seconds with
> specific x,y,w,h.
[quoted text clipped - 36 lines]
>            y_global = y_global + 30;
>        }
Family Tree Mike - 30 Nov 2007 12:53 GMT
> I have this function that will fill the ellipse every 10 seconds with
> specific x,y,w,h.
[quoted text clipped - 36 lines]
>             y_global = y_global + 30;
>         }

Reread the advise to you in your post yesterday.  It looks like you are
going back to drawing graphics outside the paint event.
Slickuser - 30 Nov 2007 20:03 GMT
If I use that way, I need some how to pass in a PaintEvents to draw.
That how why I choose doing this way.

On Nov 30, 4:53 am, Family Tree Mike
<FamilyTreeM...@discussions.microsoft.com> wrote:
> > I have this function that will fill the ellipse every 10 seconds with
> > specific x,y,w,h.
[quoted text clipped - 41 lines]
>
> - Show quoted text -
Peter Duniho - 30 Nov 2007 21:15 GMT
> If I use that way, I need some how to pass in a PaintEvents to draw.

No, you don't.  Windows generates the PaintEventArgs.  You don't call
OnPaint() yourself, and you don't raise the Paint event yourself.  You
use Control.Invalidate() to tell Windows what area of the control needs
to be redrawn, and Windows handles the rest.

> That how why I choose doing this way.

You are doing it wrong.  You will continue to have problems as long as
you continue to do it wrong.

You can find a discussion on proper techniques for custom drawing in .NET here:
http://msdn2.microsoft.com/en-us/library/kxys6ytf.aspx

While it focuses on an actual custom control, the concepts are the same
whether you are overriding OnPaint() or just handling the Paint event
of a Control instance.

You may also want to learn more about the underlying Windows drawing
model, which is documented here
http://msdn2.microsoft.com/en-us/library/ms534857.aspx

Note that this model is not unique to Windows.  It's a common paradigm,
and so if you learn how to do it in Windows, you will be familiar with
drawing in many different GUI platforms.  More importantly, because its
close relationship with the basic .NET drawing model, learning about
the unmanaged Windows paradigm will actually help you understand the
.NET model better as well.

Finally, you may want to consider learning about the Windows
Presentation Foundation (WPF).  While I don't know much about it
myself, my understanding is that it's a more declarative paradigm, as
opposed to the event-driven paradigm you're trying to use in a sort of
declarative way.
http://msdn2.microsoft.com/en-us/library/ms754130.aspx

Pete
Slickuser - 01 Dec 2007 01:14 GMT
I am looking through examples right now.

Can you give me example that let call(or not) a function which draw at
x,y,w,h with PaintEventArgs?

I still want to call this function with this argument when I want it
to draw: drawNote(int x, int y, int width, int height, SolidBrush
brush)

       private void drawNote(int x, int y, int width, int
height,SolidBrush brush)
       {
      ////PaintEventArg???
           //Graphics graphicGlobal = this.CreateGraphics();
          /// this.Show();

           graphicGlobal.FillEllipse(brush, x, y, width, height);

       }

> > If I use that way, I need some how to pass in a PaintEvents to draw.
>
[quoted text clipped - 31 lines]
>
> Pete
Peter Duniho - 01 Dec 2007 01:23 GMT
> I am looking through examples right now.

Eventually, you should find a discussion of the Paint event and what  
PaintEventArgs contains.

> Can you give me example that let call(or not) a function which draw at
> x,y,w,h with PaintEventArgs?

In that discussion, you will find that the PaintEventArgs.Graphics member  
provides the Graphics instance to which you need to draw.

> I still want to call this function with this argument when I want it
> to draw: drawNote(int x, int y, int width, int height, SolidBrush
> brush)

Since the PaintEventArgs.Graphics member is the Graphics instance to which  
you need to draw, that means that you need to pass the Graphics instance  
from PaintEventArgs to any code that wants to draw.  The simplest way to  
do that would be to include it as a parameter to the method called from  
the OnPaint() method or the Paint event handler (however you've decided to  
implement it).

So:

>         private void drawNote(int x, int y, int width, int
> height,SolidBrush brush)

becomes:

>         private void drawNote(Graphics gfx, int x, int y, int width, int
> height,SolidBrush brush)

and the method body:

>         {
>        ////PaintEventArg???
[quoted text clipped - 4 lines]
>
>         }

becomes:

>         {
>             gfx.FillEllipse(brush, x, y, width, height);
>         }

Hope that helps.

Pete
Slickuser - 01 Dec 2007 01:48 GMT
Which in that case, now I need to pass in Graphics as input argument
to call drawNote (5 input arguments)?

How can I achieve with my timer? Thank you so much for your help.

// Timer to draw
       private void timer_note_Tick(object sender, EventArgs e)
       {
           SolidBrush colorBrush = new SolidBrush(Color.Cyan);
           SolidBrush colorBrush2 = new SolidBrush(Color.Magenta);

           //drawNote(x_global, y_global, width_global,
height_global,colorBrush);

           //drawNote(x_global + 15, y_global + 15,
width_global,height_global, colorBrush2);

           x_global = x_global + 30;
           y_global = y_global + 30;
       }

On Nov 30, 5:23 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

> > I am looking through examples right now.
>
[quoted text clipped - 48 lines]
>
> Pete
Slickuser - 01 Dec 2007 01:51 GMT
I should use ??

protected override void OnPaint(PaintEventArgs e)
{
  // If there is an image and it has a location,
  // paint it when the Form is repainted.
  base.OnPaint(e);
//base.Invalidate();

}

> Which in that case, now I need to pass in Graphics as input argument
> to call drawNote (5 input arguments)?
[quoted text clipped - 72 lines]
>
> > Pete
Peter Duniho - 01 Dec 2007 02:10 GMT
> I should use ??
>
[quoted text clipped - 6 lines]
>
> }

That depends.  Are you putting the drawing code into the same class as  
that which represents the control or form into which the drawing is  
actually being done?  If so, then yes...I personally feel that writing an  
override for OnPaint() is more appropriate than handling the Paint event.

Note: you almost always will want to call the base.OnPaint() as you've  
shown there.  However, you should _never_ call Invalidate() from within  
OnPaint() or a Paint event handler.  I realize the line is commented out  
here, but it should never have been there in the first place.

Pete
Peter Duniho - 01 Dec 2007 02:07 GMT
> Which in that case, now I need to pass in Graphics as input argument
> to call drawNote (5 input arguments)?

Yes.  If it bothers you and your drawing code is complex enough, you may  
find it makes sense to create a class instantiated for each time you draw  
and to which you pass the Graphics instance as well as any other  
frequently-used data items you might want access to from the drawing code.

> How can I achieve with my timer? Thank you so much for your help.

You don't draw in response to a timer.  You can update your data, and then  
invalidate the area of the control/form that needs to be redrawn  
(depending on the data and what you're drawing, this might just be the  
whole control or form).

Pete
Slickuser - 01 Dec 2007 02:22 GMT
On Nov 30, 6:07 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

> > Which in that case, now I need to pass in Graphics as input argument
> > to call drawNote (5 input arguments)?
[quoted text clipped - 12 lines]
>
> Pete

Update my data of x,y,...?

Here is my code so far..

//code

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

namespace fill3
{
   public partial class Form1 : Form
   {

       int x_global = 10;
       int y_global = 10;
       int width_global = 50;
       int height_global = 50;

       public Form1()
       {
           InitializeComponent();
       }

       private void Form1_Load(object sender, EventArgs e)
       {

       }

       private void timer_note_Tick(object sender, EventArgs e)
       {
           SolidBrush colorBrush = new SolidBrush(Color.Cyan);
           SolidBrush colorBrush2 = new SolidBrush(Color.Magenta);

           //drawNote(x_global, y_global, width_global,
height_global, colorBrush);
           //drawNote(x_global + 15, y_global + 15, width_global,
height_global, colorBrush2);

           x_global = x_global + 30;
           y_global = y_global + 30;
       }

       private void drawNote(Graphics gfx, int x, int y, int width,
int height,SolidBrush brush)
       {
           gfx.FillEllipse(brush, x, y, width, height);

           gfx.Dispose();
           this.Invalidate();
       }

   }
}
Peter Duniho - 01 Dec 2007 04:11 GMT
[...]
>> You don't draw in response to a timer.  You can update your data, and  
>> then
[quoted text clipped - 3 lines]
>
> Update my data of x,y,...?

Yes.

> Here is my code so far..

Here's what it should look like instead:

> [...]
>         private void timer_note_Tick(object sender, EventArgs e)
[quoted text clipped - 9 lines]
>             gfx.FillEllipse(brush, x, y, width, height);
>         }

          protected override void OnPaint(object sender, PaintEventArgs  
pea)
          {
              using(SolidBrush colorBrush = new SolidBrush(Color.Cyan),
                      colorBrush2 = new SolidBrush(Color.Magenta))
              {
                  drawNote(pea.Graphics, x_global, y_global,
                      width_global, height_global, colorBrush);
                  drawNote(pea.Graphics, x_global + 15, y_global + 15,
                      width_global, height_global, colorBrush2);
              }
          }

Note that I removed the Dispose() and Invalidate() calls from your  
drawNote() method.  Those are _both_ extremely important to NOT do while  
handling a Paint event.  The Dispose() is bad because you didn't create  
the Graphics instance and it needs to stick around until Windows is ready  
to dispose it itself.  The Invalidate() is bad because every time you call  
Invalidate(), that will cause another Paint event to be raised, creating  
an endless loop.

Also note the "using" statement in the OnPaint() method.  You _do_ create  
the SolidBrush objects, and they must be disposed when you're done with  
them.  The using() statement provides a convenient way to do that.

Finally note that the above doesn't accumulate the ellipses.  It's not  
clear from your question or code whether you expect it to.  But if you  
want to gradually add new ellipses without erasing the previously drawn  
ones, you'll need to manage that in addition to the code shown above.  
IMHO, we should straighten out the basic drawing mechanism first though.  
Baby steps.  :)

Pete
Peter Webb - 02 Dec 2007 01:59 GMT
Peter:

I have been following this thread, as I have similar problems/issues (as you
may recall).

Since your last round of advice, I have played a lot, and even bought a C#
book, but its still not working. After many hours without luck, I would
really appreciate some more help

In my case, the OnPaint command would be extremely easy to implement as I am
drawing entirely to a graphics buffer (so I have a complete copy of the
image) and all I need to do is execute a MyBuffer.Render() to physically
redraw.

Here is my problem.

I have put this code into my app:

          protected override void OnPaint(object sender, PaintEventArgs
pea)
          {
              MyBuffer.Render();
           }

This actually works, but only sort-of. This OnPaint is triggered by a redraw
of Form1. I start my app, it comes up with a blank PictureBox1. As soon as I
move the mouse off the PictureBox (eg to the button area) it triggers the
above and my image appears. But only (very annoyingly) when the user moves
the mouse to the button area. This is very inconvenient because I can't play
my animation on start up (and it looks tacky).

Clearly, I have wired the OnPaint to the Form, and not to PictureBox1.

My book says that I need to insert the OnPaint override in the control
setup. I can do this for Form1, because the system generates a block of code
to initialise Form1. I can find no equivalent for PictureBox1.

If I click on my PictureBox1 in the designer, it has a Paint method
(member?) listed, but this is Paint but not OnPaint. I can't see where my
On_Paint method has to be inserted in my code to trigger off PictureBox1
instead of Form1.

Somebody suggested that I create a custom control which inherits from
PictureBox but overrides OnPaint. I tried this, but got into a fair amount
of mess. I have abandoned this as it seemed a very complicated solution to a
pretty simple problem, and I got even further out of my depth.

So, is there a simple way of wiring my OnPaint method (which works fine) to
be triggered off a repaint of PictureBox1 instead of Form1? If so, how do I
do it?

Thanks,

Peter Webb
Peter Duniho - 02 Dec 2007 02:41 GMT
> [...]
> So, is there a simple way of wiring my OnPaint method (which works fine)  
> to be triggered off a repaint of PictureBox1 instead of Form1? If so,  
> how do I do it?

It seems to me that you actually have two different issues.  One is, where  
to do the drawing?  That is, where does your drawing code go?  The other  
is, how do you cause the drawing to occur?

With respect to the first question...

The PictureBox class is not for people who want to do their own drawing.  
It's a convenient control to which you can attach an existing Image, and  
let the control itself deal with a variety of display issues.  Such as,  
when to draw, if and how to scale the image, that sort of thing.

You _could_ certainly derive a new class from PictureBox and override the  
OnPaint() method, but that would be sort of pointless.  You can easily do  
the same thing deriving from the Control class, without having all the  
extra PictureBox functionality dragged along.

You could also handle the PictureBox's Paint event, but again it would be  
pointless, for the same reasons.

The reason for deriving from PictureBox would be if you want to use and  
extend or override functionality that is specific to the PictureBox  
class.  So far I haven't seen anything that would suggest that's what  
you're doing or what you want.

So where should you do the drawing?  IMHO, it depends on what your UI is  
like, which I don't know.  If you intend to manage all of the drawing  
inside the form, then drawing in the form class would be a reasonable  
place.  If, however, you want to be able to use the VS Designer to  
implement and maintain the user interface, and you want to be able to  
manipulate where you custom drawing happens as part of that maintenance,  
then you will probably want to create a custom Control-derived class.  
That way, you'll get a custom control added to your Designer toolbox that  
you can drag and drop, placing it wherever you like.

Creating a custom control is very simple, practically the same as creating  
a new form class.  Just add a new item to the project (using the  
Project/Add New Item... menu or the Solution Explorer), and select "Custom  
Control" from the template list.  This will create a new class derived  
from Control.  In that class, you can override OnPaint() where you want to  
draw.

Of course, you will want to move any other code related to managing the  
graphics into that control class, or somewhere related to it.  That's a  
broader design question, and frankly it's much harder to answer those  
questions in a newsgroup like this.  Providing good advice on design  
generally requires a lot of background knowledge of the problem being  
solved, and not only is that background knowledge difficult to express in  
this context, so too is explaining how a good design would work.

Suffice to say, a good design makes it easy to put all your pieces  
together.  Conversely, if you're having trouble putting the pieces  
together, you should rethink the design.

Now, finally...there's the question of how to cause the drawing to occur.  
The basic mechanism is invalidation of the control.  In this context  
"invalidation" means something very specific: to communicate to Windows  
that an area of the control no longer has valid graphics and needs to be  
redrawn.  You use the Control.Invalidate() method to do this.

I've already explained that in this thread, and I believe that the various  
links that have been posted, by myself and others, also explain it  
reasonably well.  The basic idea is this though: you don't draw in direct  
reaction to changes in the data; you design your drawing code so that it  
can always draw whatever the current state of the data is, and you  
invalidate the control in reaction to changes to data.

Since you're using the BufferedGraphics class, it seems to me that this  
should be especially simple.  When you change the BufferedGraphics by  
drawing to it, you need to call Invalidate() on whatever control it is  
that you are drawing to (the Form class inherits Control as well).  If you  
know specifically what area of the BufferedGraphics has changed, you can  
use that information to restrict the invalidated area, passing a rectangle  
to the Invalidate() method so that only the part that changed winds up  
getting redrawn.

Pete
Slickuser - 02 Dec 2007 02:07 GMT
On Nov 30, 8:11 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

> [...]
>
[quoted text clipped - 59 lines]
>
> Pete

Thank you so much Pete! You're awesome!

I'll add these basic drawing to my code. I'll reply back if run into
any more problems.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.