MFC's life and death

zhaozj2021-02-16  52

I often download a good program from the Internet, but open the VC, I don't have a few lines. The mouse is moved to the uppermostmost corner, and the "X", click ... (heart is also impressed: 死 死!), I don't say that I look for QQ existence in the "Program" menu, start entering the leisure time! ! This is what I often do, hehe! Biting the foundation is not solid, often being kicked out of the door by a beautiful code. But fortunately, I also had a feeling of her. Recently, I have been able to buy Mr. Hou 's "in-depth MFC", see Chapter 6: The cause of life and death of the MFC program, I feel that I am learning MFC, I don't want to see the MFC program code. The starting point, the chapter is also explained in detail to the MFC program (no support for document / view). In order to deepen memory, I summarize the following procedures for your reference.

Startup and death order of the MFC program:

1. Create an Application Object Object THEAPP

The program starts to produce one (and only one) Application Object object THEAPP, which is also a CWINAPP object. This global object is generated, and its constructor is executed because there is no CMYWINAPP constructor, so the constructor of the CWINAPP class is executed. This function is defined in APPCORE.CPP 75, you can search yourself, so member variables among CWINAPPs will get configuration and initial values ​​because of the birth of THEAPP's global object.

2, WinMain debut

When using the SDK programming, the entry point of the program is the WinMain function, and we have not seen the Winmain function in the MFC program, oh! ~ It turns out that she is hidden in the MFC code. When the theApp configuration is complete, WinMain debut, slow! Look at the program, is not the code of the Winmain function! I don't know this, MFC has already prepared it and applied directly to the application code directly. It turned out that she is in appmodul.cpp, well, we think that when the theApp configuration is completed, the program is turned to AppModul.cpp . What does it do? Take a look at the code from AppModul.cpp from AppModul.cpp:

EXTERN "C" int WinApi

_TwinMain (Hinstance Hinstance, Hinstance Hprevinstance, LPTSTR LPCMDLINE, INT NCMDSHOW)

{

// call shared / exported WinMain

Return AFXWINMAIN (Hinstance, Hprevinstance, LPCMDline, ncmdshow);

}

The _twinmain function "_t" is a macro to support Unicode.

_twinmain function return value is the return value of the AFXWINMAIN function, the AFXWINMAIN function is defined in WinMain.cpp 21st line, slightly adding, go to the deposit, you can see this "program entry point" mainly:

Int Afxapi AFXWINMAIN (Hinstance 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 a CMYWINAPP object pointer, so the above functions are equivalent to calls:

CMYWINAPP :: initApplication ();

CMYWINAPP :: InitInstance ()

CMYWINAPP :: Run ();

Thus, the call:

CWINApp :: initApplication (); // Because CMYWINAPP does not overwrote initApplication

CMYWINAPP :: InitInstance () // Because CMYWINAPP rewritten InitInstance

CWINAPP :: Run (); // Because CMYWINAPP does not rewrite Run

Users who have used SDK write programs now may now make a smile.

3, AFXWININIT - AFX internal initialization operation

AfxWinInit is the first operation after the CWINAPP constructor, mainly doing the internal initialization operation of the AFX, the function is defined in the appinit.cpp 24th line, this is not enough, you have searched it!

4. Execute CWINAPP :: InitApplication

The operation after AfxWininit is PAPP-> INitApplication, we already know that PAPP points to CMYWINAPP objects when calling:

PAPP-> INITAPPLICATION ();

Equivalent to calls:

CMYWINAPP :: initApplication ();

But you have to know that CMYWINAPP inherits from cwinapp, and initApplication is a virtual function of CWINAPP. We did not rewrite it (most cases do not need to be rewritten), so the above operation is equivalent to call:

CWINAPP :: initApplication ();

This function is defined in the appcore.cpp 125 line, you search yourself! I didn't move out, the operations inside were made by MFC for internal management (in fact, I can't understand it, I know that this is good).

5. Execute CWINAPP :: InitInstance

After the INitApplication function, the AFXWINMAIN calls PAPP-> InitInstance. When the program is called:

PAPP-> InitInstance ();

Equivalent to calls:

CMYWINAPP :: InitInstance ();

But you have to know that CMYWINAPP inherits from CWINAPP, and InitInstance is a virtual function of CWINAPP. Since we have rewritten it, the above operation is to call this INITINSTANCE function of our own (CMYWINAPP).

6, cframeWnd :: Create Generates the main window (and register the window class first)

Now I have come to CWINAPP :: InitInstance, the function first New a CMYFrameWnd object, resulting in a main window. Before creating a CMYFrameWnd pair, you must perform the constructor cmyframeWnd :: CMYFRAMEWnd (), which generates a window with the CREATE function:

CMYFRAMEWND :: CMYFrameWnd ()

{

Create (NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, RectDefault, Null, "MainMenu");

}

