从NotifyIcon激活我的MainForm的正确方法,如果它还没有集中

时间:2016-04-22 15:10:23

标签: c# .net windows winforms trayicon

我只想用托盘通知图标替换我的winforms应用程序的任务栏按钮。这意味着,如果用户左键单击该图标,则表单应该被激活,如果它没有被聚焦,否则被最小化或隐藏。

我阅读了很多关于正确使用NotifyIcon的文章,似乎我必须接受一个hackish解决方案。那么,最恰当的方式是什么?

我主要是为了运行它,但是现在我一直在检测我的表单是否已经处于活动状态 - 因为当单击图标时,表单会失去焦点,因此我无法检查Focused属性。

以下代码尚未解决此问题,因此如果表单只是被其他窗口隐藏,则必须单击2次,因为第一次单击最小化。

如何改进?

    private void FormMain_Resize(object sender, EventArgs e)
    {
        if (WindowState == FormWindowState.Minimized)
            Hide();
    }

    private void notifyIcon_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
            if (WindowState == FormWindowState.Minimized) {
                WindowState = FormWindowState.Normal;
                Show();
                Activate();
            }
            else {
                Hide();
                WindowState = FormWindowState.Minimized;
            }
    }

(我也不明白为什么Click事件在右键单击时触发,在我的情况下已打开上下文菜单...)

(当然,有一个适当的最小化动画会很好,但是这里有其他问题,这些问题并没有真正解决)

(我知道我说Focused,但如果表单已经完全可见(但可能没有聚焦),并且用户点击了托盘图标,他很可能想隐藏它。

1 个答案:

答案 0 :(得分:1)

@LarsTech建议使用计时器进行黑客攻击,这很有效,谢谢,但我仍然希望有更好的解决方案或改进。

也许有趣:我还解决了部分动画问题 - 当没有任务栏按钮时,动画源自最小化表单所在的位置。您可以在最小化后调用Show()使其可见。它位于屏幕的左下方,无法通过设置Left属性来移动它。所以我直接使用winapi,它的工作原理! 不幸的是,仅用于恢复动画,因为我不知道如何在最小化之前设置最小化位置。无论如何Hide()禁用了动画,所以我不得不推迟它......

这一切都令人失望!为什么没有好的解决方案?我永远无法确定它是否适用于所有情况。例如,在一台机器上,它与100毫秒计时器很好地工作,但在另一台机器上我需要200毫秒。所以我建议至少有500毫秒。

[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, 
    int X, int Y, int nWidth, int nHeight, bool bRepaint);

private void FormMain_Resize(object sender, EventArgs e)
{
    if (!ShowInTaskbar && WindowState == FormWindowState.Minimized) {
        Hide();
        //Move the invisible minimized window near the tray notification area
        if (!MoveWindow(Handle, Screen.PrimaryScreen.WorkingArea.Left
                + Screen.PrimaryScreen.WorkingArea.Width - Width - 100,
                Top, Width, Height, false))
            throw new Win32Exception();
    }
}

private void notifyIcon_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
        if (WindowState == FormWindowState.Minimized || !timer.Enabled) {
            Show();
            WindowState = FormWindowState.Normal;
            Activate();
        }
        else {
            WindowState = FormWindowState.Minimized;
            //FormMain_Resize will be called after this
        }
}

private void FormMain_Deactivate(object sender, EventArgs e)
{
    timer.Start();
}

private void timer_Tick(object sender, EventArgs e)
{
    timer.Stop();
}

//other free goodies not mentioned before...

private void taskbarToolStripMenuItem_Click(object sender, EventArgs e)
{
    ShowInTaskbar = !ShowInTaskbar;
    taskbarToolStripMenuItem.Checked = ShowInTaskbar;
}

private void priorityToolStripMenuItem_Click(object sender, EventArgs e)
{
    //Set the process priority from ToolStripMenuItem.Tag
    //Normal = 32, Idle = 64, High = 128, BelowNormal = 16384, AboveNormal = 32768
    Process.GetCurrentProcess().PriorityClass
        = (ProcessPriorityClass)int.Parse((sender as ToolStripMenuItem).Tag.ToString());
    foreach (ToolStripMenuItem item in contextMenuStrip.Items)
        if (item.Tag != null)
            item.Checked = item.Equals(sender);
}

private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
    Close();
}