Странные перекрестные помехи: мышь и клавиатура, WPF и Rx? - PullRequest
0 голосов
/ 27 ноября 2010

Я написал действительно крошечную программу WPF + Rx в VS 2010, и у нее есть неожиданное поведение - по-видимому, сбор событий alt-key в наблюдаемых событиях мыши. Буду благодарен за совет по любому из

  1. что конкретно не так
  2. идей или инструментов о том, как проводить дальнейшую диагностику самостоятельно [например, есть ли инструменты, которые инструментируют код для отслеживания и регистрации всех событий, которые запускаются, чтобы я мог более четко видеть, что происходит?]
  3. как понять поведение - это "по замыслу"? Я неправильно использую WPF или Rx или оба?
  4. как получить поведение, которое я предпочел бы описать ниже

Первое, что он делает правильно, это запускает наблюдателей движения мыши, начиная с мыши вниз и заканчивая мышью вверх. Конкретный наблюдатель, которого я только что поместил, помещает правильные координаты mouseDown + mouseUp в заголовок окна (см. Код + XAML ниже).

Странность начинается, если я нажимаю и отпускаю клавишу alt, когда мышь не работает. Это, кажется, немедленно останавливает наблюдателей событий mouseMove. Теперь, если я отпущу mouseButton, наблюдатели события mouseMove снова запустятся и будут продолжать, пока я не сгенерирую новый mouseDown или не нажму и не отпущу alt снова. Дальше больше, если я пройду эту последовательность, а именно

mouseDown
mouseMove
alt-key down
alt-key up
mouseUp
alt-key down
alt-key up

а затем нормальный

mouseDown
mouseMove

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

Мне не удалось сделать это с помощью других клавиш, кроме alt, что углубило тайну.

желаемое поведение может быть

  1. либо явно проверяет состояние клавиши alt в обработчиках перемещения мыши
  2. или отдельные потоки событий для событий keyDown и keyUp, и я выясню чередование в моем коде

Но, конечно, иметь такое поведение и, что еще хуже, не понимать, как его понять, действительно плохо. Буду благодарен за любые идеи!

(ПРИМЕЧАНИЕ: добавить ссылки на System.coreex, System.Reactive и System.Interactive)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace DownAndMoveTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            (from mDown in this.GetLeftMouseDownObservable().
                 Do(e => this.Title = "DOWN: " + e.EventArgs.GetPosition(this).ToString())
             let mDownP = mDown.EventArgs.GetPosition(this)
             from mMove in this.GetMouseMoveObservable().TakeUntil(this.GetLeftMouseUpObservable())
             select new
             {
                 D = mDownP,
                 M = mMove.EventArgs.GetPosition(this)
             }).Subscribe(ps =>
             {
                 this.Title = String.Format(
                   "Window MouseDown({0:G}, {1:G}), MouseMove({2:G}, {3:G})",
                   ps.D.X, ps.D.Y,
                   ps.M.X, ps.M.Y);
             });
        }
    }
    public static partial class UIElementExtensions
    {
        public static IObservable<IEvent<MouseButtonEventArgs>>
            GetLeftMouseDownObservable(this UIElement uiElement)
        {
            return Observable.FromEvent<MouseButtonEventHandler, MouseButtonEventArgs>(
               h => new MouseButtonEventHandler(h),
               h => uiElement.MouseLeftButtonDown += h,
               h => uiElement.MouseLeftButtonDown -= h);
        }

        public static IObservable<IEvent<MouseEventArgs>>
            GetMouseMoveObservable(this UIElement uiElement)
        {
            return Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
               h => new MouseEventHandler(h),
               h => uiElement.MouseMove += h,
               h => uiElement.MouseMove -= h);
        }

        public static IObservable<IEvent<MouseButtonEventArgs>>
            GetLeftMouseUpObservable(this UIElement uiElement)
        {
            return Observable.FromEvent<MouseButtonEventHandler, MouseButtonEventArgs>(
               h => new MouseButtonEventHandler(h),
               h => uiElement.MouseLeftButtonUp += h,
               h => uiElement.MouseLeftButtonUp -= h);
        }
    }
}

и его XAML

<Window x:Class="DownAndMoveTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
    </Grid>
</Window>

1 Ответ

1 голос
/ 28 ноября 2010

Есть ли в вашем приложении главное меню? Нажатие клавиши alt фокусирует строку меню, а нажатие alt снова возвращает фокус к тому, что было раньше. Это объясняет функциональность, которую вы видите. (Это не похоже на проблему Rx)

...