1,手动编写MFC
下面就是我们要手写MFC的代码,

class CMyApp:public CWinApp
{
public:
	virtual BOOL InitInstance();
};
class CMainWnd:public CFrameWnd
{
public:
	CMainWnd();
};
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
//创建窗口
	m_pMainWnd=new CMainWnd;
	m_pMainWnd->ShowWindow(m_nCmdShow);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}
CMainWnd::CMainWnd()
{
	Create(NULL,TEXT("Hell MFC"));
}

MFC程序的入口是WinMain而我们并没有提供入口而上面这段程序却能创建出一个窗口出来。
当我们没有提供入口的时候,实际上MFC已经帮我准备了入口,对于这段程序运行在vc6.0上,按下F10即可进入到函数入口:
MFC六大核心机制之一:MFC程序的初始化流程
进入到AfxWinMain函数中:
MFC六大核心机制之一:MFC程序的初始化流程
这个就是MFC为我们准备好的入口,实际上已经做了很多的事情。
这里面有几个重要的函数:AfxGetThread,pThread->InitInstance,pThread->Run()
在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是在什么时候进行的初始化呢?最可能就是在theApp初始化的时候,
theApp继承了CWinApp,所以CWinApp的构造函数会执行。下面就是CWinApp构造函数的源代码,创建了2个指针:AFX_MODULE_STATE和AFX_MODULE_THREAD_STATE分别指向了CWinApp和它的父类。

CWinApp的构造函数
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
	if (lpszAppName != NULL)
		m_pszAppName = _tcsdup(lpszAppName);
	else
		m_pszAppName = NULL;

	// initialize CWinThread state   创建了一个AFX_MODULE_STATE指针
	AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
创建了一个AFX_MODULE_THREAD_STATE的指针
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;
	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
}

有一个知识点一定要知道:
在main函数中没有写任何程序,但是仍然会打印Hello出来

class BB
{
	void BB()
	{
		printf("Hello");
	}
};
BB b;
int main(int argc, char* argv[])
{
}

所以CMyApp theApp;会先于程序入口执行,初始化的时候会写填写好
AFX_MODULE_STATE和AFX_MODULE_THREAD_STATE这两个指针,于是我们可以考虑在内存中有一份AFX_MODULE_STATE和AFX_MODULE_THREAD_STATE的全局变量,不然AfxGetApp怎么得到这些数据。

然后我们进入到pThread->InitInstance函数中就得到下面的函数了,为什么会得到下面的函数呢,首先InitInstance是一个虚函数,被我们写的子类重写了,而pThread是Cwinapp的父类,cwinapp是Cmyapp的父类,虚函数被覆盖了,所以调用的是cmyapp的InitInstance函数。
MFC六大核心机制之一:MFC程序的初始化流程
然后我们进入到pThread->Run()中,再进入到CWinThread::Run()中,就发现了我们非常熟悉的东西,消息循环。
MFC六大核心机制之一:MFC程序的初始化流程
MFC六大核心机制之一:MFC程序的初始化流程

相关文章: