1

这是我在 .NET WinForms 鼠标事件中看到的一个烦恼。要重现,请执行以下操作:

  1. 鼠标左键按下按钮控件。(这会将捕获控件更改为该按钮)
  2. 将鼠标从该按钮上移开。
  3. 在仍然按住鼠标左键的同时,单击鼠标右键。(这会将捕获控件更改为鼠标光标现在所在的位置)
  4. 松开鼠标左键。按钮永远不会收到鼠标向上事件。(鼠标向上事件转到当前的捕获控件。)

我只关心鼠标左键,但是用户不小心按下了右键会阻止鼠标左键事件返回到最初单击的按钮。

一种可能的解决方案是使用MouseLeaveMouseCaptureChanged事件来检测何时从按钮上发生右键单击,并了解捕获控件何时发生更改。我已经尝试过了,而且效果很好。

另一种方法是使用MessageFilters并过滤掉右键事件。但是有些按钮需要右键单击,因此您不想过滤掉所有的右键单击,只针对需要此功能的按钮。

所以我想看看是否有人知道更好的解决方案。如果 Windows 有某种标志来执行以下操作,那就太好了: button1.RightMouseButtonCanChangeMouseCapture = false;

4

1 回答 1

0

这似乎在我使用 MessageFilter 方法的测试中效果很好:

public partial class Form1 : Form
{

    private MyFilter mf;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        mf = new MyFilter();
        Application.AddMessageFilter(mf);
        mf.MouseLeftUp += Mf_MouseLeftUp;
    }

    private void button1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            mf.ButtonDown = true;
            Console.WriteLine("Transmitting...");
        }            
    }

    private void Mf_MouseLeftUp()
    {
        Console.WriteLine("Transmission Stopped.");
    }

}

public class MyFilter : IMessageFilter
{

    public bool ButtonDown = false;

    private const int WM_LBUTTONUP = 0x0202;

    public event dlgMouseLeftUp MouseLeftUp;
    public delegate void dlgMouseLeftUp();

    public bool PreFilterMessage(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_LBUTTONUP:
                if (ButtonDown)
                {
                    ButtonDown = false;
                    MouseLeftUp?.Invoke();
                }
                break;

        }
        return false; // allow normal dispatching of messages
    }

}
于 2020-09-10T18:45:56.977 回答