【问题标题】:C#/.NET - WinForms - Instantiate a Form without showing itC#/.NET - WinForms - 实例化表单而不显示它
【发布时间】:2010-10-22 20:42:13
【问题描述】:

我在加载事件期间将表单的可见性更改为 false,并且表单仍然显示自己。绑定 this.Visible = false; 的正确事件是什么?到?我想实例化 Form1 而不显示它。

using System;
using System.Windows.Forms;

namespace TestClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Visible = false;
        }

    }
}

【问题讨论】:

  • 我很困惑有多少人在这个线程中给出了答案而不检查结果。隐藏();可见=假;在这种情况下,这些东西都不起作用。它不像其他形式,它是主要形式,无论你做什么都会显示出来。这里的人在给出虚假答案之前需要三思。顺便说一句,Visual Studio 2010 中的主窗体没有 Visible 属性。它根本不存在。
  • @Draek,好点子。但是您可以使用名为 ShowInTaskbar 和 WindowState 的属性的组合来实现类似的功能。我将其添加为答案。

标签: c# .net winforms events visibility


【解决方案1】:

无论您在显示表单之前尝试设置 Visible 属性多少,它都会弹出。据我了解,这是因为它是当前 ApplicationContext 的 MainForm。让表单自动加载但在应用程序启动时不显示的一种方法是更改​​ Main 方法。默认情况下,它看起来像这样(.NET 2.0 VS2005):

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

如果您改为执行此类操作,应用程序将启动、加载您的表单并运行,但表单不会显示:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Form1 f = new Form1();
    Application.Run();        

}

我不完全确定这有什么用,但我希望你知道 ;o)

更新:您似乎不需要将 Visible 属性设置为 false,或提供 ApplicationContext 实例(将在“幕后”为您自动创建)。相应地缩短了代码。

【讨论】:

  • +1 好主意。明白了。听起来像它的 Application.Run 是罪魁祸首。
  • 是的,出于好奇,我检查了幕后发生的事情,ApplicationContext 将在 MainForm 上设置 Visible=true,如果有的话。如果您使用表单实例作为输入调用 Application.Run,​​则会创建一个新的 ApplicationContext 来获取分配给 MainForm 属性的表单。
  • 这个解决方案的问题是关闭表单并没有关闭应用程序。因此,您必须通过在 FormClose 上调用 Application.Exit() 来补偿。当然,除非您的应用程序使用不止一种形式,在这种情况下,您需要更智能一些。幸运的是我的只使用了一个表单和一个系统托盘图标,所以上面的例子工作得很好。
  • 我找到了解决此问题的更好方法,我将其添加为另一个答案。
  • @AnatoliiGumennyi 你能详细说明你是怎么做的吗?我刚刚重试了这个(VS2013)并且表格没有显示给我。
【解决方案2】:

我知道这是一个老问题,但我只是偶然发现了它,我很惊讶没有人提到SetVisibleCore

bool isVisibleCore = false;
protected override void SetVisibleCore(bool value)
{
    base.SetVisibleCore(isVisibleCore);
}

在该代码 sn-p 中,只要 isVisibleCore 保持为 false,表单将保持不可见。如果在实例化表单时将其设置为 false,则不会像在 Shown 事件中设置 Visible = false 那样获得短暂的可见性。

【讨论】:

  • 这没有创建表单
  • 当我在 application.run 之外创建了表单并且没有执行 form.show(); (女巫在第一次演出时可能有创建组件的事件)。所以表单上的组件没有完全创建。当我尝试与他们交互时,我得到一个错误组件没有初始化。同样的错误是当我在开始时覆盖 setvisible 或将表单设置为不可见。
  • 有效的是创建表单并在窗口状态最小化的情况下显示它,然后才隐藏它并将窗口状态设置为正常。 (这次触发了 onload 事件)在trayicon click 必须在其中任何一个中设置左上角高度和宽度之后是错误的,例如 -32000
  • 警告:这不仅可以防止“显示”事件(您可能会想到),还可以防止“加载”和其他事件。请注意它。它们在第一次调用 base.SetVisibleCore(true) 时引发。
  • NB 这种方法将阻止关闭表单(以及其他正常的生命周期事件)。请参阅stackoverflow.com/a/4556649/67392 以获得更好的方法。
【解决方案3】:

我花了一些时间才找到一个正常工作的解决方案。

在属性窗口下将名为 WindowState 的属性设置为 Minimized 并将 ShowInTaskbar 设置为 False。完整加载表单后,调用下面的代码行。

        this.ShowInTaskbar = true;
        this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
        //this.WindowState = System.Windows.Forms.FormWindowState.Normal;

PS:此解决方案已在 Visual C# 2008 Express Edition 上测试

