也许你需要一个特殊的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,在这里面滚动条处理自己的键按下等等消息;主窗口的键按下消息由主窗口过程处理;