Saturday, December 19, 2009

MFC running procedure

When you run your program the kernel first calls this function, WinMainCRTStartup. WinMainCRTStartup first initializes the CRT routines. Then it parses the command line and removes the filename portion and calls WinMain passing the parsed command line as lpszCommandLine. _tWinMain is a macro that equates to wWinMain / Winmain based on the UNOCDE preprocessor.

#ifdef _UNICODE

#define _tWinMain wWinMain

#else /* ndef _UNICODE */

#define _tWinMain WinMain

#endif /* _UNICODE */

The WinMain will call AfxWinMain defined in winmain.cpp.

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

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
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)
{
TRACE0("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)
{
TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif

AfxWinTerm();
return nReturnCode;
}

The functions AfxGetThread and AfxGetApp are used to get pointers to the CWinApp and CWinThread. AfxGetThread and AfxGetApp got their information from the CWinApp constructor in appcore.cpp

pThreadState->m_pCurrentWinThread = this;

pModuleState->m_pCurrentWinApp = this;
pThreadState is a AFX_MODULE_THREAD_STATE* and pModuleState is a AFX_MODULE_STATE*.

All MFC applications have at least two objects: an application object derived from CWinApp, and some sort of main window object, derived from CFrameWnd / CMDIFramend / CDialog, all of which are derived from CWnd. C++ programs will first create all global and static objects before execution begins. It will happen much before AfxWinMain gets called. There is only statement in the entire program that has global scope is the statement that instantiates the application object.

CWinApp derived class constructor gets called and the AFX_MODULE_STATE structure is setup properly. Now AfxWinInit is called and this function initializes the MFC framework. Here it calls the InitInstance of the CWinApp derived object.

Then CWinApp::Run is called. Within the Run function is implemented default message loop. The Run() acquires and dispatches Windows messages until the application receives a WM_QUIT message. After WM_QUIT message, Run returns and control returns to AfxWinMain which performs clean-up and lastly calls AfxWinTerm which deletes all the global application structures that were created.

No comments:

Post a Comment