The Calling sequence of several message functions onerasebkgnd, onpaint, and onctlcolor in the dialog box background in MFC

Source: Internet
Author: User
Set the background color and background image of the dialog box in onctlcolor (), onerasebkgnd (), onpaint (). After the dialog box is initialized, onsize ()-> onerasebkgnd () is called for display (), -> onpaint ()-> onctlcolor (),

To change the dialog box size, for example, showwindow (sw_showmaximized); updatewindow ();

Showwindow calls onsize ()-> onerasebkgnd (),

Updatewindow (); Call onpaint ()-> onctlcolor (),

If the message response onerasebkgnd () is not set in the dialog box, the system calls onctlcolor () to set the background of the message response onerasebkgnd ())

The background setting of the dialog box can be performed in onctlcolor (), because onctlcolor () is generally called multiple times, so the cfont and cbrush to be set should be initialized in oninitdialog, to set it in onctlcolor (), call detach before setting it, as shown in the following example:

Hbrush cdb3dlg: onctlcolor (CDC * PDC, cwnd * pwnd, uint nctlcolor)
{

If (pwnd-> getdlgctrlid () = idc_static5)
{

M_font.createpointfont (300, "");
PDC-> SelectObject (& m_font );
M_font.detach ();
PDC-> setbkmode (transparent );
Return (hbrush): getstockobject (null_brush );
}

}

However, if you set a background image in onctlcolor (), the image is not scaled proportionally with the dialog box size.

So you can call the stretchblt () function settings, as shown in the following example:

Void cdb3dlg: onpaint ()
{

Cclientdc CDC (this); CDC comdc;
Comdc. createcompatibledc (& CDC );
Cbitmap bitmap;
Bitmap. loadbitmap (idb_bitmap2 );
Comdc. SelectObject (& Bitmap );
Crect rect;
Getclientrect (rect );
Bitmap bit;
Bitmap. getbitmap (& bit );
CDC. stretchblt (0, 0, rect. Width (), rect. Height (), & comdc, 0, 0, bit. bmwidth, bit. bmheight, srccopy );

} // Background image of the dialog box displayed in full screen (limited to BMP Format)

After using VC for two years, the working principle of onpaint has always been unknown. In the past two days, I sent a message to BBS and asked about it. I finally figured it out. Now I will summarize it.

For WindowsProgramGenerally, there is a feature: Most of the window areas remain unchanged, and only do not need to be re-drawn. If you refresh the entire window, you do a lot of unnecessary work. Therefore, MFC uses a processing mechanism based on the invalid zone. Before processing the Invalid Analysis zone, we need to understand the reality that the current machine is not good enough. If it is good enough, we will simply redraw the entire window. In fact, even if it is good enough, for a single-threaded program, the program will not be able to refresh the window through a while loop (unless multithreading is used ), it seems that the processing mechanism of invalid zones is inevitable.

The VC program is based on the message mechanism. Any operations you perform, such as clicking and dragging the window, first enter the system message queue. The system message queue includes messages of multiple programs, and the system sends the messages to the corresponding program. Since it is a queue, there is an issue of first-in-first-out, and the frequency of updating messages in invalid areas on the screen will be particularly high. For example, if the UPDATE message in the upper left corner is not processed, the update message in the lower right corner has arrived. To avoid processing wm_paint messages multiple times, the system merges these window update messages into one, but changes the range of invalid areas to a rectangular area including the range of invalid areas of the two updates. This reduces the number of wm_paint message processing times and improves the efficiency.

In the onpaint message processing function, how does one update the invalid zone? First, you must understand that all the drawing operations in MFC are based on the device context (dc). For details, refer to any VC textbook. DC contains various information about the drawing device. For Screen Drawing, there is actually a memory (Display memory) dedicated to storing the information to be displayed on the screen, A display refreshes its content on a screen at a frequency of 85hz (my previous display. The key point is that the display refresh is to completely update the content in the display to the display, there is no problem of processing the invalid area, then, the processing of invalid zones must occur in the drawing processing of DC. Indeed, when the program calls the onpaint message, it first passes the invalid zone range to the DC. When the DC performs the Drawing operation, it only updates the information within the invalid zone range, other places do not care, which improves efficiency. There are three options to enable the onpaint function:

1) Send the wm_paint message directly. Use the postmessage () and sendmessage () functions to send the wm_paint message. The preceding two functions can be used to send the wm_paint message to the Windows program Message Queue. When Windows sends the wm_paint message to a specific message processing function, if the window's invalid region is empty, Windows ignores the message. If an invalid region exists, call the window handler. Note that an invalid region exists here. Therefore, call the function in 2 to make the form (or part) invalid. The processing process is the same as that in 2. Send the wm_paint message to the message processing queue. 3) The difference is that wm_paint is not processed immediately;

2) Call the corresponding API to send the wm_paint message: invalidate (), invalidaterect (), invalidatergn (): The above function sets the specific area of the window as invalid, when Windows detects that an invalid area exists in the window, the wm_paint message is sent to the message queue. I used the invalidate () function;

3) updatewindow (): After this function is called, Windows will send a non-queue wm_paint message to the window, which is directly sent to the window message processing function without passing through the message loop. If the window does not exist, Windows ignores the message. Note that the invalidate (), invalidaterect (), invalidatergn (), and 2) are called because the window does not exist) the difference is that the wm_paint message is processed immediately, and 2) is added to the message processing queue.

For simplicity, you can use the solution 2) to solve the problem.

Now you understand what onpaint is like? Here we also want to talk about the difference between invalidate and updatewindow. Invalidate adds a wm_paint message to the message queue, and its invalid zone is the entire customer zone. Updatewindow directly sends a wm_paint message, and its invalid zone range is the invalid zone of the wm_paint message (up to one) in the message queue. The effect is obvious. After invalidate is called, the screen may not be updated immediately, because the wm_paint message is not necessarily in the queue header, and calling updatewindow will immediately execute the wm_paint message, bypassing the message queue. If you want to update the screen immediately after calling invalidate, add the updatewindow () statement.

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.