it-swarm.com.de

C # Abrufen der Position eines Steuerelements in einem Formular

Gibt es eine Möglichkeit, die Position eines Steuerelements in einem Formular abzurufen, wenn sich das Steuerelement möglicherweise in anderen Steuerelementen befindet (z. B. in Bedienfeldern)?

Die Eigenschaften Left und Top des Steuerelements geben mir nur die Position innerhalb des übergeordneten Steuerelements an. Was passiert jedoch, wenn sich das Steuerelement in fünf verschachtelten Bedienfeldern befindet und ich die Position im Formular benötige?

Ein kurzes Beispiel:

Die Schaltfläche btnA befindet sich an den Koordinaten (10, 10) im Bereich pnlB.
Das Panel pnlB befindet sich an den Koordinaten (15,15) innerhalb des Formulars frmC.

Ich möchte den Standort von btnA auf frmC, also (25,25).

Kann ich diesen Ort bekommen?

63
Erlend D.

Normalerweise kombiniere ich PointToScreen und PointToClient:

Point locationOnForm = control.FindForm().PointToClient(
    control.Parent.PointToScreen(control.Location));
88
Fredrik Mörk

Mit der Methode Steuerelemente PointToScreen können Sie die absolute Position in Bezug auf den Bildschirm ermitteln.

Sie können die Methode Forms PointToScreen ausführen und mit einfachen Berechnungen die Position des Steuerelements ermitteln.

11
Raj More

Ich mache es normalerweise so .. Funktioniert jedes Mal ..

var loc = ctrl.PointToScreen(Point.Empty);
7
noisyass2

Sie können durch die Eltern gehen und deren Position innerhalb der Eltern notieren, bis Sie zum Formular gelangen.

Edit: Etwas wie (ungetestet):

public Point GetPositionInForm(Control ctrl)
{
   Point p = ctrl.Location;
   Control parent = ctrl.Parent;
   while (! (parent is Form))
   {
      p.Offset(parent.Location.X, parent.Location.Y);
      parent = parent.Parent;
   }
   return p;
}
6
Hans Kesting

Supergeek, Ihre nicht-rekursive Funktion hat nicht das richtige Ergebnis geliefert, meine jedoch. Ich glaube, deine macht eine zu viele Ergänzungen.

private Point LocationOnClient(Control c)
{
   Point retval = new Point(0, 0);
   for (; c.Parent != null; c = c.Parent)
   { retval.Offset(c.Location); }
   return retval;
}
5
Plater

Merkwürdigerweise waren PointToClient und PointToScreen für meine Situation nicht ideal. Vor allem, weil ich mit Offscreen-Steuerelementen arbeite, die keiner Form zugeordnet sind. Ich fand die Lösung von sahin am hilfreichsten, entfernte jedoch die Rekursion und beendete die Formularbeendigung. Die folgende Lösung funktioniert für alle meine Steuerelemente, die sichtbar sind oder nicht, die in Formularen enthalten sind oder nicht, IContainered oder nicht. Danke Sahim.

private static Point FindLocation(Control ctrl)
{
    Point p;
    for (p = ctrl.Location; ctrl.Parent != null; ctrl = ctrl.Parent)
        p.Offset(ctrl.Parent.Location);
    return p;
}
3
BoeroBoy
private Point FindLocation(Control ctrl)
{
    if (ctrl.Parent is Form)
        return ctrl.Location;
    else
    {
        Point p = FindLocation(ctrl.Parent);
        p.X += ctrl.Location.X;
        p.Y += ctrl.Location.Y;
        return p;
    }
}
1
sahin

In meinen Tests gaben sowohl die Lösungen von Hans Kesting als auch die von Fredrik Mörk die gleiche Antwort. Aber:

Ich fand eine interessante Diskrepanz in der Antwort mit den Methoden von Raj More und Hans Kesting und dachte, ich würde teilen. Vielen Dank an beide für ihre Hilfe. Ich kann nicht glauben, dass eine solche Methode nicht in das Framework integriert ist.

