【问题标题】:Hide form instead of closing when close button clicked单击关闭按钮时隐藏表单而不是关闭
【发布时间】:2011-01-02 13:29:41
【问题描述】:

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

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

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    像这样:

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

    (通过Tim Huffman

    【讨论】:

    • 如何重新启用 e.cancel = false?以便我稍后可以关闭表单?
    • 我想我只需添加一个标志,如果我想真正关闭它,我现在就可以了。
    • 注意!您应该检查e.CloseReason(查看其他答案)。否则,当系统关闭或其他事件关闭表单时,表单不会关闭。
    • 但是如何在 Windows 任务栏的隐藏图标上显示图标?
    • 对于最后一个问题的好奇者,答案是:Icon appIcon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      来自MSDN

      要取消关闭表单,请将传递给事件处理程序的FormClosingEventArgsCancel 属性设置为true

      所以取消然后隐藏。

      【讨论】:

        【解决方案4】:

        如果你想使用显示/隐藏方法,我实际上已经为我最近完成的游戏菜单结构做了这个......我就是这样做的:

        为您自己创建一个按钮以及您想要执行的操作,例如“下一步”按钮,并将以下代码与您的程序相匹配。对于本例中的下一个按钮,代码为:

        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.
        

        这是我在游戏中使用的代码的 sn-p,可帮助您理解我要解释的内容:

            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
            }
        

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

        【讨论】:

          【解决方案5】:

          根据其他响应,您可以将其放入您的表单代码中:

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

          根据MSDN,首选覆盖:

          OnFormClosing 方法还允许派生类处理 没有附加委托的事件。这是首选技术 用于处理派生类中的事件。

          【讨论】:

            【解决方案6】:

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

            我解决此问题的方法是检查堆栈跟踪 - 用户尝试单击 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;
                }
            }
            

            【讨论】:

            • 完全同意你所说的。
            • 我在谈论您之前的评论,而不是最后一条。是的,尽管上面的代码适用于我的子表单。但由于 e.Cancel 我不能再关闭父表单!有什么线索吗?
            • 为了使上述代码正常工作,我需要为 StackTrace 添加命名空间。请通过说明命名空间来提供帮助。
            • 这似乎是不必要的复杂 - 当你可以只使用无模式表单时,为什么要以这种方式与模式表单行为作斗争?
            • @John 我同意,假设 .NET 2.0 或更高版本,为什么不只检查 e.CloseReason == CloseReason.WindowsShutDown ....msdn.microsoft.com/en-us/library/…
            【解决方案7】:

            这是模态表单的行为。当您使用form.ShowDialog() 时,您要求这种行为。这样做的原因是 form.ShowDialog 在表单被隐藏或销毁之前不会返回。所以当表单被隐藏时,form.ShowDialog里面的pump会销毁它,这样它就可以返回了。

            如果你想显示和隐藏一个表单,那么你应该使用无模式对话框模型 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() 将返回。

            如果不了解表单的层次结构以及决定何时隐藏表单和何时退出的规则,就不可能更具体。

            【讨论】:

            • 你能扩展 Application.doevents 吗?我想我需要它。添加 e.Cancel = false;在父表单中关闭也不起作用。
            • 对不起,我不清楚。当我单击 X 时应用程序关闭。但 Application.Exit();不起作用。
            • 我有两种形式。父母和孩子虽然这不是 mdi。
            • 如果这是子窗体,而父窗体是模态的,那么你就可以了。如果这是父表单,那么您可能应该使用Application.Run(MyAppContext)
            • 我正在做的程序:Application.Run(new gameForm());但我认为这不是问题。出于某种原因,当我做 e.cancel = true;在子窗体上。父表单采用此值,application.exit() 不会关闭父表单。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-01-29
            • 1970-01-01
            • 2014-02-12
            • 2017-01-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多