8

有没有办法在 WinForms 中获取剪辑控件的可见部分的大小?

一个很简单的例子:在窗体上放置一个控件,并使窗体宽度小于控件宽度。你如何获得控件可见区域的宽度?在这种情况下,您可以使用表单的 ClientSize,但并不总是那么简单。

一个更复杂(和真实)的例子:我有一个 AutoSize 设置为 true 的标签,它可以增长到超出其包含控件的宽度,导致它被剪裁。当这种情况发生时,我需要知道。这并不像比较标签的宽度与其容器的宽度那么简单,因为容器也可能有 AutoSize = true 并且也会被裁剪。

目前我的方法是沿着容器树向上走,直到找到一个 AutoSize = false 的容器,并获得它的宽度。我还必须考虑每个容器的填充。但这仅考虑控件被其容器或其容器的容器等裁剪。如果有问题的控件或任何容器被具有更高 Z 顺序的同级控件裁剪,则它将不起作用。我怀疑还有其他方法可以轻松打破这种方法。

将标签 AutoSize 更改为 false 不是一种选择。标签位于设置为 AutoSize 的 UserControl 上,因此当标签增长时,UserControl 也会随之增长。在不使用 AutoSize 的情况下让它工作很痛苦。

我尝试使用的东西,但没有成功:

Control.ClientSize, Control.ClientRectangle, Control.PreferredSize, Control.CreateGraphics().VisibleClipBounds.

我已经玩了一点图形类,但我在那里过头了。Graphics.VisibleClipBounds听起来很有希望,但似乎总是返回与提到的其他大小属性相同的值。

这特别适用于 WinForms。如果仅此而已,我会对 ap/invoke 解决方案感到满意。

在发布之前,我确实做了详尽的搜索。类似的问题都没有帮助。

4

1 回答 1

6

您可以为此使用 Control.ClientRectangle。您需要做的是在上树时获取每个控件的屏幕边界,并计算交点。

它会是这样的:

Control c = myControl;
var rect = c.RectangleToScreen(c.ClientRectangle);
while (c != null) {
    rect = Rectangle.Intersect(rect, c.RectangleToScreen(c.ClientRectangle));
    c = c.Parent;
}
rect = myControl.RectangleToClient(rect);

现在这应该对您有用,但是为了解决您决定何时绘制椭圆的问题,我建议改为引入更好的控件大小。如果每个控件的大小适当,通常会更好,以便它需要的所有信息都是它自己的大小来决定如何绘制它的内容。

您描述的问题是典型的自动尺寸方案。您希望它自动调整大小,但在容器太小时也受到限制。我尽量避免自动调整大小,而是通过覆盖 OnSizeChanged 来使用 Dock 属性和自定义布局登录。不过,这可能会或可能不会满足您的需求。

于 2012-05-11T07:38:33.357 回答