单个窗体在启动时隐藏

81

我有一个应用程序,在其中有一个表单,在Load方法中,我需要隐藏这个表单。

当它需要显示时,这个表单会自行显示(类似于Outlook 2003样式的弹出窗口),但我无法想出如何在加载时隐藏表单而不使代码混乱。

有什么建议吗?

25个回答

119

通常,只有在使用托盘图标或其他方法稍后显示窗体时才需要这样做,但即使您从不显示主窗体,它也可以很好地工作。

在您的窗体类中创建一个布尔变量,并将其默认设置为false:

private bool allowshowdisplay = false;

然后覆盖 SetVisibleCore 方法

protected override void SetVisibleCore(bool value)
{            
    base.SetVisibleCore(allowshowdisplay ? value : allowshowdisplay);
}
因为Application.Run()在加载表单后会将表单的.Visible属性设置为true,因此这会截获该操作并将其设置为false。在上述情况中,它将始终设置为false,直到您通过将allowshowdisplay设置为true来启用它。
现在,这将阻止表单在启动时显示,现在您需要通过设置allowshowdisplay = true来重新启用SetVisibleCore以使其正常工作。您需要在显示该表单的任何用户界面函数上执行此操作。在我的示例中,这是我的通知图标对象中的左键单击事件。
private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        this.allowshowdisplay = true;
        this.Visible = !this.Visible;                
    }
}

2
谢谢!与这里几乎所有其他建议不同,这个不会显示主窗口的短暂闪烁。 - Andy
2
这是实际正确的做法,因此应该被接受为答案。在 MFC 时代,我们曾经做过类似的事情,即处理第一个 WM_WINDOWPOSCHANGING 消息并在那里隐藏表单以防止“窗口闪烁”。 - enriquein
这个可以用,但我认为@Jeff的答案更好,因为它不需要使用一些逻辑黑客来覆盖。 - Mark Lakata
对我来说,这在某种程度上影响了线程模型:我的一个工作线程最终创建了一些 UI 控件,这是完全错误的...所以我必须放弃这个解决方案。 - Learner
1
不幸的是,当我将SetVisibleCore()方法添加到表单时,通知图标根本不会出现,因此我无法在鼠标单击后显示它。 - Dan W
显示剩余5条评论

117

我是从C#的角度来看待这个问题的,但vb.net应该非常相似。

在你的主程序文件中的Main方法中,你会有类似这样的内容:

Application.Run(new MainForm());

这将创建一个新的主窗体,并将应用程序的生命周期限制为主窗体的生命周期。

但是,如果您删除 Application.Run() 的参数,则应用程序将以无窗体显示的方式启动,您可以自由地显示和隐藏窗体。

与其在 Load 方法中隐藏窗体,不如在调用 Application.Run() 之前初始化窗体。我假设该窗体上有一个 NotifyIcon 用于显示任务栏中的图标 - 即使窗体本身尚不可见,也可以显示它。从 NotifyIcon 事件句柄中调用 Form.Show()Form.Hide() 将分别显示和隐藏窗体。


15
迄今为止最好的解决方案之一(也是最简单的解决方案)。 所有那些关于将不透明度设置为零、使用单独的计时器实例隐藏表单等的垃圾代码,在数日内都会散发出味道。 - nathanchere
13
就我所见,该设计师没有“可见性属性”。 - Dan W
5
这里使用的是Visual Studio 2015和.NET 4.5,但表单设计器没有“visible”属性。我是否漏掉了什么? - Ben Philipp
1
如果我没记错的话,Application.Run 为进程提供了在 Windows 窗体中所需的消息循环。如果没有它,你窗体内的代码将会崩溃。 - manit
4
请注意,在这种情况下,“Form_Load”不会在第一次显示窗体之前调用,可能永远不会被调用。此外,关闭主窗体不会关闭应用程序。您必须使用“Application.Exit”。 - rattler
显示剩余4条评论

39

我使用这个:

private void MainForm_Load(object sender, EventArgs e)
{
    if (Settings.Instance.HideAtStartup)
    {
        BeginInvoke(new MethodInvoker(delegate
        {
            Hide();
        }));
    }
}

