窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的

1. 子类化

理论:子类化是这样一种技术,它允许一个应用程序截获发往另一个窗口的消息。一个应用程序通过截获属于另一个窗口的消息,从而实现增加、监视或者修改那个窗口的缺省行为。子类化是用来改变或者扩展一个已存在的窗口的行为、而不用重新开发的有效途径。想要获得那些预定义控件窗口类(按钮控件、编辑控件、列表控件、下拉列表控件、静态控件和滚动条控件)的功能而又要修改它们的某些行为的一个便利的方法就是对它们进行子类化。例如,对于一个在对话框中的多行编辑框来说,当用户按下Enter键时,对话框会关闭。通过对编辑控件子类化,一个应用程序就能拥有一个可以往文本中插入回车和换行,而同时又不会关闭对话框的编辑控件,应用程序不用为这个特殊的需要而去专门开发一个编辑控件。

改变一个已经存在的窗口实例的性质:消息处理与其他实例属性。
在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 0;
        }
    default: return ::CallWindowProc(pSubclassOldEditProc, hWnd, message, wParam, lParam);
    }
}

// 对创建好的窗体进行子类化代码
   {
       // 创建
       HWND hEdit = CreateWindowEx(NULL, "EDIT", "SubClass",
           WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL, 100,120, 128, 16, 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 0;
        }
    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, 100,100, 128, 16, 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.fmddlmyy.cn/text19.html

时间: 2024-10-12 18:17:53

窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的的相关文章

Delphi的子类化控件消息, 消息子类化

所谓的子类化,网上有很多说明,我就说我个人的随意理解,可能有误,请列位看官斟酌理解. 所谓子类化,个人理解就是拦截某个控件的消息以及样式,来进行自己的特定处理以达到特殊的功能需求.这个子类化,可以有子类化别人的程序的控件,也有子类化自己程序的控件. 子类化别人的,就需要注入到别人的程序内部,然后做对应处理拦截,我这里主要针对的是自己程序的处理. 这个就比较简单了,有API函数SetWindowLong,用这个函数,就可以拦截某WinControl的Wndproc窗口过程了. 在Delphi中,所

5.1 类、超类和子类

5.1 类.超类和子类 子类比超类拥有的功能更加丰富. 在本例中,Manager类比超类Employee封装了更多的数据,拥有更多的功能. 在Manager类中,增加了一个用于存储奖金信息的域,以及一个用于设置这个域的方法: class Manager extends Employee { private double bonus; ... public void setBouns(double b) { bonus = b; } } 如果有一个Manager对象,就可以使用setBonus方法

Core Java (十一) Java 继承,类,超类和子类

Core Java (十一) Java 继承,类,超类和子类 标签: javaJavaJAVA 2013-01-22 17:08 1274人阅读 评论(0) 收藏 举报  分类: java(58) 读书笔记(46)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 继承关系 两个类之间存在三种关系: 依赖,uses-a,如果一个类的方法操纵另一个对象,我们就说一个类依赖于另一个类. 聚合(关联),has-a,一个对象包含另外一个对象,聚合关系意味着类A的对象包含类B的对象

Java超类引用子类对象的规律

首先,对于JVM实现引用的一个机制是:类实例的引用就是指向一个句柄(handle)的指针,这个句柄就是一堆指针:一个指针指向一块从java堆中为分配出来内存空间:另一个指针指向一张表(实际上这个表格也有两个指针(一个指针指向一个包含了对象的方法表,另外一个指向类对象,表明该对象所属的类型)) 下面举例进行分析:  Student st=new Student();//Student为子类 Person p=st;//Person 为超类 p.sayHello();//该方法在超类和子类中都存在

JAVA构造函数在超类与子类定义鲁波总结

1.子类无构造函数,超类无构造函数,创建的无参数的对象: 编译通过. 1 class A 2 { 3 4 } 5 6 class B extends A 7 { 8 9 } 10 public class Testeeer 11 { 12 public static void main(String [] args) 13 { 14 B b_01=new B(); 15 } 16 } 2.子类有无参数构造函数,超类无构造函数,创建的无参数的对象: 运行结果: 调用了B的无参构造函数 1 clas

继承——类、超类、子类

http://user.qzone.qq.com/1282179846/blog/1470248763 引入一个简单的例子: //Employee类 import java.util.*; public class Employee { private String name; private double salary; private Date hireday; public Employee(String n,double s,int year,int month,int day) { n

JS 超类和子类

此篇由别的大神的博客与<javascript高级程序设计>一书整理而来 原博客地址:https://hyj1254.iteye.com/blog/628555 看到javascript高级程序设计的面向对象章节看到超类与子类这个概念词,不懂上度娘查了才知道是怎么一回事. 说到超类与子类,就不得不提起原型模式,原型对象,原型链与原型链继承了 在原型模式章节中,对于原型模式这样描述:“我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含

[项目构建 九]babasport 页面静态化技术Freemarker技术的介绍及使用实例.

一.FreeMarker简介 1.动态网页和静态网页差异 在进入主题之前我先介绍一下什么是动态网页,动态网页是指跟静态网页相对应的一种网页编程技术.静态网页,随着HTML代码的生成,页面的内容和显示效 果就不会再发生变化(除非你修改页面代码).而动态网页则不然,页面代码虽然没有发生变化,但是显示的内容却是可以随着时间.环境或者数据库操作的结果而 发生相应的变化.简而言之,动态网页是基本的HTML语法规范与java.VB.VC等高级程序设计语言.数据库编程等多种技术的融合,以实现对网站内容 和风格

在CMD窗口中使用javac和java命令进行编译和执行带有包名的具有继承关系的类

一.背景 最近在使用记事本编写带有包名并且有继承关系的java代码并运行时发现出现了很多错误,经过努力一一被解决,今天我们来看一下会遇见哪些问题,并给出解决办法. 二.测试过程 1.父类代码 1 package com.hafiz.zhang; 2 3 public class Fu 4 { 5 private Integer i ; 6 7 public void sayHello(String name) { 8 System.out.println("Hello " + name

超类 与 子类 构造器使用与继承

构造器是隐式静态方法,而静态方法是不能继承的,所以构造器不能继承: 如果父类中实现了其它构造器,则无参数构造器就消失了,不能再调用了: 默认情况下,如果没有显式调用父类构造器,则调用默认的那一个: 编写子类时,必须调用父类构造器(默认调用父类无参构造器) 父类中有自己编写的构造器时(父类中的默认无参构造器就消失了),编写子类时,必须编写自己的构造器,并且在子构造器中调用父类的某一个构造器进行创建父类,如:super(name)等,因为要想有子类,必须先有父类吧  (super()这种形式的父类构