Windows 是一個基於消息驅動的作業系統,所有視窗與控制項之間的互動都透過消息傳遞機制完成。子類化技術正是建立在這一核心機制之上,它允許開發者攔截、修改甚至過濾系統或進程中流轉的消息,從而實現標準 API 難以達到的行為定制。
簡單來說,子類化就是建立一個新的視窗消息處理函數,並將其插入到原有預設視窗程序之前。當消息到達目標視窗前,先經過你的自定義處理邏輯,再決定是否傳遞給原視窗程序。這項技術主要分為三類:
若用 C++ 繼承來類比:父類定義 func(),子類覆寫同名函數,調用時自動走子類實現。Windows 子類化雖無「繼承」關係,但本質相同——透過 SetWindowLong(hWnd, GWL_WNDPROC, NewProc) 替換視窗程序指針,將感興趣的消息(如 WM_CHAR、WM_CLOSE)在 NewProc 中優先處理,其餘透過 CallWindowProc(OldProc, ...) 轉交原程序。
標準 Edit 控制項僅支援大小寫或純數字限制,無法直接限制浮點數輸入。透過實例子類化即可輕鬆實現:
case WM_INITDIALOG:
EditProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_EDIT), GWL_WNDPROC, (LONG)ProcFloat);
StaticProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_ST_HOMEPAGE), GWL_WNDPROC, (LONG)ProcLink);
break;
LRESULT CALLBACK ProcFloat(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
if (Msg == WM_CHAR && wParam != '.' && (wParam < '0' || wParam > '9') && wParam != VK_BACK) {
MessageBeep(MB_OK); // 非法字符發出提示音
return 0; // 丟棄該消息
}
return CallWindowProc(EditProc, hWnd, Msg, wParam, lParam); // 其他消息交給原程序
}
關鍵點:攔截 WM_CHAR,僅允許數字、小數點、退格鍵(缺少退格鍵會導致無法刪除輸入)。其他消息(如繪製、焦點切換)透過 CallWindowProc 保持原有行為。
cbClsExtra/cbWndExtra)。WM_CREATE 等早期消息。掌握子類化,能讓你在不重寫控制項的前提下,精準注入自定義邏輯,是 Windows 程式設計進階必備的利器。