Почему MouseMove не срабатывает при нажатии кнопки мыши? - PullRequest
0 голосов
/ 25 мая 2020

В работе с мышью WPF есть кое-что, что я, очевидно, не понимаю, поэтому буду признателен за любую помощь, которую смогу получить. Извините за то, что сделал это слишком длинным - мне сказали предоставить достаточно контекстной информации, чтобы другие могли понять, что я пытаюсь выполнить. sh.

У меня есть ряд кнопок, каждая из которых содержит предварительный просмотр образ. При увеличении полного изображения, которое я также показываю, я хотел бы использовать соответствующую кнопку предварительного просмотра в качестве индикатора того, какую часть полного изображения я на самом деле увеличиваю. Для этого я использую Adorner, что dr aws простой прямоугольник angular поверх изображения предварительного просмотра, отражающий увеличенную область. Пожалуйста, посмотрите на снимок экрана для пояснения - кнопка в левом нижнем углу показывает увеличенную область в оранжевом прямоугольнике.

Снимок экрана

Все это уже хорошо работает, и если я перемещаю увеличенную область, щелкая полное изображение и перемещая его, оранжевое поле перемещается соответственно, когда оно должен.

Теперь вот моя проблема: я также хотел бы иметь возможность перемещать основную область масштабирования, помещая мышь в оранжевую рамку на кнопке предварительного просмотра, а затем перемещая рамку. Как я пытаюсь реализовать это, я даю обработчики событий кнопки предварительного просмотра для событий PreviewMouseDown, PreviewMouseUp и MouseMove следующим образом:

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, так что, как я понимаю, он не должен мешать событиям мыши. (Или может?) Я уже провел много часов, пытаясь найти обходной путь, и не мог заставить его работать. Буду признателен за любую помощь, которую вы можете мне оказать. Спасибо.

1 Ответ

0 голосов
/ 25 мая 2020

Это нормальное поведение. Событие MouseMove по-прежнему вызывается диспетчером ввода. Но поскольку события и их зарегистрированные обработчики выполняются синхронно (WPF не реализует асинхронные события), обработчики MouseMove могут выполняться только после того, как все выполняющиеся в данный момент обработчики, например, MouseDown, вернулись. Вот почему MouseDown прерывает MouseMove (на время всех зарегистрированных обработчиков событий).

Если вас интересует в первую очередь MouseMove и вы также хотели бы реагировать на кнопки мыши (во время движения мыши), вам следует обрабатывать эти кнопки внутри обработчика MouseMove.
You это можно сделать, опросив состояние кнопки во время последовательности 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]
    }
}
...