我只想用托盘通知图标替换我的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
,但如果表单已经完全可见(但可能没有聚焦),并且用户点击了托盘图标,他很可能想隐藏它。
答案 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();
}