MFC 应用程序初始化与消息传递的 生死因果

原创 2012年03月27日 16:37:10

构造全局对象:   theApp
应用程序对象(Applicate Object)的产生,内存于是获得配置,初值也设立,也调用了CWinApp的构造函数。
于是: CWinApp::m_pCurrentWinApp = this(this的动态指针类型是CMyWinApp,即:CWinApp::m_pCurrentWinApp = &theApp)。

theApp 配置完成之后,WinMain 登场。但我们并未撰写 WinMain程序代码。其实这是 MFC 早已准备好并由链接器直接加到应用程序代码中的。
代码如下:
extern "C"
int WINAPI   _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    return   AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

int AFXAPI   AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    int nReturnCode = -1;
 CWinApp *pApp = AfxGetApp();
 
 if ( !AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
     goto InitFailure;
  
 if (!pApp->InitApplcation())
     goto InitFailure;
  
 if (!pApp->InitInstance())
 {
     if (pApp->m_pMainWnd != NULL)
  {
      TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
   pApp->m_pMainWnd->DestroyWindow();
  }
  nReturnCode = pApp->ExitInstance();
  goto InitFailure;
 }
 
 nReturnCode = pApp->Run();
 
 AfxWinTerm();
 return nReturnCode;
}

稍加整理,重点是调用了如下几个函数:
     AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  pApp->InitApplcation()
  pApp->InitInstance()
  pApp->Run()

 

下面我们着手分析这四个函数在调用中,都具体做了那些操作。

AFX 应用程序内部初始化操作
     AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
                     |
        AfxInitThread()
   
  
MFC 为内部管理而做一些设置   
 pApp->InitApplcation() 

 
注册窗口类,设置窗口样式,创建窗口 ,窗口显示与更新
  pApp->InitInstance()
 
  BOOL CMyWinApp::InitInstance()
  {
     m_pMainWnd = new CMyFrameWnd;   // 创建一个框架窗口,将调用 CMyFrameWnd 类的构造函数
  m_pMainWnd->ShowWindow(m_nCmdShow);
  m_pMainWnd->UpDateWindow();
  }
 
  CMyFrameWnd::CMyFrameWnd()
  {
     Create(...)                    // Create 函数是个虚函数。但 CMyFrameWnd 并没有重写他,所以这里调用的是其父类CFrameWnd的Create函数
  ...
  }
 
  BOOL CFrameWnd::Create(...)
  {
     CreateEx(...)                  // CreateEx 是类 CWnd 的一个成员函数
  }
 
  BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
                      int x, int y, int nWidth, int nHeight,
       HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
 {
     CREATESTRUCT    cs;               // 这里我们将设置窗口产生时样式,cs用于保存窗口样式的名个参数
  
  ...
  
  PreCreateWindow(cs)              // 在这里注册窗口类。注意,cs.lpszClass 用于保存,是注册后的窗口类的名字
  
  ::CreateWindowEx(cs.?, cs.?...)  // 创建窗口
 }
 
 BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT &cs)
 {
     if (cs.lpszClass = NULL)
  {
      AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);
   cs.lpszClass = _afxWndFrameOrView;
  }
 }
 
 #define AfxDeferRegisterClass(fClass) \
 ((afxRegisteredClasses & fClass) ? TRUE : AfxEndDeferRegisterClass(fClass))
 这个宏表示,如果已经注册了fClass 这种窗口, MFC 什么都不做;否则就调用 AfxEndDefRegisterClass(fClass) 来注册窗口类
 
 之后将调用
 BOOL AFXAPI AfxEndDeferRegisterClass(short fClass)
 {
     ...          // 在这里,将根据给出的fClass 注册窗口类
 }
 
 // 我们发现,当 fClass = AFX_WNDFRAMEORVIEW_REG 时,其窗口类的类名就为 _afxWndFrameOrView

窗口显示与更新
当创建窗口的操作完成之后,我们再看回InitInstance 这个函数
  BOOL CMyWinApp::InitInstance()
  {
     m_pMainWnd = new CMyFrameWnd;   // 创建一个框架窗口,将调用 CMyFrameWnd 类的构造函数
  m_pMainWnd->ShowWindow(m_nCmdShow);
  m_pMainWnd->UpDateWindow();
  }

可以看到,程序在这里完成了窗口的显示和更新操作

消息循环
pApp->Run();
相当于调用:
CMyWinApp::Run()
后又调用
CWinThread::Run
do
{
    ::GetMessage(&msg,...);
 PreTranslateMessage(&msg);
 ::TranslateMessage(&msg);
 ::DispatchMessage(&msg);
}while (::PeekMessage(...));

