【发布时间】:2015-05-03 06:06:13
【问题描述】:
我有一个用户控件,它由两个控件和四个按钮组成,排列在一个窗体上:两个控件在侧面,按钮在中间垂直排列。
在应用程序中使用控件时,我将其放置在表单上。
现在,当水平调整表单大小时,两个控件只是向左或向右移动而不改变它们的大小。
我需要的是控件保持固定在表单的中间并增长到两侧(抱歉不够清晰,我准备了屏幕截图,但网站不允许我附加它们)。
有没有办法在不覆盖 Resize 事件的情况下完成此操作?
【问题讨论】:
我有一个用户控件,它由两个控件和四个按钮组成,排列在一个窗体上:两个控件在侧面,按钮在中间垂直排列。
在应用程序中使用控件时,我将其放置在表单上。
现在,当水平调整表单大小时,两个控件只是向左或向右移动而不改变它们的大小。
我需要的是控件保持固定在表单的中间并增长到两侧(抱歉不够清晰,我准备了屏幕截图,但网站不允许我附加它们)。
有没有办法在不覆盖 Resize 事件的情况下完成此操作?
【问题讨论】:
使用TableLayoutPanel 作为用户控件的基础。
您需要 3 列和 1 行。中间一列需要有一个固定的大小,另外 2 个你设置为 50%。不用担心,.Net 足够聪明,可以计算出他们实际占用的百分比。
在左右两列中放置控件并将两者的Dock 属性设置为fill。在中间列中放置一个面板并将其 Dock 属性设置为 fill 作为墙,然后在该面板中将按钮放在中间。
将您的表格布局面板 Dock 设置为 fill 以及将用户控件添加到表单时使用 Dock top、bottom 或 fill。
【讨论】:
勘误: 上面的代码大部分时间都可以工作,但是对于某些 Move-Resize 序列它会失败。解决方案是响应父窗体(控件的使用者)的移动和调整大小事件,而不是控件本身。 还有一件事:由于事件触发顺序(先移动后调整大小,必须将工作代码从 Resize() 移动到 Move(),这似乎违反直觉,但似乎是正确的方式。
【讨论】:
似乎确实无法在 Designer 中完成,但这是使用覆盖的解决方案。 它工作正常,除了一些我无法克服的控制闪烁。
public partial class SB : UserControl
{
//variables to remember sizes and locations
Size parentSize = new Size(0,0);
Point parentLocation = new Point (0,0);
......
// we care only for horizontal changes by dragging the left border;
// all others take care of themselves by Designer code
public void SB_Resize(object sender, EventArgs e)
{
if (this.Parent == null)
return;//we are still in the load process
// get former values
int fcsw = this.parentSize.Width;//former width
int fclx = this.parentLocation.X;//former location
Control control = (Control)sender;//this is our custom control
// get present values
int csw = control.Parent.Size.Width;//present width
int clx = control.Parent.Location.X;//present location
// both parent width and parent location have changed: it means we
// dragged the left border or one of the left corners
if (csw != fcsw && clx != fclx)
{
int delta = clx - fclx;
int lw = (int)this.tableLayoutPanel1.ColumnStyles[0].Width;
int nlw = lw - delta;
if (nlw > 0)
{
this.tableLayoutPanel1.ColumnStyles[0].Width -= delta;
}
}
this.parentSize = control.Parent.Size;//always update it
this.parentLocation = control.Parent.Location;
}
//contrary to documentation, the Resize event is not raised by moving
//the form, so we have to override the Move event too, to update the
//saved location
private void SB_Move(object sender, EventArgs e)
{
if (this.Parent == null)
return;//we are still in the load process
this.parentSize = this.Parent.Size;//always update it
this.parentLocation = this.Parent.Location;
}
}
上面的代码大部分时间都可以工作,但是对于某些 Move-Resize 序列它会失败。解决方案是响应父窗体(控件的使用者)的 Move 和 Resize 事件,而不是控件本身。
还有一件事:由于事件触发顺序(Move 首先是 Resize,必须将工作代码从 Resize() 移动到 Move(),这似乎违反直觉,但似乎是正确的方式。
【讨论】: