MFC analysis (7) cwnd virtual function call time and default implementation.

Source: Internet
Author: User

1. Create
2. precreatewindow
3. presubclasswindow
4. pretranslatemessage
5. windowproc
6. oncommand
7. onnotify
8. onchildnotify
9. defwindowproc
10. destroywindow
11. postncdestroy

As the most basic class in MFC that deals with windows, cwnd completes most window management tasks. At the same time, many virtual functions are provided. These virtual functions provide appropriate interfaces for the derived classes to participate in management.

For a long time, the ins and outs of these virtual functions have been confused, so it is impossible to clearly determine when they are called and what is done by default. Which of the following should be paid attention to during heavy load.

Take the time to view the source code of the MFC and check whether it is correct.

Summary:

1. Create

Virtual bool create (maid, maid, DWORD dwstyle, const rect & rect, cwnd * pparentwnd, uint NID, ccreatecontext * pcontext = NULL );
Call time:

Window Creation

As the main window, most of them will directly or indirectly call create in initinstance ()

As a child window, most of them are sent out after the parent window is created and called in oncreate () when it is processed.

Function:

Control creation details

Cwnd implementation:

.......
// Register the window class and call the API to create a window
// Allow modification of several common create parameters
Createstruct Cs;
CS. dwexstyle = dwexstyle;
CS. lpszclass = lpszclassname;
CS. lpszname = lpszwindowname;
CS. Style = dwstyle;
CS. x = X;
CS. Y = y;
CS. Cx = nwidth;
CS. Cy = nheight;
CS. hwndparent = hwndparent;
CS. hmenu = nidorhmenu;
CS. hinstance = AfxGetInstanceHandle ();
CS. lpcreateparams = lpparam;
// Call the virtual function precreatewindow here to allow parameters to be "Tampered" before they are actually created.
If (! Precreatewindow (CS ))
{
Postncdestroy ();
Return false;
}
Afxhookwindowcreate (this );
Hwnd =: createjavaswex (CS. dwexstyle, CS. lpszclass,
CS. lpszname, CS. style, CS. X, CS. Y, CS. CX, CS. Cy,
CS. hwndparent, CS. hmenu, CS. hinstance, CS. lpcreateparams );
# Ifdef _ debug
If (hwnd = NULL)
{
Trace1 ("Warning: window creation failed: getlasterror returns 0x % 8.8x/N ",
Getlasterror ());
}
# Endif
If (! Afxunhookwindowcreate ())
Postncdestroy (); // cleanup if createmediawex fails too soon
If (hwnd = NULL)
Return false;
Assert (hwnd = m_hwnd); // shold have been set in send MSG hook
Return true;
}

2. precreatewindow
Call time:
See the previous section. In create (), after setting the data CS in the window, "expose" Cs to the derived class before creating the window, and allow the derived class to change the window parameters at this time.
Function:
Control the creation parameters (Create information can be set in create (), but create is sometimes implicitly called by the framework structure, so a chance to create parameters in the precreatewindow is provided ).
Cwnd implementation:
Bool cwnd: precreatewindow (createstruct & CS)
{
// If you do not have a custom class name or a window class name in the derived class, use the default registration class of MFC.
If (CS. lpszclass = NULL)
{
// Make sure the default window class is registered
Verify (afxdeferregisterclass (afx_wnd_reg ));
// No wndclass provided-use child window default
Assert (CS. Style & ws_child );
CS. lpszclass = _ afxwnd;
}
Return true;
}

If you need to use a custom window class, you should register it in the precreatewindow of the derived class and get and specify the class name.

3. presubclasswindow
call time:
when a window is created, the C ++ WND object is attached to the window.
cwnd: Create:
...
afxhookwindowcreate (this);
hwnd =: createmediawex (CS. dwexstyle, CS. lpszclass,
CS. lpszname, CS. style, CS. x, CS. y, CS. CX, CS. cy,
CS. hwndparent, CS. hmenu, CS. hinstance, CS. lpcreateparams);
afxunhookwindowcreate ();
...

When creating a window, the system establishes the wh_cbt (training) Hook (intercepting Window Action), and completes the "Wrap" of the window for the cwnd object in the hook function ".
File: // many operations, mainly including
// Pwndinit is the input parameter, which should be the cwnd object pointer.
// The object connects to the window handle
Pwndinit-> attach (hwnd );
...
// Call the virtual function presubclasswindow to give users the opportunity to define related operations, such as sub-control attachment.
Pwndinit-> presubclasswindow ();
...
// Set message processing functions.
Wndproc * poldwndproc = pwndinit-> getsuperwndprocaddr ();
...
Wndproc afxwndproc = afxgetafxwndproc ();
Oldwndproc = (wndproc) setwindowlong (hwnd, gwl_wndproc,
(DWORD) afxwndproc );
...

Cwnd implementation:
In the cwnd class, there is no default action in this virtual function.

