From: http://blog.csdn.net/ringphone/article/details/2042693
Generally, complex Windows interfaces require multi-layer windows and textures for beautification. Therefore, it is inevitable that the window will flash when moving or changing the size.
Let's talk about the causes of flickering.
Cause 1:
If you are familiar with the graphics card principle, calling the GDI function to output to the screen is not immediately displayed on the screen.
It is only written to the video memory, and the video card outputs the video content to the screen at intervals, which is the refresh cycle.
Generally, the refresh cycle of a video card is about 1/80 seconds. You can set the number on your own.
This is the problem. Generally, the background color is first painted, and then the content is painted. If these two operations are not the same
After the refresh period is completed, the visual experience is to first see the image with only the background color, and then see the image on the painting,
In this way, you will feel flickering.
Solution: output the image as quickly as possible so that the output can be completed within a refresh cycle. If the output content is much slower, use
The memory buffer method first prepares the content to be output in the memory and then outputs the content to the video memory at a time. You must know that an API call is generally acceptable.
Completed within a refresh cycle.
For GDI, use the memory DC creation method.
Cause 2:
A complex interface consists of multiple layers of windows. When the window size is changed in windows, the parent window is re-painted first, and then the child window is re-painted.
The process of repainting windows is generally not completed in a refresh cycle, so it will flash.
We know that there is no need to reproduce the blocked part of the quilt window in the parent window.
Solution: Add ws_clipchildren style to the window so that the blocked part of the quilt window in the parent window will not be re-painted.
If there are overlapping windows at the same level, you need to add the ws_clipsiblings style.
Cause 3:
Sometimes you need to use some controls in the window, such as IE. When the size of your window changes, ie will flash, even if you have ws_clipchildren
It's useless. The reason is that the class style of the window is cs_hredraw or cs_vredraw. These two styles indicate that the window width or height changes.
Re-draw, but this will cause IE to flash
Solution: Do not use these two styles when registering the window class. If the window needs to be re-painted when the size is changed, you can use the wm_size
Call redrawwindow.
Cause 4:
There are many windows on the interface, and many windows need to be moved and changed in size when the window is changed. If you use movewindow or setwindowpos APIs
Change the size and position of the window. Because they are returned only after the window is re-painted, the process is slow and the visual effect may flash.
Solution:
Use the following APIs to process window movement: begindeferwindowpos, deferwindowpos, and enddeferwindowpos.
Call begindeferwindowpos to set the number of windows to be moved.
Use deferwindowpos to move the window. This API does not actually cause window movement.
Enddeferwindowpos changes the size and position of all windows at a time.
Pay special attention to the following points: calculate the number of windows to be moved and set begindeferwindowpos.
The number of windows must be the same as the actual number. Otherwise, in Win9x, if the number of windows actually moved is more
The number, which may cause system crashes. This problem does not occur in the Windows NT series.
Non-blinking images without double buffering
From: http://blog.csdn.net/ringphone/article/details/1914052
First, let's talk about the cause of flickering. When the window needs to be re-painted for any reason, the background color or background image is used to clear the display area before the image is displayed, in this way, the background color and the display image appear in turn in a short period of time, making the display window appear flashing. If you set the background fl to null, no matter how you duplicate the drawing, it will not flash, but it will make the display of the window messy, because there is no background color to clear the original image during the re-painting, and a new image is superimposed.
The general solution is to use dual buffering to create a memory image, draw the background and image to the image first, and then display the drawn image to the window, in this way, no flashes will occur. In fact, the image display process is hidden. It was originally at the front-end. You can see that the background is first painted on the canvas, and then the image is painted, now we have finished the painting in the background and show it to you.
It seems that the solution is to draw images at a time. In fact, the key is not to overlap any background and images during painting. It has little to do with whether to draw images at a time. The computer's drawing speed is still very fast. If you don't believe it, you can try setting the background to null so that the background will not flash. Then, you can call bitblt repeatedly to fill the entire window with a small image, it will not flash, but if you change the cycle step to overlap the image, it will start to flash.
Knowing the cause of flickering, it is not difficult to find a solution without double buffering. Calling excludecliprect can exclude the area of painting, draw the image first, excludecliprect the area of the image, and then draw the background, it is equivalent to sticking a canvas with a hole dug to a window, so that no overlap will be drawn and no flashes will be generated.
API code. A 300*200 image is always displayed in the lower right corner of the window. The background is Black:
case WM_PAINT:{
PAINTSTRUCT ps; RECT rc; HDC hMemDC; GetClientRect(hWnd,&rc); BeginPaint(hWnd,&ps); hMemDC = CreateCompatibleDC(ps.hdc); SelectObject(hMemDC,hbmp); BitBlt(ps.hdc,rc.right-300,rc.bottom-200,300,200,hMemDC,0,0,SRCCOPY); ExcludeClipRect(ps.hdc,rc.right-300,rc.bottom-200,rc.right,rc.bottom); FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); DeleteDC(hMemDC); EndPaint(m_hWnd,&ps); return 0;}
Sometimes, due to the refresh area issue, the window may be adjusted, but the wm_paint Code does not work. In this case, you need to respond to the wm_size message and notify the screen to update it:
Case wm_size:
Invalidaterect (hwnd, null, false );
Break;
This method is also applicable to displaying multiple images. As long as an image is drawn, excludecliprect can drop the image area. However, if the image overlaps, the order of drawing is reversed, that is, the image that is built on the top needs to be drawn first, and the background is refreshed for the entire window.