有没有办法在表单中检索控件的位置,即使该控件可能在其他控件(如面板)内部?
控件的Left和Top属性仅给出它在父控件内的位置,但如果我的控件位于五个嵌套的面板中,我需要它在表单上的位置怎么办?
举个例子:
按钮btnA位于面板pnlB内的坐标为(10,10)。
面板pnlB位于窗体frmC内的坐标为(15,15)。
我想要btnA在frmC上的位置,即(25,25)。
我能获取这个位置吗?
我通常使用PointToScreen
和PointToClient
相结合:
Point locationOnForm = control.FindForm().PointToClient(
control.Parent.PointToScreen(control.Location));
我通常这样做...每次都有效...
var loc = ctrl.PointToScreen(Point.Empty);
您可以使用控件的 PointToScreen
方法来获取相对于屏幕的绝对位置。
您可以使用窗体的 PointToScreen
方法,并结合基本数学知识,获取控件的位置。
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;
}
Supergeek,你的非递归函数没有产生正确的结果,但我的函数做到了。我相信你的函数进行了多余的加法运算。
private Point LocationOnClient(Control c)
{
Point retval = new Point(0, 0);
for (; c.Parent != null; c = c.Parent)
{ retval.Offset(c.Location); }
return retval;
}
奇怪的是,PointToClient和PointToScreen对于我的情况并不理想。特别是因为我正在处理与任何表单都没有关联的离屏控件。我发现sahin的解决方案最有帮助,但去掉了递归并消除了表单终止。下面的解决方案适用于我所有可见或不可见的控件,无论是否包含在表单中或容器中。谢谢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;
}
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;
}
}
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;
}
这就是我所做的,非常完美。
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);
}
control.PointToScreen(Point.Empty);
有什么不同? - strongrileycontrol.PointToScreen(Point.Empty)
返回相对于屏幕的位置,而答案返回相对于顶级窗体的位置。 - nawfalcontrol.Parent.PointToScreen(control.Location)
和control.PointToScreen(Point.Empty)
是一样的;它们都返回控件相对于屏幕的位置(我更喜欢第二个因为更短)。然后,我们把这个值传递给Form.PointToClient()
以获取相对于窗体的位置。 - 41686d6564 stands w. Palestine