第六章 MFC程序的生死因果

  MFC学习过程,这个方法不错,条例清晰。

  1、CWinApp  -- 取代WinMain地位

  WinMain函数的功能由CWinApp的三个函数实现

 virtual BOOL InitApplication();
virtual BOOL InitInstance();
virtual int Run();

  在CWinThread类中定义m_pMainWnd 

  CWnd* m_pMainWnd;           // 记录主窗口的句柄

  2、CFrameWnd --- 取代WndProc的地位

  通过消息映射来实现消息与函数的关联,宏DECLARE_MESSAGE_MAP()

  BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
              ON_WM_PAINT()
              ON_COMMAND(IDM_ABOUT, OnAbout)
  END_MESSAGE_MAP()

  3、运行过程

    1 Ctest7App theApp;//全局对象

    2 AfxWinInit(...) 在头文件afxwin.h中定义的AfxWinInit(....),这个函数的参数和WndProc()的一样。

    1 BOOL AFXAPI AfxWinInit( HINSTANCE hInstance,  HINSTANCE hPrevInstance,  //在CWind中被引用为友元函数
     LPTSTR lpCmdLine, int nCmdShow);
      //在这个函数中 的主要动作之一  CWinApp* pApp = AfxGetApp();//导致CWinApp::InitApplication()的调用

        //                    之二   AfxInitThread();//初始化线程    

    3 CWinApp::InitApplication();     //初始化应用

    4 BOOL Ctest7App::InitInstance();//自己定义的类

    注意:     

      应用程序一定要改写虚拟函数InitInstance,因为它在CWinApp 中只是个空函数,没有任何内建(预设)动作。

    5 CFrameWnd::Create()产生窗口(并先注册窗口类别)

 BOOL Create( LPCTSTR lpszClassName,//窗口类别
LPCTSTR lpszWindowName,//窗口标题
DWORD dwStyle = WS_OVERLAPPEDWINDOW,//窗口样式
const RECT& rect = rectDefault,//窗口位置和大小
CWnd* pParentWnd = NULL,//父窗口
LPCTSTR lpszMenuName = NULL,//指定菜单
DWORD dwExStyle = ,//附加样式
CCreateContext* pContext = NULL );//在文档/视图中会用到,这里为默认值NULL

    在Create()中调用PreCreateWindow();//虚函数

    然后在PreCreateWindow()中调用宏AfxDeferRegisterClass();

    6 窗口的更新与显示     

      m_pMainWnd->ShowWindow(m_nCmdShow);//显示窗口
      m_pMainWnd->UpdateWindow();//发送WM_PAINT消息

    7 CWinApp::Run() ---- 程序的活水源头

      Run()内部有一个GetMessage/DispatchMesage 循环

      函数接收到WM_PAINT消息,通过消息映射跳转到OnPaint()函数

  整个运行机制看起来很复杂,但是只要多看几遍,必然能熟记于心中,为以后的程序书写打下基础。总结如下:

程序的诞生:

  Application object 产生,内存于是获得配置,初值亦设立了。

  Afx WinMain 执行AfxWinInit,后者又调用AfxInitThread,把消息队列尽量加大到96。

  Afx WinMain 执行InitApplication。这是CWinApp 的虚拟函数,但我们通常不改写它。

  AfxWinMain 执行InitInstance。这是CWinApp 的虚拟函数,我们必须改写它。

  CMyWinApp::InitInstance 'new' 了一个CMyFrameWnd 对象。

  CMyFrameWnd 构造式调用Create,产生主窗口。我们在Create 参数中指定的窗口类别是NULL, 于是MFC 根据窗口种类, 自行为我们注册一个名为"AfxFrameOrView42d" 的窗口类别。

  回到InitInstance 中继续执行ShowWindow,显示窗口。
  执行UpdateWindow,于是发出WM_PAINT。
  回到AfxWinMain,执行Run,进入消息循环。   

程序开始运作:
  程序获得WM_PAINT 消息(藉由CWinApp::Run 中的::GetMessage 循环)。
  WM_PAINT 经由::DispatchMessage 送到窗口函数CWnd::DefWindowProc 中。

  CWnd::DefWindowProc 将消息绕行过消息映射表格(Message Map)。

  绕行过程中发现有吻合项目,于是调用项目中对应的函数。此函数是应用程序利用BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 之间的宏设立起来的。

  标准消息的处理例程亦有标准命名,例如WM_PAINT 必然由OnPaint 处理。程序的死亡:

  使用者选按【File/Close】,于是发出WM_CLOSE。

  CMyFrameWnd 并没有设置WM_CLOSE 处理例程,于是交给预设之处理例程。
  预设函数对于WM_CLOSE 的处理方式是调用::DestroyWindow, 并因而发出WM_DESTROY。

  预设之WM_DESTROY 处理方式是调用::PostQuitMessage,因此发出WM_QUIT。
  CWinApp::Run 收到WM_QUIT 后会结束其内部之消息循环, 然后调用ExitInstance,这是CWinApp 的一个虚拟函数。

  如果CMyWinApp 改写了ExitInstance , 那么CWinApp::Run 所调用的就是CMyWinApp::ExitInstance,否则就是CWinApp::ExitInstance。

  最后回到AfxWinMain,执行AfxWinTerm,结束程序。

  4、Callback函数-----全局函数 或者 static 函数

  定义:凡是由你设计而却由Windows 系统调用的函数,统称为callback 函数。这些函数都有一定的类型,以配合Windows的调用动作。

   注意:如果类别的成员函数是一个callback 函数, 你必须声明它为"static",才能把C++ 编译器加诸于函数的一个隐藏参数this 去掉。

  5、 空闲时间(idle time)的处理:OnIdle

  如果你的MFC 程序也想处理idle time,只要改写CWinApp 衍生类别的OnIdle 函数即可  virtual BOOL OnIdle(LONG lCount);

  6、Dialog 与 Control

  MFC中的对话框的创建与打开使用CDialog类。下面是一些常用的对话框:

