旅途

如果想飞得高,就该把地平线忘掉

窗口子类化和超类化技术的应用------好!!!!!

在讲述窗口的子类化和超类化之前,我们必须 先了解windows窗口类的概念。windows的窗口类 是windos 用来创建窗口的依据之一,每个窗口 必然属于某个窗口类。窗口类是一个窗口模板,包 含一个窗口所具有的部分窗口属性。编写一个windows程序时,首先要做的工作就是注册一个窗 口类,然后基于此注册的窗口类创建一个新的窗 口。在 windows平台中,注册窗口类的函数是 RegisterClass和 RegisterClassEX, 其 中 RegisterClassEx是推荐使用的函数,使用这个函数注册窗 口类时,需要先填写一个 WNDCLASS结构。这 个结构实际上反映了一个窗口类的特征,一个窗口 类有本类所有窗口公用的类属性、窗口函数、类图 标和小图标、类鼠标、窗口背景刷、类菜单,当然还 有类名。除此之外,每个类还有一定大小的类存储
区,可以用来存储该类的公共数据。 每一个创建的窗口都有一个窗口函数,其地址 由结构的 wndclASS参数lpfnWndProc设定, 该窗口函数处理对应于该窗口类的所有实例的消 息。当创建一个窗口时,windows 将分配一个内存 块,用来存放与该窗口相关的信息,并将参数 lpfnWndClass 从窗口类内存块拷贝到该内存块中。当消 息被分发到窗口时, windows 检查该窗口中内存块 中的 lpfnWndClass值,并调用该内存块地址上的窗 口函数。
一个窗口的行为主要取决于它的窗口函数,如 果能够改变一个窗口的窗口函数,使它指向自己写 的某个函数,那就意味着发给这个窗口的各种消息 将由我们自己写的这个函数来处理。 子类化一个窗口,实际上就是改变窗口内存块 中的窗口函数的地址,使其指向用户自定义的新的 窗口函数入口,以实现用户希望的窗口特性。 超类化则是利用原来的那个窗口类的某些特 征,改变它另外的一些特征,包括窗口函数,重新注 册一个新的窗口类。 超类化和子类化的共同之处就是,这两种方法 都是从一个已经存在的窗口类产生新的窗口或窗 口类的方法,新的窗口或窗口类具有原来的窗口类 的某些特征,也具有一些新增的特征。但子类化是 从窗口的角度出发的,而超类化是从窗口类的角度 出发的。

    窗日了类化技术最大的特点就是能够截取eindows的消息。一日_用户自定义的窗日函数截取犷传向原窗日函数的消息,就可以对被截取的消息进行如下处理曰:
    .将其传给原来的窗日函数。这是对大多数消息应该采取的措施,因为了类通常只对原来的窗日特性作少量的修改。
    .截取该消息,阻止其向原窗日函数发送。
    .修改该消息,修改完毕以后再向原窗口函数发送。

GetWindowLong SetWindowLong


    在Windows编程中,使用窗子类化技术,可以方便地达到改变一个窗日的特性的日的。但了
子类化也存在其局限性。实际上,了类化的概念是针对一个己经创建的窗口来谈的,所以修改窗口函数
是在窗口创建之后进行的,在窗口创建期间的消息无法捕获,也就无法处理。另外有些窗日的特性与
窗日类本身的属性有关。比如如果一个窗日类没有CS_ DBLCLKS属性的话,那么要通过了类化这些窗u达到处理WM_ LBUTTOIVDBLCLK消息的日的。对于了类化的以上局限性,可以通过窗口的超类化技术来消除。实际上超类化可以完全实现了类化的功能。


    超类化需要注册一个新的窗日类,达到改变窗日类的各种特征的目的。超类化实现的简单过程是
获得一个己经存在的窗日类的特征,然后改变这些特征,最后重新注册一个窗日类。具体的步骤如下:
    ①定义一个类型为WNDCLASSEX的变量。因为需要注册新的窗日类,定义这个变量是必要的。
    ②调用GetClasslnfoEx函数得到希望超类化的那个窗口类的信息。
    ③改变窗口类的基本特征,显然窗口类名和模块句柄hlnstance是必须改变的。注意如果需要改
变窗口类的窗口函数的话,在改变窗口函数之前应该保存原来的窗口函数,井且在新的窗日函数中把
不需要处理的消息传递给原来的窗口函数,以保留原窗口类的一些特征。
    ④利用修改后的WIVDCLASSEX变量,调用RegisterClassEX函数重新注册一个新的窗u类。
    ⑤创建这个新窗日类的一个窗日实例。


      (1)用MFC Application Wizard新建一个MDl
程序SuperClassingo
      2)利用ClassWizard建一个从 CWnd类派生
的新类CDblClkWnd。添加MDl客户窗口对左键双
击的处理函数:

3)重新注册一个窗口类,进行超类化。
BOOL CDblClkWnd::RegisterNewClass()
{
    WNDCLASS wc;
    if(!GetClassInfo(NULL,"MDIClient",&wc))
     return FALSE;
   wc.style=SC_DBLCLKS;
   wc.lpszClassName="DBLCLCMDIClient";修改名字
   return RegisterClass(&wc);

}
在APP类的InitInstance函数前创建主框架的代码前调用上面的注册新窗口的类的代码
if(!CDblClkWnd::RegisterNewClass())
return false;


在使用CreateWindowEx创建MDI客户窗口的时候,把原来的窗口类MDIClient改为DB LCLCMDIClient

在主窗口中添加变量CDblClkWnd m_client,在主窗口的OnCreate中对MDIClient进行子类化。在OnDestroy中进行反子类化。


pclient.SuhclassWindow(phWndMDlClient);

m client.UnsubclassWindow()://反子类化




posted on 2007-07-20 00:35 旅途 阅读(384) 评论(0)  编辑 收藏 引用 所属分类: 深入windows


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理