您的位置:首页 > 其它

MFC入程序的分析

2014-04-02 21:12 288 查看
转自 http://blog.sina.com.cn/s/blog_620475be0100mavz.html

先从一个最小的MFC程序说起。
// The minimal MFC program

************************************************
#include <afxwin.h>

class CMinApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};

// 重载的InitInstance()实现
BOOL CMinApp::InitInstance ()
{
// 分配C 窗口对象
CFrameWnd * pFrame = new CFrameWnd();

// 创建窗口并命名标题栏,_T()是支持UNICODE之用,
// 不过这行代码常有人把它放在CFrameWnd构造函数中
pFrame->Create( 0, _T( "A Minimal MFC Program" ) );

// 显示窗口
pFrame->ShowWindow( SW_SHOWDEFAULT );
pFrame->UpdateWindow ();

// 将已经指定的框架与应用程序对象建立关联
AfxGetApp()->m_pMainWnd = pFrame;

return TRUE;
}

// 创建唯一的也是必须的应用程序对象。由于
// 它不存在任何函数之中,所以也是全局对象。
CMinApp MyApp;

*************************************************************

作为一个最小的MFC应用程序,你只需要在代码中初始化一个CWinApp对象,并重
载其
CWinApp::InitInstance()方法。习惯了C/C DOS编程和SDK编程的人可能会觉得
奇怪,
程序的入口函数main()或WinMain()在哪里呢?

其实,在MFC应用程序中,MFC维护着一个WinMain()函数,只是它被隐藏了,程序
员看不见
罢了。通过你写的MFC代码,你已经建立了一个CWinApp对象,这个全局对象的初
始化工作在
WinMain()被调用之前就已经完成。

在北京科海培训中心,清华出版社的大部头著作"MFC开发Windows 95/NT4应用程
序"
(Peter Norton, Rob McGregor, 1996)的75页上说:"当声明应用程序对象时,应
用程序
运行,因为应用程序类的构造函数调用Run()方法,它如同在CWinApp MyApp内一
样自动
启动应用程序的消息泵。" 其意思是说,CMinApp MyApp这句代码调用CMinApp::
CMinApp(),
而这个构造函数导致程序的运行。这是错误的!如果是构造函数调用WinMain(),
而WinMain()
有调用CMinApp::InitInstance(), 那么就是说在执行InitInstance()时构造函数
的工作还没
完成,那么显然MyApp这个应用程序对象也就还不存在。试问在CMinApp::InitIn
stance()中既然
可以用AfxGetApp()获得指向一个应用程序对象的指针,那么这个应用程序对象必
然是已经初始化
好了。如果初始化还在进行中,InitInstance()怎么运行呢?所以,程序不是在
CMinApp MyApp
时运行,而是在其之后。换句话说,WinMain()不是在CMinApp MyApp这行语句中
被隐含调用,
而是在其后由MFC自动调用的。

有时大师也会犯低级错误。

下面我将逐行解释MFC的WinMain(),这段代码在VC98目录下的MFC\SRC\WinMain.
cpp中。
请记住,在这段代码能够被执行之前,我们已经有了一个CWinApp类全局对象。而
且请
注意,CWinApp类是CWinThread类的派生类,而且当前的CWinApp类全局对象(这个
对象
有且只能有一个)能够通过调用全局函数AfxGetApp()来得到指向其的指针。

//////////////////////////////////////////////////////////////////////
///////

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
// AfxWinMain()就是MFC应用程序的入口函数WinMain()
{
ASSERT(hPrevInstance == NULL);
// Win32应用程序只有一个实例,所以hPrevInstance肯定是NULL,
// 如果不是,则肯定是出了问题。

int nReturnCode = -1;
// 预设返回值为-1。这个返回值是用来与父进程通信的。不过并没有这个值的标

// 使用方法。

CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// CWinApp是CWinThread的派生类,上两行代码分别初始化了一个指向CWinThre
ad对象的
// 指针和一个CWinApp对象。它们的初始化是通过调用AfxGetThread()和AfxGet
App()得到
// 的,也就是说,它们分别被初始化为指向当前应用程序的唯一全局线程/应用
程序对象的
// 指针。

// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// AfxWinInit()函数初始化MFC程序,处理很多难以预料的问题。该函数和后面

// AfxWinTerm()对应。

// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
// 调用pApp->InitApplication(),初始化应用程序。不过这还不够。

// Perform specific initializations
if (!pThread->InitInstance())
// 调用pThread->InitInstance()函数,进行线程初始化。注意,InitInstance
()通常
// 是你的MFC代码中唯一必须重载的函数。
// 下面的语句块是当初始化不成功时的处理。
{
if (pThread->m_pMainWnd != NULL)
{
TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
// ExitInstance()也是一个值得注意的函数
goto InitFailure;
}
nReturnCode = pThread->Run();
// pThread->Run()是重要函数,它使得MFC进入消息循环。其细节待另文介绍。

// 以下代码处理各种初始化失败情形
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;
}

//////////////////////////////////////////////////////////////////////
///////

总之,MFC程序先建立应用程序对象,然后将内部准备好的WinMain()与之连接,

执行一系列动作,从而使程序运行。

上面的解释还是十分浅层次的,更具体的内容待俺学清楚之后慢慢贴出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: