MFC的Main函数跑哪去了

原文 MFC的Main函数跑哪去了

0 习惯的思维

一般拿到C/C++程序. 首先会找 main 函数在哪里.然后顺序往下看.
因为 main 函数是程序的入口.

当在C++中SDK(win32 API project)开发时也继承沿用C的思维

  • 有个 main 函数. 叫WinMain 或者_tWinMain
  • QT也和C一样.有一个 main 函数

1 SDK中的流程

开发一个带界面的SDK程序大致流程是这样的

  • 有个main函数作为入口

然后按以下流程来进行:

  • 第1步,注册窗体类,并在这里指定了窗体过程WndProc
  • 第2步,创建窗体
  • 第3步消息循环,分派消息
  • 第4步,退出程序
nt _tWinain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
	 MSG msg; // 消息
	 InitApplicatio(HINSTANCE hInstance)   //第1步,注册窗体类,并在这里指定了窗体过程WndProc
	  InitInstance(HINSTANCE hInstance, int nCmdShow)   //第2步,创建窗体
	  while (GetMessage(&msg, NULL, 0, 0))    //第3步消息循环,分派消息
	  {
		  TranslateMessage(&msg);
		  DispatchMessage(&msg);
		  return (int) msg.wParam;  //第4步,退出程序
	  }
}

BOOL InitApplicatio(HINSTANCE hInstance)
{
  return RegisterClass(...);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	CreateWindow(...); //创建窗体
	ShowWindow(...); //显示窗体
	UpdateWindow(...); //送出WM_PAINT
	return TRUE;
}

LRESULT CALLBACK WndProc(...){ }

2 MFC封装背后流程

在MFC中生成一个有界面的程序大体过程和上述一样,只不过封装起来了.
我们感兴趣的就是两个问题:
1. MFC中有没有main函数了,如果有它跑哪去了?
2. 如果有main函数,它里面的那4步涉及到的具体操作是否也跟win32 API一样?

2.1 MFC中是有main函数的

// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow);

main就是以上这个函数. 在MFC的源文件appmodul.cpp中能看到这些代码
那么这个代码如何被MFC调用呢?

  • 注释,是linkage to this module,也就是被链接器去调用的.准确说是被C-Runtime DLL,C运行时动态链接库调用的.

调用main函数的顺序:

  • 在MFC中能从代码里看到的入口点是定义一个全局的继承于CWinApp的类.比如CMyApp theApp;
  • 这样定义下. 在C++中全局变量是先于main被执行的,所以先初始化theApp后才接着调用main

2.2 main函数里具体的操作

MFC有main函数,
但是这main函数里的具体操作是否跟SDK中的一样,是不是也来那么几步,先注册窗口再创建窗口之类的.
答案是MFC调用的main函数大概流程差不多是那样,
但实现细节很不一样.
看下上面说的AfxWinMain里面的内容是啥吧.可以在winmain.cpp中看到详细代码.
将main函数简化如下:

AfxWinMain(...){
	 //先通过一个全局函数获得CWinApp和CWinThread的指针,
	 // 因为调用main之前已经初始化了这两个类.
	 // CMyApp初始化时也会初始化他的父类CWinApp,及父类的父类CWinThread
	 CWinThread* pThread = AfxGetThread(); 
	 CWinApp* pApp = AfxGetApp();
	 
	//这下面几个函数就差不多是完成前面讲的SDK中的所有步骤
	 pApp->InitApplication();
	 pThread->InitInstance();
	 pThread->Run();

	 AfxWinTerm(); //结束程序
}

重点关注前面三步:注册窗口,创建窗口,还有消息分派.

前面的SDK程序中也恰好有函数InitApplication 注册窗口, InitInstance创建并显示窗口.而Run函数你猜想可能是分派消息的…其实大体思路还是没错,但实现细节还是有蛮多区别.

pApp->InitApplication() 这函数实际上并没有注册窗口.

pThread->InitInstance() 注册窗口,创建显示窗口

  • 这函数中完成,InitInstance是个 虚函数 ,而且我们在自己的代码中会重写它.所以最后调用的是我们自己写的那个InitInstance函数,这就是面向对象里多态的功能了啊.你指针最终指向对应的子类定义的函数.
BOOL CMyApp::InitInstance()
{
 	m_pMainWnd = new CMyFrameWnd; //这张操作会注册并创建窗口,m_pMainWnd就是返回的窗口句柄
	m_pMainWnd->ShowWindow(m_nCmdShow); //显示窗口
	m_pMainWnd->UpdateWindow();
}

pThread->Run();是分派消息,你可以在thrdcore.cpp中查看CWinThreed的run函数的源码,下面摘了一点点.

// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
}

不过关于消息的处理MFC用到了消息映射机制,
比如复杂.这里不讨论了,反正大概就把CMyFrameWnd当成是窗口过程就行了.

MFC怎么封装CreateWindow见: http://blog.csdn.net/weiwenhp/article/details/8796337

3 总结

总结起来可以这样简单的说,

  • MFC中有main函数,但是由系统去调用.然后main函数里面执行的操作差不多,只不过它是通过CWinApp和CWinThread的指针去调用一些相关的函数.而指针嘛由于调用了虚函数,所以用到了面向对象中的多态,
  • 然后最难的地方可能就是消息机制在这里更复杂一点了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值