单击关闭按钮时隐藏表单而不是关闭

时间:2010-01-07 16:05:13

标签: c# .net winforms

当用户点击表单上的 X 按钮时,如何隐藏它而不是关闭它?

我在this.hide()中尝试了FormClosing,但它仍然关闭了表单。

7 个答案:

答案 0 :(得分:90)

像这样:

private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing) 
    {
        e.Cancel = true;
        Hide();
    }
}

(通过Tim Huffman

答案 1 :(得分:53)

我在之前的回答中评论过,但我想我会提供自己的回答。根据您的问题,此代码与最佳答案类似,但添加了另一个提及的功能:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing) 
    {
        e.Cancel = true;
        Hide();
    }
}

如果用户只是在窗口中点击 X ,表单就会隐藏;如果还有其他任务,例如任务管理器,Application.Exit()或Windows关闭,表单将被正确关闭,因为return语句将被执行。

答案 2 :(得分:8)

来自MSDN

  

要取消对表单的关闭,请将传递给您的事件处理程序的Cancel的{​​{1}}属性设置为FormClosingEventArgs

所以取消然后隐藏。

答案 3 :(得分:4)

如果你想使用show / hide方法,我实际上是自己做了一个菜单结构我最近做过的游戏......这就是我做的:

创建一个按钮以及您想要做的事情,例如“下一步”按钮,并将以下代码与您的程序相匹配。对于此示例中的下一个按钮,代码为:

btnNext.Enabled = true; //This enabled the button obviously
this.Hide(); //Here is where the hiding of the form will happen when the button is clicked
Form newForm = new newForm(); //This creates a new instance object for the new form
CurrentForm.Hide(); //This hides the current form where you placed the button.

以下是我在游戏中使用的代码片段,以帮助您了解我要解释的内容:

    private void btnInst_Click(object sender, EventArgs e) 
    {
        btnInst.Enabled = true; //Enables the button to work
        this.Hide(); // Hides the current form
        Form Instructions = new Instructions(); //Instantiates a new instance form object 
        Instructions.Show(); //Shows the instance form created above
    }

所以有一个显示/隐藏方法几行代码,而不是为这么简单的任务做一大堆代码。 我希望这有助于解决您的问题。

答案 4 :(得分:3)

请注意,在执行此操作时(已发布多个答案),您还需要找到一种方法来允许用户在他们真正想要的时候关闭表单。如果用户在应用程序运行时尝试关闭计算机,这确实会成为一个问题,因为(至少在某些操作系统上)这将阻止操作系统正常或有效地关闭。

我解决这个问题的方法是检查堆栈跟踪 - 当用户尝试单击 X 与系统尝试结束应用程序以准备关闭时之间存在差异。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    StackTrace trace = new StackTrace();
    StackFrame frame;
    bool bFoundExitCommand = false;
    for (int i = 0; i < trace.FrameCount; i++)
    {
        frame = trace.GetFrame(i);
        string methodName = frame.GetMethod().Name;
        if (methodName == "miExit_Click")
        {
            bFoundExitCommand = true;
            Log("FormClosing: Found Exit Command ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName);
        }
        if (methodName == "PeekMessage")
        {
            bFoundExitCommand = true;
            Log("FormClosing: Found System Shutdown ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName);
        }
        Log("FormClosing: frame.GetMethod().Name = {0}", LogUtilityLevel.Debug4, methodName);
    }
    if (!bFoundExitCommand)
    {
        e.Cancel = true;
        this.Visible = false;
    }
    else
    {
        this.Visible = false;
    }
}

答案 5 :(得分:2)

这是Modal表单的行为。当您使用form.ShowDialog()时,您要求此行为。原因是form.ShowDialog在窗体被隐藏或销毁之前不会返回。因此,当窗体被隐藏时,窗体内的窗口.ShowDialog会将其销毁,以便它可以返回。

如果要显示和隐藏表单,则应使用“无模式”对话框模型 http://msdn.microsoft.com/en-us/library/39wcs2dh(VS.80).aspx

form.Show()立即返回,您可以显示和隐藏此窗口,只有在明确销毁它之后才会销毁它。

当您使用非模态形式的子模式时,您还需要在循环中使用Application.RunApplication.DoEvents运行消息泵。如果创建表单的线程退出,则表单将被销毁。如果该线程没有运行泵,那么它拥有的表单将没有响应。

编辑:这听起来像是ApplicationContext旨在解决的问题。 http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext.aspx

基本上,您从ApplicationContext派生一个类,将ApplicationContext的一个实例作为参数传递给Application.Run()

// Create the MyApplicationContext, that derives from ApplicationContext,
// that manages when the application should exit.

MyApplicationContext context = new MyApplicationContext();

// Run the application with the specific context. 
Application.Run(context);

您的应用程序上下文需要知道何时可以退出应用程序,并且隐藏表单时不应退出应用程序。什么时候应用程序退出。您的应用程序上下文或表单可以调用应用程序上下文的ExitThread()方法来终止消息循环。届时Application.Run()将返回。

如果不了解您的表格的层次结构以及决定何时隐藏表格以及何时退出的规则,则无法更具体。

答案 6 :(得分:1)

根据其他回复,您可以将其放在表单代码中:

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);
        if (e.CloseReason == CloseReason.UserClosing)
        {
            e.Cancel = true;
            Hide();
        }
    }

首选是覆盖:MSDN“OnFormClosing方法还允许派生类在不附加委托的情况下处理事件。这是在派生类中处理事件的首选技术。”