【讨论】:

    【解决方案4】:

    如何在设计时将 Opacity 属性设置为 0,当您要显示表单时设置回 100?

    【讨论】:

    • 使用这种方法,如果用户使用 alt + tab,表单仍然可以访问。
    【解决方案5】:

    我可以接受的解决方案 因此创建表单并在创建时调用 on_load。 将 WindowState 设置为最小化,然后在加载时将可见设置为 false 并将 windowstate 设置为正常

    private void Form1_Load(object sender, EventArgs e)
    {
            this.Visible = false;
            this.WindowState = FormWindowState.Normal;
    }
    

    什么没用:

    SetVisibleCore 覆盖解决方案未创建表单

    也是

    Application {
     Form1 f = new Form1();
     Application.Run(); 
    

    ):

    【讨论】:

      【解决方案6】:

      对于无闪烁显示的解决方案,还要在加载期间将表单的位置设置为屏幕外:

      private Point startuplocation;
      
      private void Form1_Load(object sender, EventArgs e)
      {
          this.startuplocation = this.Location;
          this.Location = new Point(-1000, -1000);
      }
      
      private void Form1_Shown(object sender, EventArgs e) //fires first time shown
      {
          this.Visible = false;
          this.Location = this.startuplocation;
      }
      

      【讨论】:

        【解决方案7】:

        只需创建Form1 的实例,不要调用方法来显示/显示它。但我敢打赌你做错了什么。

        【讨论】:

          【解决方案8】:

          尝试 VisibleChanged 事件。

          【讨论】:

            【解决方案9】:

            显示的事件可能会给您想要的。虽然表单会在隐藏之前“闪烁”一秒钟。

            private void Form1_Shown(object sender, EventArgs e)
                {
                    this.Visible = false;
                }
            

            【讨论】:

              【解决方案10】:

              我的建议是在 IntializeComponent() 调用之后的 _Show 事件之前的事件中实例化表单,例如构造函数。

              【讨论】:

              • 我想也许你的意思是隐藏而不是实例化,对吗?无论如何(没有双关语),您必须确保无论您在哪里调用它都发生在使表单可见的调用之后,但在它实际变得可见之前。
              • 实际上我建议了一种在显示表单之前初始化任何必要的方法。
              【解决方案11】:

              如果这是您的主要形式,那么可能没有比 Shown 事件更好的地方了。但在这种情况下,你会得到闪烁。

              我找不到一个好地方来阻止正在运行的主窗体至少快速显示。即使在加载事件中激活的计时器也不会这样做。

              如果它是辅助表单,只需创建它但不要显示它。

              【讨论】:

                【解决方案12】:

                你试过了吗

                this.Hide();
                

                form_loadform_activated 事件中

                【讨论】:

                • 仅供参考,这在 form_load 事件中使用时不起作用,但在 form_activated 事件中起作用,尽管在隐藏之前会显示表单一瞬间。
                【解决方案13】:

                在构造函数上设置可见性,在 init 之后然后 this.Show() 之后

                【讨论】:

                  【解决方案14】:

                  InitializeComponent() 设置 this.Visible = true,因为您指定表单在设计器中应该是可见的(或者默认设置为)。您应该在设计器中将 Visible 设置为 false,它不会被 InitializeComponent() 调用。然后,您可以随时显示它。

                  【讨论】:

                    【解决方案15】:

                    Load 事件中包含.Visible = falseHide() 将导致您的表单短暂显示,因为在它变为物理可见和Load 事件被触发之间存在时间,尽管事实上文件说相反。

                    你在某处打电话给Show()ShowDialog() 吗?我不确定这种行为是否仍然存在,但至少在框架的过去版本中,对ShowDialog() 的调用不会触发Load 事件,所以也许这就是你的问题(尽管我认为调用ShowDialog()那么隐藏模态表单将是一种不好的做法!)

                    如果您必须为要执行的任何操作创建句柄(以及控件的句柄),最好将StartLocation 设置为Manual,然后设置@987654332 @ 属性到屏幕外的位置。这将创建并显示表单,同时使其对用户不可见。

                    【讨论】:

                      【解决方案16】:

                      是的,与应用程序视觉相比,从代码角度来看,真正优雅的一种方式是通过隐藏在构造函数/加载事件中来闪烁表单。

                      【讨论】:

                        【解决方案17】:

                        我同意这确实令人抓狂,因为 Winform 在初始化一堆控件或填充大 DataGridView 或其他任何东西时通常看起来并不漂亮。您仍然需要存在窗口句柄才能执行此操作,从而创建所有已提到的问题。

                        这对我有用,你有两个选择:你可以隐藏你的主窗体直到它准备好,或者你可以显示一些小闪屏让你的用户知道你正在处理它.享受吧。

                        public partial class MainForm : Form
                        {
                            public MainForm()
                            {
                                InitializeComponent();
                            }
                            Size mDeferredSize;
                            protected override void OnHandleCreated(EventArgs e)
                            {
                                // Capture the "real" size...
                                mDeferredSize = Size;
                                // and set it to nothing...
                                Size = new Size(0, 0);
                                DoSomeUglyInitialization(showOptionalSplash: true);
                                Size = mDeferredSize; // ...and now put it back to the original size    
                                base.OnHandleCreated(e);
                            }
                            private void DoSomeUglyInitialization(bool showOptionalSplash)
                            {
                                MySplash splash = null; 
                                if (showOptionalSplash)
                                {
                                    // We have made some borderless form class with a logo or something...
                                    splash = new MySplash(); 
                                    splash.Show();
                                }
                                // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
                                // Initialization that REQUIRES A HANDLE, e,g,
                                // we might be creating a bunch of controls, or 
                                // populating a big DataGridView. Whatever it is,
                                // we don't want everyone looking at our biz.
                                System.Threading.Thread.Sleep(2500); // (Here simulated...)
                                // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                splash?.Dispose();      
                            }
                        }
                        

                        【讨论】:

                          【解决方案18】:

                          我为表单设置了这三个属性设置:

                          ShowInTaskbar = false
                          ShowIcon = false
                          WindowState = Minimized
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2010-10-26
                            • 2013-07-07
                            • 1970-01-01
                            • 1970-01-01
                            • 2022-01-08
                            • 1970-01-01
                            相关资源
                            最近更新 更多