I often download programs from the Internet, but I can't see a few lines of VC. I move the mouse to the top right corner, aiming at the "X", click it... (The heart is still thinking: killing you !), Let alone look for the existence of QQ in the "program" menu and start leisure time !! This is something I often do, alas! Because of its poor foundation, it is often kicked out of the door by good code. Fortunately, I still have a feeling for her. Recently, I was lucky enough to buy Mr. Hou's "Let's go through MFC". I saw Chapter 6: The cause and death of the MFC program. I thought it was learning MFC. Oh no, it should be a good starting point to look at the MFC program code. This chapter also gives a detailed explanation of the Life and Death Causes of the MFC Program (no document/view is supported), in order to deepen the memory, I have summarized the following process for your reference.
The initiation and death sequence of the MFC program:
1. Create the Application Object theapp
The program first produces one (and only one) Application Object theapp, that is, a cwinapp object. Once this global object is generated, it executes its constructor, because cmywinapp constructor is not defined, the constructor of the cwinapp class is executed. This function is defined in the appcore. cpp 75th line. You can search for it by yourself. Therefore, the member variables in cwinapp will get the configuration and initial values because of the birth of theapp global object.
2. winmain debut
When programming with SDK, the entry point of the program is the winmain function, and we do not see the winmain function in the MFC program !~ It turns out that she is hidden in the MFC code. After theapp configuration is complete, winmain comes on stage, slow! Looking at the program, the Code is not connected to the winmain function! I don't know about this. MFC is already ready and directly added to the application code by the linker. It turns out that she is in appmodul. in CPP, we think that after theapp configuration is complete, the program will be transferred to appmodul. CPP is coming. So what is the execution? Let's take a look at the code extracted from appmodul. cpp:
Extern "C" int winapi
_ Twinmain (hinstance, hinstance hprevinstance, lptstr lpcmdline, int ncmdshow)
{
// Call shared/exported winmain
Return afxwinmain (hinstance, hprevinstance, lpcmdline, ncmdshow );
}
_ Twinmain function "_ t" is a macro prepared to support Unicode.
_ The return value of the twinmain function is the return value of the afxwinmain function. The afxwinmain function is defined in the winmain. cpp 21st line. After a little sorting, you can see what this "program entry point" mainly does:
Int afxapi afxwinmain (hinstance, hinstance hprevinstance, lptstr lpcmdline, int ncmdshow)
{
Int nreturncode =-1;
Cwinapp * PAPP = afxgetapp ();
Afxwininit (hinstance, hprevinstance, lpcmdline, ncmdshow );
PAPP-> initapplication ();
PAPP-> initinstance ()
Nreturncode = PAPP-> Run ();
Afxwinterm ();
Return nreturncode;
}
The afxgetapp () function is used to obtain the cmywinapp Object Pointer. Therefore, the above functions are equivalent to the following calls:
Cmywinapp: initapplication ();
Cmywinapp: initinstance ()
Cmywinapp: Run ();
Therefore, the following code is called:
Cwinapp: initapplication (); // because cmywinapp has not changed initapplication
Cmywinapp: initinstance () // because cmywinapp has changed initinstance
Cwinapp: Run (); // because the cmywinapp has not rewritten run
A friend who has used the SDK to write a program may now smile.
3. afxwininit-afx internal Initialization
Afxwininit is the first operation after the cwinapp constructor. It mainly performs afx internal initialization operations, which are defined in appinit. line 3 of CPP won't be taken out here. You can find it yourself!
4. Run cwinapp: initapplication.
The operation after afxwininit is PAPP-> initapplication. We know that PAPP points to the cmywinapp object. When you call:
PAPP-> initapplication ();
Equivalent to calling:
Cmywinapp: initapplication ();
However, you need to know that cmywinapp inherits from cwinapp, and initapplication is a virtual function of cwinapp. We have not rewritten it (in most cases, we do not need to rewrite it), so the above operation is equivalent to calling:
Cwinapp: initapplication ();
This function is defined in appcore. cpp row 125th. You can find it by yourself! I won't move it out, and the operations in it are all done by MFC for internal management (in fact, I can't understand it, I know this is the case ).
5. Run cwinapp: initinstance.
After the initapplication function, afxwinmain calls PAPP-> initinstance. When the program calls:
PAPP-> initinstance ();
Equivalent to calling:
Cmywinapp: initinstance ();
However, you must know that cmywinapp inherits from cwinapp, and initinstance is a virtual function of cwinapp. Since we have changed it, the above operation is to call the initinstance function of our (cmywinapp.
6. cframewnd: Create generates the main window (and registers the window class first)
Now we have come to cwinapp: initinstance. This function first creates a cmyframewnd object to generate the main window. Before creating a cmyframewnd pair, you must first execute the constructor cmyframewnd: cmyframewnd (). This function uses the create function to generate a window:
Cmyframewnd: cmyframewnd ()
{
Create (null, "Hello MFC", ws_overlappedwindow, rectdefault, null, "mainmenu ");
}
Here, create is a member function of cframewnd, which will generate a window. All the friends who have used the SDK programming know that to create the main window, you must first register a window class and specify window attributes, but which window class is used here? The first parameter of the create function (for details about other parameters, refer to msdn or in-depth introduction to MFC). What does it mean to set the window class to null? It means to generate a standard out-of-box window using the built-in air class of MFC. However, our programs generally do not register any window classes! Oh, before the create function generates a window, it will trigger the registration operation of the window class.
Let's dig out what the create function has done first. The create function is defined in winfrm. THE 538th rows of CPP (here I won't copy the code, you can open it by yourself). The function calls the createex function in line 562, because createex is a member function of cwnd, cframewnd is followed by cwnd, so cwnd: createex will be called. This function is defined in wincore. cpp row 665th. The following code is used:
Bool cwnd: createex (DWORD dwexstyle, lpctstr lpszclassname,
Lpctstr lpszwindowname, DWORD dwstyle,
Int X, int y, int nwidth, int nheight,
Hwnd hwndparent, hmenu nidorhmenu, lpvoid lpparam)
{
// 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;
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 );
...
}
If you have used SDK programming, you may feel a little bit about the above Code. The precreatewindows called in the function is a virtual function, which is defined in cwnd and cframewnd. The cframewnd: precreatewindow should be called here because this pointer refers to the object. This function is defined in winfrm. cpp line 521st. The following code is used:
Bool cframewnd: precreatewindow (createstruct & CS)
{
If (CS. lpszclass = NULL)
{
Verify (afxdeferregisterclass (afx_wndframeorview_reg ));
CS. lpszclass = _ afxwndframeorview; // color_window background
}
...
}
Afxdeferregisterclass is a macro defined in afximpl. h. This macro is shown below:
# Define afxdeferregisterclass (fclass) afxenddeferregisterclass (fclass)
Note: The macro here is different from the "let alone MFC". The above code is extracted from Visual C ++ 6.0.
Afxenddeferregisterclass is defined in wincore. cpp row 3,619th. This function is very complex and mainly involves registering five window classes (Wow! How can I use five window classes? I still don't know). The precreatewindow member functions of different classes are called at the moment before the window is generated and ready to register the window class. If the specified window class is null, the system default class is used. The precreatewindow member functions of cwnd and Its Derived classes show the window classes used by the framework for different functions.
7. window display and update
After cmyframewnd: cmyframewnd is completed, the window has been generated; the program flow is returned to cmywinapp: initinstance, so the showwindow function is called to display the window and the updatewindow function is called to send the wm_paint message. In the SDK program, messages are processed by window functions. Where are window functions and how are they delivered to window functions? Let's start with cwinapp: Run.
8. Execute cwinapp: Run -- the source of live water of program life
After executing the cmywinapp: initinstance function, the program goes to the PAPP-> run of the afxwinmain function. Now we know that this will execute the cwinapp: Run function, this function is defined in appcore. line 2 of CPP. The following is the program code:
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 ();
}
The function calls the cwinthread: Run function. This function is defined in line 456th of thrdcore. cpp. I will not copy it here. The function calls the pumpmessage function in Row 3. This function is defined in Row 3 of thrdcore. cpp. The Code is as follows:
Bool cwinthread: pumpmessage ()
{
If (! : Getmessage (& m_msgcur, null ))
{
Return false;
}
// Process this message
If (m_msgcur.message! = Wm_kickidle &&! Pretranslatemessage (& m_msgcur ))
{
: Translatemessage (& m_msgcur );
: Dispatchmessage (& m_msgcur );
}
Return true;
}
The main operation of this function is to send the message from: dispatchmessage to the window function (cwnd: defwindowproc), but the program generally does not provide any window function, but in afxenddeferregisterclass, before registering the five window classes, you have specified the window function:
Wndcls. lpfnwndproc = defwindowproc;
Although the window function is specified as the defwindowproc member function (cwnd: defwindowproc), the message is actually not sent to this place, but a global function named afxwndproc.
9. Connect messages and processing functions-message map mechanism
At this point, the main window has been generated, waiting for various messages, and then calling the corresponding processing function. However, how can messages and processing functions be connected together? MFC uses the message map mechanism (Message ing mechanism) to provide two sets of macros for the "very convenient interface" used by the application. The principle is not clear yet, it cannot be explained here. The main usage is: first, use declare_message_map () in the class declaration to provide the processing function, for example:
Class cmyframewnd: Public cframewnd
{
Public:
Cmyframewnd ();
Afx_msg void onpaint (); // For wm_paint
Afx_msg void onabout (); // For wm_command (idm_about)
Declare_message_map ()
}
Then, use the bebin_message_map () and end_message_map () Macros in any location of the corresponding. cpp file (of course not in the function) to add the corresponding messages, such:
Begin_message_map (cmyframewnd, cframewnd)
On_command (idm_about, onabout)
On_wm_paint ()
End_message_map ()
Why does a message automatically flow to the specified function after such a macro? The answer lies in the structure design of the message map. Find the message map simulation program in Chapter 3rd of "let's get down to MFC!
Well, I will write it here. If you are new to MFC, you may be confused after reading it, sorry! I have never written a summary. It's okay! Just take out Mr. Hou's "Let's get down to MFC" and just chew it a few times.