當第一次使用Windows 7 時,工作列(Taskbar)的改變可以說讓我眼前一亮。在以前版本Windows 案頭功能的基礎上,Windows 7 工作列為我們增添了許多其他功能:Jump Lists,Window Preview,Process Bar,Overlay Icon 等等。
新工作列的功能使我們的操作更加方便快捷,在參加北京.Net俱樂部舉辦的“Windows 7 發布”活動時初步瞭解到有關應用程式支援Windows 7 工作列特性方面的內容。那麼作為一名開發人員我們的應用程式能否實現這些功能呢?答案當然是“可以”,微軟提供了方便的工具Windows API Code Pack for .NET Framework 來協助我們完成這些開發。
本篇主要示範Overlay Icon(MSDN上直譯為“覆蓋表徵圖”)的功能,從字面上來看也許不太明白這是什麼意思,在Windows 7 中UAC 功能為系統增加了安全性,當UAC 啟動時有些應用程式的表徵圖上方會顯示一個盾牌標誌(如),沒錯這個就是Overlay Icon 功能,下面就來看看它是如何?的。
準備工作
1. 添加一些Overlay Icon 圖片(.ico)到項目Resources 中。
2. 下載Windows API Code Pack,增加Microsoft.WindowsAPICodePack.dll 和Microsoft.WindowsAPICodePack.Shell.dll。
3. 引用Microsoft.WindowsAPICodePack.Taskbar 命名空間。
TaskbarManager.SetOverlayIcon(Icon, String) 方法
TaskbarManager 類提供了一些常用的工作列特性設定方法,其中SetOverlayIcon 方法有三種不同的方式來設定Overlay Icon:
//用於應用程式主視窗public void SetOverlayIcon(System.Drawing.Icon icon, string accessibilityText){ CoreHelpers.ThrowIfNotWin7(); TaskbarList.SetOverlayIcon(OwnerHandle,
icon != null ? icon.Handle : IntPtr.Zero, accessibilityText);}//用於指定視窗public void SetOverlayIcon(IntPtr windowHandle, System.Drawing.Icon icon,
string accessibilityText){ CoreHelpers.ThrowIfNotWin7(); TaskbarList.SetOverlayIcon(windowHandle,
icon != null ? icon.Handle : IntPtr.Zero, accessibilityText);}//用於指定的WPF視窗public void SetOverlayIcon(System.Windows.Window window,
System.Drawing.Icon icon, string accessibilityText){ CoreHelpers.ThrowIfNotWin7(); TaskbarList.SetOverlayIcon( (new WindowInteropHelper(window)).Handle, icon != null ? icon.Handle : IntPtr.Zero, accessibilityText);}
在程式中通過TaskbarManager.Instance.SetOverlayIcon() 即可實現Overlay Icon 效果:
Icon icon = iconList.SelectedItem as Icon;TaskbarManager.Instance.SetOverlayIcon(icon, "Overlay Icon Demo");
如果將Icon 和 String 都設為Null 則取消Overlay Icon 效果:
TaskbarManager.Instance.SetOverlayIcon(null, null);
單視窗樣本
程式運行後的狀態:
在表徵圖列表中選擇Overlay Icon 後的不同效果:
多視窗樣本
在預設情況下,如果從父視窗中調出子視窗,其工作列表徵圖是組合疊加在一起的(如):
如果想為不同的視窗中實現Overlay Icon 則首先需要通過修改TestWindow 的Application ID (AppID)將兩個視窗的工作列表徵圖分離開。每個啟動並執行視窗都會有各自的AppID,用來決定工作列表徵圖屬於哪個視窗。這也就是為什麼當我們開啟多個Word 文檔或IE 標籤後工作列表徵圖都是自動疊加在一起的,所以我們可以通過修改視窗的AppID 使工作列表徵圖分開顯示。
通過使用TaskbarManager.SetApplicationIdForSpecificWindow(IntPtr windowHandle,String appID) 方法可以修改視窗的AppID。但是目前下載的Windows API 1.0.1 版本有些小問題,使得SetApplicationIdForSpecificWindow 方法根本不起作用。根源就在TaskbarNativeMethods.cs 的SetWindowProperty 方法,沒有對pv 進行任何賦值操作,導致propStore 根本沒有值,所以在該方法中增加pv.SetString(value),重新編譯並替換掉原來的Microsoft.WindowsAPICodePack.Shell.dll 即可:
internal static void SetWindowProperty(IntPtr hwnd, PropertyKey propkey,
string value){ // Get the IPropertyStore for the given window handle IPropertyStore propStore = GetWindowPropertyStore(hwnd); // Set the value PropVariant pv = new PropVariant(); pv.SetString(value); propStore.SetValue(ref propkey, ref pv); // Dispose the IPropertyStore and PropVariant Marshal.ReleaseComObject(propStore); pv.Clear();}
程式改好後,就可以使用SetApplicationIdForSpecificWindow(IntPtr, String) 幹活了:
Window newWindow = new TestWindow();newWindow.Show();WindowInteropHelper helper = new WindowInteropHelper(newWindow);IntPtr ptr = helper.Handle; TaskbarManager.Instance.SetApplicationIdForSpecificWindow(ptr, "AppID");
修改了TestWindow 的AppID,兩個視窗的工作列表徵圖才真正的完成了分離:
通過SetOverlayIcon(IntPtr, Icon, String) 來設定指定視窗(TestWindow)的Overlay Icon:
TaskbarManager.Instance.SetOverlayIcon(ptr, icon, "Overlay Icon Demo");
分離後再來看看效果,只顯示MainWindow 表徵圖:
兩個視窗的表徵圖都顯示:
相關參考資料
1. Windows 7 New Taskbar - An Overview
http://channel9.msdn.com/posts/yochay/Windows-7-New-Taskbar-an-overview/
2. The Windows 7 Taskbar
http://blogs.msdn.com/e7/archive/2008/11/20/happy-anniversary-windows-on-the-evolution-of-the-taskbar.aspx
3. Windows API Code Pack for .NET Framework
http://code.msdn.microsoft.com/WindowsAPICodePack
4. Introducing The Taskbar APIs
http://msdn.microsoft.com/en-us/magazine/dd942846.aspx
5. Windows 7 Taskbar Dynamic Overlay Icons and Progress Bars
http://windowsteamblog.com/blogs/developers/archive/2009/07/28/windows-7-taskbar-dynamic-overlay-icons-and-progress-bars.aspx
6. Coding 4 Fun - Windows 7 Taskbar
http://blogs.msdn.com/coding4fun/archive/2009/08/18/9874533.aspx
原始碼下載