窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(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 ...
随机推荐
- ASP.NET 设计模式中依赖倒置原则
依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象. B.抽象不应该依赖于具体,具体应该依赖于抽象. 依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于 ...
- java新手笔记17 参数
package com.yfs.javase; public class ParamDemo { public static void main(String[] args) { int a = 3, ...
- 动态加载js、css 代码
一.原生js: /** * 加载js和css文件 * @param jsonData.path 前缀路径 * @param jsonData.url 需要加载的js路径或css路径 * @param ...
- windows server 2003 禁止开机显示“关闭事件跟踪”
关机事件跟踪(Shutdown Event Tracker)也是Windows server 2003区别于其他工作站系统的一个设置,对于服务器来说这是一个必要的选择,但是对于工作站系 ...
- 08_使用TCP/IP Monitor监视SOAP协议
[SOAP定义] SOAP 简单对象访问协议,基于http传输xml数据,soap协议体是xml格式.SOAP 是一种网络通信协议SOAP 即Simple Object Access Pr ...
- 【C++11】新特性——Lambda函数
本篇文章由:http://www.sollyu.com/c11-new-lambda-function/ 文章列表 本文章为系列文章 [C++11]新特性--auto的使用 http://www.so ...
- OpenJudge 2749 分解因数
1.链接地址: http://bailian.openjudge.cn/practice/2749/ 2.题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 给出一个正整数a,要求分 ...
- 利用Xlinix SDK 建立Linux程序以及对该程序进行调试
一.创建Linux程序 1. 点击File > New > Application Project .并参照下图设置. 2. 输入工程名,并选择存储路径. 3. 选择所需的操作系统平台(O ...
- 【转】Nginx 服务器安装及配置文件详解
1. 安装nginx 1.1 选择稳定版本 我们编译安装nginx来定制自己的模块,机器CentOS 6.2 x86_64.首先安装缺少的依赖包: # yum -y install gcc gcc-c ...
- sublime2 Ctags 快捷键
Commands Listing Command Key Binding Alt Binding Mouse Binding rebuild_ctags ctrl+t, ctrl+r navi ...