Windows 窗口子类化和超类化

子类化(Subclass)是指替换窗口过程(WNDPROC)

超类(Superclass)是替换窗口过程(WNDPROC),并且替换ClassName。

Subclass不太像继承,而像一种外挂(HOOK)行为。

Superclass更像继承,因为生成了新的窗口类,并且继承了行为。

WinX中Subclass和Superclass用同一个类实现,都是 WinX::SubclassWindow。

关于用法上:

以Button为例,如果是SubClass,那么用户先要有一个Button,然后Subclass它。

也就是Subclass发生在CreateWindow之后。

如果是Superclass,那么用户CreateWindow时直接传入新的窗口类名称,根本没有Button被生成。

当然,这要求CreateWindow之前调用该窗口类的RegisterClass

MFC是子类化技术

---------------------------------------------------------------------------------------华丽分割---------------------------------

Windows GUI 窗体的子类化和超类化

窗体子类化的作用:窗口子类化技术最大的特点就是能够截获windows的消息。一旦用户自定义的窗口函数截取了传向原窗口函数的消息,就可以对被截取的消息进行如下处理:

将其传给原窗口函数。这是对大多数消息应该采取的措施,因为子类通常只对原来的窗口特性做少量的改动。

截取该消息,阻止其向原窗口函数发送。

修改该消息,修改完毕以后再向原窗口函数发送。

Windows SDK提供了一些设计好的窗口类,如edit  listbox  treeview 等。通过截取这些通用窗口类的消息,用户程序可以为它们添加新的特性,改善其外观,扩充其功能

子类化的优点:不需创建新的窗口类,不需了解一个窗口的窗口过程。这在原来的窗口函数是由别人编写,而且创建过程不可见的情况下非常有用。子类化比较容易实现,因为只需写一个窗口函数

VC中实现窗口子类化:

VC基于SDK编程的窗口子类化的基本步骤如下:

正常创建原始窗口,得到窗口的句柄。

调用GetWindowLong得到原来的窗口函数OldWndProc

调用SetWindowLong设置新的窗口函数NewWndProc

新的窗口函数的代码如下所示:

LRESULT NewWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)

{

            if(msg==WM_USER+N)

            {

            }

            return CallWindowProc(OldWndProc,hwnd,msg,wParam,lParam);

}

注意:调用旧的窗口函数时,不能直接用OldWndProc(....),必须CallWndProc,否则出现堆栈错误;

 

窗口子类化允许你接管被子类化的窗口,使你对它有绝对的控制权

子类化并不局限于控件,可以子类化任意窗口,现在我们把精力集中于如何子类化一个窗口上,让我们想想Windows如何知道button控件的窗口处理函数放在哪里,

通过WNDCLASSEX 成员 lpfnWndProc指出了窗口函数地址,如果能用自己编写的窗口函数地址来替换这个成员变量,那Windows不就把消息发到自定义窗口函数了么,通过调用SetWindowLong来实现。工作还是比较简单的:写一个窗口函数用于处理发给button控件的消息,用参数GWL_WNDPROC调用SetWindowLong,如果调用成功就返回与调用功能相联系的一个32位整数。注意:有一些不处理的消息,需要派遣给原来的窗口函数来处理。

在创建了button控件后,通过调用SetWindowLong把原来的窗口函数地址替换为自定义函数的地址,从而对它实施了窗口子类化,要注意为了调用函数CallWindowproc,我们存储了原窗口函数地址,自己编写的hBmpButtonProc仅仅是个普通的窗口函数,当然也可以调用一次SetWindowLong来储存这个32位值.

---------------------------------------------------------------------------------------华丽分割---------------------------------

Windows窗口子类化

利用子类化技术拓展Edit控件功能

认识子类化技术

把一个窗体子类化其实就是使用SetwindowLong为该窗体设计一个新的窗体过程,然后可以在该窗体函数中处理特定消息,而那些不关心的消息可以通过CallWindowProc传递给默认处理

从功能上说,子类化技术有点类似于钩子函数(SetWindowHookEx),都可以对一些特定的消息进行处理。但两者有本质区别,钩子函数是针对系统的消息传递机制,而子类化是针对特定的窗体。利用钩子可以处理某一类或几类消息,而利用子类化技术则能处理特定窗体的绝大部分消息。

一个对话框(IDD_TEST_SAMPLE)和一个EDIT控件(IDC_TEST)

#include "resource.h"

#include <tchar.h>

#include <windows.h>

LONG DefWndProc=NULL;

 

LRESULT CALLBACK EditNewProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);

BOOL CALLBACK TestSampleProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

         DialogBox(hInstance,MAKEINTRESOURCE(IDD_TEST_SAMPLE,0,TestSampleProc);

         return 0;

}

LRESULT CALLBACK EditNewProc(HWND hwnd,UINT msg,WPARAM  wParam,LPARAM lParam)

{

 

//        return CallWindowProc((WNDPROC)DefWndProc,hwnd,msg,wParam,lParam);

          if(msg==WM_CHAR)

          {

                       .......

          }

}

BOOL CALLBACK TestSampleProc(HWND hwnd,MSG msg,WPARAM wParam,LPARAM lParam)

{

           LONG DlgWndProc,EditWndProc;

           TCHAR buf[128];

            switch(msg)

            {

                            case WM_INITDIALOG:

                                           DlgWndProc=GetWindowLong(hwnd,GWL_WNDPROC);

                                           EditWndProc=GetWindowLong(GetDlgItem(hwnd,IDC_TEST),GWL_WNDPROC);

                                           wsprintf(buf,_T("DlgWndProc  :%08X\nEditWndProc  :  %08X\nDefWndProc:%08X\n"),

                                                             DlgWndProc,EditWndProc,DefWndProc);

                                            MessageBox(hwnd,buf,_T("zileihuazhiqian"),0);

                                            DefWndProc=GetDlgItem(hwnd,IDC_TEST),GWL_WNDPROC,(LONG)EditNewProc);

                                            return true;

                                  case WM_COMMAND:

                                             switch(LOWORD(wParam))

                                               {

                                                               case IDCANCEL:

                                                                        EndDialog(hwnd,0);

                                                                        return true;

                                               }

                                               break;

                                   case WM_LBUTTONDOWN:

                                                         DlgWndProc=GetWindowLong(hwnd,GWL_WNDPROC);

                                                          EditWndProc=GetWindowLong(GetDlgItem(hwnd,IDC_TEST),GWL_WNDPROC);

                                                           wsprintf(buf,_T("DlgWndProc : %08X\nEditWndProc: 08X\nDefWndProc : 08X\n"),

                                                                               DlgWndProc,EditWndProc,DefWndProc);

                                                            MessageBox(hwnd,buf,_T("zileihuazhihou"),0);

                                                            return false;

            }

           return false;

          

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值