アプリに通知アイコンを追加しましたが、私のシステムトレイに通知アイコンのコピーが3つまで表示されることがよくあります。これには理由がありますか?複数のSystrayアイコンが表示されるのはなぜですか?
これが起こるのを防ぐ方法があります。
多くの場合、これはアプリケーションが終了してから、システムトレイに落とされ、システムトレイが拡張して折りたたまれて折りたたまれ、すべて消滅するまで持続します。
アプリに通知アイコンを追加しましたが、私のシステムトレイに通知アイコンのコピーが3つまで表示されることがよくあります。これには理由がありますか?複数のSystrayアイコンが表示されるのはなぜですか?
これが起こるのを防ぐ方法があります。
多くの場合、これはアプリケーションが終了してから、システムトレイに落とされ、システムトレイが拡張して折りたたまれて折りたたまれ、すべて消滅するまで持続します。
これはアプリケーションのデバッグ中ですか?これは、システムトレイからアイコンを削除するメッセージは、アプリケーションが正常に終了した場合にのみ送信されるため、例外のために終了した場合、またはVisual Studioから終了するためアイコンにマウスを重ねるまでアイコンが残ります。
親WindowのClosedイベントを使用してアイコンを強制終了できます。これは、(私の場合は2010)のVisual Studioでテストする場合でも、私のWPFアプリケーションで動作します。私がやったこと
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);
}
}
}
}
}
}
}
}
}
}
コピーxxは
編集マクロ
追加のVisual Studioのバージョン番号
録音がマクロですし、それを保存"%ProgramFiles%\Microsoft Visual Studio x.x\Common7\IDE\PublicAssemblies\SystrayUtil.dll"
へのdll作成されたdllへの参照。
Module EnvironmentEventsの最上部にあるインポートリストにImports SystrayUtil
を追加します。
不要な項目を削除し、それはあなたがデバッグセッションから戻るたびにポップアップメッセージボックスを持つように迷惑だから、それはMsgBox("Entered design mode!")
を削除する動作する場合
Public Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode
Systray.Cleanup()
MsgBox("Entered design mode!")
End Sub
EnvironmentEventsモジュールに次のコードを追加します。
あなたが正常にアプリケーションを閉じると、この作業をする必要があります:
// 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の停止デバッグボタンからアプリケーションを停止する - プロセスが殺され、何の処分イベントが発生されていません。
NotifyIconをどのように追加しましたか?デザイナーやコードで? – OregonGhost
...アプリケーション終了中にどうやって削除しますか? –
デザイナーと私はそれを削除しないでください? –