我只想用托盘通知图标replace我的winforms应用程序的任务栏button。 这意味着,如果用户左键单击该图标,则表单应该被激活,否则将被最小化或隐藏。
我阅读了很多关于正确使用NotifyIcon
的文章,似乎我不得不接受一个黑客解决scheme。 那么,最合适的方法是什么?
我主要是为了运行,但现在我被困在检测,如果我的表单已被激活 – 因为当单击图标,表单失去焦点,所以我不能检查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
事件触发右键单击,这已经打开我的情况下的上下文菜单…)
(当然,最好有一个适当的最小化animation,但这里还有其他的问题,这个问题没有真正解决)
(我知道我说的Focused
,但是如果表格已经完全可见(但可能没有关注),并且用户点击了托盘图标,他很可能想隐藏它)
@LarsTech建议使用计时器的黑客,这工作,谢谢,但我仍然希望有更好的解决方案或改进。
也许有趣:我也解决了动画问题的一部分 – 当没有任务栏按钮时,动画源自最小化窗体所在的位置。 最小化之后,可以通过调用Show()
来使其可见。 它位于屏幕的左下方,不能通过设置Left
属性来移动它。 所以我直接使用了winapi,并且工作正常! 不幸的是只有恢复动画,因为我不知道如何在最小化之前设置最小化的位置。 Hide()
禁止动画,所以我不得不推迟它…
这一切都是如此令人失望! 为什么没有好的解决方案? 我永远无法确定它是否能在任何情况下都能正常工作。 例如,在一台机器上,它使用100ms定时器运行良好,但另一台机器需要200ms。 所以我建议至少有500ms。
[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(); }