系列第二篇:深入剖析 System.Windows.Forms.NativeWindow 的底層封裝原理,示範如何利用 AssignHandle / ReleaseHandle 實現視窗子類別化,攔截 WndProc 訊息流,為全自動皮膚引擎鋪路。
MSDN 定義:「Provides a low-level encapsulation of a window handle and a window procedure.」 實際上它是 視窗子類別化 的托管包裝器:
AssignHandle(hwnd):將現有視窗句柄掛接至 NativeWindow 實例,內部呼叫 SetWindowLongPtr(GWLP_WNDPROC) 替換視窗程序為托管委派,實現 Hook。ReleaseHandle():恢復原始視窗程序,解除掛接。WndProc(ref Message m):覆寫此虛擬方法即可攔截/處理/轉發視窗訊息。使用 Reflector 反編譯 AssignHandle 可見關鍵程式碼:
IntPtr userDefWindowProc = UnsafeNativeMethods.GetProcAddress(
new HandleRef(null, UnsafeNativeMethods.GetModuleHandle("user32.dll")),
"DefWindowProcW"); // 取得預設視窗程序位址
// 隨後呼叫 SetWindowLongPtr 替換 WndProc
此為標準 子類別化 Hook 技術,比全域 Hook (SetWindowsHookEx) 更精準、效能更高、不需注入 DLL。
SkinEngine : Component,內部持有 Dictionary<IntPtr, SkinningForm> 對應 HWND 與包裝物件。WndProc:優先處理皮膚相關訊息 (WM_NCPAINT, WM_NCCALCSIZE, WM_NCHITTEST, WM_SIZE 等),再呼叫 base.WndProc 轉發給原始 Form。Application.Idle 或 Control.HandleCreated 事件中,對所有 Form 執行 nativeWindow.AssignHandle(form.Handle)。註冊 Hook 後輸出所有攔截訊息:

可見訊息流極其頻繁,凸顯 WndProc 效能優化重要性 (如快取 Graphics、縮小裁剪區域)。
下一篇將實作 SkinAppearance.SetRegion 設定圓角視窗 Region,正式進入視覺重構階段。