首页 > 解决方案 > 是否可以通过鼠标右键触发 ListView 上的 DoubleClicked 事件?

问题描述

此处的表格演示了当用户在 a或DoubleClick上双击鼠标左键或右键时引发事件;我只希望在鼠标左键双击时触发此事件。这里的备注说明是之前提出的,所以没有办法取消或者短路。TreeViewListViewDoubleClickMouseDoubleClickDoubleClicked

从逻辑上讲,正确的解决方案似乎是使用MouseDoubleClickand not DoubleClick,但对前一种状态的注释:

DoubleClick 事件在逻辑上是控件的更高级别事件。它们可能由其他用户操作引发,例如快捷键组合。

...这似乎暗示我实际上应该使用DoubleClick,但我又不能,因为这不允许我忽略或取消鼠标右键双击。

是否有任何相对简单的方法可以防止DoubleClick鼠标右键双击触发,或者我是否需要弄脏并手动处理 Windows 消息?

标签: c#winforms

解决方案


更新

事情发生在void WndProc(ref Message m). 我试图用不同的控件(PictureBox)重现问题。左键双击给出:

protected virtual void WndProc(ref Message m)
{
    // ...
    switch (m.Msg)
    {
        // ...
        case 514:
            WmMouseUp(ref m, MouseButtons.Left, 1);
            return;
        // ...
    }
    // ...
}

右键双击导致调用:

protected virtual void WndProc(ref Message m)
{
    // ...
    switch (m.Msg)
    {
        // ...
        case 517:
            WmMouseUp(ref m, MouseButtons.Right, 1);
            return;
        // ...
    }
    // ...
}

哪里void WmMouseUp(ref Message m, MouseButtons button, int clicks)看起来像:

private void WmMouseUp(ref Message m, MouseButtons button, int clicks)
{
    // ...
    OnDoubleClick(new MouseEventArgs(button, 2, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
    OnMouseDoubleClick(new MouseEventArgs(button, 2, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
    // ...
}

两者都OnDoubleClickOnMouseDoubleClick火一起MouseEventArgs。这就是该解决方案有效的原因。

private void control_DoubleClick(object sender, EventArgs e)
{
    if ((e as MouseEventArgs)?.Button == MouseButtons.Right)
        return;

    // do your stuff
}

但情况有所不同ListView

protected virtual void WndProc(ref Message m)
{
    // ...
    switch (m.Msg)
    {
        // ...
        case 514:
        case 517: // m.Msg value
        case 520:
        {
            NativeMethods.LVHITTESTINFO lvhi = new NativeMethods.LVHITTESTINFO();
            int indexOfClickedItem = GetIndexOfClickedItem(lvhi);
            if (!base.ValidationCancelled && listViewState[262144] && indexOfClickedItem != -1)
            {
                listViewState[262144] = false;
                OnDoubleClick(EventArgs.Empty);
                OnMouseDoubleClick(new MouseEventArgs(downButton, 2, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
            }
            if (!listViewState[524288])
            {
                OnMouseUp(new MouseEventArgs(downButton, 1, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
                listViewState[1048576] = false;
            }
            ItemCollectionChangedInMouseDown = false;
            listViewState[524288] = true;
            base.CaptureInternal = false;
            return;
        }
        // ...
    }
    // ...
}

OnDoubleClickEventArgs.Empty. 所以第一个解决方案不起作用

解决方法可能是使用已修补的ListView

public class PatchedListView : ListView
{
    protected override void WndProc(ref Message m)
    {
        var suppress = m.Msg == 517 &&
                       Enum.TryParse(typeof(ListView).GetField("downButton", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this).ToString(),
                                     out MouseButtons mouseButtons) &&
                       mouseButtons == MouseButtons.Right;
        if (suppress)
            return;

        base.WndProc(ref m);
    }
}

推荐阅读