我已经在我的应用程序中添加了通知图标,但很常见地在系统托盘中看到多达3个副本的通知图标。这是有原因的吗?
有没有办法阻止它发生。
通常,在我的应用程序关闭后,这种情况仍会持续存在,直到我将鼠标移到系统托盘上并展开和折叠系统托盘,然后它们都会消失。
我已经在我的应用程序中添加了通知图标,但很常见地在系统托盘中看到多达3个副本的通知图标。这是有原因的吗?
有没有办法阻止它发生。
通常,在我的应用程序关闭后,这种情况仍会持续存在,直到我将鼠标移到系统托盘上并展开和折叠系统托盘,然后它们都会消失。
这是在你调试应用程序时出现的吗?如果是,那么这是因为从系统托盘中删除图标的消息仅在应用程序正常退出时发送,如果它由于异常或通过 Visual Studio 终止而终止,则图标将保留,直到你将鼠标悬停在其上。
你可以通过父窗口的关闭事件来结束图标。这在我的WPF应用程序中有效,即使在Visual Studio(我是2010版本)中测试也有效:
parentWindow.Closing += (object sender, CancelEventArgs e) =>
{
notifyIcon.Visible = false;
notifyIcon.Icon = null;
notifyIcon.Dispose();
};
我做了什么:
Create a class library that updates the system tray.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace SystrayUtil
{
internal enum MessageEnum
{
WM_MOUSEMOVE = 0x0200,
WM_CLOSE = 0x0010,
}
internal struct RECT
{
internal int Left;
internal int Top;
internal int Right;
internal int Bottom;
internal RECT(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
}
public sealed class Systray
{
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, IntPtr lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, int message, uint wParam, long lParam);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool GetClientRect(IntPtr hWnd, out RECT usrTray);
public static void Cleanup()
{
RECT sysTrayRect = new RECT();
IntPtr sysTrayHandle = FindWindow("Shell_TrayWnd", null);
if (sysTrayHandle != IntPtr.Zero)
{
IntPtr childHandle = FindWindowEx(sysTrayHandle, IntPtr.Zero, "TrayNotifyWnd", IntPtr.Zero);
if (childHandle != IntPtr.Zero)
{
childHandle = FindWindowEx(childHandle, IntPtr.Zero, "SysPager", IntPtr.Zero);
if (childHandle != IntPtr.Zero)
{
childHandle = FindWindowEx(childHandle, IntPtr.Zero, "ToolbarWindow32", IntPtr.Zero);
if (childHandle != IntPtr.Zero)
{
bool systrayWindowFound = GetClientRect(childHandle, out sysTrayRect);
if (systrayWindowFound)
{
for (int x = 0; x < sysTrayRect.Right; x += 5)
{
for (int y = 0; y < sysTrayRect.Bottom; y += 5)
{
SendMessage(childHandle, (int)MessageEnum.WM_MOUSEMOVE, 0, (y << 16) + x);
}
}
}
}
}
}
}
}
}
}
Copy the dll to "%ProgramFiles%\Microsoft Visual Studio x.x\Common7\IDE\PublicAssemblies\SystrayUtil.dll"
Where x.x is the version number of Visual Studio
Record a macro and save it
Edit the macro
Add a reference to the created dll.
Add Imports SystrayUtil
to the list of imports at the top of Module EnvironmentEvents.
Remove any unwanted items and add the following code to the EnvironmentEvents module
Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode
Systray.Cleanup()
MsgBox("Entered design mode!")
End Sub
If it works remove MsgBox("Entered design mode!")
because it's annoying to have a message box popping up every time you return from a debugging session.
当您正常关闭应用程序时,这应该可以工作:
// in form's constructor
Application.ApplicationExit += new EventHandler(this.OnApplicationExit);
private void OnApplicationExit(object sender, EventArgs e)
{
try
{
if (notifyIcon1!= null)
{
notifyIcon1.Visible = false;
notifyIcon1.Icon = null;
notifyIcon1.Dispose();
notifyIcon1= null;
}
}
catch { }
}
当您使用Visual Studio停止调试按钮停止应用程序时,进程将被终止,不会触发任何Dispose事件。