C # Paint solves flicker problems

Source: Internet
Author: User

analysis of key causes of screen flicker:      One, the drawing window because of the size position state changes in the redraw operation, the plot window content or size each change, to call the paint event to redraw, which will cause 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 problems is:once the window is refreshed, all elements are displayed to the window at the same time.      Twowhen a mouse-tracking drawing operation is performed or when the entity is deformed, the Paint event occurs frequently when a mouse-tracking drawing operation or an entity is deformed, which increases the number of times the window is refreshed. 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:set several key properties for a form or control. key technologies to solve 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, the window refreshes the process, so that all the elements are displayed to the window at the same time. This can be done in several ways, which involve how the graphics object is created.How the Graphics object is created:A. Create a Graphics object on this canvas by creating a piece of canvas in memory that is the same size as the display control. 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 = new Bitmap (this. Width, this. Height);
Graphics g = graphics.fromimage (bufferimage); G.clear (this. BackColor);
G.smoothingmode = smoothingmode.highquality; Quality
G.pixeloffsetmode = pixeloffsetmode.highquality; High pixel offset quality foreach (IShape drawobject in doc.drawobjectlist)
{if (rect. Intersectswith (drawobject. Rect))
{
drawobject. Draw (g);
if (drawobject. Trackerstate = = Config. Module.Core.TrackerState.Selected
&& this. Currentoperator = = Enum.Operator.Transfrom)//Display entity hotspot only when editing node operation
{
drawobject. Drawtracker (g);
}
}

} using (Graphics TG = e.graphics)
{
Tg.  DrawImage (bufferimage, 0, 0); Stick the canvas on the screen
}b, create a 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 drawobject in doc.drawobjectlist)
{
if (rect. Intersectswith (drawobject. Rect))
{
drawobject. Draw (g);
if (drawobject. Trackerstate = = Config. Module.Core.TrackerState.Selected
&& this. Currentoperator = = Enum.Operator.Transfrom)//Display entity hotspot only when editing node operation
{
drawobject. Drawtracker (g);
}
}
} mybuffer.render (E.graphics);
G.dispose ();
Mybuffer.dispose ();//release resources to this end, double-buffering problem solving, two ways to achieve the same effect, but the last way to occupy less memory, there will be no memory leaks!
Or: 1. Create a "virtual canvas" in memory:

Bitmap bmp = New Bitmap (600, 600);

2. Get the graphics reference for this memory canvas:

Graphics g = graphics.fromimage (BMP);

3. Draw on this piece of memory canvas:

G.fillellipse (Brush, I *, J * 10, 10, 10);

4. Draw the memory canvas into the window

This. CreateGraphics (). DrawImage (BMP, 0, 0);

There are ways
Add the following code in the constructor

Code One:
SetStyle (Controlstyles.userpaint, true);
SetStyle (Controlstyles.allpaintinginwmpaint, true); Erase background is forbidden.
SetStyle (Controlstyles.doublebuffer, true); Double buffering

Code two:
This. SetStyle (Controlstyles.doublebuffer | Controlstyles.userpaint | Controlstyles.allpaintinginwmpaint, True);
This. UpdateStyles ();

=======================================================================

solve drawing flicker problems with GDI + double buffering

Now the problem is that many people don't know how to use GDI + double buffering

public partial class Form1:form
{
Variables that record the position of a rectangle
Point P = point. Empty;
Point location = new Point (0, 0);
int x = 0;
int y = 0;

Public Form1 ()
{
InitializeComponent ();
Required settings for controls with double buffering technology
This. SetStyle (Controlstyles.optimizeddoublebuffer, true);
This. SetStyle (Controlstyles.allpaintinginwmpaint, true);
This. SetStyle (Controlstyles.userpaint, true);

}
protected override void OnPaint (PaintEventArgs e)
{
Base. OnPaint (e);
Graphics g = e.graphics;
G.fillrectangle (Brushes.black, x, Y, 200, 200);
}
private void Form1_mousedown (object sender, MouseEventArgs e)
{
if (E.button = = mousebuttons.right) return;
p = e.location;
}
private void Form1_mouseup (object sender, MouseEventArgs e)
{
if (E.button = = mousebuttons.right) return;
Location. X + = e.x-p.x;
Location. Y + = E.Y-P.Y;
p = point.empty;
}
private void Form1_mousemove (object sender, MouseEventArgs e)
{
if (p = = point.empty) return;
x = e.x-p.x + location. X
y = e.y-p.y + location. Y
This. Invalidate (TRUE);//Trigger Paint Event
}
}
This simple example allows you to drag the rectangle in the window with the mouse and use the double buffering technique to make the animation process flicker-less.
In this case I made the mistake:
In OnPaint (PaintEventArgs e), I use the following two ways to get a Graphics object
Graphics g = this. CreateGraphics ();
Graphics g = Graphics.fromhwnd (this. Handle);
This causes double buffering to fail.
There are two more ways to get a Graphics object
Graphics g = graphics.fromimage (image); This method is used to implement the double buffering
Graphics g = e.graphics; It's the only way to do it.

