English 中文(简体)
How to start WinForm app minimized to tray?
原标题:

I ve successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs when trying to start with the app minimized. At first the problem was that the app would be minimized but would still appear in the alt-tab dialog. Changing the FormBorderStyle to one of the ToolWindow options (from the "None" option) fixed this, but introduced another problem. When the app first starts the titlebar of the minimized window is visible just above the start menu:

enter image description here

Opening the form and the closing it causes it to hide properly. I ve tried lots of variations, but here s essentially how it s working right now...

WindowState is set to Minimized in the Designer. After some initialization in the constructor I have the following lines:

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

When the NotifyIcon is double-clicked I have the following:

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

Like I said, I ve tried lots of minor variations on this (this.Hide(), etc.). Is there a way to have the NotifyIcon be the primary component such that I can completely start and dispose of the form while leaving the NotifyIcon running? There s got to be a way to start the app with the form minimized without any of the weirdness. Please help me find it!

最佳回答

The right way to do this is to prevent the form from getting visible in the first place. That requires overriding SetVisibleCore(). Let s assume a context menu for the NotifyIcon with a Show and Exit command. You can implement it like this:

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();
    }
}

Note a wrinkle with the Load event, it won t fire until the main form is first shown. So be sure to do initialization in the form s constructor, not the Load event handler.

问题回答

I m reading all the answers and see hacks and black magic... (no offense, mates)

No hacks needed. You don t even have to set "ShowInTaskbar=false" and other stuff. Just do this:

    //"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();
    }

NOTE: I strongly recommend NOT TOUCHING the "ShowInTaskbar" property. For example, if your application registers system-wide hotkeys or other similar stuff (hooks, etc) - setting ShowInTaskBar=false and minimizing your app will prevent Windows from sending some messages to your window... And your hooks/hotkeys/etc will stop working.

In the constructor, remove these two lines:

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

and add after InitializeComponent();:

this.WindowState = FormWindowState.Minimized;

In designer, set ShowInTaskbar to false & FormWindowState to Normal.

EDIT: If you post the same in Load event, the window does get minimized but still shows minimized on the desktop. I think this is a bug.

When minimizing an application and you want to hide it from Alt+Tab:

You also need to set the Opacity to stop the titlebar showing near the Start Menu when you set the Border Style to a Tool Window.

On Minimize Event:

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

On Normalize Event:

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

Move the following code from the Form s constructor to Form_Main_Load(). With the same setup on Notification_Icon when Form_Resize().

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

This "quick and dirty fix" worked for me:

$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()

Hope it helps someone else...





相关问题
Bring window to foreground after Mutex fails

I was wondering if someone can tell me what would be the best way to bring my application to the foreground if a mutex was not able to be created for a new instance. E.g.: Application X is running ...

How to start WinForm app minimized to tray?

I ve successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

Handle DataTable.DataRow cell change event

I have a DataTable that has several DataColumns and DataRow. Now i would like to handle an event when cell of this DataRow is changed. How to do this in c#?

Apparent Memory Leak in DataGridView

How do you force a DataGridView to release its reference to a bound DataSet? We have a rather large dataset being displayed in a DataGridView and noticed that resources were not being freed after the ...

ALT Key Shortcuts Hidden

I am using VS2008 and creating forms. By default, the underscore of the character in a textbox when using an ampersand is not shown when I run the application. ex. "&Goto Here" is not ...

WPF-XAML window in Winforms Application

I have a Winforms application coded in VS C# 2008 and want to insert a WPF window into the window pane of Winforms application. Could you explain me how this is done.

热门标签