1、MFC程序中的WinMain函数
在win32应用程序中WinMain是入口函数,然后设计窗口类、注册窗口类,产生窗口,注册窗口,显示窗口,更新窗口,最后进入消息循环,将消息录音到窗口过程函数中去处理。
在MFC程序中微软把WinMain函数封装起来,在MFC中是看不到的,实际上是在安装目录中我的是在“D:\Visual Studio Ultimate 2013\VC\atlmfc\src\mfc\appmodul.cpp”
_tWinMain实际上是一个宏:#define _tWinMain WinMian。展开之后就是WinMin函数
2、theApp全局变量
全局变量、全局对象,程序在运行时,在加载main函数之前,就已经为全局变量、全局对象分配了内存空间,对一个全局对象来说,此时会调用该对象的构造函数,构造该对象,并进行初始化操作。
对MFC程序来说,通过产生一个应用程序类的对象来唯一标识应用程序的实例。每一个MFC程序有且仅有一个从应用程序派生的类。每一个MFC程序实例有且仅有一个该派生类的实例化对象,即theApp全局对象。
该全局变量定义在MFCHello\MFCHello\MFCHello.cpp(我的应用程序名为MFCHello)
如果在CMFCHelloApp的构造函数中设置断点会发现,在程序运行时时先运行到该构造函数,然后才运行到上面的_tWinMain
3、AfxWinMain函数
在D:\Visual Studio Ultimate 2013\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;
}
其中
以上两个指针调用的函数即完成了win32程序所需的几个步骤:设计窗口类、注册窗口类、创建窗口类、显示窗口、更新窗口、消息循环、以及窗口过程函数。
注:AFX
MFC以全局函数的形式提供了自己各类API函数,名字以Afx打头。类成员仅能在所属的对象说明体中被滴用,而在任何时候任何地方都可使用Afx函数。常用AFX函数如下。
3、MFC框架窗口
(1)设计和注册窗口
有了WinMain函数后,设计窗口类和注册窗口类。窗口类的注册为AfxEndDeferRegisterClass在D:\Visual Studio Ultimate 2013\VC\atlmfc\src\mfc\wincore.cpp中
AfxEndDeferRegisterClass 函数首先判断窗口类的类型,然后赋予其相应的类名( wndcls.lpszClassName变量),这些类名都是MFC预定义的。之后就调用AfxRegisterClass函数注册窗口类,后者的定义也位于WINCORE.CPP文件中
AfxDeferRegisterClass 实际上是一个宏,真正指向的是AfxEndDefer-RegisterClass函数。根据前面介绍的内容,我们知道这里完成的功能就是注册窗口类。
(2)创建窗口
设计窗口类和注册窗口类后,就是创建窗口。在MFC中,窗口创建功能是由CWnd类的CreateEx函数实现,该函数声明位于AFXWin.h文件中,实现位于wincore.cpp中。
(3)显示和更新窗口
在MFCHello.cpp的InitInstance()中
4、消息循环
消息循环在CWinThread::Run()。在D:\Visual Studio Ultimate 2013\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));
}
}
5、窗口过程函数
在AfxEndDeferRegisterClass函数中,位于D:\Visual Studio Ultimate 2013\VC\atlmfc\src\mfc\wincore.cpp中。窗口过程函数为:
这行代码的作用就是设置窗口过程函数,这里指定的是一个默认的窗口过程:DefWindowProc.但实际上, MFC程序并不是把所有消息都交给DefWindowProc这-默认窗口过程来处理的,而是采用了一种称之为消息映射的机制来处理各种消息的。
6、过程整理
■首先利用全局应用程序对象theApp启动应用程序。正是产生了这个全局对象,基
类CWinApp中的this指针才能指向这个对象。如果没有这个全局对象,程序在编译时不会出错,但在运行时就会出错。
■调用全局应用程序对象的构造函数,从而就会先调用其基类CWinApp的构造函数。后者完成应用程序的- 些初始化工作,并将应用程序对象的指针保存起来。
■进入WinMain函数。在AfxWinMain的数中可以获取子类(对Test程序来说,就是CTestApp类)的指针,利用此指针调用虚函数: InitInstance, 根据多态性原理,实际上调用的是子类(CTestApp) 的InitInstance函数。后者完成应用程序的一-些初始化工作,包括窗口类的注册、创建,窗口的显示和更新。期间会多次调用CreateEx函数,因为一一个单文档MFC应用程序有多个窗口,包括框架窗口、工具条、状态条等。
■进入消息循环。虽然也设置了默认的窗口过程函数,但是, MFC应用程序实际上是采用消息映射机制来处理各种消息的。当收到WM QUT消息时,退出消息循环,程序结束。