Я написал действительно крошечную программу WPF + Rx в VS 2010, и у нее есть неожиданное поведение - по-видимому, сбор событий alt-key в наблюдаемых событиях мыши. Буду благодарен за совет по любому из
- что конкретно не так
- идей или инструментов о том, как проводить дальнейшую диагностику самостоятельно [например, есть ли инструменты, которые инструментируют код для отслеживания и регистрации всех событий, которые запускаются, чтобы я мог более четко видеть, что происходит?]
- как понять поведение - это "по замыслу"? Я неправильно использую WPF или Rx или оба?
- как получить поведение, которое я предпочел бы описать ниже
Первое, что он делает правильно, это запускает наблюдателей движения мыши, начиная с мыши вниз и заканчивая мышью вверх. Конкретный наблюдатель, которого я только что поместил, помещает правильные координаты 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, что углубило тайну.
желаемое поведение может быть
- либо явно проверяет состояние клавиши alt в обработчиках перемещения мыши
- или отдельные потоки событий для событий 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>