1 Windows Refresh Management
The window handle (HWND) is managed by the operating system kernel, which has a z-order sequence that records the current window from the bottom of the screen (from the illusion of the screen to the direction of the eye) to a window handle at the top of the screen, which does not concern the parent window or the child window.
When any window receives a WM_PAINT message resulting in a redraw, after the update area is drawn, it searches for a window in front of it, and if the scope and update area of this window intersect, it sends a WM_PAINT message to the window until it executes to the top-level window. is complete.
1.1 Refresh management between parent and child windows
For a dialog box (main window), in theory all of its child windows are in front of him-that is, closer to the eye position, when the main window receives the WM_PAINT drawing completes, causes the update area to redraw all the child windows (all child windows are also bottom-up sort).
A child window is a window with a ws_child or Ws_childwindow style. As with the normal window, the Subwindow is plotted by WM_PAINT. Child windows also maintain an update area, and both applications and systems can generate WM_PAINT messages by setting the update area invalid.
The update and display area of the child window is affected by the parent window, and other styles of the window do not. The system often sets the update area of the parent window while setting the update area of the child window, so that the parent window receives the WM_PAINT message while the child window can receive the WM_PAINT message. The position of the system's window is limited to the client area of the parent window, and will be trimmed out of the area.
Whenever a parent window's update area contains part of a child window, the update area is set for the child window. At this point, the system first sends a WM_PAINT message to the parent window and then sends a message to the child window so that the child window can recover the content that was overwritten by the parent window.
However, if only the child window is set to the update area, the system is not set to the parent window. When the child window is invalidated, the system does not send a WM_PAINT to the parent window (because it is overwritten, it is not necessary at all). Similarly, if the portion of the parent window that covers the quilt window is invalidated, the system does not send wm_paint to the parent window. In this case, neither the child window nor the parent window will receive the WM_PAINT message.
The refresh between parent and child windows is also affected by whether the parent window has the Ws_clipchildren style set.
Parent window if the Ws_clipchildren style is set, the update area of the child window will not be set when the update area of the parent window is set. Any drawing that the parent window functions under the child window is all cut off.
Therefore, when the parent window is invalid and a WM_PAINT message is received, if the Ws_clipchildren style is not set, all child windows receive WM_PAINT redraw message after the parent window processes the WM_PAINT, if the parent window has Ws_ The Clipchildren style does not cause the child window to redraw.
1.2 Sibling refresh management between windows
If two windows overlap, two windows will receive a WM_PAINT message. They receive the WM_PAINT message in the same order as Z-index, which is the topmost (Z-order highest) receive WM_PAINT message at the latest.
The application can set the Ws_clipsibling style for the window to avoid overlapping the drawing of the sibling window. Set this, the High-z-order window part will be cut off by the above window, this part of the area covered by will not be refreshed.
Conclusion
1) The Ws_clipchildren style is mainly used for the parent window, that is, when the parent window is drawn, there is a child window on the parent window, and if this style is set, the parent window of the child window area is not responsible for drawing;
2) all overlapped and popup-style windows have ws_clipsiblings properties. In other words, this style of window, you are not going to drop the ws_clipsiblings style, so that it does not overlap with the Brothers window of the area to draw;
3) The Ws_clipsiblings style applies only to sibling windows, and in fact needs to be used in conjunction with the control's stacking order (Z order) to see the obvious effect.
2. Common problems of ONERASEBKGND and OnPaint2.1
In OnEraseBkgnd, if you do not call the original default OnEraseBkgnd just redraw the background there will be no flicker. In OnPaint, because it implicitly calls the OnEraseBkgnd, and you do not handle the ONERASEBKGND function, it is related to the window's default background brush. The default ONERASEBKGND action uses the window's default background to brush the new background (usually white brush), and then you re-draw the background yourself causing the screen to blink.
However, OnEraseBkgnd is not always called. If the argument is true when you call invalidate, the WM_ERASEBKGND message is generated when the beginpaint is implicitly called in OnPaint, and if the argument is false, the background is not re-brushed.
There are three and a half ways to solve the problem:
1) Implement with ONERASEBKGND, do not call the original OnEraseBkgnd function.
2) implemented with OnPaint, while overloading ONERASEBKGN, which directly returns TRUE.
3) implemented with OnPaint, set the background brush to empty when creating the window.
4) implemented with OnPaint, but requires a function such as invalidate (FALSE) when refreshing. (However, in this case, the window overlay and other causes of the refresh is to flash, so it is not a thorough solution).
2.2 About the return value of ONERASEBKGND
An application should return nonzero inresponse to WM_ERASEBKGND if it processes the message and erases thebackground; This indicates, no further erasing is required. If Theapplication returns zero, the window would remain marked for erasing. (Typically, this indicates then the Ferase member of the paintstruct Structurewill be TRUE.)
Execution of 2.3 OnPaint
Windows saves a "drawing information structure" for each window, which is paintstruct, as defined below:
typedef struct TAGPAINTSTRUCT
{
HDC hdc;
BOOL ferase;
RECT Rcpaint;
BOOL Frestore;
BOOL fincupdate;
BYTE rgbreserved[32];
} paintstruct;
When the program implicitly calls BeginPaint, Windows fills in the values of the structure appropriately. The application uses only the first three values, and the other values are used internally by Windows. HDC is the device DC handle. In older versions of Windows, the return value of BeginPaint was also the value. In most cases, Ferase is flagged as False (0), which means that Windows has erased the background of an invalid rectangle. This occurs first in the BeginPaint function (if you want to define some background erasure behavior in the window message processing, you can handle the WM_ERASEBKGND message yourself). Windows uses the WNDCLASS structure's hbrbackground specified brush to erase the background, which is used by the WNDCLASS structure program when registering the window type. Many Windows programs use white paint brushes. The following description sets the value of the brush in the window type structure:
Wndclass.hbrbackground = (hbrush) getstockobject (White_brush);
However, if a program invalidates a rectangle in the display area by calling the Windows function InvalidateRect, the last parameter of the function specifies whether to erase the background. If this parameter is False (that is, 0), Windows will not erase the background, and the ferase of the PAINTSTRUCT structure will be true (not 0) after BeginPaint is called.
The rcpaint of the PAINTSTRUCT structure is the structure of the RECT type. It defines the bounds of the invalid rectangle, which are in pixels and relative to the upper-left corner of the customer area. An invalid rectangle is an area that should be redrawn.
The rcpaint of the PAINTSTRUCT structure is not only an invalid rectangle, it is also a "cropping" rectangle. This means that Windows restricts the drawing operation to the clipping rectangle (or rather, if the invalid rectangular area is not a rectangle, Windows restricts the drawing operation to the area).
In order to draw outside the updated rectangle when processing the WM_PAINT message, you can use the following function:
InvalidateRect (hwnd, NULL, TRUE);
This function is made before the BeginPaint call, which invalidates the entire display area and erases the background. However, if the last parameter is equal to False, the background is not erased and the original thing remains in place. Typically this is the most convenient way for Windows programs to simply redraw the entire display area whenever they receive a WM_PAINT message without regard to the rcpaint structure.
3. WM_PAINT News
In Windows API programming, WM_PAINT is an important message in Windows window, and the application is to finish drawing the window by responding to the message.
The WM_PAINT message is generated by thesystem and should not being sent by an application. The system sends this messagewhen there is no other messages in the application ' s message queue.
Note: WM_PAINT messages are generated by the system and are not sent WM_PAINT messages until the application's message queue is empty.
In fact, the system will be a lot of different mechanisms to send WM_PAINT messages, such as Call UpdateWindow function, the first time to create a window, change the size of the window, maximize, minimize and so on. These actions are generated by the system to control, the application simply receives the message, and processes the message.
When Windows detects that a window is overwritten, it sends a WM_PAINT message to the user program, which includes the area to be recovered, and then the user program decides how to recover the overwritten content. When the window process receives the WM_PAINT message, it does not mean that the entire client area needs to be refreshed, it is possible that the area covered by the client area is only a small block, which is called an "invalid area" and the program only needs to update the area. Like the Wm_timer message, the WM_PAINT message is also a low-level message, and although it is not discarded like a wm_timer message, Windows always puts wm_paint into it when the message loop is empty, in fact, Windows maintains a "drawing information structure" for each window, in which the coordinates of the invalid area are in which, whenever the message loop is empty, if Windows discovers an invalid zone, a WM_PAINT message is placed.
The coordinates of the invalid zone are not included in the parameters of the WM_PAINT message, there are other methods available in the program, the WM_PAINT message just notifies the program that an area needs to be updated, so Windows does not put two WM_PAINT messages into the message loop at the same time. When Windows wants to put a WM_PAINT message, if it finds an invalid area, then it only needs to combine the old and new invalid areas to compute an invalid area, and only one WM_PAINT message is needed in the message loop.
If the program does not end after flushing the client area in the WM_PAINT message, if the invalid zone is not valid, Windows will continue to place a WM_PAINT message in the next round of message loops, rather than depending on whether the program has performed a refresh process. So the program can also not refresh the client area, but simply with a validaterect function directly to the client area to become effective, in order to "deceive" Windows has no invalid area, when Windows checked the "Drawing information structure" when the discovery of the invalid area, It will not continue to send WM_PAINT messages.
Most of the time the application also needs to be able to actively raise the window of the drawing operations, such as when the window display data changes, this is generally done by the invalidaterect and INVALIDATERGN functions. InvalidateRect and INVALIDATERGN Add the specified area to the window's update region, and the system automatically generates a WM_PAINT message if the window's update zone is not empty when there is no other message for the application's message queue.
Why is the system not sending WM_PAINT messages when calling invalidate? Why do I have to wait until the app message queue is empty to send WM_PAINT messages? This is because the system treats the drawing operations in the window as a low-priority operation, so as to be pushed backwards as much as possible. However, this also helps to improve the efficiency of drawing: Two WM_PAINT messages between the InvalidateRect and Invaliatergn to invalidate the area will be added up, and then in a WM_PAINT message is updated once, It not only avoids updating the same area multiple times, but also optimizes the app's update operations. such as this through InvalidateRect and invalidatergn to invalidate the window area, depending on the system at the right time to send the WM_PAINT message mechanism is actually an asynchronous way of working, that is, in the invalid window area and send Wm_ There is a delay between the paint messages, and sometimes this delay is not what we want, and we can certainly use SendMessage to send a WM_PAINT message after the invalid window area to force immediate redrawing, but instead of using Windows GDI provides us with more convenient and powerful functions: UpdateWindow and RedrawWindow. UpdateWindow checks the window's update region to send the WM_PAINT message when it is not empty; RedrawWindow gives us more control: whether to redraw non-client areas and backgrounds, whether to always send WM_PAINT messages regardless of the update Whether the region is empty or not.
4, BeginPaint
BeginPaint sets the update region of Awindow to NULL. This clears, preventing it fromgenerating subsequentwm_paint messages. If an application processes a WM_PAINT message but does Notcall beginpaint or otherwise clear the update region, the Appli Cation Continuesto receive WM_PAINT messages as long as the region was not empty. In all Cases,an application must clear the update region before returning from the Wm_paintmessage.
One of the functions of the BeginPaint function is to set the area where the window needs to be redrawn to be empty (that is, the update region is empty). Under normal circumstances, when we receive the WM_PAINT message, the window's update region is non-empty (if it's empty, you don't need to send a WM_PAINT message). When you respond to this message and do not call BeginPaint to empty, the window's update region is always non-empty, the system will continue to send WM_PAINT messages. This creates a dead loop that handles WM_PAINT messages.
BeginPaint and WM_ERASEBKGND messages are also related. When the window's update region is marked as needing to erase the background, BeginPaint sends a WM_ERASEBKGND message to redraw the background, and in its return message there is a flag indicating whether the window background has been redrawn. When we use InvalidateRect and invalidatergn to add the specified area to the update region, you can set whether the region needs to be erased, so that the next beginpaint knows whether to send the WM_ Erasebkgnd the news.
BeginPaint can only be used in WM_PAINT processing functions, and after calling the BeginPaint function, the EndPaint function must be called, they are a pair.
5. Redraw function 5.1 Invalidaterect/invalidatergn
The InvalidateRect function adds a rectangleto the specified window ' s update region. The update region represents theportion of the window's client area this must be redrawn.
The invalidated areas accumulate in Theupdate region until the region was processed when the next WM_PAINT message occurs O R until the region isvalidated by using the ValidateRect or ValidateRgn function.
The system sends a WM_PAINT message to Awindow whenever it update region was not empty and there be no other messagesin t He application queue for that window.
If the bErase parameter is TRUE If a partof the update region, the background is erased in the entire region and not justi n the specified part.
InvalidateRect and INVALIDATERGN Add the specified area to the window's update region, and the system automatically generates a WM_PAINT message if the window's update zone is not empty when there is no other message for the application's message queue.
If you specify Berase as true, the entire background will be erased.
5.2 UpdateWindow
The UpdateWindow function updates the clientarea of the specified window by sending a WM_PAINT message to the window if th Ewindow ' s update region was not empty. The function sends a WM_PAINT messagedirectly to the window procedure of the specified window, bypassing theapplication qu Eue. If the update is empty, no message is sent.
UpdateWindow is a direct call to the window function to immediately respond to a refresh message, so that the window refresh message takes precedence of the response (in Message Queuing if no WM_PAINT message is executed), it is generally called after ShowWindow.
5.3 RedrawWindow
RedrawWindow is equivalent to calling InvalidateRect first, followed by a call to UpdateWindow, in addition to RedrawWindow also provides a number of features that the former two can not do, such as whether to redraw the non-client area and background, whether always send Wm_ Paint messages Regardless of whether the update region is empty or not.
Its flags are defined as follows:
Flag (Invalid tag) |
Describe |
Rdw_erase |
You receive a WM_ERASEBKGND message when the window is redrawn. Must be used in conjunction with rdw_invalidate, otherwise invalid. |
Rdw_frame |
A non-client area that has an intersection with an invalid zone receives a WM_NCPAINT message and must be used with rdw_invalidate, otherwise it is not valid. Wm_ncpaint messages are not sent during RedrawWindow processing unless Rdw_updatenow or rdw_earsenow are specified |
Rdw_internalpaint |
Post a WM_PAINT message, regardless of whether the update region is empty |
Rdw_invalidate |
The area specified by the invalid parameter |
Flag (Active marker) |
Describe |
Rdw_noerase |
Block upcoming WM_ERASEBKGND Messages |
Rdw_noframe |
To prevent an impending wm_ncpaint message, use it with special care, which may cause the window to be drawn incorrectly. It must be used in conjunction with Rdw_validate, Usually used in conjunction with Rdw_nochildren. |
Rdw_nointernalpaint |
WM_PAINT message that blocks an impending null invalid zone |
Rdw_validate |
To make a specified region of a parameter valid |
Flag (Refresh Time flag) |
Describe |
Rdw_earsenow |
If necessary, the affected window (specified by Rdw_allchildren and Rdw_nochildren) will receive Wm_ncpaint and WM_ERASEBKGND messages before the RedrawWindow returns |
Rdw_updatenow |
If necessary, the affected windows (specified by Rdw_allchildren and Rdw_nochildren) receive Wm_ncpaint, WM_ERASEBKGND, and WM_PAINT messages before the RedrawWindow returns |
Flag (Impact marker) |
Describe |
Rdw_allchildren |
If there are child windows, the child window will be affected |
Rdw_nochildren |
If there are child windows, the child window is not affected |
By default, if you do not specify Rdw_nochildren and Rdw_allchildren, the affected window is determined by the Ws_clipchildren style, and if the specified window is set to be unaffected by the style child window, Otherwise, the child window will be affected by recursion until it encounters a window with a ws_clipchildren style.
Go Window refresh mechanism for Windows