启动时隐藏表单

10

我有一个程序,只需要一个NotifyIcon就能正常运行。因此,我一直在尝试让主窗体在程序启动时隐藏。

在frmMain_Load中,我尝试了以下两种方法:

this.Hide();
this.Visible = false;

没有成功。

它们在其他方法中起作用,比如在NotifyIcon_MouseClick方法中,但我希望在加载时隐藏。

我在SO的另一个问题中看到Matias建议了这个:

BeginInvoke(new MethodInvoker(delegate
{
    Hide();
}));

这个方法可以用,但当我启动程序时,我可以看到表单闪烁得非常快。虽然比什么都没有要好,但我想知道是否有更好的解决方案。

谢谢。

5个回答

16
// In Your Program.cs Convert This
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

// To This
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Form1 TheForm = new Form1();
    Application.Run();
}

// Call Application.Exit() From Anywhere To Stop Application.Run() Message Pump and Exit Application

1
这个解决方案存在一个问题。在这种情况下,当你关闭窗体时,“FormClose”和“FormClosing”事件将不会被触发。 - parseh
当用户使用 X 按钮关闭窗体时,如何让应用程序退出? - xandermonkey
更好的解决方案是创建一个 ApplicationContext,并将其实例传递给 Application.Run(),它管理窗体的生命周期,从而避免在其他地方调用 Application.Exit() 的需要。 - Quolonel Questions

6

如果您的程序具有默认的Visual Studio生成的Program.cs文件,则有一种简单的方法:

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

仅仅调用Run方法就可以让窗体显示出来。在您的窗体属性中尝试以下操作:

  1. WindowState设置为Minimized
  2. ShowInTaskbar设置为false

这样应该就可以了!


谢谢您的回复!我忘了提到我已经尝试过这种方法。它部分地起作用,但我可以在左下角看到表单标题栏,所以我想用其他方式来解决它。无论如何,还是谢谢! - sippa

1
不要在您的表单上调用 Show 或 ShowDialog,您可以让 Application.Run 目标定位自定义类,然后实例化一个表单并不显示或创建一个 NotifyIcon 实例并从那里处理所有内容。

你也可以直接调用Application.Run()而不带任何参数。当你的应用程序完成后,请调用Application.Exit(); - VBNight
你只需要创建一个基本类,而不是告诉应用程序在表单上阻塞。在对象内部,您可以处理实例化您的表单和处理NotifyIcon,这很像VBNight在他的评论中建议的那样。您的类没有任何特殊之处。 - Quintin Robinson
我在下面添加了一个例子,说明我正在谈论什么(注释无法正确格式化)。 - VBNight
感谢您的帮助!VBNight的示例正如我所期望的那样工作。 - sippa
很好,很高兴你把它搞定了,而且没有使用任何魔法来隐藏代码! - Quintin Robinson
显示剩余2条评论

1

你也可以在form_shown事件中加入this.hide = true。我相信该事件仅会在load事件之后触发一次。但是,如果你的表单有很多控件和/或计算机速度较慢,可能会看到一些闪烁。


我刚试了一下,虽然它可以工作,但你仍然可以看到表格闪烁得非常快。我宁愿完全修复它,但还是谢谢你的建议! - sippa

1

如果你的程序不需要表格运行,那么最好的方法就是不要有表格。

在程序代码中设置你的NotifyIcon,然后进入循环,直到你想通过设置某个值或调用某个方法退出程序为止。

例如,将UserExitCalled设置为true(Program.UserExitCalled = true)将导致程序退出。

以下是一个简短的示例:

static class Program {
    internal static Boolean UserExitCalled;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // Setup your tray icon here

        while (!UserExitCalled) {
            Application.DoEvents(); // Process windows messages
            Thread.Sleep(1);
        }

        return;
    }
}

这是我其中一个系统托盘应用程序的完整程序类,作为一个工作示例。
// *********************************************************************
// [DCOM Productions .NET]
// [DPDN], [Visual Studio Launcher]
//
//   THIS FILE IS PROVIDED "AS-IS" WITHOUT ANY WARRANTY OF ANY KIND. ANY
//   MODIFICATIONS TO THIS FILE IN ANY WAY ARE YOUR SOLE RESPONSIBILITY.
//
// [Copyright (C) DCOM Productions .NET  All rights reserved.]
// *********************************************************************

