![windows forms manual double buffering windows forms manual double buffering](http://blog.shubhamsaxena.com/wp-content/uploads/2012/08/2.png)
That’s pretty much all you need to get a custom double buffered control going. You may have noted that I made a few calls to “Redraw().” Redraw() is where I put.
Hi, I have used your code to get my pitiful attempt at a screensaver to show on multiple monitors. That is working, and I just have it so either some default images.
Introduction I wanted to write a screensaver. Yeah, I bet everyone goes through this stage, but this time I got the needed info so the purpose of this article is to impart to you the info that for so many years was missing or hidden or only available to a privileged few. First of all I would like to thank Rakesh Rajan for his fine article that got the ball rolling, and I was able to fill in the gaps and complete a screensaver with all the features I really could possibly want. You can view his fine article - How to develop a screen saver in C# . Hmmm, that's a long URL, I hope it fits! Thanks again!. Further credits to two others can be found in the source code. Double-buffering This is a technique to do flicker free, and faster drawing. It involves doing all your drawing on an off-screen bitmap. Because this bitmap is not on display the drawing routines run much faster because the drawing doesn't invoke a paint event. After all drawing is done, it is processed for display. There are extremely quick double-buffering that forms and other controls have built in, but it has its issues, which means you might be tortured by the InvalidOperationException error. This was a particularly nasty error to try to deal with because in my program, it drops right through the catch statements that I made for this error as if it did not match and what makes it worse is it's so intermittent, it might show up immediately, or might run for several hours before showing its ugly head. To rid yourself of this nefarious bug, use the Flush method on your Graphics object after you've done a drawing cycle . Example ... pev.Graphics.Flush(System.Drawing.Drawing2D.FlushIntention.Flush); and this will eliminate the error. The cause of the error is that unless you do use the above command, sometimes, the buffer is not drawn to the screen right and your code could end up doing another paint cycle while the buffer is being written, or usually while the buffer is being disposed, which causes a conflict where your code is trying to use the buffer, while it is unavailable! The GDI+ does not check for this. If you use the Flush as above, the buffer is written to the screen and refreshed and ready to use when you need it. Update: 06/18/2005 - I have solved the above issue. It is quite an interesting find, as to why. See end of article for more info. 6/10/2005- Neat new stuff added. You gotta try this with seven swarms a screen ! I have just succeeded in getting this screensaver to work on multiple monitors in duel mode on a single system at the same time!! I am going to upload the new code, and then I'll work on the snippets, for that is quite a job. As far as I know this is the only screensaver that can do this. I tried many others, and none worked. I have explained what I had to do in EntryPoint.cs in the source files. I have been having some stability issues. Hopefully the changes I made on 6/13/2005 fix some of them. 6/16/2005- I have implemented event and delegate driven engine. I separated some of the code that was getting rather cluttered into separate classes, solved the stability issues and modified snippets. See end of article ! After searching the internet for weeks, trying to find the info I needed to make my own screensavers and coming up with woefully incomplete examples that glossed over vital information, or examples that were enormous, yet devoid of meaningful comments so that by the time I found the answer, I had forgotten the question. Almost all the examples did not work or had bugs that prevented me from testing them. I determined that I would write a "Complete" screensaver and post it on the web so that others need not go through the torment I did trying to find the info needed. What I mean by putting "Complete" in quotes, is that the only feature I did not implement was bringing up the password dialog box when the program received an/a as an argument. I did not wish to have some bug or future change in Windows, to cause my screensaver to lock a user out of the system. Caveat: On NT 2000, if the computer has the feature to lock the computer turned on after X minutes of inactivity, and the computer is locked while the screensaver is running, when you touch your machine, the screensaver shuts down, but the welcome box from Windows asking for the password does not show. The fix is simple .. Hit Ctrl-Alt-Delete or Ctrl-C and the welcome screen comes up and you are good to go. This article will still give you the info you need to make your own screensaver. The problems I needed to solve were .... How to attach the Configuration dialog as a child of the Display Properties box from Windows. How to draw to the little mini-preview box on the above form. Where to put the drawing routines and how should I execute them. How to save my configurations to the registry, and just recently, how to save CONFIG stuff to an XML file instead of the registry. How to get a screensaver instance to draw to all active screens on a system! If the system only has one monitor, I found that calling sf[i].Invalidate(sf[i].Bounds) method where i = the screen number, the primary screen worked fine and was faster when this method failed to cause the second monitor to show anything. The first monitor would hog all the CPU time at the complete expense of the second. I found that if I used the ScreenSaverForm's Refresh() method when there were multiple active screens, I was able to invoke drawing on both monitors and the results would show when I called Application.DoEvents(). I no longer use Invalidate as it caused synchronization issues with timing as I learned that events are on a separate thread, and Refresh() was the only way to get the truth, of the state of a variable I used to query if the form was ready for another call to PaintMe(). I have my code for drawing in the screensaver forms one form per monitor, but I had issues with the program triggering the form to draw before it was finished and ready to draw again. Update: I ended up writing some delegates and passing them into the forms and using these delegates to notify the calling class ScreenSaver when a form was ready for drawing via Application.DoEvents() and then invoking a new paint event via the form's Refresh() method. Originally, I had written this to use threading, but I found that the worker threads were very slow compared to having all instances of the ScreenSaverForm running under the main thread. It was also good for avoiding thread locking issues. With one thread acting as if it were multiple threads, there was no chance of thread locking problems. Now, I do the drawing in the paint events, wherever possible. One thing you will notice right off is that the source code is chock full of comments to the point that the code itself is nearly buried for two reasons... Latest change as of 06/04/2005 Configuration is now saved as an XML file and it's a lot simpler. Your CONFIG file will be created if it doesn't' exist, and will be the name of the executing file + .config.xml. Example. Swarm.scr creates Swarm.scr.config.xml. The changes to the code were minor, so I won't change the snippets above, because the concept is the same except minor changes and re-doing the snippets is a nightmare so I've just uploaded a new source file zip. If you wish, just look at the code and code comments web pages included to see the changes. Notice the extra file XmlSwarmScreenSaverConfig.cs. I have also added a call to a parsing routine in the entrypoint.cs' case statement to more clearly parse the command line, so you can better see what is happening. 06/07/2005 Just cleaned up some horrible grammar in the article and references to SaverLoop that no longer exists. Isn't it funny how trying to get rid of spelling and grammar errors is like trying to vacuum up all the sand out of a shag carpet that has been washed up on a beach? 06/10/2005 - New things added ... Added some code to the insects class which does my drawing, so that it will stop immediately if the form it is drawing on is in the process of closing. I hope this might solve the un-catchable InvalidOperationException I was getting. Added the ability of the saver to handle multiple swarms and wasp groups on the same screen!! It really looks neat, having several swarms dancing about. I found that the swarms would start out in about the same area and then diverge, with some swarms going off on their own, and then strangely, all the swarms moving in sync as in a dance! It was very nice to watch! I accomplished this by changing the single instance of the insects class to an array. I added a configuration option where you can specify between 1 and 100 swarms, so if you feel like going nuts, go for it, give that computer a REAL stress test! Added code to the XML CONFIG saver reading method, so that if it discovers that a field is missing, in this case, the new SwarmsPerScreen field or is corrupted in some other way, it self recovers by recreating a new configuration file with default values and so no worries about forgetting to remove the old CONFIG file. Discovered that the insects class was using a STATIC instance of the CommonFunctions class which is used to derive random numbers, color adjustment and other functions, and this could very well explain why it failed to run on multiple monitors. Later, I may uncomment out the multiple monitor code and give it a try, but not just yet. Obviously, if one is having multiple objects addressing a single instance, this can be a bit of a problem. 6/11/2005 Hopefully fixed issue with object in use exception. It seems the issue was caused by my process trying to access the Graphics object in the paint event before the screen was done painting. I could have put in some sort of waiting between calls, but I wanted to have the thing run as fast as possible, so I simply put a lock(e.Graphics) statement on the Graphics object passed in the paint event argument e. This seems to have cleared it up, but as with all intermittent bugs it has a life of its own, thus proving the truth of my suspicion that C# is an upgrade of Murphy's C++ ! I have just succeeded in getting this screensaver to work on multiple monitors in duel mode on a single system at the same time !! 6/15/2005 In an ongoing effort to solve the InvalidOperationException event, "Object in use elsewhere" issue, I have utilized graphics paths instead of drawing one line at a time, I build the graphics and then draw the graphics path. I use the Graphics object's CloseFigure() method which starts a new subfigure which causes each bee to be considered as a separate subfigure otherwise there would be a line connecting the bees together. The effect was like a wad of paper in model form. It was interesting to look at. I use delegates to inform the ScreenSaver class when a form is shutting down and another to inform when it's done painting, and set a boolean array so it knows which forms are ready to draw. The boolean array isn't necessary because I discovered that if one form needs a refresh, the other did too by the time it got to the refresh. I find it interesting that the Application.DoEvents() method and program events are tied together, in other words, there is no way to control what gets stopped. If I don't call DoEvents regularly, the form events stop. I can't just arbitrarily call Application.Events() without the forms getting a repaint before it's ready. The paint event draws the graphics, but it will never appear on the monitor until Application.DoEvents() is called which of course effect all screens ! I have separated the mini-preview and FullScreen Preview/Screensaver code into MiniPreview.cs and ScreenSaver.cs. Update late 06/18/2005 Found a method of eliminating wasting CPU cycles just running a loop waiting for an event instead of waiting for the event gracefully. One thing I know about Windows, is that it is message driven, and when I started implementing the event driven ScreenSaver class, I looked for a way to wait for an event instead of wasting CPU cycles. I found a method called WaitHandle.WaitForAny(Array[]). This method takes an array of ManualResetEvents or AutoResetEvents and can be used to stop the current thread wait till any of the event instances in the array is set via manualEvent.Set();. By using this one statement and then using a manualEvent.Reset() when a ScreenSaverForm.Refresh() was about to be called, I was able to cause the thread to sleep and wait for the events instead of gobbling CPU cycles like a school of hungry piranha and overburdening the computer. By using the WaitForAny method as mentioned above, I was able to eliminate a source of much un-necessary burdening on the system. The code changes I did are in bold in the snippets above. Update for 8:PM PST 06/19/2005 Due to the tenacity of the InvalidOperationEvent issue, I have added a CONFIG option to toggle the style based double buffering in favor of my manual double-buffering code, which has never generated this bug, but is much slower. Caveat: For some reason, when I execute the program within the development environment and a new option is found that is not in the CONFIG file the IDE hangs. If I run the app outside the development environment or delete the old CONFIG file, it does not hang. I've uploaded the new source code. I have left the snippets the same because there were very few changes that really mattered. I think I have found what is the cause of the InvalidOperationException event... The manual double buffering never crashes. In this kind of buffering there is no double buffer between the Graphics object, and the display, and so there is no guess work about when this buffer is written to the screen because I get complete control over this via the code. The control's built in double buffering is automatic in that the control has a back buffer that is written at a time decided by the runtime unless you call the flush method mentioned earlier. In this scenario the control has to guess when it's time to copy the back buffer to the display and also guess when it's time to write the buffer, and it tends to choose poorly. The control under double-buffering via the setstyle was deciding to copy the buffer to the screen and dispose it just as my program tries to write to this buffer ! This would explain the delay time where I have seven swarms on the screen, but one only appears every 4 seconds, till they are all on-screen. Updates 06/20/2005 Looks like, the above theory is possibly true. I got a reply from Bob Powell stating that he suspected there was some sort of bug with auto-double buffering, but it's not confirmed, except that the horror bug has been solved. It's been running for about 15 hours without crashing so the issue is solved after I did the change below ... Changes ... I removed a lot of whining and commentary about the error I spoke of. I allowed my judgment to be affected by my frustration and ranted about it. While I'm sure, it was interesting to me, it was probably boring to you. I apologize. Important change 06/24/2005 I have found the cause of the InvalidOperationException error. I was drawing outside of the buffer, forcing it to dispose and resize! Yep, it was my fault! I had assumed that the Graphics object I get in paint event arguments would have its clipping region set to the size of the form. I was wrong. By default it appears to be infinite. When drawing is done with double-buffering and this drawing happens out of bounds, the backbuffer in auto-double buffering will destroy itself and resize. This was causing the exception. I tried setting it via the bounds of the form but when the computer is running in multi-screen, the bounds and the clip bounds in the Paint event args for the secondary monitor have an offset in the X and Y values. Here is what I have done about this .. Although using Graphics.SetClip(e.ClipRectangle) seems to work, I do not trust it. Instead I put the code that was originally in the swarm class that will skip drawing of any graphic unless all of it is completely in the screen dimensions as specified in width and height and that no part of the graphic is in a negative pixel location. I might have to do some adjustments aside from this due to pixel offset, but at least I'm on the right track. I removed the flush statement as I don't need it now. Important - I found out that when a form is locked and I try to resize it in code, it causes an endless stream of paint commands trying and failing to resize the form. My code would ignore these but they would be sent again and again until I unlocked the form. Added several tests and a paintStatus variable to track the status of all paint events done. My code now resides in the paint event instead of OnPaint. Setting paintEventArgs's pev.Graphics.SetClip(Bounds) was preventing the secondary monitor from drawing. This does work here but I don't trust it ... pev.Graphics.SetClip(pev.ClipRectangle);
These terms are commonly used in information about the MySQL database server. This glossary originated as a reference for terminology about the InnoDB storage.
![A complete C# Screensaver that does double-buffering on multiple monitor systems!](http://www.codeproject.com/KB/dialog/SwarmScreenSaver/SwarmScreenSaver.jpg)
![windows forms manual double buffering windows forms manual double buffering](http://www.dotnetheaven.com/uploadfile/6459/images/4.gif)
- On this page are the system requirements, manual, and EULA for Din's Curse.
- PxBasic ™ and PxPlus ™ Language Reference Version 2014. This help file contains the language reference for version 2014 of PxBasic, PxPlus and past versions of.
![windows forms manual double buffering windows forms manual double buffering](http://i0.wp.com/s.allacronyms.com/177440pngu.png)