• AfxGetApp 解剖


    MFC中有不少的全局函数,方便在不同对象中获取不同的内容或创建不同的对象。主要全局函数有:

    AfxWinInit()  AfxBeginThread()  AfxEndThread()  AfxFormatString1()  AfxFormatString2()

    AfxMessageBox()  AfxOutPutDebugString()  AfxGetApp()  AfxGetMainWnd()  AfxGetInstance()

    AfxRegisterClass()

    这些函数从名称上可见豹斑(功能)。

    本文是学习深入浅出MFC后的第一个笔记,解析AfxGetApp()函数

    在AFXWIN.H中是这么定义的:

         CWinApp* AFXAPI AfxGetApp();

    那么AfxGetApp是怎么获取当前App的CWinApp类指针呢?

    AfxGetApp是一个内联函数,其实现如下(在AFXWIN1.INL):

         _AFXWIN_INLINE CWinApp *AFXAPI AfxGetApp()

                  { return afxCurrentWinApp;}

    而afxCurrentWinApp是一个宏,定义在AFXWIN.H中:

         #define afxCurrentWinApp    AfxGetModuleState()->m_pCurrentWinApp

    AfxGetModuleState返回的是一个:AFX_MODULE_STATE类的指针(AFXSTAT_.H):

         AFX_MODULE_STATE* AFXAPI AfxGetModuleState();

    在AFX_MODULE_STATE类中定义了如下的成员变量:

          CWinApp* m_pCurrentWinApp;
          HINSTANCE m_hCurrentInstanceHandle;
          HINSTANCE m_hCurrentResourceHandle;
          LPCTSTR m_lpszCurrentAppName;
          BYTE m_bDLL;    // TRUE if module is a DLL, FALSE if it is an EXE
          BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not
          BYTE m_bReserved[2]; // padding
          DWORD m_fRegisteredClasses; // flags for registered window classes

    转了这么多,自己都迷糊了,AFX_MODULE_STATE什么时候被初始化了,AfxGetModuleState又都干了些什么,不然怎么可能调用AfxGetModuleState()->m_pCurrentWinApp获得当前窗口的App呢?最有可能被初始化的地方是在构造函数之中。而我们获取的是App类型的指针,而App是继承之CWinApp类的。因此下面我们看看CWinApp构造函数做了些什么工作:

    CWinApp::CWinApp(LPCTSTR lpszAppName)
    {
     if (lpszAppName != NULL)
      m_pszAppName = _tcsdup(lpszAppName);
     else
      m_pszAppName = NULL;

     // initialize CWinThread state
     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();  //看,声明了一个指针
     AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
     ASSERT(AfxGetThread() == NULL);
     pThreadState->m_pCurrentWinThread = this;
     ASSERT(AfxGetThread() == this);
     m_hThread = ::GetCurrentThread();
     m_nThreadID = ::GetCurrentThreadId();

     // initialize CWinApp state
     ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
     pModuleState->m_pCurrentWinApp = this;    //又将this指针传给了m_pCurrentWinApp,哦呵呵……
     ASSERT(AfxGetApp() == this);

     // in non-running state until WinMain
     m_hInstance = NULL;
     m_pszHelpFilePath = NULL;
     m_pszProfileName = NULL;
     m_pszRegistryKey = NULL;
     m_pszExeName = NULL;
     m_pRecentFileList = NULL;
     m_pDocManager = NULL;
     m_atomApp = m_atomSystemTopic = NULL;
     m_lpCmdLine = NULL;
     m_pCmdInfo = NULL;

     // initialize wait cursor state
     m_nWaitCursorCount = 0;
     m_hcurWaitCursorRestore = NULL;

     // initialize current printer state
     m_hDevMode = NULL;
     m_hDevNames = NULL;
     m_nNumPreviewPages = 0;     // not specified (defaults to 1)

     // initialize DAO state
     m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

     // other initialization
     m_bHelpMode = FALSE;
     m_nSafetyPoolSize = 512;        // default size
    }

     CWinApp的构造函数申明了一个AFX_MODULE_STATE类的指针,里面通过this指针填充了AFX_MODULE_STATE指针中的部分内容。下面我们再来看看CWinApp中的_AFX_CMDTARGET_GETSTATE()又是什么:

    #ifdef _AFXDLL
    #define _AFX_CMDTARGET_GETSTATE() (m_pModuleState)
    #else
    #define _AFX_CMDTARGET_GETSTATE() (AfxGetModuleState())
    #endif

    如果此处不考虑_AFXDLL情况,那么在CWinApp中将直接调用AfxGetModuleState()函数,瞧,又是AfxGetModuleState()函数。于是我们可以这么考虑,在内存中有一份全局或静态的AFX_MODULE_STATE类,AfxGetModuleState只是返回这一份全局指针(猜测)。在CWinApp中通过对AFX_MODULE_STATE中的m_pCurrentWinApp填充this指针后,将使全局的AFX_MODULE_STATE保存当前WinApp中的CWinApp指针。

    其中的特殊指之处在于使用了this指针,当基类被继承后,this指针将代表继承类的this指针。因此任何一个CWinApp被继承后,如继承类为CMyWinApp,那么CMyWinApp的地址将被存在AFX_MODULE_STATE的全局变量之中,当使用AfxGetModuleState()函数获取AFX_MODULE_STATE时便可获取当前系统的CMyWinApp指针m_pCurrentWinApp。

    下面总结一下:

        当前指针通过AfxGetApp()通过返回afxCurrentWinApp,而afxCurrentWinApp宏为AfxGetModule()->m_pCurrentWinApp,即AfxGetApp()通过返回AfxGetModule()->m_pCurrentWinApp获取当前App的指针,而AfxGetModule()->m_pCurrentWinApp指针通过CWinAPP构造函数通过this指针设置,而this指针恰恰就是当前App的指针(this将转换为继承类的指针)。

        因此也就解释了不管当前App被怎么继承,AfxGetModule()->m_pCurrentWinApp始终能够获取当前App的指针的原因了。

     
    /*
    *
    * Copyright (c) 2011 Ubunoon.
    * All rights reserved.
    *
    * email: netubu#gmail.com replace '#' to '@'
    * http://www.cnblogs.com/ubunoon
    * 欢迎来邮件定制各类验证码识别,条码识别,图像处理等软件
    * 推荐不错的珍珠饰品,欢迎订购 * 宜臣珍珠(淡水好珍珠) */
  • 相关阅读:
    7月17日
    7月16日学习记录
    7月15日学习记录
    git 学习
    投稿相关
    ubuntu16.04 安装以及要做的事情
    python学习使用
    图像相关
    不识别移动硬盘
    深度学习
  • 原文地址:https://www.cnblogs.com/ubunoon/p/2058941.html
Copyright © 2020-2023  润新知