C# 在NotifyIcon上切换窗体可见性单击并在单击别处时隐藏它

C# 在NotifyIcon上切换窗体可见性单击并在单击别处时隐藏它,c#,windows,winforms,notifyicon,C#,Windows,Winforms,Notifyicon,我有一个应用程序在系统托盘中。如果用户单击notify图标,如果它还不可见,我想让它可见。如果已可见,则应将其隐藏。此外,当用户单击表单上以外的任何位置时,表单应隐藏(如果可见) 我的代码如下所示: protected override void OnDeactivated(EventArgs e) { showForm(false); } public void showForm(bool show) { if(show) { Show();

我有一个应用程序在系统托盘中。如果用户单击
notify图标
,如果它还不可见,我想让它可见。如果已可见,则应将其隐藏。此外,当用户单击表单上以外的任何位置时,表单应隐藏(如果可见)

我的代码如下所示:

protected override void OnDeactivated(EventArgs e)
{
    showForm(false);
}

public void showForm(bool show)
{
    if(show)
    {
        Show();
        Activate();
        WindowState = FormWindowState.Normal;
    }
    else
    {
        Hide();
        WindowState = FormWindowState.Minimized;
    }
}

private void notifyIcon1_MouseClicked(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        if (WindowState != FormWindowState.Normal)
        {
            showForm(true);
        }
    }
}
代码的问题是,
onDeactivated
在单击调用之前被调用,这会隐藏表单,而不仅仅是重新显示表单。如果我能够检测到焦点是否由于单击
notifyIcon
或其他地方而丢失,则可以解决问题

我做了研究,发现了一个类似的线程,但解决方案只是在调用
onDeactivated
时检测到鼠标位置是否在托盘上方:

更新: 我发布的解决方案只检测用户的鼠标是否在任务栏中的任务栏图标上,因此如果您单击任何其他任务栏,则不会触发
onDeactivated
事件。
我希望获得与system volume应用程序相同的功能。

只需跟踪上次隐藏窗口的时间即可。如果最近发生这种情况,请忽略鼠标单击。像这样:

int lastDeactivateTick;
bool lastDeactivateValid;

protected override void OnDeactivate(EventArgs e) {
    base.OnDeactivate(e);
    lastDeactivateTick = Environment.TickCount;
    lastDeactivateValid = true;
    this.Hide();
}

private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
    if (lastDeactivateValid && Environment.TickCount - lastDeactivateTick < 1000) return;
    this.Show();
    this.Activate();
}
int-lastk;
布尔·拉斯特瓦利德;
受保护的覆盖无效激活(事件参数e){
碱基(e);
LastDeactivateTk=Environment.TickCount;
LastEvalid=true;
this.Hide();
}
私有void notifyicon1u鼠标单击(对象发送方,MouseEventArgs e){
如果(lastDeactivateValid&&Environment.TickCount-lastDeactivateTick<1000)返回;
this.Show();
这个。激活();
}

现在反复单击图标可以可靠地切换窗口可见性。

只需跟踪窗口上次隐藏的时间即可。如果最近发生这种情况,请忽略鼠标单击。像这样:

int lastDeactivateTick;
bool lastDeactivateValid;

protected override void OnDeactivate(EventArgs e) {
    base.OnDeactivate(e);
    lastDeactivateTick = Environment.TickCount;
    lastDeactivateValid = true;
    this.Hide();
}

private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
    if (lastDeactivateValid && Environment.TickCount - lastDeactivateTick < 1000) return;
    this.Show();
    this.Activate();
}
int-lastk;
布尔·拉斯特瓦利德;
受保护的覆盖无效激活(事件参数e){
碱基(e);
LastDeactivateTk=Environment.TickCount;
LastEvalid=true;
this.Hide();
}
私有void notifyicon1u鼠标单击(对象发送方,MouseEventArgs e){
如果(lastDeactivateValid&&Environment.TickCount-lastDeactivateTick<1000)返回;
this.Show();
这个。激活();
}

现在,反复单击图标可以可靠地切换窗口可见性。

您找到了检查鼠标是否在notifyicon上的解决方案…因此,请检查ondeactivated事件,如果鼠标在上-不要执行
showForm(false)或我遗漏了什么?解决方案会检测鼠标是否在系统托盘(任务栏)上,而不是我的图标上。当图标被放置在通知窗口中时,焦点丢失事件也会被触发。您可以使用NotifyIcon.MouseMove事件来检测鼠标在图标上方的时间。但是,您需要知道鼠标何时离开图标区域…:/mousemove事件在窗体失去焦点后被触发您找到了检查鼠标是否在notifyicon上的解决方案…因此请检查ondeactivated事件以及鼠标是否在上面-不要执行
showForm(false)或我遗漏了什么?解决方案会检测鼠标是否在系统托盘(任务栏)上,而不是我的图标上。当图标被放置在通知窗口中时,焦点丢失事件也会被触发。您可以使用NotifyIcon.MouseMove事件来检测鼠标在图标上方的时间。但是,您需要知道鼠标何时离开图标区域…:/mousemove事件在窗体失去焦点后被激发