发信人: netmare() 
整理人: girlrong(1999-11-09 09:17:40), 站内信件
 | 
 
 
先从一个最小的MFC程序说起。
 // The minimal MFC program 
 
 ************************************************
 #include <afxwin.h>
 /*
    从CWinApp中派生CMinApp, 作为应用程序对象
    并重载InitInstance()函数
 */
 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()与之连接, 
 执行一系列动作,从而使程序运行。
 
 上面的解释还是十分浅层次的,更具体的内容待俺学清楚之后慢慢贴出来。
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.32.104]
  | 
 
 
 |