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

C# 使用 IMessageFilter 全域攔截與過濾鼠標訊息

     編輯:關於C#

應用場景

某些特殊需求下,需要在應用程式層級攔截或屏蔽特定滑鼠訊息,例如:

  • 禁止使用者點選特定控制項(如 ListBox)。
  • 實作「唯讀模式」鎖定整個視窗,僅允許關閉按鈕響應。
  • 實現熱鍵觸發前的滑鼠鎖定。

核心機制:IMessageFilter

System.Windows.Forms.Application 提供訊息泵機制,透過實作 IMessageFilter 介面並註冊至 Application.AddMessageFilter(),即可在訊息分發至控制項前進行預處理。

完整代碼範例

using System;
using System.Windows.Forms;

public class MouseMessageFilter : IMessageFilter
{
    // 攔截 WM_RBUTTONDOWN (0x204) 等滑鼠訊息
    public bool PreFilterMessage(ref Message m)
    {
        // 常見滑鼠訊息常數
        const int WM_LBUTTONDOWN  = 0x0201;
        const int WM_RBUTTONDOWN  = 0x0204;
        const int WM_MBUTTONDOWN  = 0x0207;
        const int WM_MOUSEMOVE    = 0x0200;

        // 示例:屏蔽右鍵點擊
        if (m.Msg == WM_RBUTTONDOWN)
        {
            // 返回 true 表示訊息已被處理,不再分發給控制項
            return true;
        }

        // 如需屏蔽所有滑鼠按鍵,可擴展判斷邏輯
        // if (m.Msg >= WM_LBUTTONDOWN && m.Msg <= WM_MBUTTONDOWN) return true;

        return false; // false 表示繼續正常分發
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        var filter = new MouseMessageFilter();
        Application.AddMessageFilter(filter);  // 註冊過濾器

        try
        {
            Application.Run(new Form1());
        }
        finally
        {
            Application.RemoveMessageFilter(filter); // 確保移除,避免記憶體洩漏
        }
    }
}

關鍵點說明

項目說明
PreFilterMessage 返回值true = 訊息被攔截/消費;false = 繼續傳遞
訊息常數定義於 WinUser.h,常用滑鼠訊息見代碼註釋
作用範圍全應用程式範圍,所有視窗的訊息泵均會經過此過濾器
執行時機訊息分發給 Control.WndProc 之前

進階應用:針對特定控制項過濾

若僅想屏蔽特定控制項(如 listBox1)的滑鼠事件,可在 PreFilterMessage 中判斷 m.HWnd:

public bool PreFilterMessage(ref Message m)
{
    if (m.HWnd == listBox1.Handle && 
        (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_RBUTTONDOWN))
    {
        return true; // 僅攔截 listBox1 的滑鼠按下
    }
    return false;
}

注意事項

  • 過濾器會影響整個應用程式效能,邏輯應保持極簡。
  • 務必在應用程式結束前呼叫 RemoveMessageFilter,否則可能導致殘留引用。
  • WPF 應用需使用 ComponentDispatcher.ThreadFilterMessage 事件,機制不同。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved