C # drawing Double buffering

Source: Internet
Author: User

C # drawing double buffered C # double buffering interpretation: Simply said when we are doing the drawing operation, the system does not directly render the content to the screen, but first in memory, and then output the results one time, if you do not use double buffering, you will find that in the process of drawing the screen will be very sharp, Because the background has been refreshed, and if the user after the painting and then output will not appear this situation, the specific practice, in fact, is to create a bitmap object, and then save the content in the inside, and finally the diagram presented. GDI+The double buffering problem has always been the misconception:. Net1.1and. Net2.0There is a difference in handling double buffering of controls.. NET1.1In, use: This. SetStyle (Controlstyles.doublebuffer,true);. NET2.0, using: This. SetStyle (Controlstyles.optimizeddoublebuffer,true); The key reason for the flicker of the screen: first, the drawing window because the size position state changes to redraw operation when the plot window content or size changes every time, the paint event is called to redraw the operation, which causes the screen to be refreshed again to maintain the normal display of the window. All elements are redrawn during the refresh process, and the redraw of individual entities does not cause the paint event to occur, so each refresh of the window will only call the Paint event once.      When the window is refreshed, the redraw of each element is immediately displayed to the window, so the entire window, as long as it is in the location of the entity, is refreshed, and the time of the refresh is different, flashing phenomenon will naturally occur.     Therefore, the key factor that causes the window flicker is not the number of times the paint event is called, but the redrawing of the individual elements. According to the above analysis, when the number of elements is not long, the window refresh position is not much, the window flicker effect is not serious; When the number of entities is larger, the number of elements redrawn in the drawing window increases, each time the drawing window is refreshed will cause more entities to redraw, the window more locations are refreshed, The phenomenon of flashing will naturally become more and more serious.     In particular, when the large drawing time of the entity is longer, the flicker problem is more serious because the time delay is longer.      The key to solving the above problem is to have all the entities display to the window at the same time as the window is refreshed. Second, the mouse tracking drawing operation or deformation operation of the entity when the mouse tracking drawing operation or deformation operation of the entity, the paint event will occur frequently, which will make the window refresh times greatly increased. Although all the elements are displayed to the window while the window is refreshed, there is also a time delay because the window is refreshed at a time that is much smaller than the time it takes for the entity to display to the window at any point.     Therefore flicker does not completely eliminate!     Therefore, the key factor that causes the window flicker is the number of times the paint event occurred. The key to solving this problem is to set several key properties for a form or control. Use double buffering to solve the key technology of double buffering:1, set several properties of the display element control: must be set, otherwise the effect is not very obvious!  This. SetStyle (Controlstyles.optimizeddoublebuffer |Controlstyles.resizeredraw|Controlstyles.allpaintinginwmpaint,true);2, and the window refreshes once, so that all the entities are displayed to the window at the same time. This can be done in several ways, which involve how the graphics object is created. Specific implementation1, using the default double buffering (1The easiest way to use double buffering in your application is to use the default double buffering provided by the. NET Framework for forms and controls. By setting the DoubleBuffered property totrue.  This. Doublebuffered=true; (2use the SetStyle method to enable default double buffering for Windows Forms and the authored Windows controls. SetStyle (Controlstyles.optimizeddoublebuffer,true); 2, manually set double buffering. NETFramework provides a class bufferedgraphicscontext that is responsible for assigning and managing the graphics buffers separately. Each application domain has its own default BufferedGraphicsContext instance to manage all of the default double buffering for this application. In most cases, there is only one application domain per application, so each application typically has only one default BufferedGraphicsContext. The default BufferedGraphicsContext instance is managed by the BufferedGraphicsManager class. The steps to achieve double buffering through management BufferedGraphicsContext are as follows: (1) to obtain a reference to an instance of the BufferedGraphicsContext class. (2creates an instance of the BufferedGraphics class by calling the BufferedGraphicsContext.Allocate method. (3draws a graphic to the graphics buffer by setting the BufferedGraphics.Graphics property. (4When you are finished drawing operations in all graphics buffers, you can call the BufferedGraphics.Render method to render the contents of the buffer to the drawing surface associated with the buffer or to the specified drawing surface. (5After you finish rendering the drawing, call the Dispose method that frees the system resources for the BufferedGraphics instance. The complete example, in a*400 draws 10,000 randomly generated small circles within a rectangle. BufferedGraphicsContext Current= BufferedGraphicsManager.Current;//(1)BufferedGraphics BG; BG= Current. Allocate ( This. CreateGraphics (), This. DisplayRectangle);//(2)Graphics G= BG. Graphics;//(3)//random width 400 highsystem.random Rnd=NewRandom (); intX,y,w,h,r,i;  for(i =0; I <10000; i++) {x= rnd. Next ( -); Y= rnd. Next ( -); R= rnd. Next ( -); W= rnd. Next (Ten); H= rnd. Next (Ten);            G.drawellipse (Pens.blue, X, Y, W, h); } BG. Render ();//(4)//BG. Render (this. CreateGraphics ()); BG. Dispose ();//(5)3, you open a buffer (such as a bitmap object that does not appear), and once it is drawn, it is displayed once. The complete code is as follows: Bitmap BT=NewBitmap ( -, -); Graphics BG=Graphics.fromimage (BT); System.Random Rnd=NewRandom (); intx, Y, W, H, R, I;  for(i =0; I <10000; i++) {x= rnd. Next ( -); Y= rnd. Next ( -); R= rnd. Next ( -); W= rnd. Next (Ten); H= rnd. Next (Ten); Bg.             DrawEllipse (Pens.blue, X, Y, W, h); }             This. CreateGraphics (). DrawImage (BT,NewPoint (0,0));     Another example is how the Graphics object is created: A, create a piece in memory and display the same size as the control canvas, and create a Graphics object on this canvas.  Then all the elements are drawn on this canvas, and the canvas is then used to overwrite the background of the display control to achieve the "show once only" effect! Implementation code (in the OnPaint method): Rectangle rect=E.cliprectangle; Bitmap Bufferimage=NewBitmap ( This. Width, This.     Height); Graphics g=graphics.fromimage (bufferimage); G.clear ( This.     BackColor); G.smoothingmode= Smoothingmode.highquality;//High qualityG.pixeloffsetmode = pixeloffsetmode.highquality;//High pixel offset quality    foreach(IShape drawobjectinchdoc.drawobjectlist) {if(rect. Intersectswith (drawobject. Rect) {drawobject.                    Draw (g); if(drawobject. Trackerstate = =CONFIG. Module.Core.TrackerState.Selected&& This. Currentoperator = = Enum.Operator.Transfrom)//Show entity hotspots only when editing node actions{drawobject.                    Drawtracker (g); }}}using(Graphics TG =e.graphics) {TG. DrawImage (Bufferimage,0,0);//stick the canvas on the screen} b, create the graphics object directly in memory: Rectangle rect=E.cliprectangle; BufferedGraphicsContext CurrentContext=bufferedgraphicsmanager.current; BufferedGraphics Mybuffer=currentcontext.allocate (E.graphics, E.cliprectangle); Graphics g=Mybuffer.graphics; G.smoothingmode=smoothingmode.highquality; G.pixeloffsetmode=Pixeloffsetmode.highspeed; G.clear ( This.            BackColor); foreach(IShape drawobjectinchdoc.drawobjectlist) {if(rect. Intersectswith (drawobject. Rect) {drawobject.                    Draw (g); if(drawobject. Trackerstate = =CONFIG. Module.Core.TrackerState.Selected&& This. Currentoperator = = Enum.Operator.Transfrom)//Show entity hotspots only when editing node actions{drawobject.                    Drawtracker (g);           }}} mybuffer.render (E.graphics);           G.dispose (); Mybuffer.dispose ();//Freeing ResourcesAt this point, double-buffering problem solving, the two ways to achieve the same effect, but the last way to occupy a little memory, there will be no memory leaks! Next is the implementation of the ACDSee drag picture effect. Start do not understand double buffering, think double buffering can solve this problem, the results found that the use of double buffering not much effect, ask the expert, and then modify some code, to complete the effect.        The picture is in the PictureBox1.        Bitmap Currentmap; BOOLFirst =true; Private voidPicturebox1_mousedown (Objectsender, MouseEventArgs e) {            if(Zoom = =0)            {                if(E.button = = MouseButtons.Left)//draggingMousedrag =e.location; Image MyImage=Mymap.getmap (); Currentmap=NewBitmap (myimage); First=false; }            }        Private voidPicturebox1_mousemove (Objectsender, MouseEventArgs e) {            if(Zoom = =0&&!First ) {Image img=NewBitmap (Size.width, size.height); Graphics g=graphics.fromimage (IMG); G.clear (color.transparent);//the background of the image after it is movedG.smoothingmode = smoothingmode.highquality;//High qualityG.pixeloffsetmode = pixeloffsetmode.highquality;//High pixel offset qualityG.drawimageunscaled (Currentmap,NewSystem.Drawing.Point (E.location.x-mousedrag. X, E.location.y-mousedrag. Y));//move the picture in G, the original is drawn in (0,0), so directly with the new System.Drawing.Point (E.location.x-mousedrag. X, E.location.y-mousedrag. Y) just fine. G.dispose (); pictureBox1.Image= img;//img is a temporary picture that is created when the mouse is moved in this position            }        }        Private voidPicturebox1_mouseup (Objectsender, MouseEventArgs e) {            if(Zoom = =0) {System.Drawing.Point PNT=NewSystem.Drawing.Point (Width/2+ (Mousedrag. Xe.location.x), Height/2+ (Mousedrag. Ye.location.y)); Mymap.center=Mymap.imagetoworld (PNT); pictureBox1.Image=Mymap.getmap (); First=true; }} to talk about ideas, create a bitmap,currentmap at the mouse point and use it to store the current image. When the mouse moves, according to the mouse position drawing, finally, the mouse up, re-drawing. 

C # drawing Double buffering

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.