2016-11-03 4 views
3

J'ai le numéro suivant:Écrire la position de la souris absolue dans TextBox

J'ai une fenêtre avec deux zones de texte. Lorsque je clique dans une zone de texte et puis cliquez n'importe où ailleurs (même en dehors de la fenêtre), la position du clic de souris doit être écrite dans la zone de texte.

J'ai trouvé la bibliothèque MouseKeyHook, dans laquelle une démo montre comment la position de la souris est mise à jour dans un formulaire Windows. Mais je n'ai pas encore réussi à appliquer le code à mon problème. Je ne sais même pas où je devrais écrire le code trouvé dans la démo.

Ce que je suis venu avec à ce jour est la suivante:

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace LineClicker 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void StarttextBox_GotFocus(object sender, RoutedEventArgs e) 
     { 
      Mouse.Capture(StarttextBox); 
      StarttextBox.Text = string.Format(" x {0} , y {1}", PointToScreen(Mouse.GetPosition(this)).X, PointToScreen(Mouse.GetPosition(this)).Y); 
     } 
    } 
} 

Voici le code pour une zone de texte. Lorsque je clique dessus, les coordonnées x et y sont affichées. Ils ne sont pas absolus, je pense que cela est dû au paramètre this dans la méthode GetPosition. Que dois-je choisir au lieu de this?

Une autre chose est que la position n'est pas toujours mise à jour. Lorsque je déplace la souris vers le coin inférieur droit de mon bureau, puis que j'active la zone de texte en la tabulant, la position n'est pas mise à jour.

Quelles sont les étapes à suivre ici?

+0

Si vous souhaitez obtenir la position absolue de la souris, par rapport à l'écran, et la mettre à jour même lorsque vous êtes en dehors de la fenêtre WPF, vous devrez utiliser un MouseHook (Utilise les appels API Win32 pour obtenir la position) et un minuteur, qui obtient la position et l'affiche dans votre TextBlock. –

Répondre

3

j'ai pu obtenir ce résultat en utilisant Cursor.Position:

A point cela représente la position du curseur dans les coordonnées de l'écran.

Exemple

using System.Windows; 

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void textBox_GotFocus(object sender, RoutedEventArgs e) 
     { 
      var postion = System.Windows.Forms.Cursor.Position; 
      textBox.Text = string.Format($"{postion.X}, {postion.Y}"); 
     } 
    } 
} 

Vous pouvez voir la the Microsoft reference source que Cursor.Position est défini comme:

public static Point Position { 
    get { 
     NativeMethods.POINT p = new NativeMethods.POINT(); 
     UnsafeNativeMethods.GetCursorPos(p); 
     return new Point(p.x, p.y); 
    } 
    set { 
     IntSecurity.AdjustCursorPosition.Demand(); 
     UnsafeNativeMethods.SetCursorPos(value.X, value.Y); 
    } 
} 

Ainsi, tout comme dans yan yankelevich's answer, il utilise encore SetCursorPos, mais De cette façon, il est plus facile d'appeler. En dehors de cela, il dépend probablement que vous soyez ou non heureux d'inclure la référence System.Windows.Forms.

+0

Lorsque j'essaie ceci, 'System.Windows.Forms' est souligné en rouge et il y a une erreur disant CS0234 C# Le type ou le nom d'espace de nommage 'Forms' n'existe pas dans l'espace de noms 'System.Windows' (manque-t-il un assembly référence?) –

+0

@DavidP Vous devrez ajouter 'System.Windows.Forms' comme référence en allant dans' Project' -> 'Add Reference', puis sélectionnez-le dans la liste (Il sera sous Assmblies -> Framework) – Bassie

+0

Cela a fonctionné, merci! Cette solution semble plus facile que celle de yan yankalevich. Y a-t-il des avantages/désavantages entre votre réponse et la sienne? –

2

Vous devez d'abord obtenir la position absolue de la souris (pas par rapport à votre fenêtre ou à vos contrôles). Pour ce faire, vous avez besoin d'une de ces options (d'ici: https://stackoverflow.com/a/4232281/4664754):

  • En ajoutant une référence à System.Windows.Forms dans votre projet (allez dans les références dans l'explorateur de solution -> Clic droit -> Ajouter une référence -> Assemblys-> Framework -> Cochez la case près de System.Windows.Forms). Ensuite, ajoutez cette funtcion statique dans une classe (appelons-le MouseHelper.cs):

    public static Point GetMousePositionWindowsForms() 
    { 
        System.Drawing.Point point = Control.MousePosition; 
        return new Point(point.X, point.Y); 
    } 
    
  • En collant ce code dans votre MainWindow.xaml.cs:

    [DllImport("user32.dll")] 
        [return: MarshalAs(UnmanagedType.Bool)] 
        internal static extern bool GetCursorPos(ref Win32Point pt); 
    
        [StructLayout(LayoutKind.Sequential)] 
        internal struct Win32Point 
        { 
         public Int32 X; 
         public Int32 Y; 
        }; 
        public static Point GetMousePosition() 
        { 
         Win32Point w32Mouse = new Win32Point(); 
         GetCursorPos(ref w32Mouse); 
         return new Point(w32Mouse.X, w32Mouse.Y); 
        } 
    

Quelle que soit la comme vous choisissez, vous devrez appeler l'une de ces fonctions dans votre OnFocusChanged de cette façon:

private void StarttextBox_GotFocus(object sender, RoutedEventArgs e) 
     { 
      Mouse.Capture(StarttextBox); 
      Point mouseCoord = MouseHelper.GetMousePositionWindowsForms(); 
      // Or if you choose the other way : 
      //Point mouseCoord = GetMousePosition(); 
      StarttextBox.Text = string.Format(" x {0} , y {1}", mouseCoord.X, mouseCoord .Y); 
     } 

De cette façon, les coordonnées doivent être correctes. Pour votre problème de coordonnées ne s'affichant pas au bon moment, je pense que votre solution de mise au point n'est pas ce que vous cherchez.

Vous devriez essayer de mettre en œuvre quelque chose comme ceci: https://stackoverflow.com/a/2064009/4664754 et changer vos valeurs de zones de texte à chaque fois que l'événement TheMouseMoved est appelé