由于想要将每日Task在开机时启动,而且不显示在任务栏,只是显示在右下角,由点击右下角的icon来切换其WindowState,所以,设计了这样一个东西。。
但,如果TabControl的Anchor是Top, Bottom, Left, Right的时候,先最小化,再点击右下角的Icon后,执行下面的代码后,会发现TabControl不见了……
private void notifyIcon1_Click(object sender, EventArgs e)
{
if (MouseButtons.Left == (e as MouseEventArgs).Button)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Visible = true;
this.WindowState = FormWindowState.Normal;
}
else if (this.WindowState == FormWindowState.Normal)
{
this.WindowState = FormWindowState.Minimized;
this.Visible = false;
}
}
protected override void OnSizeChanged(EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Visible = false;
}
}
经过调查,发现在执行 this.Visible = true;的时候,会改变TabControl的Size为『0,0』。看了下堆栈,才知道是为什么会发生这样的问题……
可以看到在发生VisibleChange时,会执行DoLayout这样一个方法,虽然目前不知道里面做了些什么,但无非应该是重新布局,而设定Visible=true是在改变WindowState之前执行的,所以在DoLayout的时候,其实WindowState还是最小化状态,这时做DoLayout,当然就会根据上下左右来更改控件大小了。。。试想,在一个无扩展的空间内重新布局,当然就会把TabControl的Size变成0了……
那么,能不能先改WindowState然后再设定Visible呢?结果设定WindowState的代码虽然执行了,但却没有真正的恢复
那好吧,我们再看看这是为什么,不幸的是,这回看不到堆栈了,而且没有OnWindowStateChanged这样的函数,所以,预测,在改变WindowState的值的时候,仅仅是改了一个值,而在Visible=false的情况下不会进行重绘……所以,先设定WindowState跟原来的现象一样,TabControl还是不见了
而如果没有这个在最小化的时候不显示的需求,就不会有这样的问题。因为只有在VisibleChange的时候才会进行Layout重新设定嘛
可是,这问题怎么解决好呢。既然需要先设定Visible,然后设定WindowState才有效,而设定Visible的时候就会改变子控件的大小,那可不可以在设定visible的时候先不改变子控件的大小,在设定完windowState之后,根据最后的实际大小来改变子控件大小呢。
.net提供了一个暂停Layout处理的方法:SuspendLayout,在执行完相应的处理之后再执行ResumeLayout就可以重新布局啦~
private void notifyIcon1_Click(object sender, EventArgs e)
{
if (MouseButtons.Left == (e as MouseEventArgs).Button)
{
if (this.WindowState == FormWindowState.Normal)
{
this.Visible = !this.Visible;
}
else if (this.WindowState == FormWindowState.Minimized)
{
this.SuspendLayout();
this.Visible = true;
this.WindowState = FormWindowState.Normal;
this.ResumeLayout();
}
}
}
ok,问题解决