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