当控件可能位于其他控件(如“面板”)内部时,是否有任何方法可以检索表单中的控件位置?
控件的Left和Top属性只给我它在父控件中的位置,但是如果我的控件在五个嵌套面板中,并且我需要它在窗体上的位置怎么办?
快速示例:
按钮btnA位于面板pnlB内部的坐标(10,10)上。
面板pnlB位于表格frmC内的坐标(15,15)上。
我想要btnA在frmC上的位置是(25,25)。
我可以得到这个位置吗?
Answers:
我通常结合PointToScreen
和PointToClient
:
Point locationOnForm = control.FindForm().PointToClient(
control.Parent.PointToScreen(control.Location));
control.PointToScreen(Point.Empty);
有何不同?
control.PointToScreen(Point.Empty)
给出相对于屏幕的位置,而答案则给出相对于顶层表格的位置。
您可以使用控件PointToScreen
方法来获取相对于屏幕的绝对位置。
您可以执行FormsPointToScreen
方法,并使用基本数学方法获得控件的位置。
您可以遍历父母,注意他们在父母中的位置,直到您到达表格。
编辑:类似(未经测试):
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;
}
奇怪的是,PointToClient和PointToScreen在我的情况下并不理想。特别是因为我正在使用与任何形式都不相关的屏幕外控件。我发现sahin的解决方案最有用,但是进行了递归并消除了Form终止。以下解决方案适用于我的任何控件(无论是否可见),是否包含表单,是否包含IContainer。谢谢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;
}
在我的测试中,Hans Kesting和FredrikMörk的解决方案给出了相同的答案。但:
我使用Raj More和Hans Kesting的方法在答案中发现了一个有趣的差异,并认为我会分享。感谢双方的帮助;我不敢相信这种方法没有内置在框架中。
请注意,Raj没有编写代码,因此我的实现可能与他的意思不同。
我发现的区别是,Raj More的方法通常比Hans Kesting的方法大两个像素(在X和Y方向上)。我尚未确定为什么会发生这种情况。我非常确定,这与Windows窗体的内容周围似乎有两个像素的边框有关(例如,在窗体的最外面的边框内部)。在我的测试中,这当然在任何程度上都不是详尽无遗的,我只是在嵌套的控件上碰到过它。但是,并非所有嵌套控件都可以显示它。例如,我在GroupBox内有一个TextBox表现出差异,但是在同一GroupBox内没有Button。我无法解释原因。
请注意,当答案相等时,它们会认为点(0,0)在我上面提到的内容边界之内。因此,我相信我会认为Hans Kesting和FredrikMörk的解决方案是正确的,但我认为我不会相信我为Raj More's实现的解决方案。
我还想知道Raj More会写什么代码,因为他给出了一个主意,但没有提供代码。在阅读这篇文章之前,我还没有完全理解PointToScreen()方法:http : //social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/aa91d4d8-e106-48d1-8e8a-59579e14f495
这是我的测试方法。请注意,注释中提到的“方法1”与Hans Kesting的方法略有不同。
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);
}
REAL ABSOULUTE POSITION
stackoverflow.com/questions/4998076/...