2016-01-13 90 views
8

我这是推使用一些通知WPF桌面应用程序:如何显示气球提示,如Windows 10气球提示无拉伸图标

NotifyIcon.ShowBalloonTip(,,,ToolTipIcon.None)

的问题是:

的Windows 10使用新的“Windows 10的矩形用图片和文字”样式的气球通知(我不知道它是如何准确地调用)。

如果我是use ToolTipIcon.None参数,它会得到我的应用程序图标,该图标被设置为NotifyIcon.Icon属性并在此气球通知中显示它。而且这个图标是模糊的/拉伸的(就像拍了一个太小的图标并拉伸到这个气球图像需要的大小)。

我的ico文件包含几种尺寸:16*16, 32*32, 128*128, 256*256等。我已经尝试设置只有一个128*128大小的图标文件,但它不起作用。

它应该工作吗?

谢谢。

+0

你知道这是不可能的 – tofutim

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/ee330740(v=vs.85)。aspx#install_icon显示一个美丽的自定义图标,所以它是可能的 – tofutim

+0

对于问题的参考 - 请参阅http://stackoverflow.com/questions/35242400/windows-10-notifyicon-icon-always-looks-very-pixilated – tofutim

回答

2

下面的类应该在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说气球的图标应该很大。

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

甜 - 只是对这种方法感到厌烦 - 会检查它。 – tofutim