.NET Forum / Windows Forms / Drawing / April 2005
How to give parameters to the paint event handler
|
|
Thread rating:  |
György - 27 Apr 2005 22:47 GMT I would like to place a character to different points ( X and Y coord) on a graphics screen. I use the paint event handler to draw my graphics but can not update the screen with new co-ordinates where I want to place a new character. Does anybody knows how to submit the parameters to a paint event handler?
Thanks, György
Morten Wennevik - 27 Apr 2005 23:26 GMT Hi György,
I think you need to rethink your strategy. You call the paint event (by calling Invalidate), then the code inside the event checks to see where to draw the character.
You can't pass parameters directly to the Paint event, but you can do painting outside the event using CreateGraphics. However, you should try to avoid calling CreateGraphics and do all your drawing inside Paint.
> I would like to place a character to different points ( X and Y coord) on a > graphics screen. I use the paint event handler to draw my graphics but can [quoted text clipped - 4 lines] > Thanks, > György
 Signature Happy coding! Morten Wennevik [C# MVP]
Bob Powell [MVP] - 27 Apr 2005 23:30 GMT You cannot hand new parameters to the Paint event handler. You must create a variable in your class that maintains the new coordinate.
 Signature Bob Powell [MVP] Visual C#, System.Drawing
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.
> I would like to place a character to different points ( X and Y coord) on > a [quoted text clipped - 6 lines] > Thanks, > György György - 28 Apr 2005 15:36 GMT Dear Bob and Morten,
I went through the web site of Bob and learned a lot. Thanks for bringing it to life.
But I still confused what is the right solution. According to my understanding I could do the following: • Creating a new blank image in a new Thread • Generate a Graphics object with the use of Graphics..Fromimage • Stop my thread with an AutoReset EventWait to wait on X,Y coordinates • Receiving the coordinates I create my graphics drawing ( place a “dot” character) • Set an other AutoResetEvent informing my X,Y supply thread to go ehead
Is it a possible way?
Many thanks, György
> You cannot hand new parameters to the Paint event handler. You must create a > variable in your class that maintains the new coordinate. [quoted text clipped - 9 lines] > > Thanks, > > György Bob Powell [MVP] - 28 Apr 2005 16:13 GMT What I don't understand here is exactly what you're trying to do and why you think you need a multi-threading solution.
Just explain the goal that you want to achieve.
 Signature Bob Powell [MVP] Visual C#, System.Drawing
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.
> Dear Bob and Morten, > [quoted text clipped - 32 lines] >> > Thanks, >> > György György - 28 Apr 2005 16:28 GMT I work on a data acquisition system. I measure something and basically I need to place a dot to the screen to indicate the measured value. Than comes a new measurement and the previous point should be cleared and the new dot should appear on the screen. Basically that is the case. So I need to modify the screen content continuously and because of handling the measurement device I anyway have multi threads.
György
> What I don't understand here is exactly what you're trying to do and why you > think you need a multi-threading solution. [quoted text clipped - 37 lines] > >> > Thanks, > >> > György Bob Powell [MVP] - 28 Apr 2005 17:33 GMT Just store a point and paint it whenever the screen is invalidated...
Point blob=new Point(-50,-50);
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.FillEllipse(Brushes.Red,blob.X-10,blob.Y-10,20,20);
}
private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
blob=new Point(e.X,e.Y);
}
 Signature Bob Powell [MVP] Visual C#, System.Drawing
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.
>I work on a data acquisition system. I measure something and basically I >need [quoted text clipped - 56 lines] >> >> > Thanks, >> >> > György György - 28 Apr 2005 17:54 GMT Do you mean that I should call the Invalidate method from one of my thread and that will generate a Form1_Paint event which will refresh the screen? If so, than when I get a new paint event can I save the content of the screen and only change what I intend to chane?
György
> Just store a point and paint it whenever the screen is invalidated... > [quoted text clipped - 78 lines] > >> >> > Thanks, > >> >> > György Bob Powell [MVP] - 28 Apr 2005 18:36 GMT From one of your threads you can invalidate the main form but ONLY using the Invoke or BeginInvoke methods.
You will need to repaint all elements of the screen that are in the invalid rectangle. If you just call invalidate() then that means all of it.
Don't try to save the content of the screen. The screen should know how to refresh itself at all times so if the only place you're keeping records is in the actual pixels of the display you're guaranteed to be causing yourself problems later.
 Signature Bob Powell [MVP] Visual C#, System.Drawing
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.
> Do you mean that I should call the Invalidate method from one of my thread > and that will generate a Form1_Paint event which will refresh the screen? [quoted text clipped - 93 lines] >> >> >> > Thanks, >> >> >> > György György - 28 Apr 2005 19:16 GMT There is not any other option just to simply edit the content of the screen. I just want to write out a black coloured charcter to my old position to clear the old content and write a new character in white color into the new position. Is not it possible to do it with CreateGraphics?
György
> From one of your threads you can invalidate the main form but ONLY using the > Invoke or BeginInvoke methods. [quoted text clipped - 104 lines] > >> >> >> > Thanks, > >> >> >> > György James Westgate - 28 Apr 2005 21:17 GMT Dude,
Listen to Bob. He knows what he's doing. We've been there a million times, trust me on this one.
The GDI+ graphics system is stateless and event driven, this means you need to repaint everything that is required in the correct order *everytime* the screen or control or control portion is repainted. Access the control across the thread using an invoke and set a property eg your point. The control will know when to paint itself and will then paint the dot.
Dont use CreateGraphics for the reasons outlined in this forum in recent posts and on Bob's site.
This is a really simple 5 minute job, you dont need to make it complicated ;)
James
> There is not any other option just to simply edit the content of the > screen. [quoted text clipped - 129 lines] >> >> >> >> > Thanks, >> >> >> >> > György György - 29 Apr 2005 15:00 GMT Finally I found a solution. Propably could be interesting for your FAQ site.
• First I created a blank bitmap. In one of my thread • Than I edited my screen into the bitmap. Also in the thread • In the paint event handler I just placed a DrawImage command from the bitmap • When I wanted to refresh my screen I called the Invalidate method to generate a paint event. • I again did some minor changes on my bitmap and called the invalidate()…..
It works fine. The only pending issue at the moment that I have to find a solution to invalidate only a pie or rectangle of the bitmap to lower the flickers of the screen. If you may have a better idea please let me known!
György
> Dude, > [quoted text clipped - 148 lines] > >> >> >> >> > Thanks, > >> >> >> >> > György György - 29 Apr 2005 14:58 GMT Finally I found a solution. Propably could be interesting for your FAQ site.
• First I created a blank bitmap. In one of my thread • Than I edited my screen into the bitmap. Also in the thread • In the paint event handler I just placed a DrawImage command from the bitmap • When I wanted to refresh my screen I called the Invalidate method to generate a paint event. • I again did some minor changes on my bitmap and called the invalidate()…..
It works fine. The only pending issue at the moment that I have to find a solution to invalidate only a pie or rectangle of the bitmap to lower the flickers of the screen. If you may have a better idea please let me known!
György
> From one of your threads you can invalidate the main form but ONLY using the > Invoke or BeginInvoke methods. [quoted text clipped - 104 lines] > >> >> >> > Thanks, > >> >> >> > György Frank Hileman - 29 Apr 2005 20:04 GMT This has the potential to fail if you do not lock the Bitmap. In general the GDI+ methods in .NET are no more thread-safe than Windows Forms methods. The safest solution is to do all drawing in the main thread, started by BeginInvoke on a Control or Form.
Regards, Frank Hileman
check out VG.net: http://www.vgdotnet.com Animated vector graphics system Integrated Visual Studio .NET graphics editor
> Finally I found a solution. Propably could be interesting for your FAQ > site. [quoted text clipped - 14 lines] > > György György - 29 Apr 2005 20:40 GMT Dear Frank,
Thanks for the advice. I will look after it.
By the way can you see other option to change a graphics screen with parameters coming from an other thread?
Sincerely, György
> This has the potential to fail if you do not lock the Bitmap. In general the > GDI+ methods in .NET are no more thread-safe than Windows Forms methods. The [quoted text clipped - 26 lines] > > > > György Frank Hileman - 29 Apr 2005 22:10 GMT Typically people use BeginInvoke, passing in data which is then rendered in the main UI thread. You will need an efficient rendering engine to be sure it can keep up without bogging down the UI. You can pass parameters in BeginInvoke to maintain separation between threads without locking, or you can simply use it to notify the main thread, and use locks around data structures to prevent conflicts between the threads.
For example, if you do not want to use locks, your data acquisition thread allocates and fill a buffer (collection or array), then when it has acquired enough (or enough time has passed), call BeginInvoke, passing in the buffer as a parameter. Then the data acquisition thread no longer touches that buffer but immediately allocates the new one. The garbage collector will clean up. This is a nice simple way to do it.
If you don't like to allocate so many objects, you could keep two buffers, and two locks, one associated with each buffer. The data acquisition thread locks buffer1. When buffer1 is "full" or enough time has passed, BeginInvoke is called and the lock is released. Immediately the data acquisition thread then tries to lock buffer2.
The main UI thread then locks the incoming buffer (which buffer might be specified with an int) and processes it. When done it releases the buffer lock.
Using the locking solution there is a chance that the next buffer is not ready for the DA thread when it needs it. In this case you have to decide if you need every bit of data, and if you do, you need to just keep adding to the free buffer until the other one is released, by periodically checking with Monitor.TryEnter.
Using either solution the UI thread must be able to keep up, or you must abandon data, or decide to skip the rendering. In your rendering code you could periodically check a flag indicating it is necessary to abandon rendering. The non-UI thread would set this flag (noticing a backlog of data), and the UI thread would clear the flag whenever rendering is abandoned or finished. It is a little more complicated than that to prevent a race, but I think you get the idea.
By the way, the VG.net run-time engine will automatically redraw a minimum number of pixels when you modify a graphical object. That engine is free for run-time only use.
Regards, Frank Hileman
check out VG.net: http://www.vgdotnet.com Animated vector graphics system Integrated Visual Studio .NET graphics editor
> Dear Frank, > [quoted text clipped - 40 lines] >> > >> > György György - 30 Apr 2005 20:26 GMT Dear Frank,
Thank you for your time to write down these valuable ideas! I will definitelly read the relewant documentation and try to implement them. Regarding the VG.net may I take it as an option to download from your site?
I have an other pending issue and would appreciate your idea about layering. I will need one or two layers with fix content that I do not want to change and will need a third one where I want to do my picture changes that we discussed before.
Many thanks, Sincerely, György
> Typically people use BeginInvoke, passing in data which is then rendered in > the main UI thread. You will need an efficient rendering engine to be sure [quoted text clipped - 89 lines] > >> > > >> > György Frank Hileman - 30 Apr 2005 22:15 GMT Hello György,
Regarding VG.net: the Lite version has a run-time engine in Prodige.Drawing.dll you can use. If you do not have Visual Studio 2003 send me a note through the web site, and I can get you an SDK.
Layering: you will need graphical objects that know how to draw themselves, called a retained mode graphics system. VG.net objects automatically redraw areas invalidated by animation, or you can look at Bob Powell's site for more ideas on building a system yourself. If you do it without VG.net you have to keep track of which objects overlay each other, or redraw the whole screen.
Regards, Frank
> Dear Frank, > [quoted text clipped - 77 lines] >> Animated vector graphics system >> Integrated Visual Studio .NET graphics editor György - 28 Apr 2005 16:28 GMT I work on a data acquisition system. I measure something and basically I need to place a dot to the screen to indicate the measured value. Than comes a new measurement and the previous point should be cleared and the new dot should appear on the screen. Basically that is the case. So I need to modify the screen content continuously and because of handling the measurement device I anyway have multi threads.
György
> What I don't understand here is exactly what you're trying to do and why you > think you need a multi-threading solution. [quoted text clipped - 37 lines] > >> > Thanks, > >> > György
Free MagazinesGet 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 ...
|
|
|