您的位置:首页 > 其它

MFC初始化过程

2004-07-17 16:00 253 查看
MFC应用程序不但具有一般的Win32程序的主要入口WinMain函数,还有一个CWinApp派生类的全局实例 theApp。 Mfc程序(EXE)的程序运行过程如下: 首先是全局构造 CObject构造函数à CCmdTarget àCWinThreadàCWinAppà theApp构造函数 然后进入WinMain函数 WinMainàAfxWinMainàAfxWinInitàtheApp.InitApplicationàtheApp.InitInstance 接着执行线程过程。 theApp.Run() 最后清理 AfxWinTerm 在各种初始化函数中,反复调用了AfxGetApp和AfxGetThread函数。在WinMain过程中,这两个函数实际上返回同一实例指针theApp。在其它线程中,AfxGetThread返回当前线程对象,这也就是为什么在MFC中新建线程不能使用CreateThread和beginthread(ex),而要使用AfxBeginThread。后者会创建一个CWinThread的实例。 AfxGetApp和AfxGetThread这两个全局函数是如何得知当前应用程序对象(theApp)和当前线程对象呢?在MFC中,有一个AFX_MODULE_STATE全局实例_afxBaseModuleState (实际代码中_afxBaseModuleState是_AFX_BASE_MODULE_STATE的实例,而_AFX_BASE_MODULE_STAT只是前者的一个包装,直接继承AFX_MODULE_STATE类,为了简化关系,这里把它们等同起来)。它以下划线开始,所以被认为是内部使用,不能直接操作。直接操作它的是函数AfxGetAppModuleState。 AFX_MODULE_STATE的定义相当复杂,很多是为其它部件保留的与模块(EXE)相关状态参数(所以命名为MODULE_STATE)。下面只列出与初始化过程相关的部分: 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; 14|. 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]; // padding 19|. // define thread local portions of module state 20|. CThreadLocal<AFX_MODULE_THREAD_STATE> m_thread; 21|. }; 函数AfxGetApp返回的正是_afxBaseModuleStat中m_pCurrentWinApp 成员。 _AFXDLL部分与MFC Regular Dll相关,暂不讨论。而AFX_MODULE_STATE秉承MFC的一贯原则,构造函数只保证了数据结构的有效性,而未对数据内容做出任何保证。因此,_ afxBaseModuleState构造后,其内容还是未知的。仅从成员可以知道,该类表示CWinApp所在模块(EXE)。而它的成员m_thread则表达了该模块中线程的状态(其实际类型为AFX_MODULE_THREAD_STATE)。该类的相关定义如下: 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|. }; AfxGetThread函数正是由_afxBaseModuleState取得取了AFX_MODULE_THREAD_STATE中的m_pCurrentThread成员。 下面是CCmdTarget,CWinThread和CWinApp构造函数中对以上成员变量初始化的过程。 CCmdTarget 无 CWinThread 32|. CWinThread::CWinThread() 33|. { 34|. … 35|. CommonConstruct(); 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::CWinApp(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|. } 再看AfxWinInit函数 68|. BOOL AFXAPI AfxWinInit(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|. } 这里不得不说明一下AfxGetThreadState函数。它也是一个全局变量的包装函数,这个全局变量是_afxThreadState,它是_AFX_THREAD_STATE的实例,在单线程程序中这个实例的意义不大,但在多线程条件下,它可是连接AFX_MODULE_STATE和当前线程的一个桥梁。相关定义如下: 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|. }; 因为线程与模块的对应关系是多对一的,一个模块可以有多个线程,但一个线程只能有一个模块(不是其线程入口所在的模块,而是拥有它的模块) 其中m_pModuleState的初始化过程在CWinThread的线程入口过程中: 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_pModuleState = pStartup->pThreadState->m_pModuleState; 118|. … 119|. } 120|. … 121|. } 也就是说在不起动新线程的Mfc程序中,m_pModuleState不会被赋值。其默认值为0。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息