探索MFC全局函数-AfxGetApp()

MFC做到了从C/SDK开发Win32程序到利用OOP思想开发Win32程序的过渡,它的封装完美体现的C++的三大特性,提高了Win32程序的开发效率,但它的封装也使得本来清晰的脉络,变得晦涩起来。

今天我们探究被微软冠以Afx前缀的全局函数AfxGetApp(),这个函数作用是获取当前应用进程的指针,确切的说是获取由CWinApp派生出类的对象,相信懂MFC的人都熟知,但作为全局函数的它是如何在基类获取的派生类对象的?

现在我们开始一步一步揭开AfxGetApp()神秘面纱~

(1)AfxGetApp()

函数的声明在AFXWIN.H,定义在AFXWIN1.INL

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
 { return afxCurrentWinApp; }

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

#define afxCurrentWinApp    AfxGetModuleState()->m_pCurrentWinApp

 

(2)AfxGetModuleState()

其返回值为AFX_MODULE_STATE类指针,声明在AFXSTAT_.H

AFX_MODULE_STATE* AFXAPI AfxGetModuleState();

定义在AFXSTATE.CPP

AFX_MODULE_STATE* AFXAPI AfxGetModuleState()
{
 _AFX_THREAD_STATE* pState = _afxThreadState;
 AFX_MODULE_STATE* pResult;
 if (pState->m_pModuleState != NULL)
 {
  // thread state‘s module state serves as override
  pResult = pState->m_pModuleState;
 }
 else
 {
  // otherwise, use global app state
  pResult = _afxBaseModuleState.GetData();
 }
 ASSERT(pResult != NULL);
 return pResult;
}

AfxGetModuleState函数的定义中,可以看出函数返回的是pState->m_pModuleState或者_afxBaseModuleState.GetData();

 

(3)_afxThreadState,和_afxBaseModuleState都是全局变量,上文中的pState就是_afxThreadState.

_afxThreadState声明在AFXSTAT_.H,

class _AFX_THREAD_STATE : public CNoTrackObject
{
public:
	_AFX_THREAD_STATE();
	virtual ~_AFX_THREAD_STATE();

	// override for m_pModuleState in _AFX_APP_STATE
	AFX_MODULE_STATE* m_pModuleState;//上面的pState->m_pModuleState就是这个值,存储模块状态
	AFX_MODULE_STATE* m_pPrevModuleState;

	// memory safety pool for temp maps
	void* m_pSafetyPoolBuffer;    // current buffer

	// thread local exception context
	AFX_EXCEPTION_CONTEXT m_exceptionContext;

	// CWnd create, gray dialog hook, and other hook data
	CWnd* m_pWndInit;
	CWnd* m_pAlternateWndInit;      // special case commdlg hooking
	DWORD m_dwPropStyle;
	DWORD m_dwPropExStyle;
	HWND m_hWndInit;
	BOOL m_bDlgCreate;
	HHOOK m_hHookOldCbtFilter;
	HHOOK m_hHookOldMsgFilter;

	// other CWnd modal data
	MSG m_lastSentMsg;              // see CWnd::WindowProc
	HWND m_hTrackingWindow;         // see CWnd::TrackPopupMenu
	HMENU m_hTrackingMenu;
	TCHAR m_szTempClassName[96];    // see AfxRegisterWndClass
	HWND m_hLockoutNotifyWindow;    // see CWnd::OnCommand
	BOOL m_bInMsgFilter;

	// other framework modal data
	CView* m_pRoutingView;          // see CCmdTarget::GetRoutingView
	CFrameWnd* m_pRoutingFrame;     // see CCmdTarget::GetRoutingFrame

	// MFC/DB thread-local data
	BOOL m_bWaitForDataSource;

	// common controls thread state
	CToolTipCtrl* m_pToolTip;
	CWnd* m_pLastHit;       // last window to own tooltip
	int m_nLastHit;         // last hittest code
	TOOLINFO m_lastInfo;    // last TOOLINFO structure
	int m_nLastStatus;      // last flyby status message
	CControlBar* m_pLastStatus; // last flyby status control bar

