Windows C/C++编程窗口子类化学习

592 篇文章 7 订阅 ¥99.90 ¥299.90

也许你需要一个特殊的Edit来限制浮点数的输入,但是现有的Edit却并不能完成这项工作,因为它只能够单纯的限制大小写或者纯数字。当你在论坛上求救的时候,某个网友告诉你:“用子类化。”

子类化
在Windows中,每一个窗体都会有一个HWND;Windows提供了一个API,GetWindowLong,通过这个函数得到HWND的原始消息处理过程函数的指针,将其保存起来,再调用SetWindowLong来设置一个新的函数指针,使这个指针指向我们自己的函数,这样,在我们的消息处理函数中,只处理我们关心的消息,不关心的消息就调用其原始的指针来处理消息。

超类化
用GetClassInfoEx获取原有的HWND的所有信息,然后用我们自定义的窗口处理过程取代原有的窗口过程 用我们自定义的类名比如“HexEdit”取代原有的类名“Edit” 然后用RegisterClassEx向windows注册我们的新类;

可以用函数指针的办法,将我们感兴趣的消息拦截下来,处理完之后再让预定义的窗口过程处理。这个过程大致如下: 
WNDPROC OldProc; 
OldProc = (WNDPROC)SetWindowsLong(hWnd, GWL_WNDPROC, (LONG)NewProc); 
当然,这里的新窗口过程NewProc是预先由你实现好的。上述代码执行以后,系统在处理hWnd的窗口消息时,就会先进入你实现的NewProc回调过程,然后在处理过你感兴趣的消息之后,通过CallWindowProc函数和你预先保存的OldProc再次回到原来的回调过程中完成剩余的工作。 

子类化是win32层面的概念;如果是C#这类语言的话,可以不用管;都已经封装到事件里面了;

从win32的程序来看,就是有一个主窗口过程,在里面处理主窗口的各种消息,子窗口控件的消息一般也在此处理;如果某个子窗口控件需要单独处理Windows消息来实现更强功能,就再为这个子窗口控件设置一个窗口过程,在此处理此子窗口控件的消息;

子类化的win32程序结构如下;

#include <windows.h>

LRESULT CALLBACK WndProc    (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ScrollProc (HWND, UINT, WPARAM, LPARAM) ;

WNDPROC OldScroll ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     ...变量定义,注册窗口类,创建窗口显示窗口,消息循环...
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    ...变量定义...
     
     switch (message)
     {
     case WM_CREATE :
          hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;
          hwndScroll = CreateWindow (TEXT ("scrollbar"), NULL,
                                             WS_CHILD | WS_VISIBLE | 
                                             WS_TABSTOP | SBS_VERT,
                                             0, 0, 0, 0, 
                                             hwnd, (HMENU) i, hInstance, NULL) ;
          ......
               
          OldScroll = (WNDPROC) SetWindowLong (hwndScroll, 
                                             GWL_WNDPROC, (LONG) ScrollProc) ;
          ......
          }

          return 0 ;
          
     case WM_SIZE :
          ......
          return 0 ;
          
     case WM_VSCROLL :
          i = GetWindowLong ((HWND) lParam, GWL_ID) ;
          
          switch (LOWORD (wParam))
          {
          case SB_PAGEDOWN :
          ......
          }

          return 0 ;          
              
     case WM_SYSCOLORCHANGE :
         ......
               
     case WM_DESTROY :
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
     
LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message, 
                             WPARAM wParam, LPARAM lParam)
{
     int id = GetWindowLong (hwnd, GWL_ID) ;
          
     switch (message)
     {
     case WM_KEYDOWN :
     ......
     case WM_SETFOCUS :
     ......
     }
     return CallWindowProc (OldScroll[id], hwnd, message, wParam, lParam) ;
}

    它定义了2个窗口过程;主窗口过程WndProc,滚动条控件的窗口过程ScrollProc;在主窗口中创建滚动条控件,也处理滚动条消息WM_VSCROLL;再用SetWindowLong为滚动条控件设置一个窗口过程名为ScrollProc,在这里面滚动条处理自己的键按下等等消息;主窗口的键按下消息由主窗口过程处理;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值