2010-11-26 7 views
0

J'ai écrit un très petit programme WPF + Rx dans VS 2010, et il a un comportement inattendu - apparemment ramasser des événements alt-key dans les observables de l'événement de la souris. Je serais reconnaissant des conseils sur l'un desÉtrange diaphonie d'événement: souris et clavier, WPF et Rx?

  1. ce qui est particulièrement mal
  2. idées ou des outils sur la façon de diagnostiquer davantage sur moi-même [par exemple, y at-il des outils que les instruments du code pour suivre et consignant tous les événements qui se déclenchent pour que je puisse voir plus clairement ce qui se passe?]
  3. comment comprendre le comportement - est-ce «par conception»? Est-ce que j'utilise mal WPF ou Rx ou les deux?
  4. comment obtenir le comportement que je préfère avoir, décrit ci-dessous

D'abord, ce qu'il fait est correctement déplacer la souris d'incendie observateurs à partir d'une souris vers le bas et se terminant par un haut de la souris. L'observateur de test particulier que je viens de mettre les bonnes coordonnées mouseDown + mouseUp dans la barre de titre de la fenêtre (voir le code + XAML ci-dessous).

L'étrangeté commence si j'appuie et relâche la touche alt pendant que la souris est enfoncée. Cela semble immédiatement arrêter les observateurs de l'événement mouseMove. Maintenant, si je libère mouseButton, les observateurs de l'événement mouseMove redémarrent, et continuent jusqu'à ce que je génère un nouveau mouseDown ou que j'appuie à nouveau sur alt. De plus, si je passe par cette séquence, à savoir

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

puis, la

normale
mouseDown 
mouseMove 

l'impression dans la barre de titre a un certain clignotement bizarre, me disant qu'il ya d'autres événements extérieurs être suivi et pompé à travers mon observateur lambda.

Je n'ai pas été en mesure de faire échouer avec des clés autres que alt, approfondissant le mystère.

Le comportement souhaité pourrait être

  1. soit la vérification de alt Etat clé explicitement dans les gestionnaires-déplacement de la souris
  2. ou d'un événement séparé cours d'eau pour les événements keyDown et keyUp, et je vais trouver le désentrelacement Dans mon code

Mais, pour sûr, avoir ce comportement et, pire, n'avoir aucune idée de comment procéder pour le comprendre, est vraiment mauvais. Je serai reconnaissant pour toutes les idées!

(REMARQUE: ajouter des références à System.coreex, System.Reactive et 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); 
     } 
    } 
} 

et son 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> 

Répondre

1

Votre application ont un menu principal? Appuyer sur la touche Alt permet de faire la mise au point sur la barre de menu et appuyer à nouveau sur Alt pour revenir à la mise au point. Cela pourrait expliquer la fonctionnalité que vous voyez. (Ça ne ressemble pas à un problème de Rx)

+0

Je vais y jeter un coup d'œil, Richard. Je n'ai rien fait pour mettre spécifiquement un menu dans l'application (le XAML ci-dessus est le tout), mais toute l'infrastructure «Command» de WPF semble être active et c'est peut-être le cas.L'outil snoop m'aide un peu. blois.us/snoop. –

Questions connexes