Gibt es eine Möglichkeit, die Position eines Steuerelements in einem Formular abzurufen, wenn sich das Steuerelement möglicherweise in anderen Steuerelementen (z. B. Bedienfeldern) befindet?
Die Eigenschaften Left und Top des Steuerelements geben mir nur die Position innerhalb des übergeordneten Steuerelements an. Was ist jedoch, wenn sich mein Steuerelement in fünf verschachtelten Bedienfeldern befindet und ich seine Position im Formular benötige?
Kurzes Beispiel:
Die Schaltfläche btnA befindet sich an den Koordinaten (10,10) innerhalb des Bedienfelds pnlB.
Das Panel pnlB befindet sich auf den Koordinaten (15, 15) innerhalb des Formulars frmC.
Ich möchte den Standort von btnA auf frmC (25,25).
Kann ich diesen Ort bekommen?
REAL ABSOULUTE POSITION
stackoverflow.com/questions/4998076/…control.PointToScreen(Point.Empty);
?control.PointToScreen(Point.Empty)
gibt den Ort in Bezug auf den Bildschirm an, während die Antwort den Ort mit Bezug auf das Formular der obersten Ebene angibt.Mit der Steuerungsmethode können
PointToScreen
Sie die absolute Position in Bezug auf den Bildschirm ermitteln.Sie können die Forms-
PointToScreen
Methode ausführen und mit einfachen Berechnungen die Position des Steuerelements ermitteln.quelle
Normalerweise mache ich das so. Funktioniert jedes Mal.
var loc = ctrl.PointToScreen(Point.Empty);
quelle
Sie können durch die Eltern gehen und ihre Position innerhalb ihrer Eltern notieren, bis Sie zum Formular gelangen.
Edit: So 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; }
quelle
Supergeek, Ihre nicht rekursive Funktion hat nicht das richtige Ergebnis erzielt, 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; }
quelle
Seltsamerweise waren PointToClient und PointToScreen nicht ideal für meine Situation. Vor allem, weil ich mit Offscreen-Steuerelementen arbeite, die keinem Formular zugeordnet sind. Ich fand Sahins Lösung am hilfreichsten, nahm aber die Rekursion heraus und beseitigte die Formularbeendigung. Die folgende Lösung funktioniert für alle meine Steuerelemente, die sichtbar oder nicht sichtbar, formularhaltig 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; }
quelle
In meinen Tests gaben sowohl die Lösungen von Hans Kesting als auch 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 anders sein könnte als er meinte.
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 geschieht. Ich bin mir ziemlich sicher, dass es etwas damit zu tun hat, dass der Inhalt einen Zwei-Pixel-Rand zu haben scheint eines Windows-Formulars (wie in den äußersten Rändern des Formulars). Bei meinen Tests, die sicherlich nicht erschöpfend waren, bin ich nur auf verschachtelte Steuerelemente gestoßen. Nicht alle verschachtelten Steuerelemente weisen dies jedoch auf. 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 bei äquivalenten Antworten der Punkt (0, 0) innerhalb des oben erwähnten Inhaltsrahmens liegt. Daher glaube ich, dass ich die Lösungen von Hans Kesting und Fredrik Mörk als richtig betrachten werde, aber ich glaube nicht, dass ich der von Raj More implementierten Lösung vertrauen werde.
Ich habe mich auch genau gefragt, welchen Code Raj More geschrieben hätte, da er eine Idee hatte, aber keinen Code zur Verfügung stellte. 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 Testmethode. Beachten Sie, dass sich die in den Kommentaren erwähnte Methode 1 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; }
quelle
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; } }
quelle
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); }
quelle