An Analysis of MFC (7) the invocation time and the default implementation of the CWnd class virtual function

Source: Internet
Author: User

The invocation time and default implementation of a CWnd-like virtual function

FMD (http://www.fmdstudio.net)

1. Create

2. PreCreateWindow

3. Presubclasswindow

4. PreTranslateMessage

5. WindowProc

6. OnCommand

7. OnNotify

8. OnChildNotify

9. DefWindowProc

Ten. DestroyWindow

PostNcDestroy.

CWnd, as the most basic window-related class in MFC, accomplishes most of the window management tasks. There are also a number of virtual functions that provide an interface for derived classes to participate in management where appropriate.

All along, the ins and outs of these virtual functions have been confused, unable to determine exactly when they were called, and what was done by default. What is to be noticed when overloading ... Wait a minute.

Take time to view the original code of MFC, want to see what it is.

Summarized as follows:

1. Create

Const rect& RECT, cwnd* pParentWnd, UINT nID, ccreatecontext* pContext = NULL);

Call Time:

When the window is established

As the main window, most of the InitInstance () directly or indirectly call the Create

As a child window, most of the parent windows are created after the WM_CREATE message is issued and processed when OnCreate () is called.

Function:

Control Build Details

CWnd implementations:

.......Registering the window class, invoking the API Setup windowAllow 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;This calls the virtual function PreCreateWindow, which allows "tampering" to establish parameters before actually being established.if (!  PreCreateWindow (CS)) {PostNcDestroy (); return FALSE;} Afxhookwindowcreate (this); HWND hwnd =:: CreateWindowEx (Cs.dwexstyle, Cs.lpszclass, Cs.lpszname, Cs.style, Cs.x, Cs.y, cs.cx, Cs.cy, Cs.hwndParent, C S.hmenu, Cs.hinstance, cs.lpcreateparams); #ifdef _DEBUG if (hWnd = = NULL) {TRACE1 ("Warning:window creation Failed:getlasterror returns 0x%8.8x/n", Getlas Terror ()); }#endif if (! Afxunhookwindowcreate ()) PostNcDestroy (); //cleanup if CreateWindowEx fails too soon if (hWnd = = NULL) return FALSE; ASSERT (hWnd = = m_hwnd); //should has been set in Send MSG hook return TRUE;}           

2. PreCreateWindow

Call Time:

Refer to the previous paragraph, in Create (), set the window to establish the data CS, before actually establishing the window, CS "Exposed" to the derived class, allowing derived classes at this time to change the window to establish parameters.

Function:

The control establishment parameter (in Create () can set the build information, but create is sometimes implicitly called by the framework structure, so when PreCreateWindow, then provide a revision window to establish the parameters of the opportunity).

CWnd implementations:

