Windows 程式設計核心在於訊息機制。C# 雖封裝了事件模型,但直接操作 Win32 訊息能實現事件模型難以達到的功能:跨視窗通訊、攔截系統訊息、控制項行為修改等。本文完整說明訊息定義、SendMessage 呼叫、DefWndProc 重寫、IMessageFilter 攔截四大核心技術。
Win32 訊息為 16 進位整數,需對應 WinUser.h 定義:
// 常見訊息
const int WM_LBUTTONDOWN = 0x0201; // 滑鼠左鍵按下
const int WM_MOUSEMOVE = 0x0200; // 滑鼠移動
const int WM_KEYDOWN = 0x0100; // 鍵盤按下
// 使用者自訂訊息範圍:0x0400 (WM_USER) 以上
public const int WM_USER = 0x0400;
public const int MY_CUSTOM_MSG = WM_USER + 100;
using System.Runtime.InteropServices;
public class Win32API
{
[DllImport("User32.dll", EntryPoint = "SendMessage", SetLastError = true)]
public static extern int SendMessage(
int hWnd, // 目標視窗控制代碼
int Msg, // 訊息代碼
int wParam, // 第一參數
int lParam // 第二參數
);
}
// 向指定視窗發送左鍵點擊訊息
Win32API.SendMessage(targetHwnd, WM_LBUTTONDOWN, 0, 0);
所有 Form 繼承自 Control,擁有 DefWndProc 處理訊息。重寫即可攔截:
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
string msg = string.Format("收到左鍵點擊!參數:wParam={0}, lParam={1}", m.WParam, m.LParam);
MessageBox.Show(msg);
break;
default:
base.DefWndProc(ref m); // 未處理的交給基類
break;
}
}
m.Msg:訊息代碼m.WParam、m.LParam:訊息參數(IntPtr 型別,需轉換)base.DefWndProc 處理未攔截訊息,否則視窗基本功能(繪製、焦點、關閉等)會失效若要攔截按鈕點擊,可在按鈕所在表單的 DefWndProc 判斷 m.HWnd 是否為該按鈕控制代碼,或繼承 Button 覆寫 WndProc。
應用場景:全域攔截特定訊息(如禁止滑鼠移動、熱鍵處理)、控制項子類化。
public class Form1 : Form, IMessageFilter
{
const int WM_MOUSEMOVE = 0x200;
public Form1()
{
Application.AddMessageFilter(this); // 註冊過濾器
}
// 實作介面
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
// return true = 攔截(訊息不再分派)
// return false = 放行
return true; // 忽略所有滑鼠移動
}
return false;
}
protected override void Dispose(bool disposing)
{
if (disposing)
Application.RemoveMessageFilter(this); // 註銷
base.Dispose(disposing);
}
}
| 特性 | DefWndProc | IMessageFilter |
|---|---|---|
| 作用範圍 | 單一視窗/控制項 | 整個應用程式(所有執行緒訊息佇列) |
| 攔截時機 | 訊息已分派到視窗 | 訊息分派前(更早) |
| 適用場景 | 自訂視窗行為、繪製、特定控制項 | 全域熱鍵、滑鼠/鍵盤攔截、存取控制 |
| 註冊方式 | 覆寫方法 | Application.AddMessageFilter |
C# 事件(如 Click、MouseMove)本質是對 Win32 訊息的封裝:
DefWndProc / WndProc 處理在 DefWndProc 中攔截並 不呼叫 base.DefWndProc,可阻止對應事件觸發。
掌握 Windows 訊息機制,能讓 C# 開發者:
核心工具:DllImport + SendMessage、DefWndProc 重寫、IMessageFilter 實作。