>我正在搜索一个属性,该属性为我提供了控件相对于其窗体位置的位置,而不是窗体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
所以我用不同的逻辑编写了自己的代码,我只是不知道如果在父控件之间使用一些停靠会是什么结果。我想边距和填充将需要参与这种情况。
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;
}