MFC程序入口分析

转载 2015年11月18日 23:37:11

初学mfc,发现找不到main函数和winmain函数,这篇文章解答了我的问题


先从一个最小的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()与之连接,

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

上面的解释还是十分浅层次的,更具体的内容待俺学清楚之后慢慢贴出来。





原文地址



MFC中的WinMain()入口去哪里了?

学过一段时间的MFC之后,很多人大概都有一个疑问:在MFC中,WinMain()哪去了?因为任何一个使用过Win32 SDK编程的人都知道,WinMain()函数是Win32程序开始的入口点,可是在M...
  • weiaipan1314
  • weiaipan1314
  • 2016年06月26日 23:05
  • 2726

MFC 应用程序框架-程序入口和执行流程

一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调...
  • xj2419174554
  • xj2419174554
  • 2014年07月19日 13:15
  • 1164

MFC 必须定义入口点 解决办法

一、在项目属性里面选“链接器”,然后选“系统”,在那里要记得选“子系统”,设为“Windows”!否则编译器会查找main函数作为入口! 二、定义程序入口点  参考另一篇文章可执行程序的...
  • imsaws
  • imsaws
  • 2013年07月03日 13:46
  • 1385

MFC程序的来龙去脉

引言 :   侯捷老师在他那本著名的"深入浅出MFC"(第二版)的第六章中对比着传统的Win32API编程,详细讲解了MFC应用程序“生死因果”,而且侯捷 老师还在"深入浅出MFC"(第二版)一...
  • limingmcu
  • limingmcu
  • 2014年12月08日 11:58
  • 785

MFC 学习笔记 1 程序入口主函数的处理

今天开始看MFC的书。 以前看不懂,现在还是懂非懂,太深的技术学不进去,还是学浅的吧。越浅越好 一、程序入口主函数的处理   2.win32程序中 int __stdcall WinMa...
  • aasmfox
  • aasmfox
  • 2016年10月11日 11:25
  • 606

MFC程序入口和执行流程

一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口...
  • simplelin
  • simplelin
  • 2016年04月15日 17:01
  • 931

C++程序入口

本文转载自:http://blog.163.com/lyzaily@126/blog/static/4243883720091053548157/ 今天终于有时间来研究一下一个很大很大的工程编译...
  • u010999396
  • u010999396
  • 2017年11月01日 19:45
  • 298

MFC程序入口分析

初学mfc,发现找不到main函数和winmain函数,这篇文章解答了我的问题 先从一个最小的MFC程序说起。 // The minimal MFC program *******...
  • h123120
  • h123120
  • 2015年11月18日 23:37
  • 315

MFC程序里单击按钮时执行的入口地址查找方法

  • 2008年09月02日 11:08
  • 177KB
  • 下载

使用Unicode的问题 wWinMainCRTStartup设定程序入口

 编译时通过,但连接错误,如下:                 Linking...     LIBCD.lib(wincrt0.obj)   :   error   LNK2001...
  • zhezhelin
  • zhezhelin
  • 2008年09月27日 15:27
  • 3262
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC程序入口分析
举报原因:
原因补充:

(最多只允许输入30个字)