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

C# 使用 Windows 訊息機制提升程式設計效率:定義、發送、接收與攔截

     編輯:關於C語言

前言

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;

二、發送訊息:P/Invoke 呼叫 SendMessage

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);

三、接收訊息:重寫 DefWndProc

所有 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。

四、進階攔截:IMessageFilter 介面

應用場景:全域攔截特定訊息(如禁止滑鼠移動、熱鍵處理)、控制項子類化。

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);
    }
}

IMessageFilter vs DefWndProc 比較

特性DefWndProcIMessageFilter
作用範圍單一視窗/控制項整個應用程式(所有執行緒訊息佇列)
攔截時機訊息已分派到視窗訊息分派前(更早)
適用場景自訂視窗行為、繪製、特定控制項全域熱鍵、滑鼠/鍵盤攔截、存取控制
註冊方式覆寫方法Application.AddMessageFilter

五、C# 事件與訊息的關係

C# 事件(如 Click、MouseMove)本質是對 Win32 訊息的封裝:

  1. 訊息到達視窗
  2. DefWndProc / WndProc 處理
  3. 系統將特定訊息轉換為 .NET 事件
  4. 透過委派呼叫事件處理器

在 DefWndProc 中攔截並 不呼叫 base.DefWndProc,可阻止對應事件觸發。

六、總結

掌握 Windows 訊息機制,能讓 C# 開發者:

  • 突破事件模型限制,實現跨視窗/跨程序通訊
  • 攔截/修改系統預設行為(如禁止編輯、自訂繪製)
  • 整合非受控程式碼、實作子類化控制項
  • 建立全域訊息過濾器(熱鍵、安全攔截)

核心工具:DllImport + SendMessage、DefWndProc 重寫、IMessageFilter 實作。

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