显然,您需要将if条件更改为您自己的条件。


3
这会导致程序在启动时闪烁一下,然后迅速隐藏起来。 - Dan W
我想如果我没有看到你的代码,我就不用做这么多了。谢谢。 - M at
为了解决应用程序启动时的闪烁问题,在设计器中将窗体不透明度设置为0,然后在回调函数中先调用Hide(),然后再将不透明度设置回100。 - Michael Bray

21
    protected override void OnLoad(EventArgs e)
    {
        Visible = false; // Hide form window.
        ShowInTaskbar = false; // Remove from taskbar.
        Opacity = 0;

        base.OnLoad(e);
    }

1
我想让我的表单隐藏,但仍然加载和运行。这个解决方案在这种情况下完美地工作。给你点赞! - Joe Gayetty
我认为这是最好的解决方案,谢谢 :) - Soren
我认为将“Visible”设置为false是无用的(因为在加载表单时它会被重新打开)。 - tigrou

16

在表单构建时(设计师、程序主界面或表单构造器,取决于你的目标),

 this.WindowState = FormWindowState.Minimized;
 this.ShowInTaskbar = false;
当您需要显示表单时,可能是来自您的NotifyIcon的事件触发,必要时请反转。
 if (!this.ShowInTaskbar)
    this.ShowInTaskbar = true;

 if (this.WindowState == FormWindowState.Minimized)
    this.WindowState = FormWindowState.Normal;

连续的显示/隐藏事件可以更简单地使用表单的可见属性或显示/隐藏方法。


这也适用于Load事件。我认为这就是它的预期方式。 - Mark Lakata

6
尝试将应用程序从任务栏中隐藏。
请使用以下代码实现。
  protected override void OnLoad(EventArgs e)
  {
   Visible = false; // Hide form window.
   ShowInTaskbar = false; // Remove from taskbar.
   Opacity = 0;

   base.OnLoad(e);
   }

感谢您的来信,Ruhul。

5

使用以下代码扩展主表单:

using System.Windows.Forms;

namespace HideWindows
{
    public class HideForm : Form
    {
        public HideForm()
        {
            Opacity = 0;
            ShowInTaskbar = false;
        }

        public new void Show()
        {
            Opacity = 100;
            ShowInTaskbar = true;

            Show(this);
        }
    }
}

例如:

namespace HideWindows
{
    public partial class Form1 : HideForm
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

这篇文章提供了更多关于隐藏表单的信息:

http://codelogik.net/2008/12/30/primer-form-oculto/


3

将以下内容放入Program.cs文件中:

FormName FormName = new FormName ();

FormName.ShowInTaskbar = false;
FormName.Opacity = 0;
FormName.Show();
FormName.Hide();

当您想要显示表单时,请使用此功能:

var principalForm = Application.OpenForms.OfType<FormName>().Single();
principalForm.ShowInTaskbar = true;
principalForm.Opacity = 100;
principalForm.Show();

3

您需要将窗口状态设置为最小化,并将在任务栏中显示设置为false。然后,在表单加载结束时,将窗口状态设置为最大化,并将在任务栏中显示设置为true。

    public frmMain()
    {
        Program.MainForm = this;
        InitializeComponent();

        this.WindowState = FormWindowState.Minimized;
        this.ShowInTaskbar = false;
    }

private void frmMain_Load(object sender, EventArgs e)
    {
        //Do heavy things here

        //At the end do this
        this.WindowState = FormWindowState.Maximized;
        this.ShowInTaskbar = true;
    }

3
我曾经在这个问题上遇到了很多困难,但解决方案比我想象的要简单得多。 我先尝试了这里提供的所有建议,但结果并不令我满意,于是我进行了更深入的调查。 我发现只需添加:
 this.visible=false;
 /* to the InitializeComponent() code just before the */
 this.Load += new System.EventHandler(this.DebugOnOff_Load);

这个功能运行得很好。但我需要更简单的解决方案,如果你添加:

,就会发现这是一个更简单的方法。
this.visible=false;
/* to the start of the load event, you get a
simple perfect working solution :) */ 
private void
DebugOnOff_Load(object sender, EventArgs e)
{
this.Visible = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接