You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加到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;
}

问题原因与解决方法

核心问题

  1. 循环触发事件:当Deactivate事件触发HideOverlay时,OnHideOverlay会让主窗体恢复状态并获得焦点,这又会触发Overlay的Deactivate事件,形成无限循环,导致状态恢复逻辑失效。
  2. 强制焦点干扰:HideOverlay中的this.Focus()会强制Overlay重新获取焦点,进一步打乱正常的焦点流转,加剧循环问题。

修复步骤

  1. 移除强制焦点代码
    删除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;
        }
    }
    
  2. 添加状态判断避免重复执行
    在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();
        }
    }
    
  3. 优化主窗体状态保存逻辑
    仅当主窗体非正常状态时才保存状态,避免无效赋值:

    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:15:42