/*
* Process Hacker -
* ProcessHacker Taskbar Extensions
*
* Copyright (C) 2009 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see .
*
*/
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ProcessHacker;
using ProcessHacker.Native;
using ProcessHacker.Native.Api;
using TaskbarLib.Interop;
namespace TaskbarLib
{
///
/// 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
// 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();
HResult result = _taskbarList.HrInit();
result.ThrowIf();
}
return _taskbarList;
}
}
///
/// Creates a jump list manager for this form.
///
/// An object of type
/// that can be used to manage the application's jump list.
public static JumpListManager CreateJumpListManager()
{
return new JumpListManager();
}
private static IPropertyStore InternalGetWindowPropertyStore(IntPtr hwnd)
{
IPropertyStore propStore;
HResult shGetPropertyStoreResult = UnsafeNativeMethods.SHGetPropertyStoreForWindow(
hwnd, ref SafeNativeMethods.IID_IPropertyStore, out propStore);
shGetPropertyStoreResult.ThrowIf();
return propStore;
}
private static void InternalEnableCustomWindowPreview(IntPtr hwnd, bool enable)
{
int t = enable ? 1 : 0;
HResult setFirstAttributeResult = UnsafeNativeMethods.DwmSetWindowAttribute(
hwnd, SafeNativeMethods.DWMWA_HAS_ICONIC_BITMAP, ref t, 4);
setFirstAttributeResult.ThrowIf();
HResult setSecondAttributeResult = UnsafeNativeMethods.DwmSetWindowAttribute(
hwnd, SafeNativeMethods.DWMWA_FORCE_ICONIC_REPRESENTATION, ref t, 4);
setSecondAttributeResult.ThrowIf();
}
#endregion
#region Application Id
///
/// Gets/Sets the Taskbar window's application id.
///
public static string AppId
{
get
{
IPropertyStore propStore = InternalGetWindowPropertyStore(Program.HackerWindowHandle);
PropVariant pv;
HResult getValueResult = propStore.GetValue(ref PropertyKey.PKEY_AppUserModel_ID, out pv);
getValueResult.ThrowIf();
string appId = pv.GetValue();
Marshal.ReleaseComObject(propStore);
pv.Dispose();
return appId;
}
set
{
IPropertyStore propStore = InternalGetWindowPropertyStore(Program.HackerWindowHandle);
PropVariant pv = new PropVariant();
pv.SetValue(value);
HResult setValueResult = propStore.SetValue(ref PropertyKey.PKEY_AppUserModel_ID, ref pv);
setValueResult.ThrowIf();
Marshal.ReleaseComObject(propStore);
pv.Dispose();
}
}
///
/// Gets/Sets the current process' explicit application usermode id.
///
public static string ProcessAppId
{
get
{
string appId;
HResult getProcessAppUserModeIDResult = UnsafeNativeMethods.GetCurrentProcessExplicitAppUserModelID(out appId);
getProcessAppUserModeIDResult.ThrowIf();
return appId;
}
set
{
HResult setProcessAppUserModeIDResult = UnsafeNativeMethods.SetCurrentProcessExplicitAppUserModelID(value);
setProcessAppUserModeIDResult.ThrowIf();
}
}
#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.
///
public static void EnableCustomWindowPreview(this Form form)
{
InternalEnableCustomWindowPreview(form.Handle, 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.
///
public static void DisableCustomWindowPreview(this Form form)
{
InternalEnableCustomWindowPreview(form.Handle, false);
}
///
/// Sets the specified iconic thumbnail for the specified window.
/// This is typically done in response to a DWM message.
///
/// The thumbnail bitmap.
public static void SetIconicThumbnail(this Form form, Bitmap bitmap)
{
HResult dwmSetIconicThumbnailResult = UnsafeNativeMethods.DwmSetIconicThumbnail(
form.Handle, bitmap.GetHbitmap(), SafeNativeMethods.DWM_SIT_DISPLAYFRAME);
dwmSetIconicThumbnailResult.ThrowIf();
}
///
/// Sets the specified peek (live preview) bitmap for the specified
/// window. This is typically done in response to a DWM message.
///
/// The thumbnail bitmap.
/// Whether to display a standard window
/// frame around the bitmap.
public static void SetPeekBitmap(this Form form, Bitmap bitmap, bool displayFrame)
{
HResult dwmSetIconicLivePreviewBitmapResult = UnsafeNativeMethods.DwmSetIconicLivePreviewBitmap(
form.Handle, bitmap.GetHbitmap(), IntPtr.Zero, displayFrame ? SafeNativeMethods.DWM_SIT_DISPLAYFRAME : (uint)0);
dwmSetIconicLivePreviewBitmapResult.ThrowIf();
}
///
/// 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(this Form form, Bitmap bitmap, Point offset, bool displayFrame)
{
var nativePoint = new POINT(offset.X, offset.Y);
HResult dwmSetIconicLivePreviewResult =
UnsafeNativeMethods.DwmSetIconicLivePreviewBitmap(
form.Handle, bitmap.GetHbitmap(), ref nativePoint, displayFrame ? SafeNativeMethods.DWM_SIT_DISPLAYFRAME : (uint)0);
dwmSetIconicLivePreviewResult.ThrowIf();
}
#endregion
#region Taskbar Overlay Icon
///
/// Draws the specified overlay icon on the specified window's
/// taskbar button.
///
/// The overlay icon.
/// The overlay icon description.
public static void SetTaskbarOverlayIcon(Icon icon, string description)
{
TaskbarList.SetOverlayIcon(
Program.HackerWindowHandle, icon == null ? IntPtr.Zero : icon.Handle, description);
}
public static void SetTaskbarOverlayIcon(this Form form, Icon icon, string description)
{
TaskbarList.SetOverlayIcon(
form.Handle, icon == null ? IntPtr.Zero : icon.Handle, description);
}
#endregion
#region Taskbar Progress Bar
///
/// Sets the progress bar in the containing form's taskbar button
/// to this progress bar's progress.
///
/// The progress bar.
public static void SetTaskbarProgress(this Form form, ProgressBar progressBar)
{
if (!form.IsDisposed && form.IsHandleCreated)
{
ulong maximum = Convert.ToUInt64(progressBar.Maximum);
ulong progress = Convert.ToUInt64(progressBar.Value);
SetTaskbarProgress(form.Handle, progress, maximum);
}
}
///
/// Sets the progress bar in the containing form's taskbar button
/// to this toolstrip progress bar's progress.
///
/// The progress bar.
public static void SetTaskbarProgress(this Form form, ToolStripProgressBar progressBar)
{
if (!form.IsDisposed && form.IsHandleCreated)
{
ulong maximum = Convert.ToUInt64(progressBar.Maximum);
ulong progress = Convert.ToUInt64(progressBar.Value);
SetTaskbarProgress(form.Handle, progress, maximum);
}
}
public static void SetTaskbarProgress(IntPtr hwnd, ulong progress, ulong maximum)
{
HResult valueResult = TaskbarList.SetProgressValue(hwnd, progress, maximum);
valueResult.ThrowIf();
}
///
/// Sets the progress state of the specified window's
/// taskbar button.
///
/// The window handle.
/// The progress state.
public static void SetTaskbarProgressState(this Form form, ThumbnailProgressState state)
{
SetTaskbarProgressState(form.Handle, state);
}
public static void SetTaskbarProgressState(IntPtr hwnd, ThumbnailProgressState state)
{
HResult result = TaskbarList.SetProgressState(hwnd, (uint)state);
result.ThrowIf();
}
///
/// Represents the thumbnail progress bar state.
///
[Flags]
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
}
#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.
private static void SetThumbnailClip(this Form form, Rectangle clipRect)
{
//Example: SetThumbnailClip(this, new Rectangle(button.Location, button.Size));
Rect rect = new Rect(clipRect.Left, clipRect.Top, clipRect.Right, clipRect.Bottom);
HResult setThumbnailClipResult = TaskbarList.SetThumbnailClip(form.Handle, ref rect);
setThumbnailClipResult.ThrowIf();
}
///
/// Sets the specified window's thumbnail tooltip.
///
/// The window.
/// The tooltip text.
private static void SetThumbnailTooltip(this Form form, string tooltip)
{
HResult setThumbnailTooltipResult = TaskbarList.SetThumbnailTooltip(form.Handle, tooltip);
setThumbnailTooltipResult.ThrowIf();
}
#endregion
#region Miscellaneous
///
/// Allow the taskbar and DWM-related windows messages
/// through the Windows UIPI mechanism.
/// Calling this method is not required unless the process is elevated.
///
public static void AllowWindowMessagesThroughUipi()
{
// If it's Windows 7 or above and we're elevated.
if (OSVersion.HasTaskDialogs && Program.ElevationType == TokenElevationType.Full)
{
Win32.ChangeWindowMessageFilter((WindowMessage)UnsafeNativeMethods.WM_TaskbarButtonCreated, UipiFilterFlag.Add);
Win32.ChangeWindowMessageFilter(WindowMessage.DwmSendIconicThumbnail, UipiFilterFlag.Add);
Win32.ChangeWindowMessageFilter(WindowMessage.DwmSendIconicLivePreviewBitmap, UipiFilterFlag.Add);
Win32.ChangeWindowMessageFilter(WindowMessage.Command, UipiFilterFlag.Add);
Win32.ChangeWindowMessageFilter(WindowMessage.SysCommand, UipiFilterFlag.Add);
Win32.ChangeWindowMessageFilter(WindowMessage.Activate, UipiFilterFlag.Add);
}
}
///
/// The WM_TaskbarButtonCreated message number.
///
public static uint TaskbarButtonCreatedMessage
{
get { return UnsafeNativeMethods.WM_TaskbarButtonCreated; }
}
#endregion
}
}