[MFC]关于Visual studio 2012的AfxGetMainWnd

在MSDN上对AfxGetMainWnd的解释是如果OLE服务器有一个对象在某个容器中激活且这个容器也是激活的(有点拗口),这个函数返回容纳激活文档的框架窗口对象。如果没有本地激活对象或者应用程序不是一个OLE的服务器,这个函数简单返回应用对象CWinApplication的m_pMainWnd。如果AfxGetMainWnd在主线程中调用得到的是应用程序的主窗口,如果是在第二个线程中调用的得到的是和这个线程关联的主窗口。

实际上并非这么简单,在一个动态加载的MFC常规DLL内部函数中调用这个函数可能会得到不同的结果,如果DLL中没有创建任何窗口,得到的会是主程序的主窗口,但是如果有创建窗口比如弹出一个模式对话框,在对话框的某个函数中调用AfxGetMainWnd就会得到这个对话框的窗口对象。具体的还是来看看这个函数是如何实现的吧。

_AFXWIN_INLINE CWnd* AFXAPI AfxGetMainWnd()
    { CWinThread* pThread = AfxGetThread();
        return pThread != NULL ? pThread->GetMainWnd() : NULL; }

CWinThread* AFXAPI AfxGetThread()
{
    // check for current thread in module thread state
    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
    CWinThread* pThread = pState->m_pCurrentWinThread;
    return pThread;
}

AFX_MODULE_THREAD_STATE* AFXAPI AfxGetModuleThreadState()
{
    AFX_MODULE_THREAD_STATE* pResult=AfxGetModuleState()->m_thread.GetData();
    ENSURE(pResult != NULL);
    return pResult;
}

CWnd* CWinThread::GetMainWnd()
{
    if (m_pActiveWnd != NULL)
        return m_pActiveWnd;    // probably in-place active

    // when not inplace active, just return main window
    if (m_pMainWnd != NULL)
        return m_pMainWnd;

    return CWnd::GetActiveWindow();
}

这里首先是取得当前的CWinThread对象,它是AFX_MODULE_THREAD_STATE的成员变量m_pCurrentWinThread,而AFX_MODULE_THREAD_STATE又是通过AfxGetModuleThreadState()函数得到的,它调用了AfxGetModuleState()函数,而说到AfxGetModuleState()我们必须讲到AFX_MANAGE_STATE(AfxGetStaticModuleState()),在DLL中导出一个函数时,这个函数的第一句我们一般都会调用AFX_MANAGE_STATE(AfxGetStaticModuleState()),它的作用就是切换模块相关的状态对象,这个状态对象包含了当前线程

CThreadLocal<AFX_MODULE_THREAD_STATE>、当前应用CWinApp等信息,这些信息都是保存在线程TLS中的。因此在进入DLL中我们可能使用AFX_MANAGE_STATE(AfxGetStaticModuleState())切换了模块状态,自然得到和主程序模块不同的CWinThread对象。

再来看CWinThread::GetMainWnd(),这和MSDN的解释差不多,如果有OLE激活对象返回激活窗口,没有就返回线程对象的主窗口,如果这个还为空,就获得当前应用程序的当前激活窗口,这个就实在说不定是那个窗口了,我们前面例子中说的DLL弹出模式对话框,自然就会得到这个模式对话框的窗口对象了,所以如果我们要在DLL中使用主程序框架窗口对象的化最好是从参数传入保存在DLL中吧。

关于MODULE STATE有很多的文章介绍了,比如这篇:http://hi.baidu.com/rootlife/blog/item/2f37e354ad8cdc5bd10906be.html,讲得还是比较清楚的。

原文地址:https://www.cnblogs.com/duanshuiliu/p/2629678.html