using System; using System.Drawing; using System.Runtime.InteropServices; using TaskbarLib.Interop; namespace TaskbarLib.DesktopIntegration { /// /// The primary coordinator of the Windows 7 taskbar-related activities. /// For additional functionality, see the JumpListManager /// and ThumbButtonManager classes. /// public static class Windows7Taskbar { #region Infrastructure /// /// The WM_TaskbarButtonCreated message number. /// public static uint TaskbarButtonCreatedMessage { get { return UnsafeNativeMethods.WM_TaskbarButtonCreated; } } // Use thread static to work around COM threading issues. [ThreadStatic] private static ITaskbarList3 _taskbarList; internal static ITaskbarList3 TaskbarList { get { if (_taskbarList == null) { _taskbarList = (ITaskbarList3)new CTaskbarList(); _taskbarList.HrInit(); } return _taskbarList; } } private static IPropertyStore InternalGetWindowPropertyStore(IntPtr hwnd) { IPropertyStore propStore; int rc = UnsafeNativeMethods.SHGetPropertyStoreForWindow(hwnd, ref SafeNativeMethods.IID_IPropertyStore, out propStore); if (rc != 0) throw Marshal.GetExceptionForHR(rc); return propStore; } private static void InternalEnableCustomWindowPreview(IntPtr hwnd, bool enable) { int t = enable ? 1 : 0; int rc; rc = UnsafeNativeMethods.DwmSetWindowAttribute(hwnd, SafeNativeMethods.DWMWA_HAS_ICONIC_BITMAP, ref t, 4); if (rc != 0) throw Marshal.GetExceptionForHR(rc); rc = UnsafeNativeMethods.DwmSetWindowAttribute(hwnd, SafeNativeMethods.DWMWA_FORCE_ICONIC_REPRESENTATION, ref t, 4); if (rc != 0) throw Marshal.GetExceptionForHR(rc); } #endregion #region Application Id /// /// Gets a window's application id by its window handle. /// /// The window handle. /// The application id of that window. public static string GetWindowAppId(IntPtr hwnd) { IPropertyStore propStore = InternalGetWindowPropertyStore(hwnd); PropVariant pv; propStore.GetValue(ref PropertyKey.PKEY_AppUserModel_ID, out pv); Marshal.ReleaseComObject(propStore); return pv.GetValue(); } /// /// Sets the window's application id by its window handle. /// /// The window handle. /// The application id. public static void SetWindowAppId(IntPtr hwnd, string appId) { IPropertyStore propStore = InternalGetWindowPropertyStore(hwnd); PropVariant pv = new PropVariant(); pv.SetValue(appId); propStore.SetValue(ref PropertyKey.PKEY_AppUserModel_ID, ref pv); Marshal.ReleaseComObject(propStore); } /// /// Sets the current process' explicit application user model id. /// /// The application id. public static void SetCurrentProcessAppId(string appId) { UnsafeNativeMethods.SetCurrentProcessExplicitAppUserModelID(appId); } /// /// Gets the current process' explicit application user model id. /// /// The application id. public static string GetCurrentProcessAppId() { string appId; UnsafeNativeMethods.GetCurrentProcessExplicitAppUserModelID(out appId); return appId; } #endregion #region DWM Iconic Thumbnail and Peek Bitmap /// /// Indicates that the specified window requests the DWM /// to demand live preview (thumbnail and peek) mode when necessary /// instead of relying on default preview. /// /// The window handle. public static void EnableCustomWindowPreview(IntPtr hwnd) { InternalEnableCustomWindowPreview(hwnd, true); } /// /// Indicates that the specified window does not require the DWM /// to demand live preview (thumbnail and peek) mode when necessary, /// i.e. this window relies on default preview. /// /// The window handle. public static void DisableCustomWindowPreview(IntPtr hwnd) { InternalEnableCustomWindowPreview(hwnd, false); } /// /// Sets the specified iconic thumbnail for the specified window. /// This is typically done in response to a DWM message. /// /// The window handle. /// The thumbnail bitmap. public static void SetIconicThumbnail(IntPtr hwnd, Bitmap bitmap) { int rc = UnsafeNativeMethods.DwmSetIconicThumbnail(hwnd, bitmap.GetHbitmap(), SafeNativeMethods.DWM_SIT_DISPLAYFRAME); if (rc != 0) throw Marshal.GetExceptionForHR(rc); } /// /// Sets the specified peek (live preview) bitmap for the specified /// window. This is typically done in response to a DWM message. /// /// The window handle. /// The thumbnail bitmap. /// Whether to display a standard window /// frame around the bitmap. public static void SetPeekBitmap(IntPtr hwnd, Bitmap bitmap, bool displayFrame) { int rc = UnsafeNativeMethods.DwmSetIconicLivePreviewBitmap(hwnd, bitmap.GetHbitmap(), IntPtr.Zero, displayFrame ? SafeNativeMethods.DWM_SIT_DISPLAYFRAME : (uint)0); if (rc != 0) throw Marshal.GetExceptionForHR(rc); } /// /// Sets the specified peek (live preview) bitmap for the specified /// window. This is typically done in response to a DWM message. /// /// The window handle. /// The thumbnail bitmap. /// The client area offset at which to display /// the specified bitmap. The rest of the parent window will be /// displayed as "remembered" by the DWM. /// Whether to display a standard window /// frame around the bitmap. public static void SetPeekBitmap(IntPtr hwnd, Bitmap bitmap, Point offset, bool displayFrame) { var nativePoint = new POINT(offset.X, offset.Y); int rc = UnsafeNativeMethods.DwmSetIconicLivePreviewBitmap(hwnd, bitmap.GetHbitmap(), ref nativePoint, displayFrame ? SafeNativeMethods.DWM_SIT_DISPLAYFRAME : (uint)0); if (rc != 0) throw Marshal.GetExceptionForHR(rc); } #endregion #region Taskbar Overlay Icon /// /// Draws the specified overlay icon on the specified window's /// taskbar button. /// /// The window handle. /// The overlay icon. /// The overlay icon description. public static void SetTaskbarOverlayIcon(IntPtr hwnd, Icon icon, string description) { TaskbarList.SetOverlayIcon( hwnd, icon == null ? IntPtr.Zero : icon.Handle, description); } #endregion #region Taskbar Progress Bar /// /// Represents the thumbnail progress bar state. /// public enum ThumbnailProgressState { /// /// No progress is displayed. /// NoProgress = 0, /// /// The progress is indeterminate (marquee). /// Indeterminate = 0x1, /// /// Normal progress is displayed. /// Normal = 0x2, /// /// An error occurred (red). /// Error = 0x4, /// /// The operation is paused (yellow). /// Paused = 0x8 } /// /// Sets the progress state of the specified window's /// taskbar button. /// /// The window handle. /// The progress state. public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state) { TaskbarList.SetProgressState(hwnd, (TBPFLAG)state); } /// /// Sets the progress value of the specified window's /// taskbar button. /// /// The window handle. /// The current value. /// The maximum value. public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum) { TaskbarList.SetProgressValue(hwnd, current, maximum); } #endregion #region Taskbar Thumbnails /// /// Specifies that only a portion of the window's client area /// should be used in the window's thumbnail. /// /// The window. /// The rectangle that specifies the clipped region. public static void SetThumbnailClip(IntPtr hwnd, Rectangle clipRect) { RECT rect = new RECT(clipRect.Left, clipRect.Top, clipRect.Right, clipRect.Bottom); TaskbarList.SetThumbnailClip(hwnd, ref rect); } /// /// Sets the specified window's thumbnail tooltip. /// /// The window. /// The tooltip text. public static void SetThumbnailTooltip(IntPtr hwnd, string tooltip) { TaskbarList.SetThumbnailTooltip(hwnd, tooltip); } #endregion #region Miscellaneous /// /// Specifies that the taskbar- and DWM-related windows messages should /// pass through the Windows UIPI mechanism even if the process is /// running elevated. Calling this method is not required unless the /// process is running elevated. /// public static void AllowTaskbarWindowMessagesThroughUipi() { UnsafeNativeMethods.ChangeWindowMessageFilter(UnsafeNativeMethods.WM_TaskbarButtonCreated, SafeNativeMethods.MSGFLT_ADD); UnsafeNativeMethods.ChangeWindowMessageFilter(SafeNativeMethods.WM_DWMSENDICONICTHUMBNAIL, SafeNativeMethods.MSGFLT_ADD); UnsafeNativeMethods.ChangeWindowMessageFilter(SafeNativeMethods.WM_DWMSENDICONICLIVEPREVIEWBITMAP, SafeNativeMethods.MSGFLT_ADD); UnsafeNativeMethods.ChangeWindowMessageFilter(SafeNativeMethods.WM_COMMAND, SafeNativeMethods.MSGFLT_ADD); UnsafeNativeMethods.ChangeWindowMessageFilter(SafeNativeMethods.WM_SYSCOMMAND, SafeNativeMethods.MSGFLT_ADD); UnsafeNativeMethods.ChangeWindowMessageFilter(SafeNativeMethods.WM_ACTIVATE, SafeNativeMethods.MSGFLT_ADD); } #endregion } }