The above is drawing directly in the form window, so how do you draw on a control (such as a panel) using a double-buffering technique?
Create a panel in the Windows window and modify the code
private void Panel1_paint (object sender, PaintEventArgs e)
{
Graphics g = e.graphics;
G.fillrectangle (Brushes.black, x, Y, 200, 200);
}
After running, find that the drawing on the Panel1 is still blinking, so it should be set
Panel1. SetStyle (Controlstyles.optimizeddoublebuffer, true);//This does not work,
Because SetStyle () is not the public method in the Panel class

Double buffering is set using the constructor of the Mypanel class inherited from the Panel class
Public class Mypanel:panel
{
Public Mypanel ()
{
This. SetStyle (Controlstyles.optimizeddoublebuffer, true);
This. SetStyle (Controlstyles.allpaintinginwmpaint, true);
This. SetStyle (Controlstyles.userpaint, true);
}
}

Anyway, this method does work, but notice that you're using the Mypanel class instead of the panel.
Define your own Mypanel from the toolbar and drag it to the window and use it as Panle.

Note: Drawing on a control must set the control's DoubleBuffer, not the doublebuffer of the form.

Before that, I used my own method to implement double buffering instead of the doublebuffer of the control itself.
Draw the graphics in memory first, including erasing the old picture and drawing a new picture, then drawing the memory graphics onto the screen
public void Draw (System.Windows.Forms.Panel _panel, float _x, float _y)
{
Graphics g = Graphics.fromhwnd (_panel. Handle);
try{
Create a piece in memory and a panel size area
Bitmap Bitmap = new Bitmap (_panel. Clientsize.width, _panel. Clientsize.height);
using (Graphics buffer = graphics.fromimage (bitmap))
{
Drawing in Buffer
Buffer. Clear (_panel. BackColor); Fill the screen with background color
Buffer. Transform = Matrix;
Buffer. DrawImage (source, _x/scale, _y/scale); Draw a new picture
Screen drawing
G.drawimage (bitmap, 0, 0); Draw the buffer to the screen
}
}
Finally
{
G.dispose ();
}
}
No settings are required to use the above method.

Summarize
Drawing-related controlstyles
Enum controlstyles{
Allpaininginwmpaint,//Collapse the drawing stage into the paint event
DoubleBuffer,//until paint returns, and the drawing object is displayed
UserPaint,//For controls that have their own special drawing

Opaque,//Ignore Onpaintbackground,paint event draw entire area
resizeredraw,//the entire workspace is invalid when you resize the control for a large hour
supportstransparentbackcolor,//Simulating transparent controls
...
}

1. Using E in OnPaint (PaintEventArgs e) or paint to get the graphics, I have a lot of trouble because I found an article on the Internet to implement a double-buffered article, do not use E to get the graphics, and with this . CreateGraphics(), and some articles about the strange method actually finally make it.

2. When using double-buffered drawing on controls that inherit form and control, you can set the double-buffering property in the control's constructor, and set DoubleBuffer in the window form to work only on the drawing of the window.

3. Using your own method, the double-buffering principle is the same.

Example:

private void Drawrectbackimage ()
{
Graphics g = Graphics.fromhwnd (_currentchart.handle);
Try
{
Create a piece in memory and a panel size area
Bitmap Bitmap = new Bitmap (_currentchart.clientsize.width, _currentchart.clientsize.height);
using (Graphics buffer = graphics.fromimage (bitmap))
{
Buffer. Transform =new Matrix ();

The background picture to draw

Buffer. DrawImage (Curchartimage, _currentchart.clientrectangle);

What's on the background picture
Drawfitadjustrect (buffer);
Screen drawing
G.drawimage (bitmap, 0, 0); Draw the buffer to the screen
}
}
Finally
{
G.dispose ();
}
}

C # Paint solves flicker problems

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.