if (Cs.lpszclass = = NULL) {  //Make sure the default window class is registered  VERIFY (Afxdeferregisterclass (A Fx_wnd_reg));  //No WNDCLASS provided-use child window default  ASSERT (Cs.style & ws_child);  return TRUE;}  

If desired, use a custom window class, which should be registered in the PreCreateWindow of the derived class and have the class name specified.

3. Presubclasswindow

Call Time:

Attach the C++wnd object to the window while creating the window

CWnd::Create () in: ... Afxhookwindowcreate (this); HWND hwnd =:: CreateWindowEx (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 the window is established, the system establishes a WH_CBT (training) hook (Intercept window action) and completes the "wrapping" of the CWnd object to the window in the hook function. file://operate a lot, mainly have

   Pwndinit is an incoming parameter, it should be a CWnd object pointer   //object connected to the window handle   pwndinit->attach (hWnd);   ...   //Call the virtual function Presubclasswindow, giving the user an opportunity to define the relevant action, for example, the attachment   Pwndinit->presubclasswindow () of the child control;   ...   //Set message handler functions and so on.   WNDPROC *poldwndproc = pwndinit->getsuperwndprocaddr ();   ...   WNDPROC AfxWndProc = Afxgetafxwndproc ();   Oldwndproc = (WNDPROC) SetWindowLong (hWnd, GWL_WNDPROC,     (DWORD) afxwndproc);   ...

CWnd implementation: In CWnd class, there is no default action in this virtual function.

4. PreTranslateMessage

Call Time:

In the process's Message queue processing loop, the CWinApp virtual function PreTranslateMessage is called before the window's message is distributed to the window's message handler, allowing the message to be sent to be processed in the Re-window derived class.

and CWinApp::P Retranslatemessage will have the possibility to call PreTranslateMessage to the window.

Let's take a look at the following cwinthread::P the distribution of messages in Umpmessage

CWinThread PreTranslateMessage virtual function is called  if (m_msgcur.message! = Wm_kickidle &&! PreTranslateMessage (&m_msgcur)) {  :: TranslateMessage (&m_msgcur);  ::D ispatchmessage (&m_ Msgcur); }
BOOL CWinThread::P retranslatemessage (msg* pMsg) {.... cwnd* pMainWnd = AfxGetMainWnd ();This invokes the PreTranslateMessage () from the Command issuing window to the main window between the levels of the window;See the Walkpretranslatetree source code belowif (Cwnd::walkpretranslatetree (Pmainwnd->getsafehwnd (), PMSG))return TRUE;In case of modeless dialogs, last chance route through mainWindow ' s accelerator tableif (pMainWnd! = NULL) {cwnd* pWnd = Cwnd::fromhandle (Pmsg->hwnd);if (pwnd->gettoplevelparent ()! = pMainWnd)return Pmainwnd->pretranslatemessage (PMSG);} return FALSE; //No special processing} BOOL PASCAL Cwnd::walkpretranslatetree (HWND hwndstop, msg* pMsg) {.... ///Call the PreTranslateMessage for (HWND hwnd = pmsg->hwnd; hwnd = NULL; hwnd =:: GetParent (HWND)) in each level window {cwnd* PWn D = 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:

When the window is established, it enters the message loop. During this time, Windowpro was called to process each message.

When the window is established, the message handler is created, typically AfxWndProc, which will call Afxcallwndproc, and Afxcallwndproc will eventually be called to the virtual function WindowProc.

Function:

Allows derived classes to add processing before the message is processed.

CWND implementations: LRESULT cwnd::windowproc (UINT message, WPARAM WPARAM, LPARAM LPARAM) {LRESULT LRESULT = 0; file://is mainly done by onwndmsg The classification of the information, decomposition processing. if (! ONWNDMSG (Message, WParam, LParam, &lresult)) file://The remainder is left to the default command handling function. LResult = DefWindowProc (message, WParam, LParam); return lResult; }

Attached: onwndmsg process

In Onwndmsg, according to the nature of the message, it will be classified as a command message, a notification message, a normal message

respectively by OnCommand, onnotify ... Processing

if (message = = Wm_command) {  ....  OnCommand (WParam, LParam))  if (message = = wm_notify) {  ...  OnNotify (WParam, LParam, &lresult)) ...  after you find it, call the function. MMF.PFN = lpentry->pfn; LResult = (this->*mmf.pfn_lwl) (WParam, LParam);  

6. OnCommand

Call Time:

In Onwndmsg, if the message is WM_COMMAND, which is the command message, OnCommand is called;

command handling can be manipulated in OnCommand.

CWnd implementation: file://See Analysis of command update mechanism

BOOL CWnd::OnCommand (WPARAM WPARAM, LPARAM LPARAM) {  ...  //Tentative call to OnCmdMsg (,, cn_update_command_ui.) See if the current command item is valid  Ctestcmdui state;  State.m_nid = NID;  ONCMDMSG (NID, cn_update_command_ui, &state, NULL);  if (...) //command is valid when SET flag for command flag: Cn_command  nCode = Cn_command;  ....  //If it is a notification message for a child window, it is reflected to the child window????, returned if the child window has been processed accordingly. If it is not processed, it is handled as a command.  //A part of the notification message is a    return OnCmdMsg (NID, nCode, NULL, NULL) sent via wm_command;}    

For the specific process of command processing, see article related articles.

7. Ononnotify

BOOL cwnd::onnotify (WPARAM, LPARAM LPARAM, lresult* pResult)

Call Time:

In Onwndmsg, if the message being processed is WM_NOTIFY, onnotify is called to handle the notification message specifically.

The virtual function OnNotify provides an interface for managing notification messages in derived classes.

CWND implementation: BOOL cwnd::onnotify (WPARAM, LPARAM LPARAM, lresult* pResult) {... file://the notification message is reflected to the notification window, processed by it, if the window is not processed, is handled by OnCmdMsg. if (Reflectlastmsg (Hwndctrl, PResult)) return TRUE; Eaten by child ... file://referred to oncmdmsg for processing. The corresponding message map macro is return ONCMDMSG (NID, Makelong (NCode, wm_notify), ¬ify, NULL); }

About Message Reflection:

The control typically informs the parent window of its own change in the form of a notification message. Handled by the parent window response.

The reflection mechanism of MFC can transmit the notification message back to the original window and get the processing of the event in the message map system of the original window. This facilitates the encapsulation of window functions.

If the child window does not have a reflection handler for the notification, the notification message is still handled by the parent window.

In Reflectlastmsg, Pwnd->sendchildnotifylastmsg is called, (Pwnd is a pointer to a child window)

virtual function OnChildNotify will be called in SendChildNotifyLastMsg.

In the onchildnotify of a child window, you can add processing before receiving a reflection message for processing.

8. OnChildNotify

BOOL cwnd::onchildnotify (UINT umsg, WPARAM WPARAM, LPARAM LPARAM, lresult* pResult)

Call Time:

When the window notifies the parent window, the onchildnotify is called first when it is reflected back.

You can monitor the processing of notification messages coming from the parent window in this function.

CWnd implementations:

Invoke CWnd member Reflectchildnotify

The processing of the notification message is actually done by the original message, the command processing process. The difference is that their messages, command values are adjusted to distinguish the Windows own messages, commands.

In the message map entry for the class, the Reflection message processing macro completes the corresponding notification message associated with the handler function.

BOOL cwnd::reflectchildnotify (UINT umsg, WPARAM WPARAM, LPARAM LPARAM, lresult* pResult) {Classify the returned message into a specific message formatSwitch (umsg) {General NewsWm_hscroll,wm_vscroll: ..... .....//Convert to Reflection message number, by command handler function. (in the message map, the sequence number of the reflected message is wm_reflect_base+umsg) return cwnd::onwndmsg (wm_reflect_base+umsg, WParam, LParam, PResult); //If it is wm_command case wm_command: {... //directly to the oncmdmsg of the window, and the sequence number of the command is changed accordingly, in order to distinguish it from the same command received by the window, and there are different message map entries. Cwnd::oncmdmsg (0, Makelong (NCode, Wm_reflect_base+wm_command), NULL, NULL)) ... //If it is wm_notify notify case wm_notify: {// .... //referred to oncmdmsg for processing. Change the command sequence number. Cwnd::oncmdmsg (0, Makelong (NCode, wm_reflect_base+wm_notify),? ify, NULL); ..... } //Color class 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 passed through onwndmsg in WindowProc, the corresponding processing function was not found, which will be referred to defwindowproc processing.

In DefWindowProc, you can add actions to these unhandled messages.

CWnd implementation

if (m_pfnsuper! = null)  if ((Pfnwndproc = *getsuperwndprocaddr ()) = = null)  else  return:: CallWindowProc (Pfnwndproc, M_hwnd, Nmsg, WParam, LParam);}  

Ten. DestroyWindow

First, we look at the implementation of CWnd to DestroyWindow.

BOOL CWnd::D Estroywindow () {  ....  //Destroy window  if (m_pctrlsite = = NULL)   bresult =::D Estroywindow (m_hwnd);  else   bresult = M_pctrlsite->destroycontrol ();  ....  //c++ Window object and window detach  Detach ();}   

In this implementation, call Api:bool DestroyWindow (HWND hwnd);

The DestroyWindow of the API will send Wm_destroy and Wm_ncdestroy messages to the window,

Call Time:

①. For main window: (CFrameWnd)

When the window receives a close message, the DestroyWindow is called

To send a message off:

Select Exit on the menu to give a id_app_exit command that has the default implementation in Cwinapp::onappexit: Send Wm_close to the main window;

Another, press the window Close button, will give the window a WM_CLOSE message.

In Wm_close's default processing OnClose ()

void Cframewnd::onclose () {.... DestroyWindow (); ....}

②. For other windows

When the main window is destroyed, it will be called::D Estroywindow, this API will send Wm_destroy and Wm_ncdestroy messages to the window.

and completes the destruction of the child window automatically.

In MFC, the DestroyWindow virtual function of a child window is not called, but it can be overloaded and called when needed. Controls the destruction of child windows.

PostNcDestroy.

Call Time:

After the window is destroyed, it is called in Wm_ncdestroy's handler function, OnNcDestroy ().

In PostNcDestroy, the removal of the window object of C + + is generally done.

CWnd implementations:

Empty

CFrameWnd implementation

Delete this; (Delete Window object)

http://blog.csdn.net/fmd/article/details/5529

http://blog.csdn.net/akof1314/article/details/5597669

An Analysis of MFC (7) the invocation time and the default implementation of the CWnd class virtual function

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.