private SafeNotifyIconData GetTrayItemIconData(TrayItem trayItem) { SafeNotifyIconData nid = new SafeNotifyIconData(); nid.hWnd = trayItem.hWnd; nid.uID = trayItem.uID; nid.uCallbackMessage = trayItem.uCallbackMessage; nid.szTip = trayItem.szIconText; nid.hIcon = trayItem.hIcon; nid.uVersion = trayItem.uVersion; nid.guidItem = trayItem.guidItem; nid.dwState = (int)trayItem.dwState; nid.uFlags = NIF.GUID | NIF.MESSAGE | NIF.TIP | NIF.STATE; if (nid.hIcon != IntPtr.Zero) { nid.uFlags |= NIF.ICON; } else { ShellLogger.Warning($"ExplorerTrayService: Unable to use {trayItem.szIconText} icon handle for NOTIFYICONDATA struct"); } return(nid); }
public NotificationBalloon(SafeNotifyIconData nicData, NotifyIcon notifyIcon) { NotifyIcon = notifyIcon; Title = nicData.szInfoTitle; Info = nicData.szInfo; Flags = nicData.dwInfoFlags; Timeout = (int)nicData.uVersion; Received = DateTime.Now; if (Flags.HasFlag(NIIF.ERROR)) { Icon = GetSystemIcon(SystemIcons.Error.Handle); } else if (Flags.HasFlag(NIIF.INFO)) { Icon = GetSystemIcon(SystemIcons.Information.Handle); } else if (Flags.HasFlag(NIIF.WARNING)) { Icon = GetSystemIcon(SystemIcons.Warning.Handle); } else if (Flags.HasFlag(NIIF.USER)) { if (nicData.hBalloonIcon != 0) { SetIconFromHIcon((IntPtr)nicData.hBalloonIcon); } else if (nicData.hIcon != IntPtr.Zero) { SetIconFromHIcon(nicData.hIcon); } } }
private void GetTrayItems() { IntPtr toolbarHwnd = FindExplorerTrayToolbarHwnd(); if (toolbarHwnd == IntPtr.Zero) { return; } int count = GetNumTrayIcons(toolbarHwnd); if (count < 1) { return; } GetWindowThreadProcessId(toolbarHwnd, out var processId); IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, (int)processId); IntPtr hBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)Marshal.SizeOf(new TBBUTTON()), AllocationType.Commit, MemoryProtection.ReadWrite); for (int i = 0; i < count; i++) { TrayItem trayItem = GetTrayItem(i, hBuffer, hProcess, toolbarHwnd); if (trayItem.hWnd == IntPtr.Zero || !IsWindow(trayItem.hWnd)) { ShellLogger.Debug($"ExplorerTrayService: Ignored notify icon {trayItem.szIconText} due to invalid handle"); continue; } SafeNotifyIconData nid = GetTrayItemIconData(trayItem); if (trayDelegate != null) { if (!trayDelegate((uint)NIM.NIM_ADD, nid)) { ShellLogger.Debug("ExplorerTrayService: Ignored notify icon message"); } } else { ShellLogger.Debug("ExplorerTrayService: trayDelegate is null"); } } VirtualFreeEx(hProcess, hBuffer, 0, AllocationType.Release); CloseHandle((int)hProcess); }
private void handleBalloonData(SafeNotifyIconData nicData, NotifyIcon notifyIcon) { if (string.IsNullOrEmpty(nicData.szInfoTitle)) { return; } NotificationBalloon balloonInfo = new NotificationBalloon(nicData, notifyIcon); NotificationBalloonEventArgs args = new NotificationBalloonEventArgs { Balloon = balloonInfo }; ShellLogger.Debug($"NotificationArea: Received notification \"{balloonInfo.Title}\" for {notifyIcon.Title}"); NotificationBalloonShown?.Invoke(this, args); if (!args.Handled) { notifyIcon.TriggerNotificationBalloon(balloonInfo); } }
private bool SysTrayCallback(uint message, SafeNotifyIconData nicData) { if (nicData.hWnd == IntPtr.Zero) { return(false); } NotifyIcon trayIcon = new NotifyIcon(this, nicData.hWnd); trayIcon.UID = nicData.uID; lock (_lockObject) { if ((NIM)message == NIM.NIM_ADD || (NIM)message == NIM.NIM_MODIFY) { try { bool exists = false; bool titleChanged = false; // hide icons while we are shell which require UWP support & we have a separate implementation for if (nicData.guidItem == new Guid(VOLUME_GUID) && ((EnvironmentHelper.IsAppRunningAsShell && EnvironmentHelper.IsWindows10OrBetter) || GroupPolicyHelper.HideScaVolume)) { return(false); } // hide icons per group policy if ((nicData.guidItem == new Guid(HEALTH_GUID) && GroupPolicyHelper.HideScaHealth) || (nicData.guidItem == new Guid(MEETNOW_GUID) && GroupPolicyHelper.HideScaMeetNow) || (nicData.guidItem == new Guid(NETWORK_GUID) && GroupPolicyHelper.HideScaNetwork) || (nicData.guidItem == new Guid(POWER_GUID) && GroupPolicyHelper.HideScaPower)) { return(false); } foreach (NotifyIcon ti in TrayIcons) { if (ti.Equals(nicData)) { exists = true; trayIcon = ti; break; } } if ((NIF.STATE & nicData.uFlags) != 0) { trayIcon.IsHidden = nicData.dwState == 1; } if ((NIF.TIP & nicData.uFlags) != 0 && !string.IsNullOrEmpty(nicData.szTip)) { trayIcon.Title = nicData.szTip; titleChanged = true; } if ((NIF.ICON & nicData.uFlags) != 0) { if (nicData.hIcon != IntPtr.Zero) { System.Windows.Media.ImageSource icon = IconImageConverter.GetImageFromHIcon(nicData.hIcon, false); if (icon != null) { trayIcon.Icon = icon; } else if (icon == null && trayIcon.Icon == null) { // Use default only if we don't have a valid icon already trayIcon.Icon = IconImageConverter.GetDefaultIcon(); } } else { trayIcon.Icon = null; } } trayIcon.HWnd = nicData.hWnd; trayIcon.UID = nicData.uID; if ((NIF.GUID & nicData.uFlags) != 0) { trayIcon.GUID = nicData.guidItem; } if (nicData.uVersion > 0 && nicData.uVersion <= 4) { trayIcon.Version = nicData.uVersion; } if ((NIF.MESSAGE & nicData.uFlags) != 0) { trayIcon.CallbackMessage = nicData.uCallbackMessage; } if (!exists) { // default placement to a menu bar-like rect trayIcon.Placement = defaultPlacement; // set properties used for pinning trayIcon.Path = ShellHelper.GetPathForWindowHandle(trayIcon.HWnd); trayIcon.SetPinValues(); if (trayIcon.Icon == null) { trayIcon.Icon = IconImageConverter.GetDefaultIcon(); } TrayIcons.Add(trayIcon); if ((NIF.INFO & nicData.uFlags) != 0) { handleBalloonData(nicData, trayIcon); } ShellLogger.Debug($"NotificationArea: Added: {trayIcon.Title} Path: {trayIcon.Path} Hidden: {trayIcon.IsHidden} GUID: {trayIcon.GUID} UID: {trayIcon.UID} Version: {trayIcon.Version}"); if ((NIM)message == NIM.NIM_MODIFY) { // return an error to the notifyicon as we received a modify for an icon we did not yet have return(false); } } else { if ((NIF.INFO & nicData.uFlags) != 0) { handleBalloonData(nicData, trayIcon); } if (titleChanged && trayIcon.GUID == default && !trayIcon.IsPinned) { // set properties used for pinning trayIcon.SetPinValues(); } ShellLogger.Debug($"NotificationArea: Modified: {trayIcon.Title}"); } } catch (Exception ex) { ShellLogger.Error("NotificationArea: Unable to modify the icon in the collection.", ex); } } else if ((NIM)message == NIM.NIM_DELETE) { try { foreach (var icon in TrayIcons) { if (icon.Equals(trayIcon)) { TrayIcons.Remove(trayIcon); ShellLogger.Debug($"NotificationArea: Removed: {icon.Title}"); return(true); } } return(false); } catch (Exception ex) { ShellLogger.Error("NotificationArea: Unable to remove the icon from the collection.", ex); } } else if ((NIM)message == NIM.NIM_SETVERSION) { if (nicData.uVersion > 4) { return(false); } foreach (NotifyIcon ti in TrayIcons) { if (ti.Equals(nicData)) { ti.Version = nicData.uVersion; ShellLogger.Debug($"NotificationArea: Modified version to {ti.Version} on: {ti.Title}"); break; } } } } return(true); }
public bool Equals(SafeNotifyIconData other) { return((HWnd.Equals(other.hWnd) && UID.Equals(other.uID)) || (other.guidItem != Guid.Empty && GUID.Equals(other.guidItem))); }