我正在寻找一个属性,它为我提供了一个控件相对于其窗体位置的位置,而不是窗体的ClientRectangle's
“0,0”。
当然,我可以将所有内容都转换为屏幕坐标,但我想知道是否有更直接的方法可以做到这一点。
您需要转换为屏幕坐标,然后进行一些数学运算。
Point controlLoc = form.PointToScreen(myControl.Location);
表单的位置已经在屏幕坐标中。
现在:
Point relativeLoc = new Point(controlLoc.X - form.Location.X, controlLoc.Y - form.Location.Y);
这将为您提供相对于表单左上角的位置,而不是相对于表单的客户区。
我认为这将回答您的问题。请注意,“this”是表格。
Rectangle screenCoordinates = control.Parent.ClientToScreen(control.ClientRectangle);
Rectangle formCoordinates = this.ScreenToClient(screenCoordinates);
似乎答案是没有直接的方法可以做到这一点。
(正如我在问题中所说,我正在寻找一种使用屏幕坐标以外的方法。)
鉴于问题的具体情况,所选答案在技术上是正确的:.NET 框架中不存在此类属性。
但是,如果您想要这样的属性,这里有一个控件扩展可以解决问题。是的,它使用屏幕坐标,但考虑到帖子标题的一般性质,我相信登陆此页面的一些用户可能会发现这很有用。
顺便说一句,我花了几个小时试图通过循环遍历所有控制父母来在没有屏幕坐标的情况下做到这一点。我永远无法调和这两种方法。这很可能是由于 Hans Passant 对 OP 评论 Aero 如何对窗口大小撒谎。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Cambia
{
public static class ControlExtensions
{
public static Point FormRelativeLocation(this Control control, Form form = null)
{
if (form == null)
{
form = control.FindForm();
if (form == null)
{
throw new Exception("Form not found.");
}
}
Point cScreen = control.PointToScreen(control.Location);
Point fScreen = form.Location;
Point cFormRel = new Point(cScreen.X - fScreen.X, cScreen.Y - fScreen.Y);
return cFormRel;
}
}
}
当您在 Autosize 设置为 true 的许多其他控件中拥有控件时,上述答案均无济于事,即
Form -> FlowLayoutPanel -> Panel -> Panel -> Control
所以我用不同的逻辑编写了自己的代码,我只是不知道如果在父控件之间使用一些对接会产生什么结果。我想 Margins 和 Paddings 需要参与这种情况。
public static Point RelativeToForm(this Control control)
{
Form form = control.FindForm();
if (form is null)
return new Point(0, 0);
Control parent = control.Parent;
Point offset = control.Location;
while (parent != null)
{
offset.X += parent.Left;
offset.Y += parent.Top;
parent = parent.Parent;
}
offset.X -= form.Left;
offset.Y -= form.Top;
return offset;
}