修改
到目前为止,所有的答案都指出了最初编写的代码是hacky。我没有写它,也不完全理解它是如何工作的。 然而,在一般情况下,它确实有效。我尝试了各种整理,但由于PointToScreen
的奇怪行为,它们无法解决基本问题。
解释这种行为的替代方法,我可以看到很难解释,如果不理解其他形式的内部工作(我现在不是),就是想出一种替代方法来实现所需的功能,按下按钮时出现在按钮顶部的小对话框。当前实现是一个显示在顶部的表单,然后跟踪原始表单以保持其位置。有更清洁的选择吗?
原始问题:
我正在尝试使用PointToScreen
在表单(表单C)上将表单(表单A)放在控件(按钮B)的顶部:
Point buttonCorner = buttonB.Parent.PointToScreen(buttonB.Location);
其中buttonB
是表单上FlowLayoutPanel
的按钮。
大部分时间它都有效,我得到了我期望的位置。我在表单上的LocationChanged
事件中使用此代码,以便表单A跟踪按钮B.这样工作正常。
然而,当另一个动作导致父窗体调整大小时,我发现buttonCorner
的位置是偏移的,这样窗体A最终会离开屏幕(右边)。在此次活动之前,我的表格中没有任何部分出现在屏幕之外。
我能提出的唯一理论是LocationChanged
事件在FlowLayoutPanel
重新安排时触发,并且在此期间它返回不良位置。这看起来有点牵强,但我没有更好的理论。
答案 0 :(得分:1)
假设您有panelA
和panelB
。您必须注册LocationChanged
而不是表单的panelB
:
panelB.LocationChanged += (s,e) => {
Point buttonCorner = PanelControlFlow.PointToScreen(PanelControlFlow.Location);
//...
};
无论如何,我觉得你的代码有错误的方法,你的2个控件可能不需要相互跟踪,除非你在运行时更改它们的位置。您应该提供更多详细信息,以便我们找到另一种更好的方法。请注意,FlowLayoutPanel
会自动压缩控件并对其进行定位控件不会产生任何影响。
<强>更新强>:
为什么你的PointToScreen
会返回一些屏幕外点。我已经对此进行了测试,当表单最小化时,其Location
为-32000, -32000
。所有PointToScreen
都将添加此Location
,这意味着如果您的控件在您的表单上计算Left
为300
,则其Left
计算在-32000 + 300 = -31700
上屏幕大约为Top
。 LocationChanged
也是如此。这就是为什么你的控制位置离开屏幕的原因。因此,您必须将要跟踪的控件的Location
注册到表单中。为什么最小化窗口的-32000,-32000
为{{1}}?我认为这是一个窗口隐藏在屏幕上的方式。
答案 1 :(得分:1)
Point buttonCorner = PanelControlFlow.PointToScreen(PanelControlFlow.Location);
该代码肯定是错误的,Location值是相对于控件的Parent。如果您想知道面板左上角的位置,那么您必须使用:
Point panelCorner = PanelControlFlow.PointToScreen(Point.Empty);
或面板中的按钮:
Point buttonCorner = someButtonInPanel.Parent.PointToScreen(someButtonInPanel.Location);
然后在顶部获得另一个按钮:
anotherButton.Location = anotherButton.Parent.PointToClient(buttonCorner);