面向对象大家都清楚。现在OO的主流是基于类的面向对象。子类化故名思义就是定义一个子类,也就是要订制一个类变成一个新类的意思。
不过Windows的子类化不是如此。
首先,我们知道,除了基于类的面向对象以外,还有基于原型(或者叫基于对象)的面向对象。Windows是一个基于对象的OS,它的对象系统更倾向于基于原型的OO。Windows开发的一个核心概念是Window,也就是常说的窗口,所有的一切别的东西都是围绕着这个展开的。一个Windows应用程序,其基本的逻辑框架就是:创建一个窗口,接收系统发给该窗口的消息进行处理。收到结束消息的时候,关掉窗口,程序完蛋。
Window(注意,不是 Windows)相关的一个概念叫作WindowClass,窗口类。窗口类是个啥东西?呵呵,窗口类也是一个对象,具体的可以认为是Window的原型。创建一个WindowClass对象,可以基于该窗口类对象创造多个Window,这些Window在某一方面都是一致的。举个例子,有一个窗口类叫做Button,以这个Button为原型创建的所有Window在某一方面都是一样的。哪一方面呢?某些样式,消息处理例程,菜单等等等等。这些都是 WindowClass里面规定的东西。
那位说了,哦,知道了,基于窗口类原型创建出来Window,这个过程就是子类化。呵呵,广义上说,这是对的,就是特化了一些东西。但Windows子类化有个特殊的含义,它是特指某种行为的。
WindowClass作为一个对象,拥有对象的一切特征,其中包括修改其状态(或属性)的能力。WindowClass有一个属性叫做消息处理器,其实是一个函数指针,指向一个处理发送给它的实例(也就是那些以它为原型的Window)的消息的函数。
所谓的子类化,就是替换这个函数指针成员,用一个新的消息处理函数替代原来的消息处理函数。你或许会觉得奇怪,为什么这个动作叫做子类化?仔细想想其实也不奇怪,不就是修改了WindowClass的行为了么,这个就是子类化了:)
现在我们可以深入的分析一下这个消息处理函数的特征了。
它的职责是处理OS分发给它的各种消息,所以他的典型结构如下:
Handle
{
switch (msg.name)
{
case msgA:
processMsgA(msg.params);
break;
...
default:
windowsSystemDefaultProcess(msg);
break;
}
}
对于所有感兴趣的消息,都可以加一个分支处理。于是很多人开始不满了,觉得有坏气味,要重构。重构的方式是把消息和处理做成一个map,这样消息处理就变成:
Handle
{
if (map[msg.name])
{
map[msg.name](msg.params);
return;
}
return windowsSystemDefaultProcess(msg);
}
剩下的问题就是怎么充填这个消息到处理的映射了。
这个充填的方式,MFC采用了宏(其实大多数C++框架都采用了宏),但是宏并不让人满意。采用宏也是历史原因导致的,那时候C++并没有STL这么好用的容器库。有了map,我们再采用宏的方式生成一个映射数组的方式已经过时了。
有了这一步的重构,我们就可以一个函数针对一个消息进行处理了,CWnd就帮我们干了这样一件事。我们要是相对某个特定的消息进行特定的处理,可以给它一个特定的处理函数,放在map中替换原来的处理函数即可。还有另一种方式就是override从CWnd继承下来的消息处理的虚函数,使用C++的动态分派能力进行特定化。
分享到:
相关推荐
在Windows编程中,Win32 API提供了一种强大的机制,允许开发者对已存在的窗口进行定制,这就是所谓的“窗口子类化”(Window Subclassing)。窗口子类化是一种技术,通过它,我们可以替换一个窗口的默认消息处理函数...
这就是所谓的"子类化"技术,通过子类化我们可以扩展控件的功能。 子类化是Windows API中的一种技术,允许我们创建一个新窗口类,继承自已有窗口类(如超级列表框),然后替换或添加新的消息处理函数,实现对原有...
这种方法将数据和操作数据的方法封装在一起,形成所谓的“对象”,从而使得代码更易于理解、维护和重用。本课程主要围绕面向对象方法学展开,结合VC++集成开发环境进行实践教学。 在面向对象编程(OOP)中,有四个...
C# 是一种支持面向对象特性的强类型编程语言,由微软开发,广泛应用于Windows平台上的软件开发,包括桌面应用、Web应用和游戏开发等。在C#中,多态性(Polymorphism)是面向对象三大特性(封装、继承、多态)之一,...
这就是所谓的“控件重写”(Control Overriding)。标题“control-rewrite.rar_control_重写控件”提示我们这是一个关于控件重写的资源包,适用于初学者。描述中提到这个资料已经在Visual Studio 2008环境下测试过,...
在C#编程中,WPF(Windows Presentation Foundation)和WinForms是两种常见的用户界面框架,它们各有优势,但在某些情况下,开发者可能需要在WPF应用中集成WinForms控件,或者反之,这就是所谓的“互操作性”。...
这就是所谓的"CStatic链接网站类"。这个类允许我们在对话框或其他窗口中添加一个静态文本或图像,当用户单击时,它会启动默认的浏览器并导航到预设的URL。 `CStatic`链接网站类通常涉及到以下几个关键知识点: 1. ...
wxWidgets是一个开源的C++库,它允许开发者在多个操作系统平台上创建原生GUI应用程序,包括Windows、Linux和macOS。这个测试项目主要是用来验证和展示如何使用wxWidgets来创建基本的窗口,并在窗口上进行图形绘制。 ...
在C++编程中,继承是面向对象编程的一个核心特性,它允许我们创建一个新类(子类或派生类)来扩展已存在的类(基类或超类)。在这个"Windows编程_C/C++_"主题的"Inheritence.zip"压缩包中,我们可以看到一系列关于类...
- 开发者还可以通过子类化InkCanvas并覆盖其部分方法,以实现更复杂的绘图逻辑或特殊功能。 综上所述,InkCanvas是WPF中一个强大的绘图和手写输入控件,能够轻松实现涂鸦、擦除和选择等功能,配合C#编程,可以构建...
这确保了在创建子类对象时,父类的构造方法会被自动调用,从而完成必要的初始化工作。 4. **浮点数表示**:计算机内部通常使用阶码和尾数来表示浮点数。这种方法能够有效地表示非常大或非常小的数值,并且保持较高...
当需要在`DataGridView`的列中实现可下拉选择的字段时,我们可以将`ComboBox`集成到`DataGridView`中,这就是所谓的“DataGridView+ComboBox”组合。下面我们将详细探讨如何在C#环境下实现这个功能,以及相关的技术...
QT框架是Qt公司开发的一款强大的跨平台应用开发框架,它支持Windows、Linux、macOS、Android等操作系统。在QT中,我们有时希望我们的应用程序在系统上只运行一个实例,即当用户再次尝试启动该程序时,而不是启动新的...
- **ASP (Active Server Pages)**:一种服务器端脚本环境,适用于 Windows 平台。 - **JSP (JavaServer Pages)**:基于 Java 技术的服务器端开发框架。 - **PHP (Hypertext Preprocessor)**:一种广泛使用的开源...
<<page 1>> page begin==================== 目 ...1.1.1 什么是.NET 2000 年 6 月 22 日 不论对 Microsoft 还是对整个 IT 业界都将成为值得纪念的一天 这一天 微软公司正式推出了其下一代...
所谓的“完整解决方案”意味着这个项目提供了一个解决特定问题的全面代码实现,包括所有必要的类和方法,可以作为一个参考或学习资源。 **标签:“C#”** C#是微软开发的一种现代、类型安全的面向对象编程语言,...
- 输入掩码主要用于限制或格式化输入数据,确保数据的有效性和一致性。 ### 17. 数组的遍历与求和 **题目**: 执行下列程序段后,正确的结果是? **代码**: ```c++ int k, a[3][3] = {1,2,3,4,5,6,7,8,9}; for (k ...
NEAT 开 发 指南 文档 适用于 PT80 系列 移动数据终端 版本记录 版本号 版本描述 发布日期 V 1.0 初始版本。 2012-04-12 V1.1 修改前三章内容 2012-09-25 目录 第一章 关于本手册.....................................