MFC initialization process

zhaozj2021-02-16  63

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 M_THREAD;

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.

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

New Post(0)