MFC的入口函数(main函数)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/daizhiyan1/article/details/83013126

其实想看MFC的main函数,打开任一用MFC开发的App,设一个断点,然后查看调用堆栈。拉到最底部(即最先开始调用的东西)

在appmodul.cpp中可以看到如下代码:

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "sal.h"

/////////////////////////////////////////////////////////////////////////////
// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

可以看到,转入了AfxWinMain,继续跟

在winmain.cpp中可以看到

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "sal.h"


/////////////////////////////////////////////////////////////////////////////
// Standard WinMain implementation
//  Can be replaced as long as 'AfxWinInit' is called first

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);

	int nReturnCode = -1;
	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();

	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;

	// App global initializations (rare)
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;

	// Perform specific initializations
	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;
	}
	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;
}

/////////////////////////////////////////////////////////////////////////////

可以看到,在这里面先对窗口进行了初始化,再对线程和app对象进行了初始化,即依次对三个函数的调用:

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pThread->InitInstance();

一个个看:

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow):

在appinit.cpp中:

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#ifdef _AFXDLL
#include "afxglobals.h"
#endif
#include "sal.h"

/////////////////////////////////////////////////////////////////////////////

BOOL AFXAPI AfxWinInit(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
	_In_z_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);

	// handle critical errors and avoid Windows message boxes
	SetErrorMode(SetErrorMode(0) |
		SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);

	// set resource handles
	AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
	pModuleState->m_hCurrentInstanceHandle = hInstance;
	pModuleState->m_hCurrentResourceHandle = hInstance;

	// fill in the initial state for the application
	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();
	}

	// initialize thread specific data (for main thread)
	if (!afxContextIsDLL)
		AfxInitThread();

	return TRUE;
}

pApp->InitApplication():

在appcore.cpp中:

BOOL CWinApp::InitApplication()
{
	if (CDocManager::pStaticDocManager != NULL)
	{
		if (m_pDocManager == NULL)
			m_pDocManager = CDocManager::pStaticDocManager;
		CDocManager::pStaticDocManager = NULL;
	}

	if (m_pDocManager != NULL)
		m_pDocManager->AddDocTemplate(NULL);
	else
		CDocManager::bStaticInit = FALSE;

	LoadSysPolicies();

	return TRUE;
}

pThread->InitInstance():

在thrdcore.cpp中:

/////////////////////////////////////////////////////////////////////////////
// CWinThread default implementation

BOOL CWinThread::InitInstance()
{
	ASSERT_VALID(this);

	return FALSE;   // by default don't enter run loop
}

CWinThread::Run():

// main running routine until thread exits
int CWinThread::Run()
{
	ASSERT_VALID(this);
	_AFX_THREAD_STATE* pState = AfxGetThreadState();

	// for tracking the idle time state
	BOOL bIdle = TRUE;
	LONG lIdleCount = 0;

	// acquire and dispatch messages until a WM_QUIT message is received.
	for (;;)
	{
		// phase1: check to see if we can do idle work
		while (bIdle &&
			!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
		{
			// call OnIdle while in bIdle state
			if (!OnIdle(lIdleCount++))
				bIdle = FALSE; // assume "no idle" state
		}

		// phase2: pump messages while available
		do
		{
			// pump message, but quit on WM_QUIT
			if (!PumpMessage())
				return ExitInstance();

			// reset "no idle" state after pumping "normal" message
			//if (IsIdleMessage(&m_msgCur))
			if (IsIdleMessage(&(pState->m_msgCur)))
			{
				bIdle = TRUE;
				lIdleCount = 0;
			}

		} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
	}
}

可以看到在CWinThread::Run()进入了消息循环,直到收到WM_QUIT消息,退出消息循环。

最后看看AfxWinTerm():

在appterm.cpp中:

void AFXAPI AfxWinTerm(void)
{	
	AfxUnregisterWndClasses();
	// cleanup OLE if required
	CWinThread* pThread = AfxGetApp();
	if (pThread != NULL && pThread->m_lpfnOleTermOrFreeLib != NULL)
		(*pThread->m_lpfnOleTermOrFreeLib)(TRUE, FALSE);

	// cleanup thread local tooltip window
	AFX_MODULE_THREAD_STATE* pModuleThreadState = AfxGetModuleThreadState();
	if (pModuleThreadState->m_pToolTip != NULL)
	{
		if (pModuleThreadState->m_pToolTip->DestroyToolTipCtrl())
			pModuleThreadState->m_pToolTip = NULL;
	}

	_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
	if (!afxContextIsDLL)
	{
		// unhook windows hooks
		if (pThreadState->m_hHookOldMsgFilter != NULL)
		{
			::UnhookWindowsHookEx(pThreadState->m_hHookOldMsgFilter);
			pThreadState->m_hHookOldMsgFilter = NULL;
		}
		if (pThreadState->m_hHookOldCbtFilter != NULL)
		{
			::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
			pThreadState->m_hHookOldCbtFilter = NULL;
		}
	}
    // We used to suppress all exceptions here. But that's the wrong thing
    // to do. If this process crashes, we should allow Windows to crash
    // the process and invoke watson.
}

Remark:

MFC的代码是可以一步步跟的,一步步看。

大致的基础流程就是上述代码,这篇权当抛砖引玉,需要深入学习MFC的框架还有很多要学习的。

小菜鸟一枚,与大家共同学习。

展开阅读全文

没有更多推荐了,返回首页