【问题标题】:How to start WinForm app minimized to tray?如何启动最小化到托盘的 WinForm 应用程序?
【发布时间】:2010-12-16 09:18:56
【问题描述】:

我已经成功创建了一个使用 NotifyIcon 最小化到托盘的应用。当手动关闭表单时,它会成功地从桌面、任务栏和 alt-tab 中隐藏。尝试以最小化应用程序启动时会出现此问题。起初的问题是应用程序将被最小化,但仍会出现在 alt-tab 对话框中。将 FormBorderStyle 更改为 ToolWindow 选项之一(从“无”选项)解决了这个问题,但引入了另一个问题。当应用第一次启动时,最小化窗口的标题栏在开始菜单上方可见:

打开表单并关闭它会使其正确隐藏。我已经尝试了很多变体,但基本上这是它现在的工作方式......

WindowState 在设计器中设置为最小化。在构造函数中进行一些初始化后,我有以下几行:

this.Visible = false;
this.ShowInTaskbar = false;

当双击 NotifyIcon 时,我有以下内容:

 this.WindowState = FormWindowState.Normal;
 this.Visible = true;
 this.ShowInTaskbar = true;

就像我说的那样,我已经尝试了很多细微的变化(this.Hide() 等)。有没有办法让 NotifyIcon 成为主要组件,这样我就可以在保持 NotifyIcon 运行的同时完全启动和处理表单?必须有一种方法可以以最小化的形式启动应用程序,而不会产生任何怪异。请帮我找到它!

【问题讨论】:

    标签: c# .net winforms visual-studio-2008 systray


    【解决方案1】:

    这样做的正确方法是首先防止表单变得可见。这需要重写 SetVisibleCore()。让我们假设 NotifyIcon 的上下文菜单带有 Show and Exit 命令。你可以这样实现它:

    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            notifyIcon1.ContextMenuStrip = contextMenuStrip1;
            this.showToolStripMenuItem.Click += showToolStripMenuItem_Click;
            this.exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
        }
    
        private bool allowVisible;     // ContextMenu's Show command used
        private bool allowClose;       // ContextMenu's Exit command used
    
        protected override void SetVisibleCore(bool value) {
            if (!allowVisible) {
                value = false;
                if (!this.IsHandleCreated) CreateHandle();
            }
            base.SetVisibleCore(value);
        }
    
        protected override void OnFormClosing(FormClosingEventArgs e) {
            if (!allowClose) {
                this.Hide();
                e.Cancel = true;
            }
            base.OnFormClosing(e);
        }
    
        private void showToolStripMenuItem_Click(object sender, EventArgs e) {
            allowVisible = true;
            Show();
        }
    
        private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
            allowClose = true;
            Application.Exit();
        }
    }
    

    请注意 Load 事件的一个问题,在第一次显示主窗体之前它不会触发。所以请务必在表单的构造函数中进行初始化,而不是在 Load 事件处理程序中。

    【讨论】:

    • 太棒了,谢谢!进行了一些调整以使其与我的特定应用程序一起使用,但效果很好!
    • 退出点击处理程序的小改动,当表单未显示时从上下文菜单退出应用程序时不显示表单,将行if (!mLoadFired) Show();替换为代码:if (mLoadFired) Close(); else Application.Exit();
    • if (!this.IsHandleCreated) CreateHandle(); 行非常有价值……它可以防止以后出现 ThreadExceptions。感谢您的回答!
    【解决方案2】:

    我正在阅读所有答案并看到黑客和黑魔法......(无意冒犯,伙计们)

    无需破解。您甚至不必设置“ShowInTaskbar=false”和其他内容。只需这样做:

        //"Form Shown" event handler
        private void Form_Shown(object sender, EventArgs e)
        {
            //to minimize window
            this.WindowState = FormWindowState.Minimized;
    
            //to hide from taskbar
            this.Hide();
        }
    

    注意:我强烈建议不要触摸“ShowInTaskbar”属性。例如,如果您的应用程序注册了系统范围的热键或其他类似的东西(钩子等) - 设置 ShowInTaskBar=false 并最小化您的应用程序将阻止 Windows 向您的窗口发送一些消息......而您的钩子/热键/等将停止工作。

    【讨论】:

    • 我正在研究如何为我的程序执行此操作,这个答案是实现我的目标的最简单有效的方法。
    • @Brad 不,您仍然需要手动添加 NotifyIcon。但是添加图标后它会起作用。
    • 我已经准备好最小化到托盘(通知区域)的一切,并且在手动触发时它可以工作。这是唯一缺少在启动时自动启动它的东西。不涉及黑客攻击。很好的答案!
    • 完美运行——令人惊讶的是,我花了大约 2 小时的谷歌搜索和测试其他方法来获得它。非常感谢。
    • 而且仅供参考 - 对于 VS 的新用户 - 在 UI 设计器的表单属性中,查找“SHOWN”事件 - 而不是“FORM SHOWN”。
    【解决方案3】:

    构造函数中,删除这两行:

    this.Visible = false;
    this.ShowInTaskbar = false;
    

    并在InitializeComponent();之后添加:

    this.WindowState = FormWindowState.Minimized;
    

    在设计器中,将ShowInTaskbar 设置为falseFormWindowState 设置为Normal

    编辑: 如果您在 Load 事件中发布相同内容,则窗口确实会最小化,但仍会在桌面上显示为最小化。我认为这是一个错误。

    【讨论】:

    • 或者在表单的加载事件中,因为构造函数是设计器生成的,你很容易让你的更改不时消失。
    • 我同意,加载事件会是一个更好的地方
    • 查看我的编辑。只有当您发布我在InitializeComponent(); 之前发布的行时,您的更改才会消失。您所有的设计器设置都加载到InitializeComponent();
    • 好的,我将初始化代码移至加载事件并进行了建议的更改。没有骰子。我仍然在桌面上看到最小化的标题栏,只是现在即使手动关闭表单也不会消失。还有其他想法吗?
    • Re: 编辑:它看起来确实像错误,但必须有人在做我想做的事情。我认为这样的错误会引起更多关注......
    【解决方案4】:

    当最小化一个应用程序并且你想用 Alt+Tab 隐藏它时:

    当您将边框样式设置为工具窗口时,您还需要设置不透明度以停止标题栏显示在开始菜单附近。

    关于最小化事件:

    this.Visible = false;
    this.Opacity = 0;
    this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
    this.ShowInTaskbar = false;
    

    关于标准化事件:

    this.Visible = true;
    this.Opacity = 100;
    this.FormBorderStyle = FormBorderStyle.FixedSingle; //or whatever it was previously set to
    this.ShowInTaskbar = true;
    

    【讨论】:

      【解决方案5】:

      将以下代码从Form 的构造函数移至Form_Main_Load()。在Notification_Icon when Form_Resize() 上使用相同的设置。

      // Hide the Form to System Tray
      this.WindowState = FormWindowState.Minimized;
      

      【讨论】:

        【解决方案6】:

        这个“快速而肮脏的修复”对我有用:

        $form1.FormBorderStyle = "fixedtoolwindow"
        $form1.top = -1000000
        $form1.Left = -1000000
        $form1.Width = 10
        $form1.Height = 10
        $form1.WindowState = "normal"
        $form1.ShowInTaskbar = $False
        $form1.Opacity = 0
        $form1.Hide()
        

        希望它可以帮助别人......

        【讨论】:

        • 那是什么语言?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-29
        • 1970-01-01
        • 2017-11-15
        • 2010-12-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多