如何在不拉伸图标的情况下显示类似Windows 10的气球提示

如何在不拉伸图标的情况下显示类似Windows 10的气球提示,windows,notifyicon,Windows,Notifyicon,我有一个WPF桌面应用程序,它正在使用以下方式推送一些通知: NotifyIcon.showBallootTip(,,ToolTipIcon.None) 问题是: Windows10使用新的“带图像和文本的Windows10矩形”样式进行气泡通知(我不知道它的确切名称) 如果我使用ToolTipIcon.None参数,它将获取设置为NotifyIcon.icon属性的我的应用程序图标,并将其显示在此气球通知中。该图标模糊/拉伸(例如拍摄了太小的图标,并拉伸到该气球图像所需的大小) 我的ico文件

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

NotifyIcon.showBallootTip(,,ToolTipIcon.None)

问题是:

Windows10使用新的“带图像和文本的Windows10矩形”样式进行气泡通知(我不知道它的确切名称)

如果我
使用ToolTipIcon.None
参数,它将获取设置为
NotifyIcon.icon
属性的我的应用程序图标,并将其显示在此气球通知中。该图标模糊/拉伸(例如拍摄了太小的图标,并拉伸到该气球图像所需的大小)

我的ico文件包含多个大小:
16*16、32*32、128*128、256*256
等。我已经尝试将图标文件设置为只有一个
128*128
大小,但无效

它到底应该起作用吗


谢谢。

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

原始NotifyIcon类与此类之间的关键更改是:

  • 添加(和使用)notifyiconda.hBalloonIcon成员
  • 设置
    notifyiconda.dwInfoFlags=NIIF_LARGE_ICON | NIIF_USER
    ,而不是
    NIIF_NONE
  • 您可以阅读NOTIFYICONDATA结构的详细信息,但要点如下:

    • hBalloonIcon
      是在Vista中添加的,专门用于系统托盘之外
    • NIIF\u用户
      说使用
      hBalloonIcon
      中的图标作为气球图标
    • NIIF\u LARGE\u图标
      表示气球的图标应该是大的
    NotifyIconLarge类:

    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();
    

    你知道这是可能的,这是不可能的显示一个美丽的自定义图标,所以它是有可能的问题参考-见甜-只是害怕这种方法-将检查它。