为什么当按下鼠标按钮时,MouseMove无法启动?

问题描述 投票:0回答:1

关于WPF鼠标的处理,我显然不了解,因此,我将不胜感激。冗长,很抱歉–我们被告知提供足够的上下文信息,以便其他人可以弄清楚我要完成的工作。

我有一系列按钮,每个按钮都包含图像的预览。放大我同时显示的完整图像时,我想使用相应的预览按钮来指示我实际上要放大的完整图像的哪一部分。为此,我使用Adorner在预览图像的顶部绘制一个简单的矩形框,以反映缩放区域。请查看屏幕截图以进行澄清-左下方的按钮以橙色矩形显示缩放区域。

Screenshot

所有这些都已经很好用了,如果我通过单击整个图像并将其移动来移动缩放区域,则橙色框会相应移动。

现在是我的问题:我还希望能够通过以下方式来移动主要缩放区域:将鼠标放在预览按钮的橙色框中,然后将其移动。我尝试实现此方法的方式,我为PreviewMouseDownPreviewMouseUpMouseMove事件提供了预览按钮事件处理程序,如下所示:

Button prevBut = new Button(); 
prevBut.PreviewMouseDown += PrevBut_PreviewMouseDown; 
prevBut.PreviewMouseUp += PrevBut_PreviewMouseUp; 
prevBut.MouseMove += PrevBut_MouseMove;

PreviewMouseDown检查鼠标位置是否实际上在橙色框中。如果是,它将记录开始位置并捕获按钮的鼠标。 PreviewMouseUp再次释放鼠标捕获。 MouseMove现在应该被调用,并根据鼠标位置或从开始位置的变化进行一些操作以更新缩放。

private void PrevBut_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    MouseStartPosRelativeToPreviewButton = e.GetPosition((Button)sender);

    if ( [some calculation to verify that mouse position is within orange box] )
        ((Button)sender).CaptureMouse();
}


private void PrevBut_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    ((Button)sender).ReleaseMouseCapture();
}


private void PrevBut_MouseMove(object sender, MouseEventArgs e)
{
    if (((Button)sender).IsMouseCaptured)
    {
        Point PosRelativeToPreviewImage = e.MouseDevice.GetPosition((Button)sender);

        ..  [Do some calculations and update zoom plus the position of the orange box]
    }
}

问题是,当鼠标悬停在按钮上时(我确认过),会定期调用PrevBut_MouseMove(),但是在按下鼠标按钮时会调用STOP。换句话说,如果我记录发生了什么,将鼠标移到按钮上方时会看到大量的PrevBut_MouseMove()调用,然后当我在按钮上的任意位置单击时,会得到PrevBut_PreviewMouseDown(),直接跟着PrevBut_PreviewMouseUp()(一次释放鼠标)。即使按住鼠标按钮几秒钟,也不会记录任何动作。释放鼠标按钮后,会有更多PrevBut_MouseMove()调用,直到鼠标离开按钮为止。如我所说,我不明白。为什么当鼠标按钮处于活动状态时,MouseMove将不再触发?

顺便说一下,[Adorner(橙色框)被设置为IsHitTestVisible = false,因此据我所知,它不应妨碍鼠标事件。 (或者可以吗?)我已经花费了很多时间试图找到一种解决方法,但无法使其正常工作。感谢您能给我的任何帮助。谢谢。

c# wpf mousemove
1个回答
0
投票

这是正常行为。输入管理器仍会引发MouseMove事件。但是由于事件及其注册的处理程序是synchronously执行的(WPF不实现异步事件),因此MouseMove处理程序只能在所有当前正在执行的处理程序(例如MouseDown)返回后才能执行。这就是MouseDown中断MouseMove(在所有已注册事件处理程序期间)的原因。

如果您主要对MouseMove感兴趣,并且也想对鼠标按钮做出反应(当鼠标移动时),则应在MouseMove的处理程序中处理这些按钮。您可以通过在MouseMove事件序列中通过访问MouseEventArgs来轮询按钮的状态来做到这一点:

// Track pressed mouse buttons to determine that the MouseButtonState.Released state
// immediately follows the MouseButtonState.Pressed button state
private bool IsMouseButtonPreviouslyPressed  { get; sete; }

private void OnMouseMove(object sender, MouseEventArgs e)
{
  Point currentMousePointerPosition = e.GetPosition(sender as IInputElement);
  var eventSource = sender as UIElement;

  if (e.LeftButton == MouseButtonState.Pressed)
  {
    IsMouseButtonPreviouslyPressed  = true;
    HandleLeftMouseButtonDown(currentMousePointerPosition, eventSource);
  }
  if (IsMouseButtonPreviouslyPressed  && e.LeftButton == MouseButtonState.Released)
  {
    IsMouseButtonPreviouslyPressed  = false;
    HandleLeftMouseButtonUp(currentMousePointerPosition, eventSource);
  }
  HandleMouseMove(currentMousePointerPosition, eventSource);
}

private void HandleLeftMouseButtonDown(Point mousePointerPosition, UIElement sourceElement)
{
    if ( [some calculation to verify that mouse position is within orange box] )
    {
      sourceElement.CaptureMouse();
    }
}

private void HandleLeftMouseButtonUp(Point mousePointerPosition, UIElement sourceElement)
{
    if ( [some calculation to verify that mouse position is within orange box] )
    {
      sourceElement.ReleaseMouseCapture();
    }
}

private void HandleMouseMove(Point mousePointerPosition, UIElement sourceElement)
{
    if (sourceElement.IsMouseCaptured)
    {
      ..  [Do some calculations and update zoom plus the position of the orange box]
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.