The MFC application not only has a general Win32 program's main entrance Winmain function, but also a global instance of CWINAPP derived class.
The program operation process of the MFC program (EXE) is as follows:
First of all, global construction
COBJECT constructor à ccmdtarget àcwinthreadàcwinappà theApp constructor
Then enter the WinMain function
Winmainàafxwinmainàafxwininitàtheapp.initApplicationàtheapp.initInstance
The thread process is then executed.
THEAPP.RUN ()
Final cleanup
AFXWINTERM
In various initialization functions, the AFXGetApp and AFXGetThread functions are repeated repeatedly. In the WinMain process, these two functions actually return the same instance pointer theApp. In other threads, AFXGetThread returns the current thread object, which is why the newly built thread in the MFC cannot use CreateTHRead and BeginThread (EX), and use AFXBEGINTHREAD. The latter creates an instance of CWINTHREAD.
AFXGETAPP and AFXGETTHREAD These two global functions do you know that the current application object (THEAPP) and current thread objects? In MFC, there is an AFX_Module_State Global Instance_AFXBaseModuLestate
(AfxbaseModuleState is _afx_basemodulestate is an instance of _afx_base_module_state, and only a packaging of the former, directly inheriting the AFX_Module_State class, in order to simplify the relationship, here is equivalent to it). It begins with the underscore, so it is considered to be internal use and cannot be operated directly. Direct operation is a function AFXGetAppModuleState.
AFX_MODULE_STATE definition is quite complicated, many of which are reserved for other components (So Module_State). Only parts related to the initialization process are listed below:
1 |. Class AFX_MODULE_STATE: PUBLIC CNOTRACKOBJECT
2 |. {
3 |. Public:
4 |. #Ifdef _afxdll
5 |. AFX_MODULE_STATE (Bool BDLL, WNDPROC PFNAFXWNDPROC, DWORD DWVERSION,
6 |. BOOL BSYSTEM = FALSE);
7 |. #Else
8 |. EXPLICIT AFX_MODULE_STATE (BOOL BDLL);
9 | #ENDIF
10 |. ~ AFX_MODULE_STATE ();
11 |.
12 |. Cwinapp * m_pcurrentwinapp;
13 |. Hinstance m_hcurrentinstancehandle;
Hinstance M_HcurrentResourceHandle;
15 |. LPCTSTR M_LPSZCURRENTAPPNAME;
16 |. Byte M_Bdll; // True IF Module Is A DLL, FALSE IF IT IS AN EXE
17 |. Byte M_Bsystem; // True IF Module Is A "System" Module, False IF NOT
18 |. Byte M_Breserved [2]; // Padding19 |. // Define Thread Local Portions of Module State
20 |. Cthreadlocal
21 |.
Function AFXGetApp returns to _afxbasemoduLestat in M_PCurrentWinapp member.
The _AFXDLL section is related to the MFC Regular DLL, no discussion. AFX_MODULE_STATE adheres to the consistent principles of the MFC, and the constructor only guarantees the validity of the data structure without any guarantee of the data content. Therefore, after _ AFXBaseModuleState constructs, its content is still unknown. This class represents the module (Exe) where CWINAPP is located only from a member. Its member M_Thread expresses the state of the thread in the module (which actually type AFX_MODULE_THREAD_STATE). The relevant definition of this class is as follows:
22 |. Class AFX_MODULE_THREAD_STATE: PUBLIC CNOTRACKOBJECT
23 |. {
24 |. Public:
25 |. AFX_MODULE_THREAD_STATE ();
26 |. Virtual ~ AFX_MODULE_THREAD_STATE ();
27 |.
28 |. // Current CWINTHREAD POINTER
29 |. Cwinthread * m_pcurrentwinthread;
30 |.
31 |.
The AFXGETTHREAD function is from _afxbasemoduleState to get the M_PCurrentThread member in AFX_MODULE_THREAD_STATE.
Below is the process of initialization of the above member variables in CCMDTARGET, CWINTHREAD, and CWINAPP constructors.
CCMDTARGET
no
CWINTHREAD
32 |. Cwinthread :: cwinsread ()
33 |. {
34 |. ...
35 |. ComMMonconstruct ();
36 |.
37 |.
38 |. Void cwinthread :: CommonConstruct ()
39 |. {
40 |. ...
41 |. _AFX_THREAD_STATE * PSTATE = AFXGETTHREADSTATE ();
42 |. // Initialize Message Pump
43 |. #Ifdef _debug
44 |. PState-> m_ndisablepumpcount = 0;
45 | #ENDIF
46 |. PState-> m_msgcur.Message = WM_NULL;
47 |. PState-> m_nmsglast = wm_null;
48 |. ...
49 |.
CWINAPP
50 |. CWINAPP :: CWINAP (LPCTSTR LPSZAPPNAME)
51 |. {
52 |. ...
53 |. // Initialize CWINTHREAD State
54 |. AFX_MODULE_STATE * PModuleState = _AFX_CMDTARGET_GETSTATE ();
55 |. AFX_MODULE_THREAD_STATE * PTHREADSTATE = PModuleState-> m_thread;
56 |. Assert (AFXGetThread () == null); 57 |. Pthreadstate-> m_pcurrentwinthread = this;
58 |. Assert (AFXGetThread () == this);
59 |. M_hthread = :: getcurrentthread ();
60 |. M_nthreadid = :: getCurrentThreadId ();
61 |.
62 |. // Initialize CWINAPP State
63 |. Assert (AfxCurrentwinapp == null); // Only One CWINAPP Object Please
64 |. PModuleState-> m_pcurrentwinapp = this;
65 |. Assert (AFXGetApp () == this);
66 |. ...
67 |.
Look at the AFXWININIT function
68 |. Bool AFXAPI AFXININIT (Hinstance Hinstance, Hinstance Hprevinstance,
69 |. Lptstr lpcmdline, int ncmdshow)
70 |. {
71 |. ...
72 |. // set resource Handles
73 |. AFX_MODULE_STATE * PModuleState = AFXGETMODULESTATE ();
74 |. PModuleState-> M_HcurrentInstanceHandle = Hinstance;
75 |. PModuleState-> M_HcurrentResourceHandle = Hinstance;
76 |.
77 |. // Fill in The Initial State for the Application
78 |. CWINAPP * PAPP = AFXGetApp ();
79 |. IF (PAPP! = NULL)
80 |. {
81 |. // Windows Specific Initialization (not Done if no cwinapp)
82 |. PAPP-> M_HINSTANCE = Hinstance;
83 |. HPREVINSTANCE; // Obsolete.
84 | PAPP-> M_LPCMDLINE = LPCMDLINE
85 |. PAPP-> m_ncmdshow = ncmdshow;
86 |. PAPP-> setCurrentHandles ();
87 |.
88 |.
89 |. // Initialize Thread Specific Data (for Main Thread)
90 |. If (! AfxContextISDLL)
91 |. Afxinitthread ();
92 |
93 |. ...
94 |.
95 |. Return True;
96 |.
Here, I have to explain the AFXGetThreadState function. It is also a package function of global variables. This global variable is _afxthreadState, which is _afx_thread_state instance, this instance is not large in single-threaded program, but under multithreading conditions, it is connected to AFX_Module_State and current threads A bridge. The relevant definition is as follows: 97 |. Class _afx_thread_state: Public CNOTRACKOBJECT
98 |. {
99 |. Public:
100 |. _AFX_THREAD_STATE ();
101 |. Virtual ~ _afx_thread_state ();
102 |
103 |. // Override for m_pmodulestate in _AFX_APP_STATE
104 |. AFX_MODULE_STATE * M_PMODULESTATE;
105 |. AFX_MODULE_STATE * M_PPREVMODULESTATE;
106 |.
Because the correspondence between the thread and module is multi-object, a module can have multiple threads, but a thread can only have one module (not the module where its thread entrance is located, but has its module)
Where the initialization process of M_PModuleState is in the process of CwinThread's thread inlet:
107 |. Uint apientry _afxthreadENTRY (Void * PPARAM)
108 |. {
109 |. _AFX_THREAD_STARTUP * PSTARTUP = (_afx_thread_startup *) PPARAM;
110 |. ...
111 |. Cwinthread * pthread = pstartup-> pthread;
112 |. CWND thREADWND;
113 |. TRY
114 |. {
115 |. // Inherit Parent's Module State
116 |. _AFX_THREAD_STATE * pthreadState = AFXGETTHREADSTATE ();
117 |. Pthreadstate-> m_pmodules = pstartup-> pthreadstate-> m_pmodulestate;
118 |. ...
119 |.
120 |. ...
121 |.
That is to say, m_pmoduleState will not be assigned in the MFC program that does not start a new thread. Its default is 0.