• MFC初始化过程 Anthony


    MFC应用程序不但具有一般的Win32程序的主要入口WinMain函数,还有一个CWinApp派生类的全局实例 theApp

    Mfc程序(EXE)的程序运行过程如下:

    首先是全局构造

    CObject构造函数à CCmdTarget àCWinThreadàCWinAppà theApp构造函数

    然后进入WinMain函数

    WinMainàAfxWinMainàAfxWinInitàtheApp.InitApplicationàtheApp.InitInstance

    接着执行线程过程。

    theApp.Run()

    最后清理

    AfxWinTerm

    在各种初始化函数中,反复调用了AfxGetAppAfxGetThread函数。在WinMain过程中,这两个函数实际上返回同一实例指针theApp。在其它线程中,AfxGetThread返回当前线程对象,这也就是为什么在MFC中新建线程不能使用CreateThreadbeginthread(ex),而要使用AfxBeginThread。后者会创建一个CWinThread的实例。

    AfxGetAppAfxGetThread这两个全局函数是如何得知当前应用程序对象(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返回的正是_afxBaseModuleStatm_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,CWinThreadCWinApp构造函数中对以上成员变量初始化的过程。

    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

  • 相关阅读:
    sqlalchemy 查询姿势总结
    sqlalchemy 常用总结
    rsyslog 移植与配置方案介绍
    软件设计随想录
    C语言面对对象设计模式汇编
    关于linux kernel slab内存管理的一点思考
    linux PMBus总线及设备驱动分析
    Linux x86_64 APIC中断路由机制分析
    单板控制领域模型设计与实现
    Linux mips64r2 PCI中断路由机制分析
  • 原文地址:https://www.cnblogs.com/ahuangliang/p/5309281.html
Copyright © 2020-2023  润新知