【问题标题】:Display multiple forms when C# application startsC# 应用程序启动时显示多个表单
【发布时间】:2017-11-07 22:12:39
【问题描述】:

我的 C# 应用程序中有 3 个表单——Form1、Form2 和 Form3。目前,当我的应用程序启动时,它会加载 Form1。我希望在应用程序启动时打开所有三个表单。

我尝试在Program.cs 中这样做:

static void Main()
{     
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    Application.Run(new Form2());
}

但是Form2只有在Form1关闭后才会出现。

如何在应用程序启动后让所有 3 个表单同时显示?

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    通常,让您的应用程序执行默认操作以外的操作(打开表单,等待它关闭,然后退出)的正确方法是创建一个继承自 ApplicationContext 的类。然后你将你的类的一个实例传递给Application.Run 方法。当应用程序应该关闭时,请在您的班级内致电ExitThread()

    在这种情况下,您可以在应用程序加载时创建三个表单的实例,并为它们的Closed 事件注册一个处理程序。当每个表单关闭时,处理程序会检查是否还有其他表单仍然打开,如果没有则关闭应用程序。

    The example on MSDN 正在做两件事:

    1. 打开多个表单并在它们全部关闭时退出应用程序
    2. 在每个表单关闭时保存表单的最后大小和位置。

    一个更简单的例子,只有在所有表单都关闭后才关闭应用程序:

    class MyApplicationContext : ApplicationContext {
        private void onFormClosed(object sender, EventArgs e) {
            if (Application.OpenForms.Count == 0) {
                ExitThread();
            }
        }
    
        public MyApplicationContext() {
            //If WinForms exposed a global event that fires whenever a new Form is created,
            //we could use that event to register for the form's `FormClosed` event.
            //Without such a global event, we have to register each Form when it is created
            //This means that any forms created outside of the ApplicationContext will not prevent the 
            //application close.
    
            var forms = new List<Form>() {
                new Form1(),
                new Form2(),
                new Form3()
            };
            foreach (var form in forms) {
                form.FormClosed += onFormClosed;
            }
    
            //to show all the forms on start
            //can be included in the previous foreach
            foreach (var form in forms) {
                form.Show();
            }
    
            //to show only the first form on start
            //forms[0].Show();
        }
    }
    

    那么,你的Program 类看起来像这样:

    static class Program {
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyApplicationContext());
        }
    }
    

    应用程序关闭逻辑显然可以自定义 - 任何表单仍然打开,或者只有这三种类型中的一种,或者只有前三个实例(这需要持有对前三个实例的引用,可能在 @987654332 @)。

    Re:每个表单创建的全局事件 -- this 看起来很有希望。

    类似的例子here

    【讨论】:

    • 接受的答案是错误的。它使 form1 成为潜在客户表单。这允许每个表单都是应用程序,直到所有表单都被删除。所说的 Race-Condition 可能永远不会发生,如果您绝对需要担心的话,请在 remove 语句周围放置一个锁定对象。
    • 因为表单都是在同一个线程上创建的,所以没有竞争条件。 UI 事件处理在 UI 线程上按顺序进行。
    【解决方案2】:

    Form1Form.Load事件开始其他表单。

    private void Form1_Load(object sender, EventArgs e)
    {
        Form2 form2 = new Form2();
        form2.Show();
    }
    

    【讨论】:

    • 唯一的问题是,他怎么知道程序何时关闭?根据用户的说法,他可以随时关闭任何窗口。
    • @DJBurb 他在哪里指定所需的关闭行为?应用程序应该在 all 3 关闭时、any 3 关闭时或特定表单关闭时结束?一个或任何一个都很容易。一切都会多一点工作。
    • 我认为您需要自己弄清楚这一点,但您可以使用Form.FormClosing 事件来查找表单何时关闭,中止关闭并隐藏表单。隐藏所有表单后,关闭应用程序。
    • @AlbinSunnanbo 如果您想等待所有表单关闭,您最好的选择可能是将主表单设置为空白隐藏表单,而不是任何常规表单。让它全部打开 3 并订阅关闭事件,然后在它们全部关闭时结束。
    • @Servy 他在另一个回复中提到了它。我认为它被删除了
    【解决方案3】:

    你也可以使用 3 个选项卡,一个表单而不是 3 个表单

    【讨论】:

      【解决方案4】:

      我通过稍微修改 Zev Spitz 的答案找到了我的解决方案。

      注意:此版本仅启动表单列表中指定的第一个表单。

      using System;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Windows.Forms;
      
      class MyApplicationContext : ApplicationContext
      {
          public List<Form> Forms = new List<Form>() {
              new Form1()
          };
      
          private List<Form> FormCollectionToList(FormCollection fc)
          {
              List<Form> ff = new List<Form>();
              foreach (Form f in fc)
              {
                  ff.Add(f);
              }
              return ff;
          }
      
          private void onFormClosed(object sender, EventArgs e)
          {
              Forms = FormCollectionToList(Application.OpenForms);
              if (Forms.Count == 0)
              {
                  ExitThread();
              }
              foreach (var form in Forms)
              {
                  form.FormClosed -= onFormClosed;
                  form.FormClosed += onFormClosed;
              }
          }
      
          public MyApplicationContext()
          {
              if (Forms.Count == 0)
              {
                  Process.GetCurrentProcess().Kill();
              }
              Forms[0].FormClosed += onFormClosed;
              Forms[0].Show();
          }
      }
      

      这个版本启动了所有这些。

      using System;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Windows.Forms;
      
      class MyApplicationContext : ApplicationContext
      {
          public List<Form> Forms = new List<Form>() {
              new Form1()
          };
      
          private List<Form> FormCollectionToList(FormCollection fc)
          {
              List<Form> ff = new List<Form>();
              foreach (Form f in fc)
              {
                  ff.Add(f);
              }
              return ff;
          }
      
          private void onFormClosed(object sender, EventArgs e)
          {
              Forms = FormCollectionToList(Application.OpenForms);
              if (Forms.Count == 0)
              {
                  ExitThread();
              }
              foreach (var form in Forms)
              {
                  form.FormClosed -= onFormClosed;
                  form.FormClosed += onFormClosed;
              }
          }
      
          public MyApplicationContext()
          {
              if (Forms.Count == 0)
              {
                  Process.GetCurrentProcess().Kill();
              }
              foreach (var form in Forms)
              {
                  form.FormClosed += onFormClosed;
                  form.Show();
              }
          }
      }
      

      【讨论】:

      • 您不需要FormsCollectionToList 函数。你可以写var openForms = Application.OpenForms.Cast&lt;Form&gt;().ToList();
      • 另外,在构造函数中检查Forms.Count 有什么意义?什么时候会是 0?
      • 您对Application.OpenForms 的使用表明可以摆脱私有List&lt;Form&gt; 字段。请参阅我的更新答案。
      • 为什么每次关闭any表单时都需要为所有打开的表单注销​​和重新注册onFormClosed事件处理程序?跨度>
      • 除非您关心将在MyApplicationContext 之外创建的新表单?如果是这种情况,那么这应该是您回答的主要重点。 -1.
      猜你喜欢
      • 2014-09-21
      • 2013-12-27
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多