Obtenir la position absolue de l'élément dans la fenêtre dans wpf


88

Je voudrais obtenir la position absolue d'un élément par rapport à l'élément window / root quand il est double-cliqué. La position relative de l'élément dans son parent est tout ce que je peux sembler atteindre, et ce que j'essaie d'arriver est le point relatif à la fenêtre. J'ai vu des solutions pour obtenir le point d'un élément sur l'écran, mais pas dans la fenêtre.

Réponses:


127

Je pense que ce que veut BrandonS n'est pas la position de la souris par rapport à l'élément racine, mais plutôt la position d'un élément descendant.

Pour cela, il existe la méthode TransformToAncestor :

Point relativePoint = myVisual.TransformToAncestor(rootVisual)
                              .Transform(new Point(0, 0));

Où myVisualest l'élément sur lequel vous venez de double-cliquer, et rootVisualest Application.Current.MainWindow ou tout ce à quoi vous voulez la position relative.


2
Salut, j'ai essayé cela et j'obtiens l'exception suivante: System.InvalidOperationException n'a pas été gérée Message = Le visuel spécifié n'est pas un ancêtre de ce visuel. Source = PresentationCore Une idée?
— RoflcoptrException

8
Visual.TransformToAncestor ne fonctionnera que si vous transmettez un Visual contenant. Si vous voulez la position relative de deux éléments et que l'un ne contient pas l'autre, vous pouvez utiliser Visual.TransformToVisual à la place.
— Robert Macnee

5
TransformToVisual nécessite toujours un ancêtre commun qui peut être problématique si le contrôle est dans un popup
— Adam Mills

1
Super intuitif! Ne peuvent-ils pas envelopper cela dans un appel "GetRelativePosition"? :-) Merci pour l'aide. +1
— Paul

1
@ cod3monk3y - ou peut-être, si Microsoft ouvre les sources WPF, je leur enverrai une pull request :-)
— Paul

41

Pour obtenir la position absolue d'un élément de l'interface utilisateur dans la fenêtre, vous pouvez utiliser:

Point position = desiredElement.PointToScreen(new Point(0d, 0d));

Si vous êtes dans un contrôle utilisateur et souhaitez simplement la position relative de l'élément d'interface utilisateur dans ce contrôle, utilisez simplement:

Point position = desiredElement.PointToScreen(new Point(0d, 0d)),
controlPosition = this.PointToScreen(new Point(0d, 0d));

position.X -= controlPosition.X;
position.Y -= controlPosition.Y;

4
Notez que cela ne fait probablement pas ce que vous attendez si la mise à l'échelle de votre affichage n'est pas réglée sur 100% (c'est-à-dire sur les écrans à haute résolution).
— Drew Noakes le

18

Ajoutez cette méthode à une classe statique:

 public static Rect GetAbsolutePlacement(this FrameworkElement element, bool relativeToScreen = false)
    {
        var absolutePos = element.PointToScreen(new System.Windows.Point(0, 0));
        if (relativeToScreen)
        {
            return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
        }
        var posMW = Application.Current.MainWindow.PointToScreen(new System.Windows.Point(0, 0));
        absolutePos = new System.Windows.Point(absolutePos.X - posMW.X, absolutePos.Y - posMW.Y);
        return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
    }

Définissez le relativeToScreenparamètre sur truepour le placement à partir du coin supérieur gauche de tout l'écran ou sur falsepour le placement à partir du coin supérieur gauche de la fenêtre d'application.


1
Cela fonctionne à merveille! J'utilise cela avec une animation qui fait glisser une image sur ou hors écran en modifiant le RenderTransformde l'élément, et par conséquent, il a besoin de connaître la position absolue de l'élément sur l'écran.
— cod3monk3y

6

Depuis .NET 3.0, vous pouvez simplement utiliser *yourElement*.TranslatePoint(new Point(0, 0), *theContainerOfYourChoice*).

Cela vous donnera le point 0, 0 de votre bouton, mais vers le conteneur. (Vous pouvez également donner un autre point que 0, 0)

Vérifiez ici pour le doc.


0

Hm. Vous devez spécifier la fenêtre sur laquelle vous avez cliqué dans le Mouse.GetPosition(IInputElement relativeTo) code suivant fonctionne bien pour moi

protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        Point p = e.GetPosition(this);
    }

Je soupçonne que vous devez vous référer à la fenêtre non pas depuis sa propre classe mais depuis un autre point de l'application. Dans ce cas Application.Current.MainWindow, vous aidera.


Même si ce n'est pas ce que l'auteur a demandé, cela m'a mis sur la bonne voie, merci
— Ladislav Ondris
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.