Подтвердить что ты не робот

OnMouseMove не запускается на холсте в WPF

Я сделал свой собственный элемент управления диаграммой, и я хочу нарисовать простой крест, следуя за курсором. Диаграмма реализована как PolyLine поверх холста, и я рисую две строки, меняя свои координаты в событии OnMouseMove на холсте.

Неожиданным было обнаружение того, что событие вызывается только каждые 10 секунд или около того, когда поток MainGUI простаивает (пользовательский интерфейс полностью реагирует, и если я приостанавливаю приложение, основной поток находится в приложении mainForm.ShowDialog()).

Любая идея о том, как найти, почему это происходит? Я получаю такую ​​же производительность, используя OnMouseMove или PreviewOnMouseMove.

EDIT: так я рисую крест (в любом случае, если бы я поставил точку останова на OnMouseMove, она время от времени останавливается).

XAML:

<Border BorderThickness="1" BorderBrush="White" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="2" >
    <Canvas x:Name="DrawArea" PreviewMouseMove="DrawArea_PreviewMouseMove" />
</Border>

CS:

 public Chart()
 {
    _line = new Polyline();
    _line.Stroke = Brushes.Orange;
    _crossX = new Line();
    _crossY = new Line();
    _crossX.Stroke = Brushes.Orange;
    _crossY.Stroke = Brushes.Orange;
    _crossX.StrokeThickness = 1;
    _crossY.StrokeThickness = 1;

    InitializeComponent();

    this.DrawArea.Children.Add(_line);
    this.DrawArea.Children.Add(_crossX);
    this.DrawArea.Children.Add(_crossY);
}     

private void DrawArea_MouseMove(object sender, MouseEventArgs e)
{
    Point mousePosition = System.Windows.Input.Mouse.GetPosition(this.DrawArea);

    _crossX.X1 = 0;
    _crossX.X2 = this.DrawArea.ActualWidth;
    _crossX.Y1 = _crossX.Y2 = mousePosition.Y;

    _crossY.Y1 = 0;
    _crossY.Y2 = this.DrawArea.ActualHeight;
    _crossY.X1 = _crossY.X2 = mousePosition.X;
}
4b9b3361

Ответ 1

Это странно, и я не знаю, почему...

FrameworkElement.MouseMove работает только в том случае, если в области имеется явная фоновая кисть\заполнение.

В вашем случае установите Canvas.Background="Transparent", он должен работать.

Это еще одно исправление... WPF Не отправлять события MouseMove после CaptureMouse();

Возможно, это связано с тем, что HitTest зависит от цветных пикселей и их обратной связи.

Что бы это ни было, его что-то не задокументировано по MSDN и запутывает для многих дизайнеров пользовательского интерфейса.

Ответ 2

В итоге я написал глобальный обработчик мыши:

using System.Windows.Interop;

private const int WM_MOUSEMOVE = 0x0200;
public delegate void Del_MouseMovedEvent(Point mousePosition);

// Relative to this control, the mouse position will calculated
public IInputElement Elmt_MouseMovedRelativeElement = null;

// !! This is static; needs special treatment in a multithreaded application !!
public static event Del_MouseMovedEvent Evt_TheMouseMoved = null;

// your main function call
public MyMainWindows()
{
    // install the windows message filter first
    ComponentDispatcher.ThreadFilterMessage += ComponentDispatcher_ThreadFilterMessage;

    InitializeComponent();

    ...
}   

// filtering the windows messages
private void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)
{
    if(msg.message == WM_MOUSEMOVE)
    {
        this.Evt_TheMouseMoved?.Invoke(Mouse.GetPosition(this.Elmt_MouseMovedRelativeElement));
    }
}

// individual event for mouse movement
private void MyMouseMove(Point mousePoint)
{
    // called on every mouse move when event is assigned
    Console.WriteLine(mousePoint.X + " " + mousePoint.Y);
}

private void AnyFunctionDeeperInTheCode()
{
    // assign the handler to the static var of the main window
    MyMainWindows.Evt_TheMouseMoved += MyMouseMove;

    // set the element / control to which the mouse position should be calculated; 
    MyMainWindows.Elmt_MouseMovedRelativeElement = this;

    ...

    // undassign the handler from the static var of the main window
    MyMainWindows.Evt_TheMouseMoved -= MyMouseMove;
}