【转载】MFC怎么封装CreateWindow
原文: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的更多相关文章
- [转载][MFC]MFC的美化
转载:http://blog.csdn.net/b_silence/article/details/10489085 前些天用MFC开发一个桌面程序,实现功能后客户说界面太难看,自己仔细看看也着实难看 ...
- [转载] MFC绘制动态曲线,用双缓冲绘图技术防闪烁
转载的原文地址 先上效果图 随着时间的推移,曲线向右平移,同时X轴的时间坐标跟着更新. 一.如何绘制动态曲线 所谓动画,都是一帧一帧的图像连续呈现在用户面前形成的.所以如果你掌握了如何绘制静态曲线,那 ...
- MFC resizer封装
用法: #include "resizer.h" 在mfc对话框头文件里面添加成员: CResizer m_Resizer; mydialog.cpp里面: OnInitDialo ...
- [转载]robotium脚本封装为APK,实现脱离手机数据线,使用按钮点击控制用例
原文地址:robotium脚本封装为APK,实现脱离手机数据线,使用按钮点击控制用例运行作者:机器,猫 最近一直在完成一些robotium的小功能,用来更方便的完成一些小功能的测试,或者可以说用来娱乐 ...
- 【转载】MFC的Main函数跑哪去了
原文:http://blog.csdn.net/weiwenhp/article/details/8455471 习惯的思维 用习惯了C的人要看一个程序时首先会想到找到那个main函数在哪,然后再顺着 ...
- 将MFC Grid control封装为DLL的做法及其在DLL中的使用方法
MFCGrid control是一款非常优秀的网格控件,支持非常丰富的界面元素,如下图: 因而在数据库程序及报表程序应用较为广泛,其源码可以在下面下载到: MFC Grid control2.27源码 ...
- MFC的本质
一.引言 上一专题中,纯手动地完成了一个Windows应用程序,然而,在实际开发中,我们大多数都是使用已有的类库来开发Windows应用程序.MFC(Microsoft Foundation Clas ...
- MFC GDI绘图基础
一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...
- 深入浅出话VC++(2)——MFC的本质
一.引言 上一专题中,纯手动地完成了一个Windows应用程序,然而,在实际开发中,我们大多数都是使用已有的类库来开发Windows应用程序.MFC(Microsoft Foundation Clas ...
随机推荐
- hdfs操作手册
hdfscli 命令行 # hdfscli --help HdfsCLI: a command line interface for HDFS. Usage: hdfscli [interactive ...
- 水晶报表自定义纸张大小打印 (Crystal Report Print with custom paper size)
System.Drawing.Printing.PrintDocument doc = new PrintDocument(); doc.PrinterSettings.PrinterName = & ...
- 固定UIScrollView滑动的方向
固定UIScrollView滑动的方向 一般而言,我们通过这两个参数CGRectMake以及contentSize就可以自动的让UIScrollView只往一个方向滚动.但我遇到过非常奇葩的情况,那就 ...
- orcl数据库查询重复数据及删除重复数据方法
工作中,发现数据库表中有许多重复的数据,而这个时候老板需要统计表中有多少条数据时(不包含重复数据),只想说一句MMP,库中好几十万数据,肿么办,无奈只能自己在网上找语句,最终成功解救,下面是我一个实验 ...
- Python初学者第二十四天 函数进阶(3)生成器
24day 1.列表生成式: 循环模式:[变量(加工后的变量) for 变量 in iterable] print([i for i in range(0,101,2)]) [1,4,9,16,25, ...
- Session攻击
1.简介 Session对于Web应用无疑是最重要的,也是最复杂的.对于web应用程序来说,加强安全性的第一条原则就是 – 不要信任来自客户端的数据,一定要进行数据验证以及过滤,才能在程序中使用,进而 ...
- 手动安装gradle
在学习andorid studio时发现编译超级无比的慢,网上有文说是因为gradle的原因,使用离线gradle可以大幅提高编译速度,准备尝试下看看如何.由于gradle的资料都是英文,而我又是英文 ...
- Spring Boot REST
资源(Resources) 所谓资源,就是网络上一个实体,或者是网络上一个具体信息.他可以是一段文本,一张图片,一种服务,总之是一个具体的实体.可以用一个URI(统一资源定位符)指向它,每种资源对应一 ...
- mysql workbench的PK,NN,UQ,BIN,UN,ZF,AI
mysql workbench建表时PK.NN.UQ.BIN.UN.ZF.AI的意思,后面几个老搞不清,随记在这便于以后方便查. [intrinsic column flags] (基本字段类型标识) ...
- 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 F题 Clever King(最小割)
2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...