之后,对于消息的处理将交由 窗口函数DefWindowProc来处理。
但 MFC 在这里又做了一些手脚,将消息送往了同是回调函数的::AfxWndProc,在AfxWndProc对消息进行处理

 

下面是消息的传递过程:
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
    CWnd *pWnd = CWnd::FromHandlePerManent(hWnd);
 return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}

LRESULT AFXAPI  AfxCallWndProc(CWnd *pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0)
{
    lResult = pWnd->WindowProc(nMsg, wParam, lParam);    // WindowProc 是类 CWnd 的一个函数,其子类并没有重写
 ...
 return lResult;

 
 
LRESUTL CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lPararm)
{
    LRESULT lResult = 0;
 if (!OnWndMsg(message, wParam, lParam, &lResult))
     lResult = DefWindowProc(message, wParam, lParam);
  
 return lResult;
}

在 CWnd::WindowProc中调用了OnWndMsg,而当程序进入CWnd::OnWndMsg时,程序会对消息进行分类
如是标准消息,直线上溯
如是命令消息,拐弯上溯
如是通知消息,那又是另一种处理方式
因这里内容太多,我就不详细说明了

而如果没有找到消息的处理函数,将由 CWnd::DefWindowProc 来处理。
而在 CWnd::DefWindowProc 中,将由全局函数 DefWindowProc 来进行处理

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

《深入浅出MFC》– MFC程序的生死因果

1.首先MFC程序需要哪些函数库? Windows C Runtime函数库 LIBC.LIB       C Runtime函数库的静态链接版本 MSVCRT.LIB     C ...
  • zuoyefeng1990
  • zuoyefeng1990
  • 2016年07月21日 16:16
  • 516

MFC 关于SendMessage 消息参数 传送字符串,结构体

今天在使用单文档程序时,弹出了一个新的对话框,由于是非模式对话框,当对话框结束后,需要根据一些消息传递参数到主窗体中 那么在对话框中使用了SendMessage 使用方法: GetParent()...
  • lunatic7
  • lunatic7
  • 2017年07月08日 21:51
  • 194

MFC技术内幕系列之(一)---MFC应用程序“生死因果”内幕

 ///////////////////////////////////////////////////////////////////////////////////            ...
  • xrzh8989
  • xrzh8989
  • 2015年08月03日 12:09
  • 204

深入浅出MFC之第六章—MFC程序的生死因果

1.  初学MFC程序设计的人(甚至包括已经很精通Win32API编程的大虾们)都会感到很疑惑,对MFC应用程序的运行流程不能马上领悟,多数人都会提出类似"WinMain函数跑到哪里去了?","窗口函...
  • u011120824
  • u011120824
  • 2014年04月17日 14:01
  • 463

MFC技术内幕系列之(一)---MFC应用程序“生死因果”内幕

 ///////////////////////////////////////////////////////////////////////////////////            ...
  • qlx846852708
  • qlx846852708
  • 2015年07月14日 09:57
  • 347

Windows消息传递机制详解

Windows是一个消息(Message)驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理...
  • Evankaka
  • Evankaka
  • 2015年03月19日 13:44
  • 5329

MFC 自定义消息四步曲与在参数中传递变量

本文转载自:http://blog.csdn.net/code_robot/article/details/7724667 今天自己也重学了一下 VC小自定义消息的使用,在网上查阅了相关资料,发...
  • cwt19902010
  • cwt19902010
  • 2016年11月23日 16:59
  • 522

MFC程序的剖析及生死因果揭秘

SDK下Windows程序的编程:对于一般SDK下Windows程序的编程,其主要步骤如下: 各步骤说明: 1:WinMain函数:它是Windows程序的基础,也是入口点函数,当Windows系...
  • dby3579
  • dby3579
  • 2016年01月13日 20:01
  • 359

MFC窗口之间的消息传递

窗口消息的传递 http://bbs.bccn.net/thread-348167-1-1.html 声明:本文非本人所写,本文已经写在本人CSDN博客里。本原来源于一篇英文文章的翻译。 ...
  • qq_31100961
  • qq_31100961
  • 2016年08月13日 09:31
  • 1295

六、MFC 程序的生死因果 (学习笔记)

MFC程序的生死因果 项目HELLO 理想如果不向实际做点妥协,理想就会归于尘土。 中华民国还得十次革命才得建立,对象导向怎能把一切传统都抛开。 以传统的C/SDK 撰写Window...
  • imsaws
  • imsaws
  • 2013年07月03日 20:51
  • 1177
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC 应用程序初始化与消息传递的 生死因果
举报原因:
原因补充:

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