Comment obtenir la position de la souris par rapport au bureau dans WPF?

Problème

Lorsque vous recherchez une telle question avec Google, vous obtenez beaucoup de résultats, mais toutes les solutions supposent que vous ayez au moins une fenêtre.

Mais ma question est juste comme je l’ai formulée – pas de suppositions du tout. Je peux avoir une fenêtre, mais je pourrais avoir zéro fenêtre (parce que je n’en ai même pas montré une ou j’ai juste fermé la dernière). En bref, la solution ne peut s’appuyer sur aucun widget ou fenêtre. La seule chose qu’on sache, c’est qu’il existe un ordinateur de bureau (et une application en cours d’exécution, mais qu’elle n’a aucune fenêtre).

La question est donc: comment obtenir la position de la souris?

Contexte

Je voudrais montrer des fenêtres centrées à la position de la souris. Ce mode n’existe pas dans WPF (il n’y a que centre à propriétaire, ou centre à écran), je dois donc le faire manuellement. La pièce manquante est la position de la souris.

Édite

Merci à vous tous. J’ai maintenant la première partie de la solution: la position brute. Maintenant, il y a un problème comment convertir les données pour WPF. J’ai trouvé un tel sujet: pixels WPF en pixels du bureau, mais encore une fois, cela suppose d’avoir une fenêtre.

Puis j’ai googlé plus et j’ai trouvé la solution: http://jerryclin.wordpress.com/2007/11/13/creating-non-rectangular-windows-with-interop/

le code inclut une classe pour la mise à l’échelle des coordonnées en s’appuyant uniquement sur des informations relatives au bureau Alors joignant ces deux pièces, j’ai enfin trouvé la solution :-). Merci encore.

Obtenir les coordonnées de l’écran:

[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out POINT lpPoint); [StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; public POINT(int x, int y) { this.X = x; this.Y = y; } } private void WritePoint(object sender, RoutedEventArgs e) { POINT p; if (GetCursorPos(out p)) { System.Console.WriteLine(Convert.ToSsortingng(pX) + ";" + Convert.ToSsortingng(pY)); } } 

Conversion de pixels en unités WPF:

 [DllImport("User32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("gdi32.dll")] static extern int GetDeviceCaps(IntPtr hdc, int nIndex); [DllImport("user32.dll")] static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); private Point ConvertPixelsToUnits(int x, int y) { // get the system DPI IntPtr dDC = GetDC(IntPtr.Zero); // Get desktop DC int dpi = GetDeviceCaps(dDC, 88); bool rv = ReleaseDC(IntPtr.Zero, dDC); // WPF's physical unit size is calculated by taking the // "Device-Independant Unit Size" (always 1/96) // and scaling it by the system DPI double physicalUnitSize = (1d / 96d) * (double)dpi; Point wpfUnits = new Point(physicalUnitSize * (double)x, physicalUnitSize * (double)y); return wpfUnits; } 

Mettre les deux ensemble:

 private void WriteMouseCoordinatesInWPFUnits() { POINT p; if (GetCursorPos(out p)) { Point wpfPoint = ConvertPixelsToUnits(pX, pY); System.Console.WriteLine(Convert.ToSsortingng(wpfPoint.X) + ";" + Convert.ToSsortingng(wpfPoint.Y)); } } 

Deux options:

Utilisez System.Windows.Forms.Control.MousePosition ou p / invoke

 [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] public static extern bool GetCursorPos([In, Out] NativeMethods.POINT pt); 

La première option fait déjà le p / invoke pour vous. Je ne suis pas tout à fait sûr que cela nécessite une interface utilisateur, mais je ne le pense pas. Oui, ses winforms et pas wpf, mais cela n’a vraiment rien à voir avec sa localisation.

Si vous souhaitez ignorer les dépendances de system.windows.forms.dll, consultez les informations complémentaires relatives à la seconde sur pinvoke.net .

Je suis tombé sur ce fil en cherchant une solution au même problème. En attendant, j’ai trouvé PointToScreen , qui ne nécessite aucun P / Invoke. La méthode est disponible sur tout Visual démarrant .NET 3.0 (et donc UIElement , Control , etc.) et une implémentation ressemblerait à ceci:

 protected void OnMouseLeave(object Sender, MouseEventArgs e) { var relativePosition = e.GetPosition(this); var screenPosition = this.PointToScreen(relativePosition); }