	// OLE control thread-local data
	CWnd* m_pWndPark;       // "parking space" window
	long m_nCtrlRef;        // reference count on parking window
	BOOL m_bNeedTerm;       // TRUE if OleUninitialize needs to be called
};

EXTERN_THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)//_afxThreadState全局变量声明

定义在AFXSTATE.CPP

THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)//_afxThreadState全局变量定义


_afxBaseModuleState声明定义在AFXSTATE.CPP

class _AFX_BASE_MODULE_STATE : public AFX_MODULE_STATE
{
public:
#ifdef _AFXDLL
	_AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcBase, _MFC_VER)
#else
	_AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE)
#endif
		{ }
};

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)//_afxBaseModuleState全局变量声明定义


(4)AFX_MODULE_STATE类

我们看看AFX_MODULE_STATE类中有什么?其实它包含了AfxGetApp要返回的CWinApp。

// AFX_MODULE_STATE (global data for a module)
class AFX_MODULE_STATE : public CNoTrackObject
{
public:
#ifdef _AFXDLL
	AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion);
	AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,
		BOOL bSystem);
#else
	AFX_MODULE_STATE(BOOL bDLL);
#endif
	~AFX_MODULE_STATE();

	CWinApp* m_pCurrentWinApp;//转了好几次,终于见到庐山真面目了,没错,这就是我们从AfxGetApp获取的值	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

	// runtime class data
#ifdef _AFXDLL
	CRuntimeClass* m_pClassInit;
#endif
	CTypedSimpleList<CRuntimeClass*> m_classList;

	// OLE object factories
#ifndef _AFX_NO_OLE_SUPPORT
#ifdef _AFXDLL
	COleObjectFactory* m_pFactoryInit;
#endif
	CTypedSimpleList<COleObjectFactory*> m_factoryList;
#endif
	// number of locked OLE objects
	long m_nObjectCount;
	BOOL m_bUserCtrl;

	// AfxRegisterClass and AfxRegisterWndClass data
	TCHAR m_szUnregisterList[4096];
#ifdef _AFXDLL
	WNDPROC m_pfnAfxWndProc;
	DWORD m_dwVersion;  // version that module linked against
#endif

	// variables related to a given process in a module
	//  (used to be AFX_MODULE_PROCESS_STATE)
#ifdef _AFX_OLD_EXCEPTIONS
	// exceptions
	AFX_TERM_PROC m_pfnTerminate;
#endif
	void (PASCAL *m_pfnFilterToolTipMessage)(MSG*, CWnd*);

#ifdef _AFXDLL
	// CDynLinkLibrary objects (for resource chain)
	CTypedSimpleList<CDynLinkLibrary*> m_libraryList;

	// special case for MFCxxLOC.DLL (localized MFC resources)
	HINSTANCE m_appLangDLL;
#endif

#ifndef _AFX_NO_OCC_SUPPORT
	// OLE control container manager
	COccManager* m_pOccManager;
	// locked OLE controls
	CTypedSimpleList<COleControlLock*> m_lockList;
#endif

#ifndef _AFX_NO_DAO_SUPPORT
	_AFX_DAO_STATE* m_pDaoState;
#endif

#ifndef _AFX_NO_OLE_SUPPORT
	// Type library caches
	CTypeLibCache m_typeLibCache;
	CTypeLibCacheMap* m_pTypeLibCacheMap;
#endif

	// define thread local portions of module state
	THREAD_LOCAL(AFX_MODULE_THREAD_STATE, m_thread)
};


(5)CWinApp构造函数

CWinApp* m_pCurrentWinApp;已经找到,那么它是在被赋值的呢,就是在CWinApp的构造函数,当MFC程序中CWinApp所派生的CMYWinApp(举例)类对象theApp(全局对象)被构造时,就会触动CWinApp构造函数,此时CWinApp构造函数中的this就指的是theApp,然后将this保存到m_pCurrentWinApp中。

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;//此处就是将theApp的地址保存到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
}


到目前估计大家也明白了AfxGetApp()函数实现,欢迎探讨

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。