Windows C/C++编程窗口子类化学习
也許你需要一個特殊的Edit來限制浮點數的輸入,但是現有的Edit卻并不能完成這項工作,因為它只能夠單純的限制大小寫或者純數字。當你在論壇上求救的時候,某個網友告訴你:“用子類化?!?/p>
子類化
在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,在這里面滾動條處理自己的鍵按下等等消息;主窗口的鍵按下消息由主窗口過程處理;
總結
以上是生活随笔為你收集整理的Windows C/C++编程窗口子类化学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL Server 事务日志
- 下一篇: 使用matlab构建一个信号、添加噪声信