C++ 中超类化和子类化
超类化和子类化没有具体的代码,其实是一种编程技巧,在MFC和WTL中可以有不同的实现方法。
窗口子类化:
原理就是改变一个已创建窗口类的窗口过程函数。通过截获已创建窗口的消息,从而实现监视或修改已创建窗口类的行为属性。可以用来改变或者扩展一个已存在的窗口的行为,而不用重新开发。比如要获得那些预定义控件窗口类(按钮控件、编辑控件、列表控件、下 拉列表控件、静态控件和滚动条控件)的功能而又要修改它们的某些行为。
子类化的优点主要体现在以下两个方面:首先,它不需要创建新的窗口类,不需要了解一个窗口的窗口过程。这在原来的窗口函数是由别人编写,而且创建过程不可见的情况下非常有用;其次,子类化比较容易实现,因为所有要做的工作仅仅就是写一个窗口函数。
主要步骤为
- 截取该消息,阻止其向原窗口函数发送。
- 修改该消息。
- 修改完毕以后再向原窗口函数发送。
// 保存窗口默认的消息响应函数指针
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);
}
窗口超类化:
窗口超类化是在窗口类——WNDCLASS或WNDCLASSEX(非MFC类概念)级别进行的改变窗口类特征的。改变已有窗口类的行为属性。
- 通过调用 GetClassInfoEx 来获得想要进行超类化操作的窗口类的信息。函数GetClassInfoEx 需要一个指向 WNDCLASSEX 结构的指针,用于当成功返回时填入窗口类的信息。
- 按需要修改 WNDCLASSEX 结构的成员,其中有两个成员必须修改:
hInstance 存放程序的实例句柄
lpszClassName 指向一个新类名的指针
不必修改成员 lpfnWndProc,但大多数情况下还是需要的。但要记住如果要使用函数 CallWindowProc
调用老窗口的过程,那就必须保存成员 lpfnWndProc 的原值。 - 注册修改完的 WNDCLASSEX
结构,得到一个具有旧窗口类某些特性的新窗口类。 - 用新窗口类创建窗。
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);
}
窗口子类化和超类化的区别
(1) 子类化修改窗口过程函数, 超类化修改窗口类(新的窗口类名)
(2) 子类化是在窗口实例级别上的,超类化是在窗口类(WNDCLASS)级别上的。
(3) 超类化可以完成比子类化更复杂的功能,在SDK范畴上,可以认为子类化是超类化的子集。
(4) 子类化只能改变窗口创建后的性质,对于窗口创建期间无能为力(无法截获ON_CREATE 事件),而超类化可以实现;超类化不能用于Windows创建的窗口,子类化可以。
(5) 超类化可以修改包含窗体背景等属性,而子类化不能。
C++ 中超类化和子类化的更多相关文章
- C++ 中超类化和子类化常用API
在windows平台上,使用C++实现子类化和超类化常用的API并不多,由于这些API函数的详解和使用方法,网上一大把.本文仅作为笔记,简单的记录一下. 子类化:SetWindowLong,GetWi ...
- 窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的
1. 子类化 理论:子类化是这样一种技术,它允许一个应用程序截获发往另一个窗口的消息.一个应用程序通过截获属于另一个窗口的消息,从而实现增加.监视或者修改那个窗口的缺省行为.子类化是用来改变或者扩展一 ...
- Win32中安全的子类化(翻译)
关于子类化的话题虽然有些旧,但它至今仍然不失为一种开发Windows的强有力技术,在MFC的内核.甚至.NET的内核中都离不开它,希望本连载能对Windows开发的爱好者有所帮助. 原文标题:Safe ...
- 眼见为实(2):介绍Windows的窗口、消息、子类化和超类化
眼见为实(2):介绍Windows的窗口.消息.子类化和超类化 这篇文章本来只是想介绍一下子类化和超类化这两个比较“生僻”的名词.为了叙述的完整性而讨论了Windows的窗口和消息,也简要讨论了进程和 ...
- 窗口 超类化 子类化 HOOK
body { font-family: Bitstream Vera Sans Mono; font-size: 11pt; line-height: 1.5; } html, body { colo ...
- 流畅python学习笔记:第十二章:子类化内置类型
子类化内置类型 在python2.2之后,内置类型都可以子类化,但是有一个注意事项:内置类型不会调用用户定义的类覆盖的特殊方法.这个说起来比较绕口,什么意思呢.我们来看下下面的代码: class Do ...
- 深入理解MFC子类化
子类化,通俗来讲就是用自己的窗口处理函数来处理特定消息,并将自己其他消息还给标准(默认)窗口处理函数.在SDK中,通过SetWindowLong来指定一个自定义窗口处理函数:SetWindowLong ...
- 走出MFC子类化的迷宫
走出MFC子类化的迷宫 KEY WORDS:子类化 SUBCLASSWINDOW MFC消息机制 许多Windows程序员都是跳过SDK直接进行RAD开发工具[或VC,我想VC应不属于RAD]的学习 ...
- 动态子类化CComboBox以得到子控件EDIT及LISTBOX
动态子类化CComboBox以得到子控件EDIT及LISTBOX Joise.LI写于2004-4-6 ComboBox是比较常用的一个控件,有三种样式:CBS_SIMPLE(简单),CBS_DROP ...
随机推荐
- java获取指定路径下的指定文件/java.io.File.listFiles(FilenameFilter filter)
java.io.File.listFiles(FilenameFilter filter) 返回抽象路径名数组,表示在目录中此抽象路径名表示,满足指定过滤器的文件和目录. 声明 以下是java.io. ...
- mysql explain详解
对于经常使用mysql的兄弟们,对explain一定不会陌生.当你在一条SELECT语句前放上关键词EXPLAIN,MySQL解释它将如何处理SELECT,提供有关表如何联合和以什么次序的信息.借助于 ...
- R 字符串处理函数
用R来处理字符串数据并不是一个很好的选择,还是推荐使用Perl或者Python等语言.不过R本身也提供了一些常用的字符串处理函数,这篇文章就对这些字符串函数做一个简单的总结,具体各个函数的使用方法还是 ...
- jQuery 学习之路(1):引子
一.主流 javascript 库 除 jQuery 外,还有 Prototype.Dojo.YUI.ExtJS.MooTools ,其中 Prototype 较老,结构设计较为松散,ExtJS 界面 ...
- HTML中head头结构
HTML head 头部分的标签.元素有很多,涉及到浏览器对网页的渲染,SEO等等,而各个浏览器内核以及各个国内浏览器厂商都有些自己的标签元素,这就造成了很多差异性.移动互联网时代,head 头部结构 ...
- R入门<二>-时间序列研究
续之前那篇随笔 前天写完随笔后,很自豪的拿出来去跟带我入数据挖掘和SAS基础的大牛@八公炫耀,然后收获了一堆时间序列的材料,非常感谢大牛! ARIMA就是看图形,ACF和PACF,原理不需要知道,因为 ...
- hash-4.hashtable
1.先看hashtable的源代码 public synchronized V put(K key, V value) { // Make sure the value is not null if ...
- javascript高级程序设计---NodeList和HTMLCollection
节点对象都是单个节点,但是有时会需要一种数据结构,能够容纳多个节点.DOM提供两种接口,用于部署这种节点的集合分别是NodeList和HTMLCollection MDN上的定义: NodeList: ...
- phpcms中常用代码总结
1.调用数据库模型 $this->db = pc_base::load_model('test_model');//从"phpcms/model/"目录下加载模型类文件 其中 ...
- android常见问题(一)
一:文本的颜色选择器: 在res目录下面创建color文件夹,在color文件夹下面创建font_style_colors.xml文件<?xml version="1.0" ...