首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# WinForms 截取視窗訊息的兩種實用技巧

     編輯:關於C#

在 C# WinForms 開發中,攔截並處理底層 Windows 訊息(如滑鼠點擊、鍵盤按下、視窗移動等)是實現自訂行為、全域熱鍵、拖放攔截等進階功能的基礎。本文介紹兩種主流方法:覆寫 DefWndProc 與實作 IMessageFilter,並附上常用訊息 ID 速查表。

方法一:覆寫 Form.DefWndProc

每個 Form 都有虛擬方法 DefWndProc(ref Message m),所有未被特定事件處理的訊息最終都會流經此處。覆寫它即可攔截該視窗的所有訊息。

protected override void DefWndProc(ref Message m)
{
    // WM_LBUTTONDOWN = 0x0201
    if (m.Msg == 0x0201)
    {
        MessageBox.Show($"攔截到左鍵按下: Msg=0x{m.Msg:X}");
        // 若不呼叫 base.DefWndProc,訊息將被「吃掉」,視窗不會收到點擊
        return;
    }
    base.DefWndProc(ref m); // 其餘訊息交給預設處理
}

優點:簡單直接,僅影響當前視窗。
缺點:無法攔截其他視窗或應用程式層級的訊息。

方法二:實作 IMessageFilter(應用程式層級攔截)

實作 System.Windows.Forms.IMessageFilter 介面,並透過 Application.AddMessageFilter 註冊,可攔截整個應用程式所有視窗的訊息。

public class MessageFilter : IMessageFilter
{
    public bool PreFilterMessage(ref Message m)
    {
        // WM_LBUTTONDOWN = 0x0201
        if (m.Msg == 0x0201)
        {
            MessageBox.Show("全域攔截: WM_LBUTTONDOWN");
            return true; // true = 過濾掉(不再分發),false = 繼續分發
        }
        return false;
    }
}

// 在 Program.cs Main() 中註冊:
static class Program
{
    private static MessageFilter _msgFilter = new MessageFilter();
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.AddMessageFilter(_msgFilter); // 註冊
        Application.Run(new Form1());
        // 結束前可移除:Application.RemoveMessageFilter(_msgFilter);
    }
}

優點:全域攔截,適合熱鍵、全域滑鼠手勢、記錄器。
缺點:影響範圍大,需謹慎判斷 m.HWnd 區分視窗,避免誤攔截導致 UI 假死。

常用 Windows 訊息 ID 速查表

常數名稱Hex 值說明
WM_LBUTTONDOWN0x0201滑鼠左鍵按下
WM_LBUTTONUP0x0202滑鼠左鍵放開
WM_RBUTTONDOWN0x0204滑鼠右鍵按下
WM_MOUSEMOVE0x0200滑鼠移動
WM_KEYDOWN0x0100鍵盤按下
WM_KEYUP0x0101鍵盤放開
WM_SYSKEYDOWN0x0104系統鍵(Alt)按下
WM_PAINT0x000F重繪請求
WM_CLOSE0x0010關閉視窗
WM_DESTROY0x0002視窗銷毀
WM_MOVE0x0003視窗移動
WM_SIZE0x0005視窗大小改變
WM_TIMER0x0113計時器觸發
WM_COMMAND0x0111命令(選單、按鈕)
WM_NOTIFY0x004E通用控件通知
WM_USER0x0400自訂訊息起始值

選擇建議

  • 僅需在特定 Form 處理特定訊息 → 覆寫 DefWndProc。
  • 需全域熱鍵、跨視窗滑鼠手勢、統一記錄 → IMessageFilter。
  • 若需攔截其他進程訊息,必須使用 SetWindowsHookEx (WH_GETMESSAGE/WH_CALLWNDPROC) 並配合 DLL 注入,屬更進階主題。

掌握訊息攔截,能讓你在 WinForms 中實現許多標準事件無法覆蓋的深度客製化行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved