现在的位置: 首页 > 综合 > 正文

MFC中的线程与消息

2013年11月03日 ⁄ 综合 ⁄ 共 2279字 ⁄ 字号 评论关闭

1、MFC程序的进入点其实是WinMain,源代码如下:

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

_tWinMain的定义:#define _tWinMain   WinMain

2、程序然后,进入AfxWinMain(...)函数,在此函数中初始化线程,并建立消息循环。AfxWinMain源代码如下

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

int nReturnCode = -1;

CWinThread* pThread= AfxGetThread();
CWinApp* pApp
= AfxGetApp();

        //其实pThread和pApp是指向同一个对象,都取出来是因为要分别调用各类中的函数

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

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

        /*窗口类只需注册一次,即可供同一程序的后续每一个实例(instance)使用(之所以如此,是因为所有进程同在一个地址空间中),所以我们把RegisterClass这个操作           安排在“只有第一个实例才会进入”的InitApplication函数中。 · 产生窗口,是每一个实例都得进行的操作,所以我们把CreateWindow这个操作安排在“任何实例都会进入”的           InitInstance函数中。*/

// Perform specific initializations
if (!pThread->InitInstance())//InitInstance()每一个应用程序实例都会调用一次
{
if (pThread->m_pMainWnd != NULL)
{
TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run();//在Run中启动线程的消息循环

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

AfxWinTerm();
return nReturnCode;
}

线程对象是在程序进入启动点_tWinMain之前,以全局对象的形式建立的,如下:

CTestApp theApp;

pThread->Run()中Run函数源代码:

int CWinThread::Run()
{
	ASSERT_VALID(this);

	// 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(&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))
			{
				bIdle = TRUE;
				lIdleCount = 0;
			}

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

	ASSERT(FALSE);  // not reachable
}

抱歉!评论已关闭.