我们知道Win32中创建一个窗口的流程就是先注册一个WNDCLASSEX(指定了窗口的回调函数),然后通过CreateWindow这函数正式创建一个窗口.然后就是一个while循环获取消息,分派消息.所有这些都是在一个main函数中完成.相当清晰明了.而MFC是封装了上面Win32的流程,变得极为复杂了.

简单的创建Win32与MFC窗口见:http://blog.csdn.net/weiwenhp/article/details/7960243

MFC的Main函数跑哪里了见:http://blog.csdn.net/weiwenhp/article/details/8455471

现在主要来讲下MFC封装的具体细节

1.怎么封装注册窗口, RegisterClass

2.怎么封装指定回调函数.windowClass.lpfnWndProc

3.怎么封装创建出来一个窗口的.CreateWindow

CWnd封装了RegisterClass,CreateWindow,lpfnWndProc

创建窗口的函数CreateWindow在MFC中被封装到了CWnd中,所以凡是继承自CWnd的类都可以生成窗口嘛.

当然了准确的说应该是根据不同的类型调用不同的函数,CWnd也封装了CreateDialog和MessageBox.

那么继承自CDialog的类最终调用的是CreateDialog

以CFrameWnd为例说明怎么封装的(它继承自CWnd).

(1) m_pMainWnd = new CMyFrameWnd;//实例化类CMyFrameWnd,调用它的构造函数

(2) CMyFrameWnd::CMyFrameWnd(){

Create(....); //该虚函数没被重写,所以调用父类CFrameWnd的Create函数

}

(3) BOOL CFrameWnd::Create(.....){  //见MFC源码winfrm.cpp

//其他代码

CreateEx(.....); //又是虚函数没改写,于是调用父类CWnd的CreateEx函数

}

(4) BOOL CWnd:CreateEx(.....){ //见MFC源码wincore.cpp

CREATESTRUCT cs;

//对cs的一系列初始化,这里的CREATESTRUCT跟Win32中的WNDCLASSEX起类似作用,最后它的值会与WNDCLASS的类关联起来的

PreCreateWindow(cs);  //该虚函数就是作注册窗口的作用.它被CFrameWnd改定了.见第(5)步

AfxHookWindowCreate(this); //钩子函数,跟窗口回调函数有关

HWND hWnd = ::AfxCtxCreateWindowEx(.....); //正式创建窗口了,跟CreateWindow的作用一样.

}

查看AfxCtxCreateWindowEx的定义

#define AfxCtxCreateWindowEx AfxCtxCreateWindowExW

你再选中AfxCtxCreateWindowExW右击Go To Definition会跳转到这(至于是怎么跳过去的就不清楚了,可能编译器编译的时候就把两者关联起来的吧)

AFX_ISOLATIONAWARE_STATICLINK_FUNC(HWND ,CreateWindowExW,(DWORD dwExStyle,LPCWSTR lpClassName,LPCWSTR lpWindowName,DWORD dwStyle,int X,int Y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam),(dwExStyle,lpClassName,lpWindowName,dwStyle,X,Y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam),NULL)

你终于看到个CreateWindowExW了吧,只比CreateWinow多了后面的ExW,这里的细微区别就不用管了.反正再通过些宏转来转去的结果.它们最终是同一个东东了.只是为了处理宽字符才做些这样的转换了.

至此终于找着创建窗口CreateWindow怎么被封装了.

不过还有两个问题没解决.一个是窗口怎么被注册,二个是回调函数怎么被指定的.

(5)  BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs){ //见MFC源码winfrm.cpp

//实际上在里没帮太多事,主要是对cs添加些特性,比如style,lpszClass之类的

AfxDeferRegisterClass(...); //最终调用第(6)步该函数的定义如下

//#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

//而AfxEndDeferRegisterClass的定义见MFC源文件wincore.cpp

}

(6) BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){  //MFC源文件wincore.cpp

WNDCLASS wndcls; //很激动吧,终于看到跟Win32中相同的东东了吧,
    memset(&wndcls, 0, sizeof(WNDCLASS));

wndcls.lpfnWndProc = DefWindowProc; //这里就是默认的回调函数了.Win32中默认回调函数也叫这名了
    wndcls.hInstance = AfxGetInstanceHandle();

//其他代码

AfxRegisterClass(&wndcls); //这里就是注册窗口了

}

再看AfxRegisterClass的定义

BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass){

AfxCtxRegisterClass(....);

}

AfxCtxRegisterClass定义如下

#define AfxCtxRegisterClass   AfxCtxRegisterClassW

与AfxCtxRegisterClassW关联的是

AFX_ISOLATIONAWARE_STATICLINK_FUNC(ATOM ,RegisterClassW,(const WNDCLASSW*lpWndClass),(lpWndClass),0)

至此注册窗口和回调函数的事也都搞明白了吧.

不过还有一个问题,上面的回调函数只是默认回调函数.实际上我们代码中经常使用到的回调函数不是这样去用到的.那怎么实现的?跟前面的钩子函数有关

关于这个下次再讲去了

MFC怎么封装CreateWindow相关推荐

  1. 【MFC系列-第7天】MFC类库封装原理

    关注公号[逆向通信猿]更精彩!!! 运算符重载 operator RECT* () {return this; } CString类库 例1 CString str;int n = str.GetLe ...

  2. MFC的Main函数跑哪去了

    用习惯了C的人要看一个程序时首先会想到找到那个main函数在哪,然后再顺着往下看.因为main函数作为程序的入口点,整个程序都是从那开始执行的.当在C++中SDK(win32 API project) ...

  3. 1.5 MFC封装思想

    ************************************************** * 本文由小鸟飞飞整理发表 <samboy@sohu.com> * * 首发网站:蓝丽 ...

  4. MFC中的GDI绘图

    MFC中的GDI绘图 目录(?)[+] 什么是GDI 什么是DC MFC中与GDI有关的类 获取设备环境 设置坐标映射 创建绘图工具并选入DC 调用DC绘图函数绘图 三坐标映射实例 一.关于GDI的基 ...

  5. MFC GDI绘图基础

    一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...

  6. MFC应用程序框架入门

    摘要: 本文主要对VC++ 6.0的MFC编程方法及MFC应用程序框架进行简要介绍. 关键词: VC++6.0:MFC:程序框架 1 MFC概述 顾名思意,MFC应用程序框架是以MFC作为框架基础的, ...

  7. 深入浅出话VC++(2)——MFC的本质

    一.引言 上一专题中,纯手动地完成了一个Windows应用程序,然而,在实际开发中,我们大多数都是使用已有的类库来开发Windows应用程序.MFC(Microsoft Foundation Clas ...

  8. Win32 Application 、Win32 Console Application、MFC工程项目

    Win32 Application和Win32 Console Application 都是工作在32位Windows环境的程序. Win32  Application 是标准 windows程序,完 ...

  9. 微软视窗的C++封装

    微软视窗的C++封装                                                                 (转自freex64加壳工具) Window::C ...

最新文章

  1. 从Nginx源码谈大小写字符转化的最高效代码以及ASCII码表的科学
  2. 干货回顾丨深度学习应用大盘点
  3. Android的全屏活动?
  4. 在ubuntu上安装最新稳定版本的node及npm
  5. linq to sql 插入值,以及如何取回自增的ID
  6. OpenSSL 再爆严重安全漏洞 —— CCS 注入
  7. Web 2.0 编程思想:16条法则
  8. php 选股器,RSI切线突破选股指标(TDX)..
  9. quill鼠标悬浮 出现提示_「超逸酷玩」VT300S RGB电竞游戏鼠标支持云同步自定义设置...
  10. Zookeeper集群搭建(涵盖命令详解)与Error contacting service. It is probably not running的问题解决
  11. 猪肉价格屡创新高 也许AI养猪是时候提上日程了
  12. 刷题upupup【Java中Queue、Stack、Heap用法总结】
  13. python有道-Python爬取有道词典
  14. 《正则表达式经典实例(第2版)》——2.18 向正则表达式中添加注释
  15. 使用动态时间规整来同步时间序列数据
  16. XJOI1226 走迷宫
  17. 学术论文的英文文献,国内外有哪些网站可以找得到?
  18. PaddleOCR之模型介绍与测试
  19. 只有标准账户,如何取得管理员权限?
  20. 链栈的入栈、出栈、获取长度、获取栈顶值等相关操作

热门文章

  1. CEC循环生态社区的商业模式瑞波基因XAG
  2. 物联网项目——具体分工
  3. Mysql -- 管理工具
  4. 施工企业选择智慧工地的有效方法
  5. python T检验
  6. 仅一张人脸就能被扒得底裤不剩:口罩墨镜都没用,跨平台跨时空,这个人脸搜索惹了众怒...
  7. lombok报错 InvalidDefinitionException: No serializer found
  8. Linux 操作系统的安装
  9. python 如果文件夹不存在 创建文件夹
  10. 7-4 sdut-C语言实验-分割整数