窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的
1. 子类化
理论:子类化是这样一种技术,它允许一个应用程序截获发往另一个窗口的消息。一个应用程序通过截获属于另一个窗口的消息,从而实现增加、监视或者修改那个窗口的缺省行为。子类化是用来改变或者扩展一个已存在的窗口的行为、而不用重新开发的有效途径。想要获得那些预定义控件窗口类(按钮控件、编辑控件、列表控件、下拉列表控件、静态控件和滚动条控件)的功能而又要修改它们的某些行为的一个便利的方法就是对它们进行子类化。例如,对于一个在对话框中的多行编辑框来说,当用户按下Enter键时,对话框会关闭。通过对编辑控件子类化,一个应用程序就能拥有一个可以往文本中插入回车和换行,而同时又不会关闭对话框的编辑控件,应用程序不用为这个特殊的需要而去专门开发一个编辑控件。
子类化使用消息的三种方式:当一个应用程序子类化一个窗口时,它可对消息采取三种操作:(1)把消息传递给原窗口过程;(2)修改消息然后再传递给原窗口过程;(3)不再往下传递消息。理管理好就行啦!
子类化仅被允许用在进程内,一个应用程序不能子类化属于另一个进程的窗口或窗口类(即子类化仅用于修改自己的程序行为,而非修改别人的)。
有两种子类化的类型,它们是实例子类化和全局子类化。
实例子类化是子类化一个独立的窗口信息结构,实例子类化后,只有属于一个特定的窗口实例的消息会被发送到新窗口过程。
全局子类化是替换一个窗口类的WNDCLASS结构中的窗口过程地址,所有在这之后使用该窗口类建立起来的窗口都具有这个被替换的窗口过程地址(所以超类化是全局子类化的一个替代方案)。全局子类化只对那些在子类化生效之后创建的窗口有效,在进行子类化之前,如果已经存在任何用这个被全局子类化的窗口类创建的窗口,这些已经存在的窗口不会被子类化。如果应用程序想要使子类化对这些已经存在的窗口生效,应用程序必须子类化每一个已经存在的该窗口类的实例。
改变一个已经存在的窗口实例的性质:消息处理与其他实例属性。
在SDK编程范畴内,子类化就是改变一个窗口实例的窗口函数(通过GetWindowLong()和SetWindowLong()),子类化所要做的就是为某窗口实例编写新的窗口函数。其操作是在实例级别上进行的。
在MFC中子类化的情况有所不同:所有MFC窗口有相同的窗口函数,由该窗口函数根据窗口句柄查找窗口实例,在把消息映射到该窗口类(class)得消息处理函数上。为了利用MFC的消息映射机制,不宜改变窗口函数(名),MFC也把子类化封装在函数SubclassWindow()中。但子类化的本质没有变:在实例级别影响窗口的消息及其处理。例:
Class B :public A
{
……
}
A a;
B b;
HWND ha=a.GetSafeHwnd();
b.SubclassWindow(ha); #当然A 和B 不一定是继承关系。
注意:在被子类化的窗口销毁之前,必须执行窗口的反子类化:
b.UnSubclassWindow();
2 超类化
窗口超类化是在窗口类——WNDCLASS或WNDCLASSEX(非MFC类概念)级别进行的改变窗口类特征的。
使用过程:首先获得一个已存在的窗口类,然后设置窗口类,最后注册该窗口类。
例:
WNDCLASSEX wc;
wc.cbSize=sizeof(wc); //Windows用来进行版本检查的,与窗口特征无关
GetClassInfoEx(hinst,”XXXXXX”,&wc);
// hinst—定义窗口类XXXXXX的模块的句柄,如为系统定义的窗口类(如:EDIT、BUTTON)则hinst=NULL.。
wc.lpszClassName = “YYYYYYY”;//必须改变窗口类的名字
wc.hbrBackGround = CreateSolidBrush(RGB(0,0.0));//改变背景刷
wc.lpfnWndProc = NewWndProc;//改变窗口函数
……
RegisterClassEx(&wc);// 注册新窗口类
//使用窗口类
……
::CreateWindow(_T(“YYYYYYYY”,……);
故超类化只能改变自己创建的窗口的特征,而不能用于由Windows创建的窗口(如对话框上的按钮就不能进行超类化) 。而子类化是实例级别上的,只要能获得窗口的实例,就可对其子类化,这是唯一的子类化对于超类化的优势。另外,凡是子类化可实现的,超类化都可实现,不过超类化用起来较麻烦。
3. 总结
(0) 子类化修改窗口过程函数, 超类化修改窗口类(新的窗口类名)
(1) 子类化是在窗口实例级别上的,超类化是在窗口类(WNDCLASS)级别上的。
(2) 超类化可以完成比子类化更复杂的功能,在SDK范畴上,可以认为子类化是超类化的子集。
(3) 子类化只能改变窗口创建后的性质,对于窗口创建期间无能为力(无法截获ON_CREATE 事件),而超类化可以实现;超类化不能用于Windows已创建的窗口,子类化可以。
4. 其他
在 眼见为实(2):介绍Windows的窗口、消息、子类化和超类化 这里有一个例子..
可以得出结论
a) 子类化的classname 是不会变化的, 而超类化使用新注册classname
b) 子类化 & 超类化 描述的是一个动作 和实现方法没什么关系..... 主要是子类化是SubclassWindow, SubclassDlgItem, 而超类化是RegisterClassEx(&newwindowclass)
c) 感觉具体没有必要区分这些, 实现功能就行了, 呵呵
参考:http://www.cppblog.com/bigsml/archive/2007/08/24/30780.aspx
--------------------------------------------------------------------------------------------
Delphi里的TButton就是使用超类化技术,包装了Windows的原生Button,从而变成TButton的
--------------------------------------------------------------------------------------------
子类化:
// 保存窗口默认的消息响应函数指针
WNDPROC pSubclassOldEditProc;
// 用于替换子类化窗口的消息响应函数
LRESULT CALLBACK JcEditProcSubClass(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CHAR:
{
::MessageBox(hWnd, "WM_CHAR响应", "子类化", MB_OK);
return ;
}
default: return ::CallWindowProc(pSubclassOldEditProc, hWnd, message, wParam, lParam);
}
} // 对创建好的窗体进行子类化代码
{
// 创建
HWND hEdit = CreateWindowEx(NULL, "EDIT", "SubClass",
WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL, ,, , , hWnd, NULL, hInstance, NULL);
pSubclassOldEditProc = (WNDPROC)::SetWindowLong(hEdit, GWL_WNDPROC, (DWORD)JcEditProcSubClass);
// 显示
ShowWindow(hEdit, nCmdShow);
UpdateWindow(hWnd);
}
超类化:
WNDPROC pSuperOldEditProc;// 保存窗口默认消息处理函数
// 用于替换的超类化消息响应函数
LRESULT CALLBACK JcEditProcSuper(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CHAR:
{
::MessageBox(hWnd, "WM_CHAR响应", "超类化", MB_OK);
return ;
}
default: return ::CallWindowProc(pSuperOldEditProc, hWnd, message, wParam, lParam);
}
} // 创建超类化控件代码
{
// 取得原控件信息
WNDCLASSEX myeditClass;
::GetClassInfoEx(hInstance, "EDIT", &myeditClass);
// 保存原控件默认消息处理函数
pSuperOldEditProc = myeditClass.lpfnWndProc;
// 设置替换的消息处理函数
myeditClass.lpfnWndProc = JcEditProcSuper;
// 指定新的窗口类名字
myeditClass.lpszClassName = "JcilyEdit";
// 设置结构体大小
myeditClass.cbSize = sizeof(WNDCLASSEX);
// 注册新信息
RegisterClassEx(&myeditClass);
// 创建
HWND hEdit = CreateWindowEx(NULL, myeditClass.lpszClassName, "SuperClass",
WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL, ,, , , hWnd, NULL, hInstance, NULL);
// 显示
ShowWindow(hEdit, nCmdShow);
UpdateWindow(hWnd);
}
参考:
http://www.cnblogs.com/jcily/archive/2009/10/22/1587778.html
http://blog.csdn.net/chenhao518530/article/details/628556
http://www.cnblogs.com/tonybain/archive/2006/01/19/320366.html
http://www.cnblogs.com/tonybain/archive/2006/01/20/320788.html
http://www.cnblogs.com/tonybain/archive/2006/01/20/320887.html
http://www.fmddlmyy.cn/text19.html
窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的的更多相关文章
- Delphi的子类化控件消息, 消息子类化
所谓的子类化,网上有很多说明,我就说我个人的随意理解,可能有误,请列位看官斟酌理解. 所谓子类化,个人理解就是拦截某个控件的消息以及样式,来进行自己的特定处理以达到特殊的功能需求.这个子类化,可以有子 ...
- JavaScript 超类与子类 继承
//超类和子类 继承的实现 function R(w, h) { var date = new Date(); this.width = w; this.height = h; this.create ...
- Java核心技术第五章——1.类、超类、子类(2)
继上一篇Java核心技术第五章——1.类.超类.子类(1) 6.重载解析 假如调用ClassName.Method(args) 1.编译器列出类ClassName所有名为Method的方法. 2.编译 ...
- Java核心技术第五章——1.类、超类、子类(1)
1.定义子类: 关键字extends表明正在构造的新类派生与一个已存在的类.已存在的类称为超类.基类或父类:新类称为子类.派生类或孩子类.超类和子类是Java程序员最常用的两个术语(emmm~~我觉得 ...
- JS 超类和子类
此篇由别的大神的博客与<javascript高级程序设计>一书整理而来 原博客地址:https://hyj1254.iteye.com/blog/628555 看到javascript高级 ...
- JAVA构造函数在超类与子类定义鲁波总结
1.子类无构造函数,超类无构造函数,创建的无参数的对象: 编译通过. class A { } class B extends A { } public class Testeeer { public ...
- Core Java (十一) Java 继承,类,超类和子类
Core Java (十一) Java 继承,类,超类和子类 标签: javaJavaJAVA 2013-01-22 17:08 1274人阅读 评论(0) 收藏 举报 分类: java(58) 读 ...
- 页面静态化技术Freemarker技术的介绍及使用实例.
一.FreeMarker简介 1.动态网页和静态网页差异 在进入主题之前我先介绍一下什么是动态网页,动态网页是指跟静态网页相对应的一种网页编程技术.静态网页,随着HTML代码的生成,页面的内容和显示效 ...
- Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- Java多线程系列--“JUC原子类”04之 AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
随机推荐
- C# HTTP 请求
public class HttpHelper { /// <summary> /// 创建GET方式的HTTP请求 /// </summary> public static ...
- 产品原型设计5:移动App原型设计神器 - POP(Prototyping on Paper)
一般来说,苦逼的互联网产品经理们都知道 Axure 这个原型设计工具,一方面是因为它提供了足够简单的拖拽操作,易上手,且有很多模板方便复用:另一方是因为它可直接输出html,直接在浏览器里给团队成员和 ...
- linux管理网络连接指令
ethtool eth0 查看 eth0对应网卡的设置 ethtool -i eth0 查看 eth0网卡的驱动信息 ethtool -S eth0 查看网卡的统计信息 ethtool -s eth ...
- 九度OJ 1078 二叉树遍历
题目地址:http://ac.jobdu.com/problem.php?pid=1078 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历 ...
- PHP——图片上传
图片上传 Index.php文件代码: <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 转(sphinx 多索引使用 方法 )
1 http://blog.csdn.net/adparking/article/details/7080278 文章不错 总结 1.索引合并问题,前面已经解释过,两个索引合并时,都要读入,然后还要 ...
- yii2源码学习笔记(十)
继续了解Application. /** * Registers the errorHandler component as a PHP error handler. * 注册errorHandler ...
- nginx 反向代理 odoo, 速度提升
1: sudo apt-get install nginx 2: add server: 在/etc/nginx/sites-enabled 中增加一个可用的server. 文件如下图所示 3:重 ...
- 4种方法生成二维码 (js 控制canvas 画出 二维码)
随着网络的迅速发展 发展 发展,二维码的应用将会越来越多.同时很多只是很平凡的二维码,请拿起你的手 把这个二维码 设计起来吧.下面分享了几个非常好的二维码设计. 二维码原理: 二维条码/二维码可以分 ...
- 黑马程序员-------.net基础知识五
方法(函数) 作用:用来重复代码,当我们在一个过程中反复的写了同样的代码,一般情况下,我们就可以把需要重复写的代码定义在方法中,用的时候只需调用即可 语法: [访问修饰符][static] 返回值类型 ...