Where CREATE is a member function of CFrameWnd, it will generate a window, and friends who have used the SDK programming. If you want to create a main window, you must register a window class, specify the properties of the window, but which window class is used here ? CREATE function first parameter (other parameters, please refer to MSDN or "Detailed Shallow MFC" Detailed Description) Specify window classes set to null? It means to generate a standard outer frame window with an aerial class built by MFC, but our procedures are generally not registered any window classes! Hey, the Create function will trigger the registration operation of the window class before generating a window. Let us first dig the create function, what is the operation, the Create function is defined in the 538th line of WinFrm.cpp (here I don't turn the code COPY, you open it out), the function is in 562 lines The CreateEx function, because CreateEx is a member function of CWnd, and the cframewnd is coming from CWND, so CWnd :: Createex will call. This function is defined in WinCore.cpp. 665, below is part of the code:

Bool CWnd :: Createex (DWord DwexStyle, LPCTSTR LPSZCLASSNAME,

LPCTSTSTSZZWINDOWNAME, 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;

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, cs.hmenu, cs.hinstance, cs.lpcreateparams;

...

}

Users who have used the SDK programming, seeing the above code should have a little feeling, the PrecreateWindows called in the function is a virtual function, and there is definition in CWnd and CFrameWnd. Since the THIS pointer refers to the object of the object, it should be called CFrameWnd :: PrecreateWindow. This function is defined in the WinFrm.cpp, line 521, the following is part of the code:

Bool CFrameWnd :: PrecreateWindow (CreateStruct & Cs)

{

IF (cs.lpszclass == null)

{

Verify (AFX_WNDFRAMEORVIEW_REG); cs.lpszclass = _afxwndframeorView; // color_window background

}

...

}

The AFXDeferRegisterClass is a macro defined in the AFXIMPL.H. The macro is as follows:

#define afxdeferregisterclass (fclass) AFXEnddeferRegisterClass (FCLASS)

Note: There is a macro and "deep-in-depth MFC", the above code is taken from Visual C 6.0.

AFXEnddeferRegisterClass is defined in WinCore.cpp 3619 line, which is complicated, mainly registered five window classes (wow! I finally saw the window class, how to use 5? I still don't know), different class precomreateWindow member functions It is called before the window is generated, ready to register the window class. If we specified the window class is NULL, then the system default class is used. From CWND and its various derived precreateWindow member functions, what window classes are used throughout Framework for different functions.

7, window display and update

After CMYFRAMEWND :: CMYFRAMEWND, the window has been born; the program process is returned to CMYWINAPP :: InitInstance, so call the ShowWindow function order display and call the UpdateWindow function to send a WM_PAINT message. In the SDK program, the message is handled by a window function, and now where the window function is delivered to the window function? It is going to start from cwinapp :: run.

8. Execute CWINAPP :: Run - the live water source of the program life

After executing the CMYWINAPP :: InitInstance function, the program's footsteps are PAPP-> RUN, which is now, now we already know that this will execute the cwinapp :: run function, which is defined in the appcore.cpp. 391 line, below 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, the function is defined in THRDCORE.CPP 456, here I don't Copy. The function is called the PumpMessage function on the 480th line, which is defined in THRDCORE.CPP 810, and the part of the code after the finishing is as follows:

Bool cwinthread :: pumpMessage ()

{

IF (! :: getMessage (& m_msgcur, null, null, null)

{

Return False;

}

// Process this message

IF (M_Msgcur.Message! = WM_KICKIDLE &&! PretranslateMessage (& M_MSGCUR))

{

:: TranslateMessage (& M_MSGCur);

:: DISPATCHMESSAGE (& M_MSGCUR);

}

Return True;

}

This function is the main operation of sending the message from :: DispatchMessage to the window function (CWnd :: DefWindowProc), but the program generally does not provide any window functions, but in AFXEnddeferRegisterClass, the window function has been specified before registering five window classes:

Wndcls.lpfnwndproc = defWindowproc;

Although the window function is specified as the DefWindowProc member function (CWnd :: DefWindowProc), but in fact the news is not to be taken to the point, but a global function called AFXWndProc.

9. Connect the message and the processing function - Message Map mechanism

At this point, the main window has been generated, waiting is a variety of messages, then call the corresponding processing function, however, how to connect the message and handle? The MFC uses the Message Map mechanism (message mapping mechanism), providing two groups of "very convenient interface" to the application to use, I am not clear, I can't explain here, the main usage is: first in class By the declaration of Declare_MESSAGE_MAP () gives a process function, such as:

Class CMYFRAMEWND: PUBLIC CFRAMEWND

{

PUBLIC:

CMYFRAMEWND ();

AFX_MSG void onpaint (); // for wm_paint

AFX_MSG VOID ONWABOUT (// for wm_command (idm_about)

Declare_message_map ()

}

Any position in the corresponding .CPP file (of course, you cannot use Bebin_MASSAGE_MAP () and End_MASSAGE_MAP () and end_message_map () macros, such as:

Begin_MESSAGE_MAP (CMYFRAMEWND, CFRAMEWND)

ON_COMMAND (IDM_ABOUT, ONWABOUT)

ON_WM_PAINT ()

END_MESSAGE_MAP ()

Why after passing through such a macro, the message will automatically flow to the specified function? The mystery lies in the structure of Message Map, and finds "Deep-in-depth MFC" Chapter 3 of the Message Map emulation program to pick it up!

Ok, let's write this. If you just contact MFC, I want to see it, you may have a bit confused, Sorry! I have never written a summary, nothing! I will not take it out of Mr. Hou's "in-depth MFC".

转载请注明原文地址:https://www.9cbs.com/read-28165.html

New Post(0)