【问题标题】:Why MouseMove event occurs after MouseUp event?为什么 MouseMove 事件发生在 MouseUp 事件之后?
【发布时间】:2019-07-23 18:53:29
【问题描述】:

在WindowsForms 中我刚刚添加了如下事件处理程序:

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        Debug.WriteLine($"=> Form1_MouseDown, Clicks: {e.Clicks}, Location: {e.Location}");
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        Debug.WriteLine($"=> Form1_MouseUp, Clicks: {e.Clicks}, Location: {e.Location}");
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        Debug.WriteLine($"=> Form1_MouseMove, Clicks: {e.Clicks}, Location: {e.Location}");
    }

输出是:

=> Form1_MouseMove, Clicks: 0, Location: {X=17,Y=21}
=> Form1_MouseDown, Clicks: 1, Location: {X=17,Y=21}
=> Form1_MouseUp,   Clicks: 1, Location: {X=17,Y=21}
=> Form1_MouseMove, Clicks: 0, Location: {X=17,Y=21}

你可以看到所有事件都发生在同一个位置,所以我的问题是为什么MouseUp事件之后还有MouseMove事件?

我也在 WPF 中尝试了类似的代码,并且发生了MouseMove 事件 NOT。

我在 C++ 中尝试了类似的代码,MouseMove 发生了 NOT 事件:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
     ...

    case WM_MOUSEMOVE:
        OutputDebugString(L"WM_MOUSEMOVE\n");
        break;

    case WM_LBUTTONDOWN:
        OutputDebugString(L"WM_LBUTTONDOWN\n");
        break;

    case WM_LBUTTONUP:
        OutputDebugString(L"WM_LBUTTONUP\n");
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

【问题讨论】:

  • 鼠标在移动吗?如果是这样,它将生成运动事件。
  • 假定到达 Windows 回调函数的消息顺序与您的身体动作相匹配是不正确的。它不是 FIFO 队列。
  • @JeffD。见here和here
  • 您必须始终假设操作系统可能会合成 MouseMove 通知,即使鼠标没有移动。例如,它会触发一系列影响光标形状的其他消息。在这种情况下,它发生是因为鼠标捕获状态发生了变化。将 this.Capture = false; 添加到 MouseDown 事件处理程序以查看差异。
  • 您为回应@Jeff 的评论而发布的链接只是支持他所写的内容。至于你的问题本身,“为什么?”问题通常主要基于意见,这也不例外。你需要问微软为什么在 WM_MOUSEUP 之后会生成 WM_MOUSEMOVE。也就是说,您的代码应该始终准备好处理鼠标移动,并且 Windows 或 .NET 可能会在这种情况下生成一个来解决不具有例如错误的程序的问题。在鼠标上移时重置其光标状态(大多数程序会在鼠标移动时检查光标状态)。

标签: c# .net windows winforms visual-c++


【解决方案1】:

如果您的鼠标先前已聚焦在一个单独的窗口上,那么单击一个新窗口并移动鼠标的焦点将生成一个鼠标移动事件(即使在您单击您的鼠标之前或之后鼠标没有立即移动)鼠标)。

这是一个类似 StackOverflow 响应的链接 "Ghost" MouseMove Event

【讨论】:

    【解决方案2】:

    这是因为MouseDown 的鼠标捕获是在MouseUp 上释放的。而这个额外的MouseMove可能是为了保证光标的位置。作为一种解决方法,您可以这样做

            Point LastLocation = Point.Empty;
    
            private void Form1_MouseDown(object sender, MouseEventArgs e)
            {
                Debug.WriteLine("=> Form1_MouseDown, Clicks: " + e.Location + ", Location: " + e.Location + "");
            }
    
            private void Form1_MouseUp(object sender, MouseEventArgs e)
            {
                Debug.WriteLine("=> Form1_MouseUp, Clicks: " + e.Location + ", Location: " + e.Location + "");
    
            }
    
            private void Form1_MouseMove(object sender, MouseEventArgs e)
            {
                if (LastLocation != e.Location)
                {
                    LastLocation = e.Location;
                    Debug.WriteLine("=> Form1_MouseMove, Clicks: " + e.Location + ", Location: " + e.Location + "");
                }
            }
    

    【讨论】:

      【解决方案3】:

      这是预期的行为,也将在应用切换时触发(例如:Alt+Tab)。

      您应该按照@VishnuBabu 的解决方法建议使用解决方法。要忽略初始 mousemove 触发器,您可以在加载窗口后获取光标的当前位置,而不是将 LastLocation 设置为 Empty。

      【讨论】:

        猜你喜欢
        • 2013-07-04
        • 1970-01-01
        • 1970-01-01
        • 2010-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多