When we are writing programs or reading books of the MFC class, we will always see the book asking us to add a certain function somewhere and respond to any message. So why should we add it here? Why can't I add a message response function elsewhere?
Next, let's discuss it together.
1. MFC operation steps: (this is for the application of the document view structure)
Theapp ()-> // Global Object Construction and memory allocation of the application
Winmain ()-> // enter the main function
Afxwinmain ()-> // call the API
Initaplacation () (internal application management)-> // used for initialization of Internal Application Management
Initinstance () (theapp)-> // initialize the Application Object
Initinstance ()-> // initialization of the application (create and register window classes, display and update the application framework)
Registration window class->
Afxenddeferregisterclass () (This function registers different window classes based on different applications)->
Afxregisterclass ()->
Cmainframe: precreatewindow ()->
Cframewnd: precreatewindow ()->
Afxdeferregisterclass () (if not registered, register the window class; it is actually the macro of afxendregisterclass () (generally registered window class here, because the document window involves the management of the document view class)->
Loadframe ()-> // load the framework
Cframewnd: Create ()->/
Cwnd: createex ()-> // create an application window
Cmainframe: precreatewindow () (in fact, this function is a virtual function. That is to say, if the subclass defines this function for the application, it will call the subclass function. Therefore, we can reload this function to modify the appearance of the application framework.)-> // call it before the Framework Window is displayed.
Showwindow ()-> updatewindow ()-> // display and update
Message loop:->
Cwinthread: Run ()->
Do-while () loop (-> pumpmessage ()-> getmessage ()-> translatemessage ()-> dispatchmessage ())
To put it simply, initialize the Global Object and enter the main function to create, register, and display the window class, and then enter the message loop.
Theapp: Initialize global variables or class objects before running the program. That is, allocate the memory space and the initial members. (Each MFC application has only one global object theapp. We use this global object to uniquely represent the application .)
Next we will show how to trace these functions (My is that all of them are in the C: disk .. /Mfc/src)
Winmain () function (C:/program files/Microsoft Visual Studio/vc98/mfc/src/appmodul. cpp)
Winapp (C:/program files/Microsoft Visual Studio/vc98/mfc/src/thrdcore. cpp)
Afxwinmain () (C:/program files/Microsoft Visual Studio/vc98/mfc/src/winmain. cpp)
Int afxapi afxwinmain (hinstance, hinstance hprevinstance,
Lptstr lpcmdline, int ncmdshow)
{
Assert (hprevinstance = NULL );
Int nreturncode =-1;
Cwinthread * pthread = afxgetthread ();
Cwinapp * PAPP = afxgetapp ();
// Afx internal Initialization
If (! Afxwininit (hinstance, hprevinstance, lpcmdline, ncmdshow ))
Goto initfailure;
// App global initializations (rare)
If (PAPP! = NULL &&! PAPP-> initapplication () // C:/program files/Microsoft Visual Studio/vc98/mfc/include/afxwin. h)
Goto initfailure;
// Perform specific initializations
If (! Pthread-> initinstance () // C:/program files/Microsoft Visual Studio/vc98/mfc/include/afxwin. h)
{
If (pthread-> m_pmainwnd! = NULL)
{
Trace0 ("Warning: destroying non-null m_pmainwnd/N ");
Pthread-> m_pmainwnd-> destroywindow ();
}
Nreturncode = pthread-> exitinstance ();
Goto initfailure;
}
Nreturncode = pthread-> Run ();
Initfailure:
# Ifdef _ debug
// Check for missing afxlocktempmap CILS
If (afxgetmodulethreadstate ()-> m_ntempmaplock! = 0)
{
Trace1 ("Warning: temp map lock count non-zero (% LD)./N ",
Afxgetmodulethreadstate ()-> m_ntempmaplock );
}
Afxlocktempmaps ();
Afxunlocktempmaps (-1 );
# Endif
Afxwinterm ();
Return nreturncode;
}
Afxenddeferregisterclass
# Define afxdeferregisterclass (fclass) afxenddeferregisterclass (fclass)
Bool afxapi afxenddeferregisterclass (long ftoregister)
{
// Mask off all classes that are already registered
Afx_module_state * pmodulestate = afxgetmodulestate ();
Ftoregister & = ~ Pmodulestate-> m_fregisteredclasses;
If (ftoregister = 0)
Return true;
Long fregisteredclasses = 0;
// Common Initialization
Wndclass wndcls;
Memset (& wndcls, 0, sizeof (wndclass); // start with null defaults
Wndcls. lpfnwndproc = defwindowproc;
Wndcls. hinstance = AfxGetInstanceHandle ();
Wndcls. hcursor = afxdata. hcurarrow;
Initcommoncontrolsex Init;
Init. dwsize = sizeof (init );
// Register various window classes
// Work to register classes as specified by ftoregister, populate fregisteredclasses as we go
If (ftoregister & afx_wnd_reg)
{
// Child windows-No brush, no icon, safest default class styles
Wndcls. Style = cs_dblclks | cs_hredraw | cs_vredraw;
Wndcls. lpszclassname = _ afxwnd;
If (afxregisterclass (& wndcls ))
Fregisteredclasses | = afx_wnd_reg;
}
If (ftoregister & afx_wndolecontrol_reg)
{
// Ole control windows-use parent DC for speed
Wndcls. Style | = cs_parentdc | cs_dblclks | cs_hredraw | cs_vredraw;
Wndcls. lpszclassname = _ afxwndolecontrol;
If (afxregisterclass (& wndcls ))
Fregisteredclasses | = afx_wndolecontrol_reg;
}
If (ftoregister & afx_wndcontrolbar_reg)
{
// Control bar windows
Wndcls. Style = 0; // control bars don't handle double click
Wndcls. lpszclassname = _ afxwndcontrolbar;
Wndcls. hbrbackground = (hbrush) (color_btnface + 1 );
If (afxregisterclass (& wndcls ))
Fregisteredclasses | = afx_wndcontrolbar_reg;
}
If (ftoregister & afx_wndmdiframe_reg)
{
// MDI frame window (also used for splitter window)
Wndcls. Style = cs_dblclks;
Wndcls. hbrbackground = NULL;
If (_ afxregisterwithicon (& wndcls, _ afxwndmdiframe, afx_idi_std_mdiframe ))
Fregisteredclasses | = afx_wndmdiframe_reg;
}
If (ftoregister & afx_wndframeorview_reg)
{
// SDI frame or MDI child windows or views-normal colors
Wndcls. Style = cs_dblclks | cs_hredraw | cs_vredraw;
Wndcls. hbrbackground = (hbrush) (color_window + 1 );
If (_ afxregisterwithicon (& wndcls, _ afxwndframeorview, afx_idi_std_frame ))
Fregisteredclasses | = afx_wndframeorview_reg;
}
If (ftoregister & afx_wndcommctls_reg)
{
// This flag is compatible with the old initcommoncontrols () API
Init. dwicc = icc_win95_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_win95ctls_mask );
Ftoregister & = ~ Afx_win95ctls_mask;
}
If (ftoregister & afx_wndcommctl_updown_reg)
{
Init. dwicc = icc_updown_class;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_updown_reg );
}
If (ftoregister & afx_wndcommctl_treeview_reg)
{
Init. dwicc = icc_treeview_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_treeview_reg );
}
If (ftoregister & afx_wndcommctl_tab_reg)
{
Init. dwicc = icc_tab_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_tab_reg );
}
If (ftoregister & afx_wndcommctl_progress_reg)
{
Init. dwicc = icc_progress_class;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_progress_reg );
}
If (ftoregister & afx_wndcommctl_listview_reg)
{
Init. dwicc = icc_listview_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_listview_reg );
}
If (ftoregister & afx_wndcommctl_hotkey_reg)
{
Init. dwicc = icc_hotkey_class;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_hotkey_reg );
}
If (ftoregister & afx_wndcommctl_bar_reg)
{
Init. dwicc = icc_bar_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_bar_reg );
}
If (ftoregister & afx_wndcommctl_animate_reg)
{
Init. dwicc = icc_animate_class;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_animate_reg );
}
If (ftoregister & afx_wndcommctl_internet_reg)
{
Init. dwicc = icc_internet_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_internet_reg );
}
If (ftoregister & afx_wndcommctl_cool_reg)
{
Init. dwicc = icc_cool_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_cool_reg );
}
If (ftoregister & afx_wndcommctl_userex_reg)
{
Init. dwicc = icc_userex_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_userex_reg );
}
If (ftoregister & afx_wndcommctl_date_reg)
{
Init. dwicc = icc_date_classes;
Fregisteredclasses | = _ afxinitcommoncontrols (& init, afx_wndcommctl_date_reg );
}
// Save New State of registered controls
Pmodulestate-> m_fregisteredclasses | = fregisteredclasses;
// Special case for all common controls registered, turn on afx_wndcommctls_reg
If (pmodulestate-> m_fregisteredclasses & afx_win95ctls_mask) = afx_win95ctls_mask)
{
Pmodulestate-> m_fregisteredclasses | = afx_wndcommctls_reg;
Fregisteredclasses | = afx_wndcommctls_reg;
}
// Must have registered at least as Mamy classes as requested
Return (ftoregister & fregisteredclasses) = ftoregister;
}
Bool cframewnd: loadframe (uint nidresource, DWORD dwdefaultstyle,
Cwnd * pparentwnd, ccreatecontext * pcontext)
{
// Only do this once
Assert_valid_idr (nidresource );
Assert (m_nidhelp = 0 | m_nidhelp = nidresource );
M_nidhelp = nidresource; // ID for help context (+ hid_base_resource)
Cstring strfullstring;
If (strfullstring. loadstring (nidresource ))
Afxextractsubstring (m_strtitle, strfullstring, 0); // first sub-string
Verify (afxdeferregisterclass (afx_wndframeorview_reg ));
// Attempt to create the window
Lpctstr lpszclass = geticonwndclass (dwdefaultstyle, nidresource );
Lpctstr lpsztitle = m_strtitle;
If (! Create (lpszclass, lpsztitle, dwdefaultstyle, rectdefault,
Pparentwnd, makeintresource (nidresource), 0l, pcontext ))
{
Return false; // will self destruct on failure normally
}
// Save the default menu handle
Assert (m_hwnd! = NULL );
M_hmenudefault =: getmenu (m_hwnd );
// Load accelerator Resource
Loadacceltable (makeintresource (nidresource ));
If (pcontext = NULL) // send initial update
Sendmessagetodescendants (wm_initialupdate, 0, 0, true, true );
Return true;
}
Cwnd: createex ()
Virtual bool createex (
DWORD dwexstyle,
Lpctstr lpszclassname,
Lpctstr lpszwindowname,
DWORD dwstyle,
Int X,
Int y,
Int nwidth,
Int nheight,
Hwnd hwndparent,
Hmenu nidorhmenu,
Lpvoid lpparam = NULL
);
Virtual bool createex (
DWORD dwexstyle,
Lpctstr lpszclassname,
Lpctstr lpszwindowname,
DWORD dwstyle,
Const rect & rect,
Cwnd * pparentwnd,
Uint NID,
Lpvoid lpparam = NULL
);
Cmainframe: precreatewindow ()
Virtual bool precreatewindow (
Createstruct & CS
);
Typedef struct tagcreatestruct {
Lpvoid lpcreateparams;
Handle hinstance;
Hmenu;
Hwnd hwndparent;
Int Cy;
Int CX;
Int y;
Int X;
Long style;
Lpcstr lpszname;
Lpcstr lpszclass;
DWORD dwexstyle;
} Createstruct;
Cwinthread: Run ()
Int cwinapp: Run ()
{
If (m_pmainwnd = NULL & afxolegetuserctrl ())
{
// Not launched/embedding or/automation, but has no main window!
Trace0 ("Warning: m_pmainwnd is null in cwinapp: Run-quitting application./N ");
Afxpostquitmessage (0 );
}
Return cwinthread: Run ();
}
Int cwinthread: Run ()
{
Assert_valid (this );
// For tracking the idle time state
Bool bidle = true;
Long lidlecount = 0;
// Acquire and dispatch messages until a wm_quit message is wrongly ed.
For (;)/enters the message loop
{
// Phase1: Check to see if we can do Idle Work
While (bidle &&
! : Peekmessage (& m_msgcur, null, pm_noremove ))
{
// Call onidle while in bidle state
If (! Onidle (lidlecount ++ ))
Bidle = false; // assume "no idle" state
}
// Phase2: pump messages while available
Do
{
// Pump message, but quit on wm_quit
If (! Pumpmessage ())
Return exitinstance ();
// RESET "no idle" state after pumping "normal" Message
If (isidlemessage (& m_msgcur ))
{
Bidle = true;
Lelecount = 0;
}
} While (: peekmessage (& m_msgcur, null, pm_noremove ));
}
Assert (false); // not reachable
}
When a window in MFC is destroyed, the object is not necessarily destroyed. The window is only associated with the m-hwnd of the object. However, if an object is destroyed, the window that owns the object must also be destroyed.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/liwenlong26363/archive/2010/08/08/5796964.aspx