VC中MFC程序的入口函数

VC中MFC程序的入口函数

一、程序的入口函数介绍

程序代码都有一个主函数,它是整个项目的第一个入口点,其它函数直接或间接被它调用。VC项目前后出现如下六个入口函数:main、wmain、_tmain、WinMain、 wWinMain、_tWinMain,以下分别介绍它们的用法。

1、介绍它们的作用,参考如下:

(1)、main()是WINDOWS的控制台程序(32位)或DOS程序(16位);

(2)、wmain()是UNICODE版本的main();

(3)、_tmain()是个宏,若是UNICODE,则它为wmain();否则为main()。

(4)、WinMain()是WINDOWS的GUI程序;

(5)、wWinMain是UNICODE版本的WinMain ();

(6)、_tWinMain是个宏,若是UNICODE,则它为wWinMain ();否则为WinMain()。

2、这些入口函数的理解,参考如下:

基本的入口函数是main(),其余的无非是加了一些前缀而也,以下分别说明这个问题:

(1)、Win前缀

前三者不含“Win”,为控制台程序或DOS程序的入口函数;后三者含“Win”,为窗口应用程序的入口函数。

(2)、w前缀

该前缀为UNICODE版本的标志。wmain()是UNICODE版本的main(),wWinMain是UNICODE版本的WinMain ()。

(3)、_t前缀

该前缀为复合版本的标志。_tmain()是个宏,若是UNICODE,则它为wmain();否则为main();_tWinMain是个宏,若是UNICODE,则它为wWinMain ();否则为WinMain()。

_tmain、_tWinMain定义在文件,参考如下:

#ifdef _UNICODE

#define _tmain wmain

#define _tWinMain wWinMain

#else /* ndef _UNICODE */

#define _tmain main

#define _tWinMain WinMain

#endif

二、寻找MFC程序程序的入口函数

我们知道在WIN32 API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数。而在MFC程序中,我们能不能找到类似于WinMain这样的程序入口?

1、在appcore.cpp文件找到疑似入口函数(_tWinMain)

在C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\appcore.cpp文件,有如下代码:

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

}

2、AfxWinMain()的代码

在C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\winmain.cpp文件,有如下代码:

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;

}

3、AfxWinMain()的主要调用过程

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

pApp->InitApplication();

pThread->InitInstance();

pThread->Run();

在C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\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;

}

在C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\ thrdcore.cpp文件,有如下代码:

BOOL CWinThread::InitInstance()

{

ASSERT_VALID(this);

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

}

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

}

}

BOOL CWinThread::PumpMessage()

{

return AfxInternalPumpMessage();

}

BOOL AFXAPI AfxInternalPumpMessage()

{

_AFX_THREAD_STATE *pState = AfxGetThreadState();

if (!::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL))

{

#ifdef _DEBUG

TRACE(traceAppMsg, 1, "CWinThread::PumpMessage - Received WM_QUIT.\n");

pState->m_nDisablePumpCount++; // application must die

#endif

// Note: prevents calling message loop things in 'ExitInstance'

// will never be decremented

return FALSE;

}

#ifdef _DEBUG

if (pState->m_nDisablePumpCount != 0)

{

TRACE(traceAppMsg, 0, "Error: CWinThread::PumpMessage called when not permitted.\n");

ASSERT(FALSE);

}

#endif

#ifdef _DEBUG

_AfxTraceMsg(_T("PumpMessage"), &(pState->m_msgCur));

#endif

// process this message

if (pState->m_msgCur.message != WM_KICKIDLE && !AfxPreTranslateMessage(&(pState->m_msgCur)))

{

::TranslateMessage(&(pState->m_msgCur));

::DispatchMessage(&(pState->m_msgCur));

}

return TRUE;

}

三、主要过程总结

Run获取并分派Windows消息,直到应用程序接收到一个WM_QUIT消息。如果应用程序的消息队列当前不包含消息,则运行调用OnIdle来执行空闲时间处理。传入的消息将转到PreTranslateMessage成员函数进行特殊处理,然后转到API函数TranslateMessage,该函数将虚拟键消息转换为字符消息,然后字符消息被发布到调用线程的消息队列中,以便在线程下一次调用GetMessage或PeekMessage函数时读取。最后,调用API函数DispatchMessage,该函数将一个消息分派给一个窗口程序,以便被GetMessage函数检索到消息。

Run很少被覆盖,但是您可以覆盖它以提供特殊的行为。

在消息运行结束,用户按下关闭按钮后,操作系统向程序发送WM_CLOSE消息,默认状况下程序调用DestoryWindow并且发送WM_DESTORY消息,应用程序接受到这个消息以后的默认操作是调用PostQuitMessage函数,由这个函数发送WM_QUIT消息。当程序对象接受到WM_QUIT消息后消息循环结束,由AfxWinMain函数调用AfxTerm函数清理程序使用过的资源并且结束整个程序。

在appcore.cpp文件中,我们能够找到MFC程序的入口函数是_tWinMain,但至于怎么调用的呢?这个问题是找不到的,这个由编译器内部自动完成了。

可见,在MFC程序中,我们不能找到类似于WinMain这样的程序入口。

更多内容,请参考http://www.it001.xyz

相关推荐

钞市官方版-小额借款信用贷款平台
365下载手机版

钞市官方版-小额借款信用贷款平台

📅 09-05 👁️ 8963
美团外卖站长岗位薪资待遇
365下载手机版

美团外卖站长岗位薪资待遇

📅 09-01 👁️ 3906
细究十二星座在世界杯后的种种表现
365赢了不让提款

细究十二星座在世界杯后的种种表现

📅 07-24 👁️ 4186