添加到Deactivate事件后C#窗体状态恢复方法失效求助
问题描述
我的应用包含主窗体与Overlay窗体:Overlay可通过调整尺寸最小化至屏幕顶部,主窗体可最小化到任务栏或系统托盘。点击Overlay上的按钮可切换其显示状态,同时主窗体会切换为FormWindowState.Normal。我希望该逻辑不仅在点击按钮时触发,还能在Overlay失去焦点时触发,但将恢复主窗体状态的OnHideOverlay调用加入Deactivate事件关联的OverlayNoFocus方法后,所有场景下该恢复逻辑均失效。
Overlay窗体代码
public event System.EventHandler OnShowOverlay; public event System.EventHandler OnHideOverlay; private void ShowOverlay() { OnShowOverlay(this, null); this.Focus(); OverlayPanel.Visible = true; this.Height = 70; this.InfoPanel.Location = new Point(25, 35); this.OverlayShowButton.Location = new Point(0, 35); } private void HideOverlay() { if(OnHideOverlay != null) { OnHideOverlay(this, null); //!!! 当将该调用加入OverlayNoFocus时,问题出现 this.Focus(); this.OverlayPanel.Visible = false; //*** 只要OnHideOverlay不在OverlayNoFocus中,这些代码均可正常运行 this.OverlayShowButton.Location = new Point(0, 0); //*** this.InfoPanel.Location = new Point(25, 0); //*** this.Height = 35; //*** } } private void OverlayShowButton_Click(object sender, MouseEventArgs e) { OverlayPanel.Visible = !OverlayPanel.Visible; if (OverlayPanel.Visible) { ShowOverlay(); } else { HideOverlay(); } } public void OverlayNoFocus(object sender, EventArgs e) { HideOverlay(); //!!! }
Overlay窗体设计器代码
this.Deactivate += new System.EventHandler(OverlayNoFocus);
主窗体代码
public MainForm() { //无关代码 this.overlay.OnShowOverlay += new System.EventHandler(onOverlayShow); this.overlay.OnHideOverlay += new System.EventHandler(onOverlayHide); this.overlay.Show(); //无关代码 } FormWindowState saveWinState = new FormWindowState(); void onOverlayShow(object sender, EventArgs e) { saveWinState = this.WindowState; this.Show(); this.WindowState = FormWindowState.Normal; } void onOverlayHide(object sender, EventArgs e) { this.WindowState = saveWinState; }
问题原因与解决方法
核心问题
- 循环触发事件:当
Deactivate事件触发HideOverlay时,OnHideOverlay会让主窗体恢复状态并获得焦点,这又会触发Overlay的Deactivate事件,形成无限循环,导致状态恢复逻辑失效。 - 强制焦点干扰:
HideOverlay中的this.Focus()会强制Overlay重新获取焦点,进一步打乱正常的焦点流转,加剧循环问题。
修复步骤
移除强制焦点代码
删除HideOverlay中的this.Focus()调用,避免干扰正常焦点切换:private void HideOverlay() { if(OnHideOverlay != null) { OnHideOverlay(this, null); // 移除this.Focus(); this.OverlayPanel.Visible = false; this.OverlayShowButton.Location = new Point(0, 0); this.InfoPanel.Location = new Point(25, 0); this.Height = 35; } }添加状态判断避免重复执行
在HideOverlay和OverlayNoFocus中增加状态判断,仅当Overlay处于展开状态时才执行隐藏逻辑:private void HideOverlay() { if(OnHideOverlay != null && OverlayPanel.Visible) { OnHideOverlay(this, null); this.OverlayPanel.Visible = false; this.OverlayShowButton.Location = new Point(0, 0); this.InfoPanel.Location = new Point(25, 0); this.Height = 35; } } public void OverlayNoFocus(object sender, EventArgs e) { if (OverlayPanel.Visible) { HideOverlay(); } }优化主窗体状态保存逻辑
仅当主窗体非正常状态时才保存状态,避免无效赋值:void onOverlayShow(object sender, EventArgs e) { if (this.WindowState != FormWindowState.Normal) { saveWinState = this.WindowState; } this.Show(); this.WindowState = FormWindowState.Normal; }
内容的提问来源于stack exchange,提问作者Jonas Alexander Offersen
相关产品推荐
相关产品推荐

