1. 程式人生 > >05 MFC框架執行大概流程

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;
}