从通知图标激活我的主窗体的正确方法(如果它尚未聚焦)
本文关键字:如果 方法 聚焦 激活 图标 通知 我的 窗体 | 更新日期: 2024-11-07 16:01:35
我只想用托盘通知图标替换我的 winforms 应用程序的任务栏按钮。这意味着,如果用户左键单击图标,则应激活表单(如果未聚焦),否则应将其最小化或隐藏。
我阅读了很多关于正确使用NotifyIcon
的文章,似乎我必须接受一个黑客解决方案。那么,最正确的方法是什么?
让它主要是为了运行,但现在我只能检测我的表单是否已经处于活动状态 - 因为单击图标时,表单会失去焦点,所以我无法检查 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
,但如果表单已经完全可见(但可能没有聚焦),并且用户单击托盘图标,他很可能想要隐藏它)
@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();
}