05 MFC框架运行大概流程

先明确以下关系:
CWinApp取代了原来Win32下的WinMain
CFrameWnd取代了原来Win32下的WndProc
调试代码如下:

/*
 *HelloMFC.h
 */
#ifndef _HELLO_MFC_
#define _HELLO_MFC_

class CMyApp : public CWinApp{
public:
	virtual BOOL InitInstance();
};

class CMainWindow : public CFrameWnd{
public:
	CMainWindow();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	DECLARE_MESSAGE_MAP()
};

#endif
/*
 *HelloMFC.cpp
 */
#include <afxwin.h>
#include "HelloMFC.h"

CMyApp myApp;

BOOL CMyApp::InitInstance()
{
	//这里虽然在堆区创建的对象,但我们并没有释放,是因为有一个PostNcDestroy函数在
	//窗口销毁时会被调用来销毁这个对象
	m_pMainWnd = new CMainWindow;
	m_pMainWnd->ShowWindow(m_nCmdShow);
	m_pMainWnd->UpdateWindow();

	return TRUE;
}

BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()			  


CMainWindow::CMainWindow()
{
	Create(NULL, TEXT("Hello MFC"));
}

void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
	AfxMessageBox(TEXT("OnLButtonDown"));
}

我们现在如图所示F9下断点,然后F10进入到AfxWinMain中;
在这里插入图片描述
在这里插入图片描述
下面我们将AfxWinMain提出来写点注释:

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);//断言,作用同容错判断
	//在进入这里前已经初始化好了myApp
	int nReturnCode = -1;
	//以下两句,效果差不多,取应用程序实例指针
	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();

	/*
	下面这个函数我们跟进去,发现其作用是初始化类成员变量,所以我们在我们InitInstance
	函数中用的m_nCmdShow成员变量实际在这里面已经初始化好了,关键代码如下:
	CWinApp* pApp = AfxGetApp();
	if (pApp != NULL)
	{
		// Windows specific initialization (not done if no CWinApp)
		pApp->m_hInstance = hInstance;
		hPrevInstance; // Obsolete.
		pApp->m_lpCmdLine = lpCmdLine;
		pApp->m_nCmdShow = nCmdShow;
		pApp->SetCurrentHandles();
	}
	*/
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;

	// 全局初始化,几乎不用,我们不去关注它
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;

	// 这就是我们的核心,就是我们代码中我们的类重写的虚函数,这里就进到我
	//们的InitInstance,这里也就解释了为什么我们的InitInstance()要放回TRUE
	//如果返回FALSE就会销毁窗口,退出程序
	if (!pThread->InitInstance())
	{
		if (pThread->m_pMainWnd != NULL)
		{
			TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
			pThread->m_pMainWnd->DestroyWindow();
		}
		nReturnCode = pThread->ExitInstance();
		goto InitFailure;
	}
	//这里就实现Win32中消息循环,下面把关键代码贴出来
	/*
	
	// acquire and dispatch messages until a WM_QUIT message is received.
	for (;;)
	{
		// 根据空闲状态标志判断线程是否为空闲,如果是就调用OnIdle虚函数,我们可以重写
		//这个虚函数实现我们想要的效果
		while (bIdle &&
			!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
		{
			if (!OnIdle(lIdleCount++))
				bIdle = FALSE; // assume "no idle" state
		}

		// 非空闲状态
		do
		{
			// PumpMessage中有我们熟悉的GetMessage  ThranslateMessage 
			//DispatchMessage
			if (!PumpMessage())
				return ExitInstance();
			if (IsIdleMessage(&(pState->m_msgCur)))
			{
				bIdle = TRUE;
				lIdleCount = 0;
			}

		} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
	}
	*/
	nReturnCode = pThread->Run();

InitFailure:
#ifdef _DEBUG
	// Check for missing AfxLockTempMap calls
	if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
	{
		TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
			AfxGetModuleThreadState()->m_nTempMapLock);
	}
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#endif

	AfxWinTerm();
	return nReturnCode;
}

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/85397763
05