类别                                                   类型
CCommonDialog 以下各类别的父类别
CFileDialog File 对话框(Open 或Save As)
CPrintDialog Print 对话框
CFindReplaceDialog Find and Replace 对话框
CColorDialog Color 对话框
CFontDialog Font 对话框
CPageSetupDialog Page Setup 对话框(MFC 4.0 新增)
COleDialog Ole 相关对话框

  派生关系如图:

具体使用方法参考MSDN

  

MFC深入浅出读书笔记第二部分1的更多相关文章

  1. MFC深入浅出读书笔记第二部分2

    第七章  MFC骨干程序 所谓骨干程序就是指有AppWizard生成的MFC程序.如下图的层次关系是程序中常用的几个类,一定要熟记于心. 1 Document/View应用程序 CDocument存放 ...

  2. MFC深入浅出读书笔记第一部分

    最近看侯捷的MFC深入浅出,简单总结一下. 第一章首先就是先了解一下windows程序设计的基础知识,包括win32程序开发基础,什么*.lib,*.h,*.cpp的,程序入口点WinMain函数,窗 ...

  3. MFC深入浅出读书笔记第三部分1

    第八章 Document-View 深入探讨(总结) 1.Document Document 在MFC 的CDocument 里头被具体化.CDocument 本身并无任何具体数据,它只是提供一个空壳 ...

  4. 《javascript权威指南》读书笔记——第二篇

    <javascript权威指南>读书笔记——第二篇 金刚 javascript js javascript权威指南 今天是今年的196天,分享今天的读书笔记. 第2章 词法结构 2.1 字 ...

  5. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  6. Getting Started With Hazelcast 读书笔记(第二章、第三章)

    第二章 起步 本章就相当简单粗暴了,用一个个例子说明hazelcast怎么用. 1.map,set,list这些集合类都是开箱即用的,只要从Hazelcast的实例中获取一份就行. 2.增加了Mult ...

  7. Java Concurrency in Practice 读书笔记 第二章

    第二章的思维导图(代码迟点补上):

  8. 《疯狂Java:突破程序员基本功的16课》读书笔记-第二章 对象与内存控制

    Java内存管理分为两个方面:内存分配和内存回收.这里的内存分配特指创建Java对象时JVM为该对象在堆内存中所分配的内存空间.内存回收指的是当该Java对象失去引用,变成垃圾时,JVM的垃圾回收机制 ...

  9. Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...

随机推荐

  1. Eucalyptus简介

    1.Eucalyptus是什么? Eucalyptus  n.桉树 Eucalyptus is a Linux-based software architecture that implements ...

  2. C#运算符、控制流

    1 运算符 1.1 一元运算符: -(负号).+(正号):可以省略 1.2 二元运算符:     优先级,*(乘)./(除).%(取余).+(加).-(减).=(赋值) 二元赋值运算符,=.+=.-= ...

  3. python any all函数

    a = [0, 0, 0, 0] b = [0, 0, 0, 1] c = [1, 1, 1, 1] >>> any(a) False >>> any(b) Tru ...

  4. 2017.12.9 Java中的排序---冒泡排序、快速排序、选择排序

    //冒泡排序 public class demo{ public static void main(String[] args) { int[] sum={2,9,10,1,5,88}; System ...

  5. 记一次加密算法MD5

    通过MessageDigest可以获取到16个字节数组: MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] ...

  6. C#的接口基础教程之二 定义接口

    定义接口 从技术上讲,接口是一组包含了函数型方法的数据结构.通过这组数据结构,客户代码可以调用组件对象的功能. 定义接口的一般形式为: [attributes] [modifiers] interfa ...

  7. C/C++ 程序基础 (一)基本语法

    域操作符: C++ 支持通过域操作符访问全局变量,C不支持(识别为重定义) ++i和i++的效率分析: 内置类型,无区别 自定义数据类型,++i可以返回引用,i++只能返回对象值(拷贝开销) 浮点数与 ...

  8. js判断是否是大小写,数字等方法

    function isEmail(str){ var regu = "^(([0-9a-zA-Z]+)|([0-9a-zA-Z]+[_.0-9a-zA-Z-]*))@([a-zA-Z0-9- ...

  9. Foxmail登录不了网易企业邮箱解决办法

    关于Foxmail登录不了网易企业邮箱问题 解决办法是:在设置账号的时候手动设置pop服务器和smtp服务器. 新建账号的图: 点击“手动设置”出现如下界面: 设置完成后问题解决.下面的两个是正确的, ...

  10. mysql的性能优化案例

    在一次项目实现中,以前写了个程序,将在txt文件中的电话号码和对应的类型往数据库中插入,小数据量的情况下,用个数组遍历循环的方式,很容易解决,但是当数据量一下 但是,几十万个电话一次性插入,就变得耗时 ...