4. pretranslatemessage
Call time:
In the message queue processing cycle of a process, the cwinapp virtual function pretranslatemessage is called before messages in the window are distributed to the message processing function of the window, and the messages to be sent can be processed in the derived class of the window.
However, cwinapp: pretranslatemessage may call the pretranslatemessage in the window.
Let's take a look at the following cwinthread: pumpmessage's message delivery process.
...
: Getmessage (& m_msgcur, null)
...
// The pretranslatemessage virtual function of cwinthread is called.
 
If (m_msgcur.message! = Wm_kickidle &&! Pretranslatemessage (& m_msgcur ))
{
: Translatemessage (& m_msgcur );
: Dispatchmessage (& m_msgcur );
}

Bool cwinthread: pretranslatemessage (MSG * PMSG)
{
....
Cwnd * pmainwnd = afxgetmainwnd ();
// Call the pretranslatemessage () for each level of Windows from the command issuing window to the main window ();
// See the following original delimiter pretranslatetree code.
If (cwnd: FIG (pmainwnd-> getsafehwnd (), PMSG ))
Return true;
// In case of modeless dialogs, last chance route through main
// Window's accelerator table
If (pmainwnd! = NULL)
{
Cwnd * pwnd = cwnd: fromhandle (PMSG-> hwnd );
If (pwnd-> gettoplevelparent ()! = Pmainwnd)
Return pmainwnd-> pretranslatemessage (PMSG );
}
Return false; // no special processing
}
Bool Pascal cwnd: FIG (hwnd hwndstop, MSG * PMSG)
{
....
// Call the pretranslatemessage of each level of window in sequence
For (hwnd = PMSG-> hwnd; hwnd! = NULL; hwnd =: getparent (hwnd ))
{
Cwnd * pwnd = cwnd: fromhandlepermanent (hwnd );
If (pwnd! = NULL)
{
If (pwnd-> pretranslatemessage (PMSG ))
Return true; // trapped by target window (eg: accelerators)
}
// Got to hwndstop window without interest
If (hwnd = hwndstop)
Break;
}
Return false; // no special processing
}

5. windowproc
Call time:
After the window is created, a message loop is displayed. During this period, windowpro is called to process various messages.
When a window is created, the message processing function is formulated, generally afxwndproc, which calls afxcallwndproc, and afxcallwndproc will eventually call the virtual function windowproc.
Function:
Allows the derived class to add processing before message processing.
Cwnd implementation:
Lresult cwnd: windowproc (uint message, wparam, lparam)
{
 
Lresult = 0;
File: // The message is classified and decomposed by onwndmsg.
If (! Onwndmsg (message, wparam, lparam, & lresult ))
File: // the remaining part is processed by the default command handler.
Lresult = defwindowproc (message, wparam, lparam );
Return lresult;
}
Appendix: onwndmsg Process

In onwndmsg, messages are classified into command messages, notification messages, and common messages based on their nature.

Processed by oncommand and oncommany...

Bool cwnd: onwndmsg (uint message, wparam, lparam, lresult * presult)
{
// If the message is a wm_command message, it is processed by the oncommand virtual function,
// Wm_command is issued by menus and tool bars to indicate specific commands, which are different from window messages.
If (Message = wm_command)
{
....
Oncommand (wparam, lparam ))
....
}
// If the message is wm_notify, that is, the notification message, which is processed by the virtual function onnotify,
If (Message = wm_policy)
{
.....
Onnotify (wparam, lparam, & lresult ))
.....
}
 
// Process special messages:
Wm_activate...
Wm_setcursor...
 
// Common message
.......
// Find the message processing function corresponding to the message in the class message ing.
// Parameter conversion...
.......
// Call this function after finding it.
MMF. PFN = lpentry-> PFN;
Lresult = (this-> * MMF. pfn_lwl) (wparam, lparam );
.......
}

6. oncommand

Call time:

In onwndmsg, if the message is wm_command, that is, the command message, oncommand is called;

Oncommand can be used to process commands.

Cwnd implementation: file: // see the analysis of the command update mechanism

Bool cwnd: oncommand (wparam, lparam)
{
.....
// Tentatively call on1_msg (, cn_update_command_ui...) to check whether the current command item is valid
Ctestcmdui state;
State. m_nid = NID;
On1_msg (NID, cn_update_command_ui, & state, null );
If (...) // when the command is valid, set the flag to the command flag: cn_command
Ncode = cn_command;
....
// If it is a subwindow notification message, it is reflected to the subwindow ????, If the subwindow has corresponding processing, return. If not, it is still processed as a command.
// Some notification messages are sent through wm_command.

If (reflectlastmsg (hwndctrl ))
Return true; // eaten by child
// After the command message is sorted, call the virtual function on1_msg !!!!!!
Return on1_msg (NID, ncode, null, null );
}
For more information about how to process commands, seeArticleRelated Articles.

7. ononnotify

Bool cwnd: onnotify (wparam, lparam, lresult * presult)
Call time:

In onwndmsg, if the message to be processed is wm_notify, onnotify is called to process the notification message.

The onnotify virtual function provides an interface for managing notification messages in a derived class.

