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