Bitte beachten Sie, dass Raj keinen Code geschrieben hat und daher meine Implementierung möglicherweise anders ist als er es gedacht hat.

Der Unterschied, den ich fand, war, dass die Methode von Raj More oft zwei Pixel größer war (sowohl in X als auch in Y) als die Methode von Hans Kesting. Ich habe noch nicht festgestellt, warum dies auftritt. Ich bin mir ziemlich sicher, dass es etwas damit zu tun hat, dass der Inhalt eines Windows-Formulars (als innerhalb der äußersten Grenzen des Formulars). In meinen Tests, die sicherlich nicht vollständig waren, bin ich nur auf verschachtelte Steuerelemente gestoßen. Es wird jedoch nicht von allen verschachtelten Steuerelementen angezeigt. Zum Beispiel habe ich eine TextBox in einer GroupBox, die die Diskrepanz aufweist, eine Schaltfläche in derselben GroupBox jedoch nicht. Ich kann nicht erklären warum.

Beachten Sie, dass, wenn die Antworten äquivalent sind, der Punkt (0, 0) als innerhalb des oben erwähnten Inhaltsrahmens betrachtet wird. Daher glaube ich, dass ich die Lösungen von Hans Kesting und Fredrik Mörk für richtig halten werde, aber glaube nicht, dass ich der von mir implementierten Lösung von Raj More vertraue.

Ich fragte mich auch genau, welchen Code Raj More geschrieben hätte, da er eine Idee hatte, aber keinen Code lieferte. Ich habe die PointToScreen () -Methode erst vollständig verstanden, als ich diesen Beitrag gelesen habe: http://social.msdn.Microsoft.com/Forums/en-US/netfxcompact/thread/aa91d4d8-e106-48d1-8e8a -59579e14f495

Hier ist meine Methode zum Testen. Beachten Sie, dass die in den Kommentaren erwähnte Methode 1 sich geringfügig von der von Hans Kesting unterscheidet.

private Point GetLocationRelativeToForm(Control c)
{
  // Method 1: walk up the control tree
  Point controlLocationRelativeToForm1 = new Point();
  Control currentControl = c;
  while (currentControl.Parent != null)
  {
    controlLocationRelativeToForm1.Offset(currentControl.Left, currentControl.Top);
    currentControl = currentControl.Parent;
  }

  // Method 2: determine absolute position on screen of control and form, and calculate difference
  Point controlScreenPoint = c.PointToScreen(Point.Empty);
  Point formScreenPoint = PointToScreen(Point.Empty);
  Point controlLocationRelativeToForm2 = controlScreenPoint - new Size(formScreenPoint);

  // Method 3: combine PointToScreen() and PointToClient()
  Point locationOnForm = c.FindForm().PointToClient(c.Parent.PointToScreen(c.Location));

  // Theoretically they should be the same
  Debug.Assert(controlLocationRelativeToForm1 == controlLocationRelativeToForm2);
  Debug.Assert(locationOnForm == controlLocationRelativeToForm1);
  Debug.Assert(locationOnForm == controlLocationRelativeToForm2);

  return controlLocationRelativeToForm1;
}
1
Tyler Collier

Das, was ich getan habe, wirkt wie ein Zauber

            private static int _x=0, _y=0;
        private static Point _point;
        public static Point LocationInForm(Control c)
        {
            if (c.Parent == null) 
            {
                _x += c.Location.X;
                _y += c.Location.Y;
                _point = new Point(_x, _y);
                _x = 0; _y = 0;
                return _point;
            }
            else if ((c.Parent is System.Windows.Forms.Form))
            {
                _point = new Point(_x, _y);
                _x = 0; _y = 0;
                return _point;
            }
            else 
            {
                _x += c.Location.X;
                _y += c.Location.Y;
                LocationInForm(c.Parent);
            }
            return new Point(1,1);
        }
0
shiroxx