2016-01-13 113 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