winforms C#方法在添加到此时停止工作,

ebdffaop  于 2023-02-24  发布在  C#
关注(0)|答案(1)|浏览(140)

我的申请表有两种:主窗口和一个覆盖层。覆盖层可以最小化(通过控制它的大小)到屏幕顶部,主窗口可以最小化到任务栏或系统托盘。
点击覆盖层上的按钮,可以切换最小化和不最小化。点击此按钮时,主窗口输入FormWindowSate.Normal
我希望这不仅在点击控制按钮时有效,而且在覆盖层失去焦点时也有效。因此我的问题是:如果我把隐藏覆盖层的代码添加到一个事件处理程序中,我可以很好地隐藏覆盖层。但是当我试图添加将主窗口返回到其原始状态的代码时,该代码在任何地方都停止工作。以下是相关代码:
在覆盖表中:

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); //!!!
        this.Focus(); 
        this.OverlayPanel.Visible = false; //***
        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(); //!!!
}

在覆盖设计器中:

this.Deactivate += new System.EventHandler(OverlayNoFocus);

主要形式为:

public MainForm()
{
    //irrelevant code here.

    this.overlay.OnShowOverlay += new System.EventHandler(onOverlayShow);
    this.overlay.OnHideOverlay += new System.EventHandler(onOverlayHide);
    this.overlay.Show();

    //irrelevant code here.
}

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;
}

//!!!当OnHideOverlay位于OverlayNoFocus中时,会出现问题。//***只要OnHideOverlay不在OverlayNoFocus中,这些行就会按预期运行
有人能告诉我我做错了什么吗?

sqyvllje

sqyvllje1#

据我所知,应用程序的初始状态可能包含一个可见的MainForm,其中覆盖按钮为:
[...]最小化(通过控制其大小)到屏幕顶部。
(我相信你的话,你的意思是在 * 屏幕 * 的顶部,而不仅仅是在主窗体的顶部。)

点击[覆盖]([Overlay])会使应用程序进入一种状态,其中覆盖被展开,主窗体可能是:
[...]最小化到任务栏或系统托盘。

我相信您关于这个问题的意图。停用是指任何焦点丢失都会导致恢复到原始状态,并且在以下情况下叠加应最小化:

  • 再次单击[覆盖]按钮。
  • 鼠标单击发生在覆盖窗体的工作区矩形之外。

我的第一个建议是通过引用主窗体来示例化OverlayForm,使其自治。同时,我将避免在Show()方法中使用this指针,因为如果主窗体是覆盖窗体的Owner,那么当主窗体最小化时,它会将覆盖窗体也一起删除!所以要避免这样做。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        _overlayForm = new OverlayForm(this);
        _overlayForm.Show(); // Avoid setting owner with 'this'.
    }
    private readonly OverlayForm _overlayForm;
}

覆盖窗体

在这个方案中,消息传递被简化了,因为OverlayForm可以直接作用于MainFormDeactivate事件所要做的就是取消选中Overlay按钮。

public partial class OverlayForm : Form
{
    public OverlayForm(Form mainForm)
    {
        _mainForm = mainForm;
        _saveWinState = mainForm.WindowState;

        InitializeComponent();
        FormBorderStyle= FormBorderStyle.None;
        BackColor= Color.Azure;
        ShowInTaskbar= false;
        _checkBoxShowOverlay.Appearance = Appearance.Button;

        _checkBoxShowOverlay.CheckedChanged += onCheckedChangedShowOverlay;
        Deactivate += (sender, e) => _checkBoxShowOverlay.Checked = false;

        // Init and give focus back to main form.
        _mainForm.HandleCreated += (sender, e) =>
            BeginInvoke(new Action(() => onCheckedChangedShowOverlay(_checkBoxShowOverlay, EventArgs.Empty)));
    }
    private readonly Form _mainForm;
    private void onCheckedChangedShowOverlay(object sender, EventArgs e)
    {
        if (_checkBoxShowOverlay.Checked)
        {
            Size = _mainForm.Size;
            Location = _mainForm.Location;
            _saveWinState = _mainForm.WindowState;

            BeginInvoke(new Action(() =>
            {
                _mainForm.WindowState = FormWindowState.Minimized;
            }));
        }
        else
        {
            Size = new Size(
                _checkBoxShowOverlay.Width + 10,
                _checkBoxShowOverlay.Height + 10);
            Screen screen = Screen.FromControl(this);
            Location = new Point(
                screen.Bounds.X,
                screen.Bounds.Y);

            BeginInvoke(new Action(() =>
            {
                _mainForm.WindowState = _saveWinState;
                _mainForm?.Activate();
            }));
        }
    }
    FormWindowState _saveWinState;
}

相关问题