首页 > 解决方案 > 当其客户区被控件覆盖时,处理 WinForms 窗体中的鼠标后退和前进按钮

问题描述

我有一个为经典的 .NET Framework(即 v4.7.2)编写的 WinForms 应用程序。我需要以其中一种形式处理鼠标后退和前进按钮。问题是表单完全被其他控件(如 SplitContainer 和 Panels)覆盖,我找不到使用标准本机 .NET 技术拦截所需按钮的方法。

例如,覆盖WndProc的解决方案

private const int WM_XBUTTONDOWN = 0x020B;
private const int MK_XBUTTON1 = 0x0020;
private const int MK_XBUTTON2 = 0x0040;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_XBUTTONDOWN)
    {
        int lowWord = (m.WParam.ToInt32() << 16) >> 16;
        switch (lowWord)
        {
            case MK_XBUTTON1:
                // navigate backward
                break;
            case MK_XBUTTON2:
                // navigate forward
                break;
        }
    }
    base.WndProc(ref m);
}

仅当鼠标指针位于未被任何控件覆盖的客户区部分上时才有效。

有没有办法使用 .NET 本机技术使所有表单控件“透明”以单击鼠标后退/前进按钮,并以WndProc或类似的表单方法处理这些 x 按钮?如果没有,我应该使用基于 WinAPI 的低级鼠标挂钩来实现我需要的吗?欢迎使用 C# 或 VB.NET 的所有解决方案。

标签: .netwinformsclickmouseback-button

解决方案


基于IMessageFilter的解决方案可以完成工作:

public partial class Form1 : Form, IMessageFilter
{
    public Form1()
    {
        Application.AddMessageFilter(this);
        this.FormClosed += (s, e) => Application.RemoveMessageFilter(this);

        InitializeComponent();
    }

    private const int WM_XBUTTONDOWN = 0x020B;
    private const int MK_XBUTTON1 = 0x0020;
    private const int MK_XBUTTON2 = 0x0040;

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_XBUTTONDOWN)
        {
            int lowWord = (m.WParam.ToInt32() << 16) >> 16;
            switch (lowWord)
            {
                case MK_XBUTTON1:
                    // navigate backward
                    BackButton_Click(null, null);
                    break;
                case MK_XBUTTON2:
                    // navigate forward
                    ForwardButton_Click(null, null);
                    break;
            }
        }
        return false; // dispatch further
    }
}

推荐阅读