原文:http://blog.csdn.net/weiwenhp/article/details/8796337

我们知道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]MFC的美化

    转载:http://blog.csdn.net/b_silence/article/details/10489085 前些天用MFC开发一个桌面程序,实现功能后客户说界面太难看,自己仔细看看也着实难看 ...

  2. [转载] MFC绘制动态曲线,用双缓冲绘图技术防闪烁

    转载的原文地址 先上效果图 随着时间的推移,曲线向右平移,同时X轴的时间坐标跟着更新. 一.如何绘制动态曲线 所谓动画,都是一帧一帧的图像连续呈现在用户面前形成的.所以如果你掌握了如何绘制静态曲线,那 ...

  3. MFC resizer封装

    用法: #include "resizer.h" 在mfc对话框头文件里面添加成员: CResizer m_Resizer; mydialog.cpp里面: OnInitDialo ...

  4. [转载]robotium脚本封装为APK,实现脱离手机数据线,使用按钮点击控制用例

    原文地址:robotium脚本封装为APK,实现脱离手机数据线,使用按钮点击控制用例运行作者:机器,猫 最近一直在完成一些robotium的小功能,用来更方便的完成一些小功能的测试,或者可以说用来娱乐 ...

  5. 【转载】MFC的Main函数跑哪去了

    原文:http://blog.csdn.net/weiwenhp/article/details/8455471 习惯的思维 用习惯了C的人要看一个程序时首先会想到找到那个main函数在哪,然后再顺着 ...

  6. 将MFC Grid control封装为DLL的做法及其在DLL中的使用方法

    MFCGrid control是一款非常优秀的网格控件,支持非常丰富的界面元素,如下图: 因而在数据库程序及报表程序应用较为广泛,其源码可以在下面下载到: MFC Grid control2.27源码 ...

  7. MFC的本质

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

  8. MFC GDI绘图基础

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

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

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

随机推荐

  1. java笔记--关于多线程如何查看JVM中运行的线程

    查看JVM中的线程 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3890280.html "谢谢-- ThreadGrou ...

  2. Python下操作sqlite3

    import sqlite3 dbpath = 'C:\\Django\\workplace\\sf\\d1.sqlite3' conn = sqlite3.connect(dbpath) cu = ...

  3. CMD命令行窗口 复制黏贴

    1.在cmd命令窗口空黑处,单击鼠标右键——选择[标记]——单击鼠标左链拖动选择要复制的文字,[再按一下Eenter键]就完成了命令的复制了. 2.粘贴就更简单了,窗口内单击右键——选择[粘贴],就将 ...

  4. (转)图形学理论知识 BRDF 双向反射分布函数(Bidirectional Reflectance Distribution Function)

    BRDF理论 BRDF表示的是双向反射分布函数(Bidirectional Reflectance Distribution Function),它描述了光线如何在物体表面进行反射,可以用来描述材质属 ...

  5. .Net开发八年,坐标杭州,上个月换工作感觉现在.Net岗位很少,希望和同在杭州的同行们交流一下

    .Net开发八年,坐标杭州,中间做过2年Java, 目前新入职一家做防伪溯源的中型公司,200人左右, 之前在一家500人规模的软件公司工作过4年,后面2年工作过3家互联网创业公司, 上个月换工作感觉 ...

  6. 阿里八八Alapa事后诸葛亮

    设想和目标 1.我们的软件要解决什么问题?是否定义的很清楚?是否对典型用户和典型场景有清晰的描述? 我们的项目希望解决用户对于时间.日程管理上不够方便.直观.易丢失的问题,因为并不是新颖高端的概念,因 ...

  7. logstash.conf 根据不同地址创建索引

    input { http { host => "0.0.0.0" port => 9700 type => "from_ys" }}input ...

  8. FWT背板笔记

    板子 背板子.jpg \(Fwt\)用于解决这样的问题 \[C_i=\sum_{j\bigoplus k=i}A_j\times B_k\] 其中\(\bigoplus\)是一种二元运算符,如\(or ...

  9. ElasticSearch 通过nginx做HTTP验证

    在ElasticSearch 的设置文件中如果设置了 network.host: 0.0.0.0 则表示ElasticSearch 服务是公开的任何ip都可以访问ElasticSearch 服务.这样 ...

  10. App-IOS与Android弱网环境测试

    弱网环境下App的功能是否正常使用,是否会发生Crash的等情况? 1.IOS ios系统一般自带弱网环境测试,可以通过设置各种网络环境,模拟弱网环境,如3G,wifi,very bad Networ ...