windows - 如何在没有拉伸(stretch)图标的情况下显示像 Windows 10 气球提示一样的气球提示

标签 windows notifyicon

我有 WPF 桌面应用程序,它使用以下方式推送一些通知:

NotifyIcon.ShowBalloonTip(,,,ToolTipIcon.None)

问题是:

Windows 10 使用新的“带有图像和文本的 Windows 10 矩形”样式用于气球通知(我不知道它的确切名称)。

如果我使用 ToolTipIcon.None 参数,它会获取设置为 NotifyIcon.Icon 属性的我的应用程序图标,并在此气球通知中显示它。这个图标是模糊的/拉伸(stretch)的(就像太小的图标被拉伸(stretch)到这个气球图像所需的大小)。

我的 ico 文件包含几种尺寸:16*16、32*32、128*128、256*256 等。我已经尝试过只用一个 设置图标文件128*128 大小,但是没用。

它应该有效吗?

谢谢。

最佳答案

下面的类应该在 Windows 10 的气球提示中显示一个平滑的大图标。它绝不是完美的,但它应该证明这个概念。很大一部分代码是直接从反编译的 Microsoft NotifyIcon 类中复制的。

原始 NotifyIcon 类与此之间的主要变化是:

  1. 添加(和使用)NOTIFYICONDATA.hBalloonIcon 成员。
  2. 的设置nOTIFYICONDATA.dwInfoFlags = NIIF_LARGE_ICON | NIIF_USER,而不是 NIIF_NONE

您可以阅读 NOTIFYICONDATA 结构的细节 here , 但要点是:

  • hBalloonIcon 是在 Vista 中添加的,专门用于系统托盘之外。
  • NIIF_USER 表示使用 hBalloonIcon 中的图标作为气球图标。
  • NIIF_LARGE_ICON 表示气球的图标应该很大。

NotifyIcon大类:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace BalloonNotification
{
    public class NotifyIconLarge : IDisposable
    {
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        public static extern int Shell_NotifyIcon(int message, NOTIFYICONDATA pnid);

        [DllImport("Comctl32.dll", CharSet = CharSet.Unicode)]
        private static extern IntPtr LoadIconWithScaleDown(IntPtr hinst, string pszName, int cx, int cy, out IntPtr phico);

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool DestroyIcon(IntPtr hIcon);

        private const int NIIF_LARGE_ICON = 0x00000020;
        private const int NIIF_USER = 0x00000004;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class NOTIFYICONDATA
        {
            public int cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA));
            public IntPtr hWnd;
            public int uID;
            public int uFlags;
            public int uCallbackMessage;
            public IntPtr hIcon;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string szTip;
            public int dwState;
            public int dwStateMask;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string szInfo;
            public int uTimeoutOrVersion;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string szInfoTitle;
            public int dwInfoFlags;
            Guid guidItem;
            public IntPtr hBalloonIcon;
        }

        private IntPtr _windowHandle;
        private IntPtr _hIcon;
        private bool _added;
        private int _id = 1;
        private string _tipText;

        public NotifyIconLarge(IntPtr windowHandle, string iconFile, int iconSize, string tipText)
        {
            _windowHandle = windowHandle;
            _tipText = tipText;
            IntPtr result = LoadIconWithScaleDown(IntPtr.Zero, iconFile, iconSize, iconSize, out _hIcon);
            UpdateIcon(true);
        }

        private void UpdateIcon(bool showIconInTray)
        {
            NOTIFYICONDATA nOTIFYICONDATA = new NOTIFYICONDATA();
            nOTIFYICONDATA.uCallbackMessage = 2048;
            nOTIFYICONDATA.uFlags = 1;
            nOTIFYICONDATA.hWnd = _windowHandle;
            nOTIFYICONDATA.uID = _id;
            nOTIFYICONDATA.hIcon = IntPtr.Zero;
            nOTIFYICONDATA.szTip = null;
            if (_hIcon != IntPtr.Zero)
            {
                nOTIFYICONDATA.uFlags |= 2;
                nOTIFYICONDATA.hIcon = _hIcon;
            }
            nOTIFYICONDATA.uFlags |= 4;
            nOTIFYICONDATA.szTip = _tipText;
            nOTIFYICONDATA.hBalloonIcon = _hIcon;
            if (showIconInTray && _hIcon != IntPtr.Zero)
            {
                if (!_added)
                {
                    Shell_NotifyIcon(0, nOTIFYICONDATA);
                    _added = true;
                }
                else
                {
                    Shell_NotifyIcon(1, nOTIFYICONDATA);
                }
            }
            else
            {
                if (_added)
                {
                    Shell_NotifyIcon(2, nOTIFYICONDATA);
                    _added = false;
                }
            }
        }

        public void ShowBalloonTip(int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon)
        {
            NOTIFYICONDATA nOTIFYICONDATA = new NOTIFYICONDATA();
            nOTIFYICONDATA.hWnd = _windowHandle;
            nOTIFYICONDATA.uID = _id;
            nOTIFYICONDATA.uFlags = 16;
            nOTIFYICONDATA.uTimeoutOrVersion = timeout;
            nOTIFYICONDATA.szInfoTitle = tipTitle;
            nOTIFYICONDATA.szInfo = tipText;
            switch (tipIcon)
            {
                case ToolTipIcon.None:
                    nOTIFYICONDATA.dwInfoFlags = NIIF_LARGE_ICON | NIIF_USER;
                    break;
                case ToolTipIcon.Info:
                    nOTIFYICONDATA.dwInfoFlags = 1;
                    break;
                case ToolTipIcon.Warning:
                    nOTIFYICONDATA.dwInfoFlags = 2;
                    break;
                case ToolTipIcon.Error:
                    nOTIFYICONDATA.dwInfoFlags = 3;
                    break;
            }
            int ret = Shell_NotifyIcon(1, nOTIFYICONDATA);
        }

        public void RemoveFromTray()
        {
            UpdateIcon(false);
            if (_hIcon != IntPtr.Zero)
                DestroyIcon(_hIcon);
        }

        ~NotifyIconLarge()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Dispose(bool disposing)
        {
            RemoveFromTray();
        }
    }
}

在某处声明:

private NotifyIconLarge _nil;

然后像这样使用它:

string fileName = @"C:\path_to_some_icon.ico";
_nil = new NotifyIconLarge(Handle, fileName, 64, "Icon Tip");
_nil.ShowBalloonTip(10000, "Balloon Title", "Balloon Text", ToolTipIcon.None);

完成后,移除托盘图标:

_nil.RemoveFromTray();

关于windows - 如何在没有拉伸(stretch)图标的情况下显示像 Windows 10 气球提示一样的气球提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34760898/

相关文章:

c# - .NET/Windows Server 中的最大传出套接字连接数

c# - 处理时动画托盘图标

c# - NotifyIcon 显示来自程序的消息

c# - 将文本而不是图标写入系统托盘

c++ - 在类函数中将参数传递给 _beginthread

python - 从本地 linux 文件夹移动到使用 cifs 挂载的 windows 共享

c++ - 让 DLL 而不是应用程序崩溃

windows - 从 Wix 安装 .NET Framework

c# - NotifyIcon MouseDown MouseEventArgs 没有位置数据

c# - 托盘图标动画