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定义在<tchar.h>文件,参考如下:  

#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

}

 

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

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消息,退出消息循环。

      CWinApp类的Run(其实它是父类CWinThread的成员)成员函数中的消息循环检索由各种事件生成的排队消息。例如,当用户单击鼠标时,Windows会发送一些与鼠标相关的消息,例如鼠标左键被按下时发送WM_LBUTTONDOWN消息,鼠标左键被释放时发送WM_LBUTTONUP消息。框架的应用程序消息循环实现将消息分派到适当的窗口。

      Run获取并分派Windows消息,直到应用程序接收到一个WM_QUIT消息。如果应用程序的消息队列当前不包含消息,则运行调用OnIdle来执行空闲时间处理。传入的消息将转到PreTranslateMessage成员函数进行特殊处理,然后转到Windows函数TranslateMessage进行标准键盘翻译。最后,调用DispatchMessage Windows函数。

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

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

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

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

 

VC中MFC程序的入口函数

上一篇:java+opencv4.5.3+wechatqrcode代码细节和 自编译类库(百度云)


下一篇:unity 编辑器 对比两次节点信息 查看新增节点和消失节点。