Verwenden von TrayIcon´s ohne Referenz auf System.Windows.Forms
Hallo,
In meinem Zivildienstprojekt “LWD.NET” will ich vermeiden eine Referenz auf die Windows Forms Bibliothek zu vermeiden, da WPF-Mäßig keine Unterstützung für ein Tray-Icon (die Icons neben der System-Uhr) mitliefer habe ich mich ein wenig mit der WinAPI herumgeschlagen und eine kleine Klasse geschrieben die mir die Arbeit abnimmt.
Vorgehensweiße:
- Dem Konstruktor werden, WPF-Window, ein System.Drawing.Icon und der String für den Namen übergeben
- Dieser erzeugt die benötigte “NOTIFYICONDATA” Struktur, abonniert die Events Closing und StateChanged vom Window selber sowie mithilfe von “HwndSource” alle Windows-Messages die das Fenster erhält.
- Wird das Fenster nun minimiert, speichert sich die Klasse den vorherigen Status (Maximiert oder Resizeable), versteckt das Fenster (über Hide()) und setzt sich selber als Icon in den Traybereich
- Wird auf das Tray-Icon geklickt erhält das WPF-Window eine Windows-Message mit der ID “WM_MyMessage” (Achtung! Dadurch kann diese Klasse nicht mehrmals verwendet werden! Müsste eindeutig für jedes TrayIcon sein ODER die uID NOTIFYICONDATA) und das Tray-Icon wird entfernt sowie das Fenster wieder wiederhergestellt.
[codesyntax lang="csharp"]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Runtime.InteropServices;
using System.Windows.Interop;
namespace LWD.NET
{
public class TrayIcon
{
IntPtr m_Handle;
Window m_Window;
WindowState m_storedWindowState;
NOTIFYICONDATA m_Data;
System.Drawing.Icon m_Icon;
const int TRAY_ADD = 0x00000000;
const int TRAY_MODIFY = 0x00000001;
const int TRAY_DELETE = 0x00000002;
const int WM_MyMessage = 0x400;
[DllImport("shell32.dll")]
static extern bool Shell_NotifyIcon(uint dwMessage,[In] ref NOTIFYICONDATA pnid);
struct NOTIFYICONDATA
{
/// <summary>
/// Size of this structure, in bytes.
/// </summary>
public int cbSize;
/// <summary>
/// Handle to the window that receives notification messages associated with an icon in the
/// taskbar status area. The Shell uses hWnd and uID to identify which icon to operate on
/// when Shell_NotifyIcon is invoked.
/// </summary>
public IntPtr hwnd;
/// <summary>
/// Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify
/// which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons
/// associated with a single hWnd by assigning each a different uID.
/// </summary>
public int uID;
/// <summary>
/// Flags that indicate which of the other members contain valid data. This member can be
/// a combination of the NIF_XXX constants.
/// </summary>
public int uFlags;
/// <summary>
/// Application-defined message identifier. The system uses this identifier to send
/// notifications to the window identified in hWnd.
/// </summary>
public int uCallbackMessage;
/// <summary>
/// Handle to the icon to be added, modified, or deleted.
/// </summary>
public IntPtr hIcon;
/// <summary>
/// String with the text for a standard ToolTip. It can have a maximum of 64 characters including
/// the terminating NULL. For Version 5.0 and later, szTip can have a maximum of
/// 128 characters, including the terminating NULL.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szTip;
/// <summary>
/// State of the icon.
/// </summary>
public int dwState;
/// <summary>
/// A value that specifies which bits of the state member are retrieved or modified.
/// For example, setting this member to NIS_HIDDEN causes only the item's hidden state to be retrieved.
/// </summary>
public int dwStateMask;
/// <summary>
/// String with the text for a balloon ToolTip. It can have a maximum of 255 characters.
/// To remove the ToolTip, set the NIF_INFO flag in uFlags and set szInfo to an empty string.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szInfo;
/// <summary>
/// NOTE: This field is also used for the Timeout value. Specifies whether the Shell notify
/// icon interface should use Windows 95 or Windows 2000
/// behavior. For more information on the differences in these two behaviors, see
/// Shell_NotifyIcon. This member is only employed when using Shell_NotifyIcon to send an
/// NIM_VERSION message.
/// </summary>
public int uVersion;
/// <summary>
/// String containing a title for a balloon ToolTip. This title appears in boldface
/// above the text. It can have a maximum of 63 characters.
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string szInfoTitle;
/// <summary>
/// Adds an icon to a balloon ToolTip. It is placed to the left of the title. If the
/// szTitleInfo member is zero-length, the icon is not shown. See
/// <see cref="BalloonIconStyle">RMUtils.WinAPI.Structs.BalloonIconStyle</see> for more
/// information.
/// </summary>
public int dwInfoFlags;
}
public TrayIcon(Window win, System.Drawing.Icon Icon,string Tip)
{
m_Window = win;
m_Icon = Icon;
m_Handle = new WindowInteropHelper(m_Window).Handle;
HwndSource source = PresentationSource.FromVisual(m_Window) as HwndSource;
source.AddHook(WndProc);
m_Window.Closing += new System.ComponentModel.CancelEventHandler(win_Closing);
m_Window.StateChanged += new EventHandler(win_StateChanged);
m_Data = new NOTIFYICONDATA();
if (Environment.OSVersion.Version.Major >= 6)
{
m_Data.cbSize = Marshal.SizeOf(m_Data);
}
else
{
m_Data.cbSize = 504;
m_Data.uVersion = 10;
}
m_Data.uFlags = 0x01 | 0x02 | 0x04;
m_Data.hwnd = m_Handle;
m_Data.uCallbackMessage = WM_MyMessage;
m_Data.hIcon = Icon.Handle;
m_Data.uID = 0x0;
m_Data.szTip = Tip;
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if ((int)msg == WM_MyMessage)
{
if ((int)lParam == 0x201)
{
//Click ?
m_Window.Show();
m_Window.WindowState = m_storedWindowState;
}
}
return IntPtr.Zero;
}
public void ShowTrayIcon()
{
Shell_NotifyIcon(TRAY_ADD, ref m_Data);
}
public void HideTrayIcon()
{
Shell_NotifyIcon(TRAY_DELETE, ref m_Data);
}
void win_StateChanged(object sender, EventArgs e)
{
if (m_Window.WindowState == WindowState.Minimized)
{
m_Window.Hide();
ShowTrayIcon();
}
else
{
m_storedWindowState = m_Window.WindowState;
HideTrayIcon();
}
}
void win_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
HideTrayIcon();
}
void m_notifyIcon_Click(object sender, EventArgs e)
{
m_Window.Show();
m_Window.WindowState = m_storedWindowState;
}
}
}
[/codesyntax]




