Почему я вижу несколько значков Systray?
Я добавил значок уведомления в свое приложение, и довольно часто я вижу до 3 копий значка уведомления в моем системном окне. Для этого есть причина?
Есть ли способ, чтобы остановить это.
Часто это сохраняется после того, как мое приложение закрылось, пока я не заскочил на системный блок, и системный блок расширился и рухнул, а затем все они исчезли.
4 ответа
Это когда вы отлаживаете свое приложение? Если это так, то это потому, что сообщения, которые удаляют значок из системного трея, отправляются только при нормальном выходе из приложения, если оно завершается из-за исключительной ситуации или из-за того, что вы закрываете его из Visual Studio, значок будет оставаться, пока вы не наведете на него курсор мыши.
Вы можете убить значок, используя событие Closed родительского окна. Это работает в моем приложении WPF, даже при тестировании в Visual Studio (2010 в моем случае):
parentWindow.Closing += (object sender, CancelEventArgs e) =>
{
notifyIcon.Visible = false;
notifyIcon.Icon = null;
notifyIcon.Dispose();
};
Что я сделал:
Создайте библиотеку классов, которая обновляет системный трей.
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); } } } } } } } } } }
Скопируйте DLL в
"%ProgramFiles%\Microsoft Visual Studio x.x\Common7\IDE\PublicAssemblies\SystrayUtil.dll"
Где хх - номер версии Visual Studio
Запишите макрос и сохраните его
Редактировать макрос
Добавить ссылку на созданную DLL.
добавлять
Imports SystrayUtil
в список импорта в верхней части модуля EnvironmentEvents.Удалите все ненужные элементы и добавьте следующий код в модуль EnvironmentEvents.
Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode Systray.Cleanup() MsgBox("Entered design mode!") End Sub
Если это работает, удалите
MsgBox("Entered design mode!")
потому что раздражает, что окно сообщения появляется каждый раз, когда вы возвращаетесь из сеанса отладки.
Это должно работать, когда вы обычно закрываете приложение:
// 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, нажмите кнопку остановки отладки - процесс завершается, и никакие события удаления не запускаются.