namespace VisualStudioLauncher
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    using System.Threading;
    using VisualStudioLauncher.Common.Objects;
    using VisualStudioLauncher.Forms;
    using System.Drawing;
    using VisualStudioLauncher.Common.Data;
    using System.IO;

    static class Program
    {
        #region Properties

        private static ProjectLocationList m_ProjectLocationList;
        /// <summary>
        /// Gets or Sets the ProjectsLocationList
        /// </summary>
        public static ProjectLocationList ProjectLocationList
        {
            get
            {
                return m_ProjectLocationList;
            }

            set
            {
                m_ProjectLocationList = value;
            }
        }

        private static ShellProcessList m_ShellProcessList = null;
        /// <summary>
        /// Gets or Sets the ShellProcessList
        /// </summary>
        public static ShellProcessList ShellProcessList
        {
            get
            {
                return m_ShellProcessList;
            }

            set
            {
                m_ShellProcessList = value;
            }
        }

        private static NotifyIcon m_TrayIcon;
        /// <summary>
        /// Gets the programs tray application.
        /// </summary>
        public static NotifyIcon TrayIcon
        {
            get
            {
                return m_TrayIcon;
            }
        }

        private static bool m_UserExitCalled;
        /// <summary>
        /// Gets a value indicating whether the user has called for an Application.Exit
        /// </summary>
        public static bool UserExitCalled
        {
            get
            {
                return m_UserExitCalled;
            }

            set
            {
                m_UserExitCalled = value;
            }
        }

        // TODO: Finish implementation, then use this for real.
        private static ApplicationConfiguration m_ApplicationConfiguration = null;
        /// <summary>
        /// Gets the application configuration
        /// </summary>
        public static ApplicationConfiguration ApplicationConfiguration
        {
            get
            {
                if (m_ApplicationConfiguration == null)
                    m_ApplicationConfiguration = ApplicationConfiguration.LoadConfigSection(@"./settings.config");

                return m_ApplicationConfiguration;
            }
        }


        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                if (args[0].ToLower() == "-rmvptr")
                {
                    for (int i = 1; i < args.Length; i++) {
                        try {
                            if (File.Exists(Application.StartupPath + @"\\" + args[i])) {
                                File.Delete(Application.StartupPath + @"\\" + args[i]);
                            }
                        }
                        catch { /* this isn't critical, just convenient */ }
                    }
                }
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            SplashForm splashForm = new SplashForm();
            splashForm.Show();

            while (!UserExitCalled)
            {
                Application.DoEvents();
                Thread.Sleep(1);
            }

            if (m_TrayIcon != null)
            {
                m_TrayIcon.Icon = null;
                m_TrayIcon.Visible = false;
                m_TrayIcon.Dispose();

                GC.Collect();
            }
        }

        #region System Tray Management

        public static void SetupTrayIcon()
        {
            m_TrayIcon = new NotifyIcon();
            m_TrayIcon.Text = Resources.UserInterfaceStrings.ApplicationName;
            m_TrayIcon.Visible = false; // This will be set visible when the context menu is generated
            m_TrayIcon.MouseDoubleClick += new MouseEventHandler(m_TrayIcon_MouseDoubleClick);

            if (Orcas.IsInstalled)
            {
                m_TrayIcon.Icon = Orcas.Icon;
            }
            else if (Whidbey.IsInstalled) {
                m_TrayIcon.Icon = Whidbey.Icon;
            }
            else {
                m_TrayIcon.Icon = SystemIcons.Warning;
                m_TrayIcon.Text = "Visual Studio is not installed. VSL cannot run properly.";
            }
        }

        static void m_TrayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
            {
                return;
            }

            SettingsForm settingsForm = new SettingsForm();
            settingsForm.Show();
        }
        #endregion
    }
}

除非你调用 Application.Run,否则我不认为消息循环/泵会启动。 - VBNight
您可以通过调用Application.DoEvents()来处理消息。由于这不是一个复杂的场景,他甚至不需要声明一个窗体,更不用使用Application.Run()运行消息循环。“如果您的代码中不需要它,请将其删除。”特别是在生产代码中。 - David Anderson

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