这不是开箱即用的;我仍然认为这不是很有用;但也许您的特殊应用确实需要它..
这是下面几行的结果:
下面是示例代码:
首先,我们需要通过在每个控件的Tag 中存储旧的边界以及原始父大小来进行设置:
// pick the top parent; in my case it wa a TabPage (not shown)
Control ctrl = pickTheParent;
foreach (Control c in ctrl.Controls) StoreBounds(ctrl, c);
ctrl.Resize += (ss, ee) =>
{
foreach (Control c in ctrl.Controls) ScaleBounds(c);
};
我们还为父级的Resize 事件绑定了一个大小调整例程。
存储和调整大小都必须发生在所有控件,包括嵌套控件;所以它们是递归的..:
void StoreBounds(Control parent, Control ctl)
{
ctl.Tag = new Tuple<Size, Rectangle>(parent.ClientSize, ctl.Bounds);
// **
foreach (Control c in ctl.Controls) StoreBounds(ctl, c);
}
void ScaleBounds(Control ctl)
{
ctl.Bounds = ScaledBounds(ctl);
foreach (Control c in ctl.Controls) ScaleBounds(c);
}
大小只是计算旧的比率,并从中计算出新的比率:
Rectangle ScaledBounds(Control c)
{
if (c.Tag == null) return c.Bounds;
Rectangle old = ((Tuple<Size, Rectangle>)c.Tag).Item2;
Size frame1 = ((Tuple<Size, Rectangle>)c.Tag).Item1;
Size frame2 = c.Parent.ClientSize;
float rx = 1f * frame2.Width / frame1.Width;
float ry = 1f * frame2.Height / frame1.Height;
int x = (int)(old.Left * rx);
int y = (int)(old.Top * ry);
int w = (int)(old.Width * rx);
int h = (int)(old.Height * ry);
return new Rectangle(x,y,w,h);
}
请注意,为了显示效果,我必须关闭所有 AutoSize 属性。
另请注意,所有Anchors(以及任何Docks)都已删除。要自动执行此操作,您可以在存储代码中添加一两行代码 (**)..:
ctl.Anchor = AnchorStyles.None;
删除Docking 取决于您,也许一些,例如Fill,实际上仍然有用..?
还请注意,该示例严格处理Size 和Location;其他属性不受影响。对于某些人,尤其是Fonts,可以添加更多代码;例如将第三个Item 添加到Tuple 以存储原始FontSize.. 对于其他人,例如Border 宽度,我想不出合理的大小调整方法。
PictureBox 显然被设置为Zoom。