Cwnd implementation: bool cwnd: onnotify (wparam, lparam, lresult * presult ){..... file: // reflect the notification message to the notification sending window for processing. If the window is not processed, it is processed by ondomainmsg. If (reflectlastmsg (hwndctrl, presult) return true; // eaten by child... file: // it is processed by on‑msg. The corresponding message ing macro is return on1_msg (NID, makelong (ncode, wm_1_y), receivify, null );}

Message reflection:

The control usually notifies the parent window of its changes in the form of a notification message. The response is processed by the parent window.

The reflection mechanism of MFC can send the notification message back to the original window to handle the event in the original window message ing system. This facilitates the encapsulation of window functions.

If the subwindow does not have a reflection processing function for the notification, the notification message is still processed by the parent window.

In reflectlastmsg, pwnd-> sendchildpolicylastmsg will be called (pwnd is a pointer to the Child Window)

The onchildnotify virtual function will be called in sendchildpolicylastmsg.

In onchildnotify of the sub-window, you can add processing before receiving the reflection message.

8. onchildnotify

Bool cwnd: onchildnotify (uint umsg, wparam, lparam, lresult * presult)

Call time:

When the window sends a notification to the parent window and is reflected back, onchildnotify is called first.

You can monitor and process notification messages sent from the parent window in this function.

Cwnd implementation:

Call the cwnd member reflectchildnotify

The processing of notification messages is actually completed by the original message and command processing process. The difference is that their message and command values are adjusted to distinguish their own messages and commands in the window.

In the message ing item of the class, reflect the message processing macro to complete the association between the corresponding notification message and the processing function.

Bool cwnd: reflectchildnotify (uint umsg, wparam, lparam, lresult * presult)
{
// Process the returned message categories into a specific message format
Switch (umsg)
{
// Common message
// Wm_hscroll, wm_vscroll :.........
.....
// Convert to the reflected message number, which is a command processing function. (In message ing, the number of reflected messages is wm_reflect_base + umsg)
Return cwnd: onwndmsg (wm_reflect_base + umsg, wparam, lparam, presult );
// For wm_command
Case wm_command:
{
.....
// Send it directly to the on1_msg of the window, and the command sequence number is changed accordingly to be different from the same command received by the window itself, and there are different message ing items.
Cwnd: on1_msg (0, makelong (ncode, wm_reflect_base + wm_command), null, null ))
.....
}
// Wm_notify notification
Case wm_notify:
{
//.......
// It is processed by onreceivmsg. Change the command sequence number.
Cwnd: on1_msg (0, makelong (ncode, wm_reflect_base + wm_notify ),? Ify, null );
.....
}
// Color
If (umsg> = wm_ctlcolormsgbox & umsg <= wm_ctlcolorstatic)
{
....
Cwnd: onwndmsg (wm_reflect_base + wm_ctlcolor, 0, (lparam) & CTL, presult );
....
}
......
}

9. defwindowproc

Call time:

After the message in windowproc passes through onwndmsg, the corresponding processing function is not found and will be processed by defwindowproc.

In defwindowproc, you can add operations for these unprocessed messages.

Cwnd implementation

Lresult cwnd: defwindowproc (uint nmsg, wparam, lparam)
{
If (m_pfnsuper! = NULL)
Return: callwindowproc (m_pfnsuper, m_hwnd, nmsg, wparam, lparam );
Wndproc pfnwndproc;
If (pfnwndproc = * getsuperwndprocaddr () = NULL)
Return: defwindowproc (m_hwnd, nmsg, wparam, lparam );
Else
Return: callwindowproc (pfnwndproc, m_hwnd, nmsg, wparam, lparam );
}

10. destroywindow

First, let's look at the implementation of cwnd on destroywindow.

Bool cwnd: destroywindow ()
{
....
// Destruction window
If (m_pctrlsite = NULL)
Bresult =: destroywindow (m_hwnd );
Else
Bresult = m_pctrlsite-> destroycontrol ();
....
// C ++ window object and window Separation
Detach ();
}
In this implementation, call the API: bool destroywindow (hwnd );

The destroywindow of the API sends messages wm_destroy and wm_ncdestroy to the window,

Call time:

①. For the main window: (cframewnd)

When the window receives a closed message, destroywindow is called.

Disable message sending:

Select exit from the menu and an id_app_exit command will be provided. This command has the default implementation in cwinapp: onappexit: Send wm_close to the main window;

In addition, press the window close button to send a wm_close message to the window.

In the default onclose () process of wm_close

Void cframewnd: onclose ()
{
....
Destroywindow ();
....
}
②. For other windows

When the main window is destroyed, the following message is called: destroywindow. This API sends wm_destroy and wm_ncdestroy messages to the window.

And the child window is destroyed automatically.

In MFC, The destroywindow virtual function of the subwindow is not called, but can be reloaded and called by yourself when necessary. Controls the destruction of subwindows.

11. postncdestroy

Call time:

After the window is destroyed, it is called in onncdestroy (), the handler of wm_ncdestroy.

In postncdestroy, the window objects of C ++ are usually deleted.

Cwnd implementation:

Null

Cframewnd implementation

Delete this; (delete window objects)

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/FMD/archive/2001/06/16/5529.aspx

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.