diff --git a/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs b/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs index ee76b649b..14e02686a 100644 --- a/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs +++ b/src/ST.Client.Desktop.Windows/Internals/UnmanagedMethods.cs @@ -1,4 +1,4 @@ -// Copyright (c) The Avalonia Project. All rights reserved. +// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. // Slightly modified and extended version for the use in SQRLDotNetClientUI @@ -19,7 +19,7 @@ namespace System public static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad); [DllImport("shell32", CharSet = CharSet.Auto)] - public static extern int Shell_NotifyIcon(NIM dwMessage, NOTIFYICONDATA lpData); + public static extern int Shell_NotifyIcon(NIM dwMessage, [In] ref NOTIFYICONDATA lpData); [DllImport("user32.dll")] public static extern void PostQuitMessage(int nExitCode); @@ -132,6 +132,46 @@ namespace System [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string szInfoTitle; public NIIF dwInfoFlags; + /// + /// 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. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string BalloonText; + /// + /// String containing a title for a balloon ToolTip. This title appears in boldface + /// above the text. It can have a maximum of 63 characters. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string BalloonTitle; + /// + /// Mainly used to set the version when is invoked + /// with . However, for legacy operations, + /// the same member is also used to set timeouts for balloon ToolTips. + /// + public uint VersionOrTimeout; + /// + /// Adds an icon to a balloon ToolTip, which is placed to the left of the title. If the + /// member is zero-length, the icon is not shown. + /// + public BalloonFlags BalloonFlags; + + /// + /// Windows XP (Shell32.dll version 6.0) and later.
+ /// - Windows 7 and later: A registered GUID that identifies the icon. + /// This value overrides uID and is the recommended method of identifying the icon.
+ /// - Windows XP through Windows Vista: Reserved. + ///
+ public Guid TaskbarIconGuid; + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The handle of a customized + /// balloon icon provided by the application that should be used independently + /// of the tray icon. If this member is non-NULL and the + /// flag is set, this icon is used as the balloon icon.
+ /// If this member is NULL, the legacy behavior is carried out. + ///
+ public IntPtr CustomBalloonIconHandle; } public enum NIM : uint @@ -2103,6 +2143,65 @@ namespace System } } + /// + /// Flags that define the icon that is shown on a balloon + /// tooltip. + /// + public enum BalloonFlags + { + /// + /// No icon is displayed. + /// + None = 0x00, + + /// + /// An information icon is displayed. + /// + Info = 0x01, + + /// + /// A warning icon is displayed. + /// + Warning = 0x02, + + /// + /// An error icon is displayed. + /// + Error = 0x03, + + /// + /// Windows XP Service Pack 2 (SP2) and later. + /// Use a custom icon as the title icon. + /// + User = 0x04, + + /// + /// Windows XP (Shell32.dll version 6.0) and later. + /// Do not play the associated sound. Applies only to balloon ToolTips. + /// + NoSound = 0x10, + + /// + /// Windows Vista (Shell32.dll version 6.0.6) and later. The large version + /// of the icon should be used as the balloon icon. This corresponds to the + /// icon with dimensions SM_CXICON x SM_CYICON. If this flag is not set, + /// the icon with dimensions XM_CXSMICON x SM_CYSMICON is used.
+ /// - This flag can be used with all stock icons.
+ /// - Applications that use older customized icons (NIIF_USER with hIcon) must + /// provide a new SM_CXICON x SM_CYICON version in the tray icon (hIcon). These + /// icons are scaled down when they are displayed in the System Tray or + /// System Control Area (SCA).
+ /// - New customized icons (NIIF_USER with hBalloonIcon) must supply an + /// SM_CXICON x SM_CYICON version in the supplied icon (hBalloonIcon). + ///
+ LargeIcon = 0x20, + + /// + /// Windows 7 and later. + /// + RespectQuietTime = 0x80 + } + [Flags] internal enum DropEffect : int { diff --git a/src/ST.Client.Desktop.Windows/Services/Implementation/PlatformNotificationServiceImpl.cs b/src/ST.Client.Desktop.Windows/Services/Implementation/PlatformNotificationServiceImpl.cs index 26cc862f2..7aeeedc4e 100644 --- a/src/ST.Client.Desktop.Windows/Services/Implementation/PlatformNotificationServiceImpl.cs +++ b/src/ST.Client.Desktop.Windows/Services/Implementation/PlatformNotificationServiceImpl.cs @@ -26,7 +26,6 @@ namespace System.Application.Services.Implementation { title ??= ThisAssembly.AssemblyTrademark; // 调用托盘显示通知 - throw new NotImplementedException(title); } public Progress NotifyDownload(string text, NotificationType notificationType, string? title) diff --git a/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs b/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs index fcb8c9768..b7b2d2c2a 100644 --- a/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs +++ b/src/ST.Client.Desktop.Windows/UI/NotifyIcon.cs @@ -20,6 +20,11 @@ namespace System.Application.UI string _toolTipText = string.Empty; bool _visible = false; bool _doubleClick = false; + /// + /// Represents the current icon data. + /// + private UnmanagedMethods.NOTIFYICONDATA iconData; + public event EventHandler? Click; public event EventHandler? DoubleClick; @@ -131,6 +136,15 @@ namespace System.Application.UI ~NotifyIcon() { + iconData = new UnmanagedMethods.NOTIFYICONDATA() + { + hWnd = _window.Handle, + uID = _uID, + uFlags = UnmanagedMethods.NIF.TIP | UnmanagedMethods.NIF.MESSAGE, + uCallbackMessage = (int)UnmanagedMethods.CustomWindowsMessage.WM_TRAYMOUSE, + hIcon = IntPtr.Zero, + szTip = ToolTipText + }; UpdateIcon(remove: true); } @@ -141,15 +155,6 @@ namespace System.Application.UI void UpdateIcon(bool remove = false) { if (_window == null) throw new ArgumentNullException(nameof(_window)); - UnmanagedMethods.NOTIFYICONDATA iconData = new UnmanagedMethods.NOTIFYICONDATA() - { - hWnd = _window.Handle, - uID = _uID, - uFlags = UnmanagedMethods.NIF.TIP | UnmanagedMethods.NIF.MESSAGE, - uCallbackMessage = (int)UnmanagedMethods.CustomWindowsMessage.WM_TRAYMOUSE, - hIcon = IntPtr.Zero, - szTip = ToolTipText - }; if (!remove && _icon != null && Visible) { @@ -158,17 +163,17 @@ namespace System.Application.UI if (!_iconAdded) { - _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.ADD, iconData); + _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.ADD,ref iconData); _iconAdded = true; } else { - _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY, iconData); + _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY,ref iconData); } } else { - _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.DELETE, iconData); + _ = UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.DELETE,ref iconData); _iconAdded = false; } } @@ -242,6 +247,37 @@ namespace System.Application.UI } } + public void ShowBalloonTip(string title, string message, BalloonFlags flags, IntPtr balloonIconHandle) + { + iconData = new UnmanagedMethods.NOTIFYICONDATA() + { + hWnd = _window.Handle, + uID = _uID, + uFlags = UnmanagedMethods.NIF.TIP | UnmanagedMethods.NIF.MESSAGE, + uCallbackMessage = (int)UnmanagedMethods.CustomWindowsMessage.WM_TRAYMOUSE, + hIcon = IntPtr.Zero, + szTip = ToolTipText + }; + + iconData.BalloonText = message ?? string.Empty; + iconData.BalloonTitle = title ?? string.Empty; + + iconData.BalloonFlags = flags; + iconData.CustomBalloonIconHandle = balloonIconHandle; + + UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY,ref iconData); + } + + /// + /// Hides a balloon ToolTip, if any is displayed. + /// + public void HideBalloonTip() + { + // reset balloon by just setting the info to an empty string + iconData.BalloonText = iconData.BalloonTitle = string.Empty; + UnmanagedMethods.Shell_NotifyIcon(UnmanagedMethods.NIM.MODIFY, ref iconData); + } + /// /// Handles the NotifyIcon-specific window messages sent by the notification icon. ///