c语言mfc与主函数调用函数,MFC框架程序中WinMain函数获取运用程序函数AfxGetApp实现原理...

通过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的指针的原因了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值