C#通过单击通知图标(任务栏图标)切换窗口
我的C#应用程序由一个任务栏图标(NotifyIcon)和一个最初隐藏的开销窗口组成。我希望用户能够通过单击Notify图标(左键,单击)来切换窗口可见性。同时,当失去焦点时,窗口被隐藏 这是到目前为止我所拥有的,一个子类C#通过单击通知图标(任务栏图标)切换窗口,c#,.net,forms,notifyicon,C#,.net,Forms,Notifyicon,我的C#应用程序由一个任务栏图标(NotifyIcon)和一个最初隐藏的开销窗口组成。我希望用户能够通过单击Notify图标(左键,单击)来切换窗口可见性。同时,当失去焦点时,窗口被隐藏 这是到目前为止我所拥有的,一个子类System.Windows.Forms.Form: 初始化: this.ControlBox = false; this.ShowIcon = false; this.ShowInTaskbar = false; // Instance variables: bool al
System.Windows.Forms.Form
:
初始化:
this.ControlBox = false;
this.ShowIcon = false;
this.ShowInTaskbar = false;
// Instance variables: bool allowVisible;
// System.Windows.Forms.NotifyIcon notifyIcon;
this.allowVisible = false;
this.notifyIcon = new NotifyIcon();
this.notifyIcon.MouseUp += new MouseEventHandler(NotifyIconClicked);
this.Deactivate += new EventHandler(HideOnEvent);
实例方法:
private void NotifyIconClicked(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (this.Visible)
this.Hide();
else
this.Show();
}
}
new public void Show()
{
this.allowVisible = true;
this.Visible = true;
this.Activate();
}
new public void Hide()
{
this.allowVisible = false;
this.Visible = false;
}
private void HideOnEvent(object sender, EventArgs e)
{
this.Hide();
}
protected override void SetVisibleCore(bool visible)
{
base.SetVisibleCore(this.allowVisible ? visible : this.allowVisible);
}
单击图标将显示该窗口。但是,只要按下鼠标,再次单击它就会隐藏它,然后将其重置为可见
我的猜测是鼠标按下事件会从窗口中窃取焦点,因此它会消失。然后触发鼠标向上事件,显示隐藏的窗口
我的下一个想法是在鼠标按下时读取窗口可见性事件,因此我测试了三个事件,并记录了UNIX时间,它们被称为:
notifyIcon.MouseDown
notifyIcon.MouseUp
this.LostFocus
结果很奇怪:假设窗口是可见的。当我单击图标时会发生这种情况:立即调用Focus lost。在鼠标向上事件之前,我一释放鼠标就调用鼠标向下
1312372231 focus lost
1312372235 mouse down
1312372235 mouse up
为什么鼠标按下事件会延迟?如何切换窗口?我想这可能适合您 我发现了一个专家交换帖子,其中包含一个类,该类提供了一种检查光标当前是否在托盘上的方法 使用此类,我修改了HideOnEvent方法,如下所示:
private void HideOnEvent(object sender, EventArgs e)
{
if (!WinAPI.GetTrayRectangle().Contains(Cursor.Position))
{
this.Hide();
}
}
这似乎能满足你的需要
我已包括以下课程:
using System.Runtime.InteropServices;
using System.Drawing;
public class WinAPI
{
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public override string ToString()
{
return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")";
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
public static IntPtr GetTrayHandle()
{
IntPtr taskBarHandle = WinAPI.FindWindow("Shell_TrayWnd", null);
if (!taskBarHandle.Equals(IntPtr.Zero))
{
return WinAPI.FindWindowEx(taskBarHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
}
return IntPtr.Zero;
}
public static Rectangle GetTrayRectangle()
{
WinAPI.RECT rect;
WinAPI.GetWindowRect(WinAPI.GetTrayHandle(), out rect);
return new Rectangle(new Point(rect.left, rect.top), new Size((rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1));
}
}
这不是一个完美的解决方案,但我希望这会有所帮助。我认为这可能对您有用 我发现了一个专家交换帖子,其中包含一个类,该类提供了一种检查光标当前是否在托盘上的方法 使用此类,我修改了HideOnEvent方法,如下所示:
private void HideOnEvent(object sender, EventArgs e)
{
if (!WinAPI.GetTrayRectangle().Contains(Cursor.Position))
{
this.Hide();
}
}
这似乎能满足你的需要
我已包括以下课程:
using System.Runtime.InteropServices;
using System.Drawing;
public class WinAPI
{
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public override string ToString()
{
return "(" + left + ", " + top + ") --> (" + right + ", " + bottom + ")";
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
public static IntPtr GetTrayHandle()
{
IntPtr taskBarHandle = WinAPI.FindWindow("Shell_TrayWnd", null);
if (!taskBarHandle.Equals(IntPtr.Zero))
{
return WinAPI.FindWindowEx(taskBarHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
}
return IntPtr.Zero;
}
public static Rectangle GetTrayRectangle()
{
WinAPI.RECT rect;
WinAPI.GetWindowRect(WinAPI.GetTrayHandle(), out rect);
return new Rectangle(new Point(rect.left, rect.top), new Size((rect.right - rect.left) + 1, (rect.bottom - rect.top) + 1));
}
}
这不是一个完美的解决方案,但我希望这能有所帮助