mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
added TaskbarLib (not compilable yet)
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1947 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace TaskbarLib.Interop
|
||||
{
|
||||
#region "Interface Classes"
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("86C14003-4D6B-4EF3-A7B4-0506663B2E68")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CApplicationDestinations { }
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("86BEC222-30F2-47E0-9F25-60D11CD75C28")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CApplicationDocumentLists { }
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CTaskbarList { }
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("00021401-0000-0000-C000-000000000046")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CShellLink { }
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("77F10CF0-3DB5-4966-B520-B7C54FD35ED6")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CDestinationList { }
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("2D3468C1-36A7-43B6-AC24-D3F02FD9607A")]
|
||||
[ClassInterfaceAttribute(ClassInterfaceType.None)]
|
||||
internal class CEnumerableObjectCollection { }
|
||||
|
||||
#endregion
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("92CA9DCD-5622-4BBA-A805-5E9F541BD8C9")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IObjectArray
|
||||
{
|
||||
void GetCount(out uint cObjects);
|
||||
void GetAt(uint iIndex, ref Guid riid, [Out(), MarshalAs(UnmanagedType.Interface)] out object ppvObject);
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute(SafeNativeMethods.IID_IObjectCollection)]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IObjectCollection
|
||||
{
|
||||
// IObjectArray
|
||||
[PreserveSig]
|
||||
void GetCount(out uint cObjects);
|
||||
[PreserveSig]
|
||||
void GetAt(uint iIndex, ref Guid riid, [Out(), MarshalAs(UnmanagedType.Interface)] out object ppvObject);
|
||||
|
||||
// IObjectCollection
|
||||
void AddObject([MarshalAs(UnmanagedType.Interface)] object pvObject);
|
||||
void AddFromArray([MarshalAs(UnmanagedType.Interface)] IObjectArray poaSource);
|
||||
void RemoveObject(uint uiIndex);
|
||||
void Clear();
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IPropertyStore
|
||||
{
|
||||
void GetCount(out UInt32 cProps);
|
||||
void GetAt(UInt32 iProp, [MarshalAs(UnmanagedType.Struct)] out PropertyKey pkey);
|
||||
void GetValue([In, MarshalAs(UnmanagedType.Struct)] ref PropertyKey pkey, [Out(), MarshalAs(UnmanagedType.Struct)] out PropVariant pv);
|
||||
void SetValue([In, MarshalAs(UnmanagedType.Struct)] ref PropertyKey pkey, [In, MarshalAs(UnmanagedType.Struct)] ref PropVariant pv);
|
||||
void Commit();
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("6332DEBF-87B5-4670-90C0-5E57B408A49E")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface ICustomDestinationList
|
||||
{
|
||||
void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
void BeginList(out uint cMaxSlots, ref Guid riid, [Out(), MarshalAs(UnmanagedType.Interface)] out object ppvObject);
|
||||
void AppendCategory([MarshalAs(UnmanagedType.LPWStr)] string pszCategory, [MarshalAs(UnmanagedType.Interface)] IObjectArray poa);
|
||||
void AppendKnownCategory([MarshalAs(UnmanagedType.I4)] KNOWNDESTCATEGORY category);
|
||||
void AddUserTasks([MarshalAs(UnmanagedType.Interface)] IObjectArray poa);
|
||||
void CommitList();
|
||||
void GetRemovedDestinations(ref Guid riid, [Out(), MarshalAs(UnmanagedType.Interface)] out object ppvObject);
|
||||
void DeleteList([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
void AbortList();
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("12337D35-94C6-48A0-BCE7-6A9C69D4D600")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IApplicationDestinations
|
||||
{
|
||||
void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
void RemoveDestination([MarshalAs(UnmanagedType.Interface)] object pvObject);
|
||||
void RemoveAllDestinations();
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("3C594F9F-9F30-47A1-979A-C9E83D3D0A06")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IApplicationDocumentLists
|
||||
{
|
||||
void SetAppID([MarshalAs(UnmanagedType.LPWStr)] string pszAppID);
|
||||
void GetList([MarshalAs(UnmanagedType.I4)] APPDOCLISTTYPE listtype, uint cItemsDesired, ref Guid riid, [Out(), MarshalAs(UnmanagedType.Interface)] out object ppvObject);
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface ITaskbarList3
|
||||
{
|
||||
// ITaskbarList
|
||||
[PreserveSig]
|
||||
void HrInit();
|
||||
[PreserveSig]
|
||||
void AddTab(IntPtr hwnd);
|
||||
[PreserveSig]
|
||||
void DeleteTab(IntPtr hwnd);
|
||||
[PreserveSig]
|
||||
void ActivateTab(IntPtr hwnd);
|
||||
[PreserveSig]
|
||||
void SetActiveAlt(IntPtr hwnd);
|
||||
|
||||
// ITaskbarList2
|
||||
[PreserveSig]
|
||||
void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
|
||||
|
||||
// ITaskbarList3
|
||||
void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
|
||||
void SetProgressState(IntPtr hwnd, TBPFLAG tbpFlags);
|
||||
void RegisterTab(IntPtr hwndTab, IntPtr hwndMDI);
|
||||
void UnregisterTab(IntPtr hwndTab);
|
||||
void SetTabOrder(IntPtr hwndTab, IntPtr hwndInsertBefore);
|
||||
void SetTabActive(IntPtr hwndTab, IntPtr hwndMDI, TBATFLAG tbatFlags);
|
||||
void ThumbBarAddButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray)] THUMBBUTTON[] pButtons);
|
||||
void ThumbBarUpdateButtons(IntPtr hwnd, uint cButtons, [MarshalAs(UnmanagedType.LPArray)] THUMBBUTTON[] pButtons);
|
||||
void ThumbBarSetImageList(IntPtr hwnd, IntPtr himl);
|
||||
void SetOverlayIcon(IntPtr hwnd, IntPtr hIcon, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription);
|
||||
void SetThumbnailTooltip(IntPtr hwnd, [MarshalAs(UnmanagedType.LPWStr)] string pszTip);
|
||||
void SetThumbnailClip(IntPtr hwnd, /*[MarshalAs(UnmanagedType.LPStruct)]*/ ref RECT prcClip);
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IShellItem
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void BindToHandler([In, MarshalAs(UnmanagedType.Interface)] IntPtr pbc, [In] ref Guid bhid, [In] ref Guid riid, out IntPtr ppv);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetDisplayName([In] SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder);
|
||||
}
|
||||
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("000214F9-0000-0000-C000-000000000046")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IShellLinkW
|
||||
{
|
||||
void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, uint fFlags);
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
void SetIDList(IntPtr pidl);
|
||||
void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
void GetHotKey(out short wHotKey);
|
||||
void SetHotKey(short wHotKey);
|
||||
void GetShowCmd(out uint iShowCmd);
|
||||
void SetShowCmd(uint iShowCmd);
|
||||
void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int iIcon);
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
|
||||
void Resolve(IntPtr hwnd, uint fFlags);
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace TaskbarLib.Interop
|
||||
{
|
||||
[Flags]
|
||||
internal enum KNOWNDESTCATEGORY
|
||||
{
|
||||
KDC_FREQUENT = 1,
|
||||
KDC_RECENT
|
||||
}
|
||||
[Flags]
|
||||
internal enum APPDOCLISTTYPE
|
||||
{
|
||||
ADLT_RECENT = 0,
|
||||
ADLT_FREQUENT
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct RECT
|
||||
{
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
|
||||
public RECT(int left, int top, int right, int bottom)
|
||||
{
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
}
|
||||
[Flags]
|
||||
internal enum TBPFLAG
|
||||
{
|
||||
TBPF_NOPROGRESS = 0,
|
||||
TBPF_INDETERMINATE = 0x1,
|
||||
TBPF_NORMAL = 0x2,
|
||||
TBPF_ERROR = 0x4,
|
||||
TBPF_PAUSED = 0x8
|
||||
}
|
||||
[Flags]
|
||||
internal enum TBATFLAG
|
||||
{
|
||||
TBATF_USEMDITHUMBNAIL = 0x1,
|
||||
TBATF_USEMDILIVEPREVIEW = 0x2
|
||||
}
|
||||
[Flags]
|
||||
internal enum THBMASK
|
||||
{
|
||||
THB_BITMAP = 0x1,
|
||||
THB_ICON = 0x2,
|
||||
THB_TOOLTIP = 0x4,
|
||||
THB_FLAGS = 0x8
|
||||
}
|
||||
[Flags]
|
||||
internal enum THBFLAGS
|
||||
{
|
||||
THBF_ENABLED = 0,
|
||||
THBF_DISABLED = 0x1,
|
||||
THBF_DISMISSONCLICK = 0x2,
|
||||
THBF_NOBACKGROUND = 0x4,
|
||||
THBF_HIDDEN = 0x8
|
||||
}
|
||||
[Flags]
|
||||
internal enum SIGDN : uint
|
||||
{
|
||||
SIGDN_NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
||||
SIGDN_PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
||||
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
||||
SIGDN_PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
||||
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||
SIGDN_FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
||||
SIGDN_URL = 0x80068000, // SHGDN_FORPARSING
|
||||
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||
SIGDN_PARENTRELATIVE = 0x80080001 // SHGDN_INFOLDER
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct POINT
|
||||
{
|
||||
internal int X;
|
||||
internal int Y;
|
||||
|
||||
internal POINT(int x, int y)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
internal struct THUMBBUTTON
|
||||
{
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
public THBMASK dwMask;
|
||||
public uint iId;
|
||||
public uint iBitmap;
|
||||
public IntPtr hIcon;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szTip;
|
||||
[MarshalAs(UnmanagedType.U4)]
|
||||
public THBFLAGS dwFlags;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
internal struct PropertyKey
|
||||
{
|
||||
public Guid fmtid;
|
||||
public uint pid;
|
||||
|
||||
public PropertyKey(Guid fmtid, uint pid)
|
||||
{
|
||||
this.fmtid = fmtid;
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public static PropertyKey PKEY_Title = new PropertyKey(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 2);
|
||||
public static PropertyKey PKEY_AppUserModel_ID = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
|
||||
public static PropertyKey PKEY_AppUserModel_IsDestListSeparator = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 6);
|
||||
public static PropertyKey PKEY_AppUserModel_RelaunchCommand = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 2);
|
||||
public static PropertyKey PKEY_AppUserModel_RelaunchDisplayNameResource = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 4);
|
||||
public static PropertyKey PKEY_AppUserModel_RelaunchIconResource = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 3);
|
||||
}
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct CALPWSTR
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal uint cElems;
|
||||
[FieldOffset(4)]
|
||||
internal IntPtr pElems;
|
||||
}
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct PropVariant
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private ushort vt;
|
||||
[FieldOffset(8)]
|
||||
private IntPtr pointerValue;
|
||||
[FieldOffset(8)]
|
||||
private byte byteValue;
|
||||
[FieldOffset(8)]
|
||||
private long longValue;
|
||||
[FieldOffset(8)]
|
||||
private short boolValue;
|
||||
[MarshalAs(UnmanagedType.Struct)]
|
||||
[FieldOffset(8)]
|
||||
private CALPWSTR calpwstr;
|
||||
|
||||
[DllImport("ole32.dll")]
|
||||
private static extern int PropVariantClear(ref PropVariant pvar);
|
||||
|
||||
public VarEnum VarType
|
||||
{
|
||||
get { return (VarEnum)vt; }
|
||||
}
|
||||
|
||||
public void SetValue(String val)
|
||||
{
|
||||
this.Clear();
|
||||
this.vt = (ushort)VarEnum.VT_LPWSTR;
|
||||
this.pointerValue = Marshal.StringToCoTaskMemUni(val);
|
||||
}
|
||||
public void SetValue(bool val)
|
||||
{
|
||||
this.Clear();
|
||||
this.vt = (ushort)VarEnum.VT_BOOL;
|
||||
this.boolValue = val ? (short)-1 : (short)0;
|
||||
}
|
||||
|
||||
public string GetValue()
|
||||
{
|
||||
return Marshal.PtrToStringUni(this.pointerValue);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
PropVariantClear(ref this);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
internal static class SafeNativeMethods
|
||||
{
|
||||
//Obviously, these GUIDs shouldn't be modified. The reason they
|
||||
//are not readonly is that they are passed with 'ref' to various
|
||||
//native methods.
|
||||
public static Guid IID_IObjectArray = new Guid("92CA9DCD-5622-4BBA-A805-5E9F541BD8C9");
|
||||
public const string IID_IObjectCollection = "5632B1A4-E38A-400A-928A-D4CD63230295";
|
||||
public static Guid IID_IPropertyStore = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
|
||||
public static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
|
||||
|
||||
public const int DWM_SIT_DISPLAYFRAME = 0x00000001;
|
||||
|
||||
public const int DWMWA_FORCE_ICONIC_REPRESENTATION = 7;
|
||||
public const int DWMWA_HAS_ICONIC_BITMAP = 10;
|
||||
|
||||
public const int WM_COMMAND = 0x111;
|
||||
public const int WM_SYSCOMMAND = 0x112;
|
||||
public const int WM_DWMSENDICONICTHUMBNAIL = 0x0323;
|
||||
public const int WM_DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326;
|
||||
public const int WM_CLOSE = 0x0010;
|
||||
public const int WM_ACTIVATE = 0x0006;
|
||||
|
||||
public const int WA_ACTIVE = 1;
|
||||
public const int WA_CLICKACTIVE = 2;
|
||||
|
||||
public const int SC_CLOSE = 0xF060;
|
||||
|
||||
public const int MSGFLT_ADD = 1;
|
||||
public const int MSGFLT_REMOVE = 2;
|
||||
|
||||
// Thumbbutton WM_COMMAND notification
|
||||
public const uint THBN_CLICKED = 0x1800;
|
||||
}
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
internal static class UnsafeNativeMethods
|
||||
{
|
||||
[DllImport("shell32.dll")]
|
||||
public static extern int SHGetPropertyStoreForWindow(IntPtr hwnd, ref Guid iid /*IID_IPropertyStore*/, [Out(), MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
|
||||
[DllImport("dwmapi.dll")]
|
||||
public static extern int DwmSetIconicThumbnail(IntPtr hwnd, IntPtr hbitmap, uint flags);
|
||||
[DllImport("dwmapi.dll")]
|
||||
public static extern int DwmSetIconicLivePreviewBitmap(IntPtr hwnd, IntPtr hbitmap, ref POINT ptClient, uint flags);
|
||||
[DllImport("dwmapi.dll")]
|
||||
public static extern int DwmSetIconicLivePreviewBitmap(IntPtr hwnd, IntPtr hbitmap, IntPtr ptClient, uint flags);
|
||||
[DllImport("dwmApi.dll")]
|
||||
internal static extern int DwmSetWindowAttribute(IntPtr hwnd, uint dwAttributeToSet, IntPtr pvAttributeValue, uint cbAttribute);
|
||||
[DllImport("dwmApi.dll")]
|
||||
internal static extern int DwmSetWindowAttribute(IntPtr hwnd, uint dwAttributeToSet, ref int pvAttributeValue, uint cbAttribute);
|
||||
[DllImport("dwmapi.dll")]
|
||||
public static extern int DwmInvalidateIconicBitmaps(IntPtr hwnd);
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool ChangeWindowMessageFilter(uint message, uint flags);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
internal static extern uint RegisterWindowMessage(string lpString);
|
||||
|
||||
public static readonly uint WM_TaskbarButtonCreated = RegisterWindowMessage("TaskbarButtonCreated");
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
public static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
|
||||
[DllImport("shell32.dll")]
|
||||
public static extern void GetCurrentProcessExplicitAppUserModelID([Out(), MarshalAs(UnmanagedType.LPWStr)] out string AppID);
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetWindowRect(IntPtr hwnd, ref RECT rect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GetClientRect(IntPtr hwnd, ref RECT rect);
|
||||
public static bool GetClientSize(IntPtr hwnd, out System.Drawing.Size size)
|
||||
{
|
||||
RECT rect = new RECT();
|
||||
if (!GetClientRect(hwnd, ref rect))
|
||||
{
|
||||
size = new System.Drawing.Size(-1, -1);
|
||||
return false;
|
||||
}
|
||||
size = new System.Drawing.Size(rect.right, rect.bottom);
|
||||
return true;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool ShowWindow(IntPtr hwnd, int cmd);
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int X, int Y, int cx, int cy, uint flags);
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool ClientToScreen(IntPtr hwnd, ref POINT point);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetWindowText(IntPtr hwnd, StringBuilder str, int maxCount);
|
||||
[DllImport("gdi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool BitBlt (IntPtr hDestDC, int destX, int destY, int width, int height, IntPtr hSrcDC, int srcX, int srcY, uint operation);
|
||||
[DllImport("gdi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool StretchBlt(IntPtr hDestDC, int destX, int destY, int destWidth, int destHeight, IntPtr hSrcDC, int srcX, int srcY, int srcWidth, int srcHeight, uint operation);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetWindowDC(IntPtr hwnd);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
|
||||
[DllImport("Shell32", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
internal static extern uint SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, /* The following parameter is not used - binding context. */ IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TaskbarLib.Interop;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of categorized jump list destinations.
|
||||
/// </summary>
|
||||
internal sealed class JumpListDestinations
|
||||
{
|
||||
//TODO: This is highly inefficient, but we want to maintain
|
||||
//insertion order when adding the categories because the bottom
|
||||
//categories are first to be truncated if screen estate is low.
|
||||
private SortedDictionary<int, List<IJumpListDestination>> _categorizedDestinations =
|
||||
new SortedDictionary<int, List<IJumpListDestination>>();
|
||||
|
||||
public void AddDestination(IJumpListDestination destination)
|
||||
{
|
||||
List<IJumpListDestination> destinations =
|
||||
_categorizedDestinations.Values.FirstOrDefault(
|
||||
list => list.First().Category == destination.Category);
|
||||
if (destinations == null)
|
||||
{
|
||||
destinations = new List<IJumpListDestination>();
|
||||
_categorizedDestinations.Add(
|
||||
_categorizedDestinations.Keys.LastOrDefault() + 1, destinations);
|
||||
}
|
||||
|
||||
destinations.Add(destination);
|
||||
}
|
||||
|
||||
public void DeleteDestination(IJumpListDestination destination)
|
||||
{
|
||||
List<IJumpListDestination> destinations =
|
||||
_categorizedDestinations.Values.First(
|
||||
list => list.First().Category == destination.Category);
|
||||
IJumpListDestination toDelete = destinations.Find(
|
||||
d => d.Path == destination.Path && d.Category == destination.Category && d.Title == destination.Title);
|
||||
if (toDelete != null)
|
||||
destinations.Remove(toDelete);
|
||||
}
|
||||
|
||||
internal void RefreshDestinations(ICustomDestinationList destinationList)
|
||||
{
|
||||
if (_categorizedDestinations.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (int key in _categorizedDestinations.Keys)
|
||||
{
|
||||
IObjectCollection categoryContents =
|
||||
(IObjectCollection)new CEnumerableObjectCollection();
|
||||
var destinations = _categorizedDestinations[key];
|
||||
foreach (IJumpListDestination destination in destinations)
|
||||
{
|
||||
categoryContents.AddObject(destination.GetShellRepresentation());
|
||||
}
|
||||
destinationList.AppendCategory(
|
||||
destinations.First().Category,
|
||||
(IObjectArray)categoryContents);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Categories
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from d in _categorizedDestinations.Keys
|
||||
select _categorizedDestinations[d].First().Category);
|
||||
}
|
||||
}
|
||||
public IEnumerable<IJumpListDestination> GetDestinationsByCategory(
|
||||
string category)
|
||||
{
|
||||
return
|
||||
(from k in _categorizedDestinations.Keys
|
||||
let d = _categorizedDestinations[k]
|
||||
where d.First().Category == category
|
||||
select d).Single();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_categorizedDestinations.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A collection of jump list tasks.
|
||||
/// </summary>
|
||||
internal sealed class JumpListTasks
|
||||
{
|
||||
private List<IJumpListTask> _tasks = new List<IJumpListTask>();
|
||||
|
||||
public void AddTask(IJumpListTask task)
|
||||
{
|
||||
_tasks.Add(task);
|
||||
}
|
||||
public void DeleteTask(IJumpListTask task)
|
||||
{
|
||||
IJumpListTask toDelete = _tasks.Find(t => t.Path == task.Path && t.Arguments == task.Arguments);
|
||||
if (toDelete != null)
|
||||
_tasks.Remove(toDelete);
|
||||
}
|
||||
|
||||
internal void RefreshTasks(ICustomDestinationList destinationList)
|
||||
{
|
||||
if (_tasks.Count == 0)
|
||||
return;
|
||||
|
||||
IObjectCollection taskCollection =
|
||||
(IObjectCollection)new CEnumerableObjectCollection();
|
||||
foreach (IJumpListTask task in _tasks)
|
||||
{
|
||||
taskCollection.AddObject(task.GetShellRepresentation());
|
||||
}
|
||||
destinationList.AddUserTasks((IObjectArray)taskCollection);
|
||||
}
|
||||
|
||||
public IEnumerable<IJumpListTask> Tasks
|
||||
{
|
||||
get { return _tasks; }
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_tasks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a shell object that can be inserted to an application's
|
||||
/// jump list.
|
||||
/// </summary>
|
||||
public interface IJumpListShellObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the object's title.
|
||||
/// </summary>
|
||||
string Title { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the object's path.
|
||||
/// </summary>
|
||||
string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shell representation of an object, such as
|
||||
/// <b>IShellLink</b> or <b>IShellItem</b>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
object GetShellRepresentation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a jump list destination.
|
||||
/// </summary>
|
||||
public interface IJumpListDestination : IJumpListShellObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the destination's category.
|
||||
/// </summary>
|
||||
string Category { get; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Represents a jump list task.
|
||||
/// </summary>
|
||||
public interface IJumpListTask : IJumpListShellObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the task's command line arguments.
|
||||
/// </summary>
|
||||
string Arguments { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags controlling the appearance of a window.
|
||||
/// </summary>
|
||||
public enum WindowShowCommand : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Hides the window and activates another window.
|
||||
/// </summary>
|
||||
Hide = 0,
|
||||
/// <summary>
|
||||
/// Activates and displays the window (including restoring
|
||||
/// it to its original size and position).
|
||||
/// </summary>
|
||||
Normal = 1,
|
||||
/// <summary>
|
||||
/// Minimizes the window.
|
||||
/// </summary>
|
||||
Minimized = 2,
|
||||
/// <summary>
|
||||
/// Maximizes the window.
|
||||
/// </summary>
|
||||
Maximized = 3,
|
||||
/// <summary>
|
||||
/// Similar to <see cref="Normal"/>, except that the window
|
||||
/// is not activated.
|
||||
/// </summary>
|
||||
ShowNoActivate = 4,
|
||||
/// <summary>
|
||||
/// Activates the window and displays it in its current size
|
||||
/// and position.
|
||||
/// </summary>
|
||||
Show = 5,
|
||||
/// <summary>
|
||||
/// Minimizes the window and activates the next top-level window.
|
||||
/// </summary>
|
||||
Minimize = 6,
|
||||
/// <summary>
|
||||
/// Minimizes the window and does not activate it.
|
||||
/// </summary>
|
||||
ShowMinimizedNoActivate = 7,
|
||||
/// <summary>
|
||||
/// Similar to <see cref="Normal"/>, except that the window is not
|
||||
/// activated.
|
||||
/// </summary>
|
||||
ShowNA = 8,
|
||||
/// <summary>
|
||||
/// Activates and displays the window, restoring it to its original
|
||||
/// size and position.
|
||||
/// </summary>
|
||||
Restore = 9,
|
||||
/// <summary>
|
||||
/// Sets the show state based on the initial value specified when
|
||||
/// the process was created.
|
||||
/// </summary>
|
||||
Default = 10,
|
||||
/// <summary>
|
||||
/// Minimizes a window, even if the thread owning the window is not
|
||||
/// responding. Use this only to minimize windows from a different
|
||||
/// thread.
|
||||
/// </summary>
|
||||
ForceMinimize = 11
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a separator in the task area of the jump list.
|
||||
/// There is no need to set any properties on this class.
|
||||
/// </summary>
|
||||
public sealed class Separator : IJumpListTask
|
||||
{
|
||||
string IJumpListTask.Arguments
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
string IJumpListShellObject.Title
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
string IJumpListShellObject.Path
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
object IJumpListShellObject.GetShellRepresentation()
|
||||
{
|
||||
ShellLink shellLink = new ShellLink
|
||||
{
|
||||
IsSeparator = true
|
||||
};
|
||||
return shellLink.GetShellRepresentation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a shell link (<b>IShellLink</b>) object.
|
||||
/// </summary>
|
||||
public sealed class ShellLink : IJumpListTask, IJumpListDestination
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the object's title.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the object's category.
|
||||
/// </summary>
|
||||
public string Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the object's path.
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the location of the object's icon.
|
||||
/// </summary>
|
||||
public string IconLocation { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the object's icon in the specified
|
||||
/// icon's location (<see cref="IconLocation"/>).
|
||||
/// </summary>
|
||||
public int IconIndex { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the object's arguments (passed to the command
|
||||
/// line).
|
||||
/// </summary>
|
||||
public string Arguments { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the object's working directory.
|
||||
/// </summary>
|
||||
public string WorkingDirectory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the show command of the launched application.
|
||||
/// </summary>
|
||||
public WindowShowCommand ShowCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a flag indicating that the shell link
|
||||
/// is a menu separator. If this flag is set, all other
|
||||
/// properties are ignored.
|
||||
/// </summary>
|
||||
internal bool IsSeparator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shell <b>IShellLink</b> representation
|
||||
/// of the object.
|
||||
/// </summary>
|
||||
/// <returns>An <b>IShellLink</b> up-cast to <b>object</b>.</returns>
|
||||
public object GetShellRepresentation()
|
||||
{
|
||||
IShellLinkW shellLink = (IShellLinkW)new CShellLink();
|
||||
|
||||
IPropertyStore propertyStore = (IPropertyStore)shellLink;
|
||||
PropVariant propVariant = new PropVariant();
|
||||
|
||||
if (IsSeparator)
|
||||
{
|
||||
propVariant.SetValue(true);
|
||||
propertyStore.SetValue(ref PropertyKey.PKEY_AppUserModel_IsDestListSeparator, ref propVariant);
|
||||
propVariant.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
shellLink.SetPath(Path);
|
||||
|
||||
if (!String.IsNullOrEmpty(IconLocation))
|
||||
shellLink.SetIconLocation(IconLocation, IconIndex);
|
||||
if (!String.IsNullOrEmpty(Arguments))
|
||||
shellLink.SetArguments(Arguments);
|
||||
if (!String.IsNullOrEmpty(WorkingDirectory))
|
||||
shellLink.SetWorkingDirectory(WorkingDirectory);
|
||||
shellLink.SetShowCmd((uint)ShowCommand);
|
||||
|
||||
propVariant.SetValue(Title);
|
||||
propertyStore.SetValue(ref PropertyKey.PKEY_Title, ref propVariant);
|
||||
propVariant.Clear();
|
||||
}
|
||||
|
||||
propertyStore.Commit();
|
||||
|
||||
return shellLink;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a <b>IShellItem</b> object.
|
||||
/// </summary>
|
||||
public sealed class ShellItem : IJumpListDestination
|
||||
{
|
||||
string IJumpListShellObject.Title { get { return null; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the object's category.
|
||||
/// </summary>
|
||||
public string Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the object's path.
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shell <b>IShellItem</b> representation
|
||||
/// of the object.
|
||||
/// </summary>
|
||||
/// <returns>An <b>IShellItem</b> up-cast to <b>object</b>.</returns>
|
||||
public object GetShellRepresentation()
|
||||
{
|
||||
return null;// GetShellItemFromPath(Path);
|
||||
|
||||
//Note: this will only work if there is a file association
|
||||
//for the extension we're trying to register to our program.
|
||||
}
|
||||
|
||||
internal static IShellItem GetShellItemFromPath(string path)
|
||||
{
|
||||
if (String.IsNullOrEmpty(path))
|
||||
throw new ArgumentNullException(
|
||||
"path", "Shell item cannot be generated from null or empty path.");
|
||||
|
||||
IShellItem resultItem = default(IShellItem);
|
||||
//Guid shellItemGuid = new Guid(IIDGuid.IShellItem);
|
||||
//uint result = SHCreateItemFromParsingName(
|
||||
// path,
|
||||
// IntPtr.Zero,
|
||||
// ref shellItemGuid,
|
||||
// out resultItem);
|
||||
//// Throw if an error occurred.
|
||||
//System.Runtime.InteropServices.Marshal.ThrowExceptionForHR((int)result);
|
||||
return resultItem;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,528 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.Win32;
|
||||
using TaskbarLib.Interop;
|
||||
using System.Runtime.CompilerServices;
|
||||
using TaskbarLib.DesktopIntegration;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides services to manage taskbar jump lists, including
|
||||
/// custom destinations and custom tasks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class mostly borrows the Windows Shell's concepts where
|
||||
/// jump lists are concerned including:
|
||||
/// <b>Application destinations</b> - Destinations added to the application's
|
||||
/// recent and frequent categories by the shell or by the application.
|
||||
/// <b>Custom destinations</b> - Destinations added to the application's
|
||||
/// jump list in other categories by the application.
|
||||
/// <b>Tasks</b> - Tasks added to the application's jump list.
|
||||
/// <b>The methods of this class are not thread-safe.</b>
|
||||
/// </remarks>
|
||||
public sealed class JumpListManager : IDisposable
|
||||
{
|
||||
#region Members
|
||||
|
||||
string _appId;
|
||||
JumpListDestinations _destinations;
|
||||
JumpListTasks _tasks;
|
||||
|
||||
ICustomDestinationList _customDestinationList;
|
||||
uint _maxSlotsInList;
|
||||
|
||||
ApplicationDestinationType _enabledAutoDestinationType = ApplicationDestinationType.Recent;
|
||||
|
||||
EventHandler _displaySettingsChangeHandler;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the jump list manager
|
||||
/// with the specified application id.
|
||||
/// </summary>
|
||||
/// <param name="appId">The application id.</param>
|
||||
public JumpListManager(string appId)
|
||||
{
|
||||
_appId = appId;
|
||||
_destinations = new JumpListDestinations();
|
||||
_tasks = new JumpListTasks();
|
||||
|
||||
_customDestinationList = (ICustomDestinationList)new CDestinationList();
|
||||
if (String.IsNullOrEmpty(_appId))
|
||||
{
|
||||
_appId = Windows7Taskbar.GetCurrentProcessAppId();
|
||||
}
|
||||
if (!String.IsNullOrEmpty(_appId))
|
||||
{
|
||||
_customDestinationList.SetAppID(_appId);
|
||||
}
|
||||
|
||||
_displaySettingsChangeHandler = delegate
|
||||
{
|
||||
RefreshMaxSlots();
|
||||
};
|
||||
SystemEvents.DisplaySettingsChanged +=
|
||||
_displaySettingsChangeHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the jump list manager
|
||||
/// with the specified window handle.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
public JumpListManager(IntPtr hwnd)
|
||||
: this(Windows7Taskbar.GetWindowAppId(hwnd))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a task to the application's jump list.
|
||||
/// </summary>
|
||||
/// <param name="task">An object implementing <see cref="IJumpListTask"/>,
|
||||
/// such as <see cref="ShellLink"/>.</param>
|
||||
public void AddUserTask(IJumpListTask task)
|
||||
{
|
||||
_tasks.AddTask(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the tasks currently present in the application's
|
||||
/// jump list. If the tasks are modified through the use of this
|
||||
/// property, the <see cref="Refresh"/> method must be called to
|
||||
/// repopulate the application's jump list.
|
||||
/// </summary>
|
||||
public IEnumerable<IJumpListTask> Tasks
|
||||
{
|
||||
get { return _tasks.Tasks; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified task from the application's jump list.
|
||||
/// </summary>
|
||||
/// <param name="task">The task to delete.</param>
|
||||
public void DeleteTask(IJumpListTask task)
|
||||
{
|
||||
_tasks.DeleteTask(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all the tasks from the application's jump list.
|
||||
/// </summary>
|
||||
public void ClearTasks()
|
||||
{
|
||||
_tasks.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a custom destination to the application's jump list.
|
||||
/// </summary>
|
||||
/// <param name="destination">An object implementing
|
||||
/// <see cref="IJumpListDestination"/> such as <see cref="ShellLink"/>
|
||||
/// or <see cref="ShellItem"/>.</param>
|
||||
public void AddCustomDestination(IJumpListDestination destination)
|
||||
{
|
||||
_destinations.AddDestination(destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified custom destination from the application's
|
||||
/// jump list.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination to delete.</param>
|
||||
public void DeleteCustomDestination(IJumpListDestination destination)
|
||||
{
|
||||
_destinations.DeleteDestination(destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The currently enabled automatic application destination type.
|
||||
/// The supported values are the values of the
|
||||
/// <see cref="ApplicationDestinationType"/> enumeration.
|
||||
/// Only of the values can be set at any given time.
|
||||
/// </summary>
|
||||
public ApplicationDestinationType EnabledAutoDestinationType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _enabledAutoDestinationType;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_enabledAutoDestinationType == value)
|
||||
return;
|
||||
|
||||
_enabledAutoDestinationType = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all destinations from the application's jump list.
|
||||
/// </summary>
|
||||
public void ClearAllDestinations()
|
||||
{
|
||||
ClearApplicationDestinations();
|
||||
ClearCustomDestinations();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all application destinations (such as frequent and recent)
|
||||
/// from the application's jump list.
|
||||
/// </summary>
|
||||
public void ClearApplicationDestinations()
|
||||
{
|
||||
IApplicationDestinations destinations = (IApplicationDestinations)
|
||||
new CApplicationDestinations();
|
||||
if (!String.IsNullOrEmpty(_appId))
|
||||
{
|
||||
destinations.SetAppID(_appId);
|
||||
}
|
||||
try
|
||||
{
|
||||
//This does not remove pinned items.
|
||||
destinations.RemoveAllDestinations();
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
{//There are no destinations. That's cool.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all application destinations belonging to the specified
|
||||
/// application destination type.
|
||||
/// </summary>
|
||||
/// <param name="type">The application destination type.</param>
|
||||
/// <returns>A copy of the application destinations belonging to
|
||||
/// the specified type; modifying the returned objects has no effect
|
||||
/// on the application's destination list.</returns>
|
||||
public IEnumerable<IJumpListDestination> GetApplicationDestinations(ApplicationDestinationType type)
|
||||
{
|
||||
if (type == ApplicationDestinationType.NONE)
|
||||
throw new ArgumentException("type can't be NONE");
|
||||
|
||||
IApplicationDocumentLists destinations = (IApplicationDocumentLists)new CApplicationDocumentLists();
|
||||
Guid iidObjectArray = typeof(IObjectArray).GUID;
|
||||
object obj;
|
||||
|
||||
destinations.GetList((APPDOCLISTTYPE)type, 100, ref iidObjectArray, out obj);
|
||||
|
||||
List<IJumpListDestination> returnValue = new List<IJumpListDestination>();
|
||||
|
||||
Guid iidShellItem = typeof(IShellItem).GUID;
|
||||
Guid iidShellLink = typeof(IShellLinkW).GUID;
|
||||
IObjectArray array = (IObjectArray)obj;
|
||||
uint count;
|
||||
array.GetCount(out count);
|
||||
for (uint i = 0; i < count; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
array.GetAt(i, ref iidShellItem, out obj);
|
||||
}
|
||||
catch (Exception)//Wrong type
|
||||
{
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
array.GetAt(i, ref iidShellLink, out obj);
|
||||
//This shouldn't fail since if it's not IShellItem
|
||||
//then it must be IShellLink.
|
||||
|
||||
IShellLinkW link = (IShellLinkW)obj;
|
||||
ShellLink wrapper = new ShellLink();
|
||||
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
link.GetPath(sb, sb.Capacity, IntPtr.Zero, 2);
|
||||
wrapper.Path = sb.ToString();
|
||||
|
||||
link.GetArguments(sb, sb.Capacity);
|
||||
wrapper.Arguments = sb.ToString();
|
||||
|
||||
int iconId;
|
||||
link.GetIconLocation(sb, sb.Capacity, out iconId);
|
||||
wrapper.IconIndex = iconId;
|
||||
wrapper.IconLocation = sb.ToString();
|
||||
|
||||
uint showCmd;
|
||||
link.GetShowCmd(out showCmd);
|
||||
wrapper.ShowCommand = (WindowShowCommand)showCmd;
|
||||
|
||||
link.GetWorkingDirectory(sb, sb.Capacity);
|
||||
wrapper.WorkingDirectory = sb.ToString();
|
||||
|
||||
returnValue.Add(wrapper);
|
||||
}
|
||||
else //It's an IShellItem.
|
||||
{
|
||||
IShellItem item = (IShellItem)obj;
|
||||
ShellItem wrapper = new ShellItem();
|
||||
|
||||
string path;
|
||||
item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out path);
|
||||
wrapper.Path = path;
|
||||
|
||||
//Title and Category are irrelevant here, because it's
|
||||
//an IShellItem. The user might want to see them, but he's
|
||||
//free to go to the IShellItem and look at its property store.
|
||||
|
||||
returnValue.Add(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified application destination from the application's
|
||||
/// jump list.
|
||||
/// </summary>
|
||||
/// <param name="destination">The application destination.</param>
|
||||
public void DeleteApplicationDestination(IJumpListDestination destination)
|
||||
{
|
||||
IApplicationDestinations destinations = (IApplicationDestinations)
|
||||
new CApplicationDestinations();
|
||||
if (!String.IsNullOrEmpty(_appId))
|
||||
{
|
||||
destinations.SetAppID(_appId);
|
||||
}
|
||||
|
||||
destinations.RemoveDestination(destination.GetShellRepresentation());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all custom destinations from the application's jump list.
|
||||
/// </summary>
|
||||
public void ClearCustomDestinations()
|
||||
{
|
||||
try
|
||||
{
|
||||
_customDestinationList.DeleteList(_appId);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{//Means the list is empty, that's cool.
|
||||
}
|
||||
|
||||
_destinations.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repopulates the application's jump list.
|
||||
/// Use this method after all current changes to
|
||||
/// the application's jump list have been introduced,
|
||||
/// and you want the list to be refreshed.
|
||||
/// </summary>
|
||||
/// <returns><b>true</b> if the list was refreshed; <b>false</b>
|
||||
/// if the operation was cancelled. The operation might have
|
||||
/// been cancelled if the <see cref="UserRemovedItems"/> event
|
||||
/// handler instructed us to cancel the operation.</returns>
|
||||
/// <remarks>
|
||||
/// If the user removed items from the jump list between the
|
||||
/// last refresh operation and this one, then the
|
||||
/// <see cref="UserRemovedItems"/> event will be invoked.
|
||||
/// If the event handler for this event instructed us to cancel
|
||||
/// the operation, then the current transaction is aborted,
|
||||
/// no items are added, and this method returns <b>false</b>.
|
||||
/// Check the return value to determine whether the jump list
|
||||
/// needs to be changed and the operation attempted again.
|
||||
/// </remarks>
|
||||
public bool Refresh()
|
||||
{
|
||||
if (!BeginList())
|
||||
return false; //Operation was cancelled
|
||||
|
||||
_tasks.RefreshTasks(_customDestinationList);
|
||||
_destinations.RefreshDestinations(_customDestinationList);
|
||||
|
||||
switch (EnabledAutoDestinationType)
|
||||
{
|
||||
case ApplicationDestinationType.Frequent:
|
||||
_customDestinationList.AppendKnownCategory(KNOWNDESTCATEGORY.KDC_FREQUENT);
|
||||
break;
|
||||
case ApplicationDestinationType.Recent:
|
||||
_customDestinationList.AppendKnownCategory(KNOWNDESTCATEGORY.KDC_RECENT);
|
||||
break;
|
||||
}
|
||||
|
||||
CommitList();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum number of items to be placed
|
||||
/// in the application's jump list. This number depends
|
||||
/// on factors such as the display resolution or monitor
|
||||
/// change - do not assume it is always constant.
|
||||
/// </summary>
|
||||
public uint MaximumSlotsInList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_maxSlotsInList == 0)
|
||||
{
|
||||
RefreshMaxSlots();
|
||||
}
|
||||
return _maxSlotsInList;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans the resources associated with this jump list.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
SystemEvents.DisplaySettingsChanged -=
|
||||
_displaySettingsChangeHandler;
|
||||
if (_customDestinationList != null)
|
||||
Marshal.ReleaseComObject(_customDestinationList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register to this event to receive notifications when custom
|
||||
/// destinations are being removed from your jump list by the user.
|
||||
/// If you do not register to this event, you will not be able
|
||||
/// to refresh the list. Additionally, if you attempt to add
|
||||
/// items to the list which have been previously removed by the user,
|
||||
/// the next refresh will fail to add your category.
|
||||
/// </summary>
|
||||
public event EventHandler<UserRemovedItemsEventArgs> UserRemovedItems;
|
||||
|
||||
#region Implementation
|
||||
|
||||
private void RefreshMaxSlots()
|
||||
{
|
||||
object obj;
|
||||
_customDestinationList.BeginList(out _maxSlotsInList, ref SafeNativeMethods.IID_IObjectArray, out obj);
|
||||
_customDestinationList.AbortList();
|
||||
}
|
||||
|
||||
private bool BeginList()
|
||||
{
|
||||
if (UserRemovedItems == null)
|
||||
{
|
||||
throw new InvalidOperationException("You must register for the JumpListManager.UserRemovedItems event before adding any items");
|
||||
}
|
||||
|
||||
object obj;
|
||||
_customDestinationList.BeginList(out _maxSlotsInList, ref SafeNativeMethods.IID_IObjectArray, out obj);
|
||||
|
||||
IObjectArray removedItems = (IObjectArray)obj;
|
||||
uint count;
|
||||
removedItems.GetCount(out count);
|
||||
if (count == 0)
|
||||
return true;
|
||||
|
||||
string[] removedItemsArr = new string[count];
|
||||
for (uint i = 0; i < count; ++i)
|
||||
{
|
||||
object item;
|
||||
removedItems.GetAt(i, ref SafeNativeMethods.IID_IUnknown, out item);
|
||||
|
||||
try
|
||||
{
|
||||
IShellLinkW shellLink = (IShellLinkW)item;
|
||||
if (shellLink != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
shellLink.GetPath(sb, sb.Capacity, IntPtr.Zero, 2);
|
||||
removedItemsArr[i] = sb.ToString();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
catch (InvalidCastException) //It's not a ShellLink
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
IShellItem shellItem = (IShellItem)item;
|
||||
if (shellItem != null)
|
||||
{
|
||||
string path;
|
||||
shellItem.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out path);
|
||||
removedItemsArr[i] = path;
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
//It's neither a shell link nor a shell item.
|
||||
//This is impossible.
|
||||
Debug.Assert(false,
|
||||
"List of removed items contains something that is neither a shell item nor a shell link");
|
||||
}
|
||||
}
|
||||
|
||||
UserRemovedItemsEventArgs args = new UserRemovedItemsEventArgs(removedItemsArr);
|
||||
UserRemovedItems(this, args);
|
||||
if (args.CancelCurrentOperation)
|
||||
{
|
||||
_customDestinationList.AbortList();
|
||||
}
|
||||
return !args.CancelCurrentOperation;
|
||||
}
|
||||
|
||||
private void CommitList()
|
||||
{
|
||||
_customDestinationList.CommitList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The application destination type.
|
||||
/// </summary>
|
||||
public enum ApplicationDestinationType
|
||||
{
|
||||
/// <summary>
|
||||
/// No application destination type is selected.
|
||||
/// </summary>
|
||||
NONE = -1,
|
||||
/// <summary>
|
||||
/// Destinations used recently.
|
||||
/// </summary>
|
||||
Recent = 0,
|
||||
/// <summary>
|
||||
/// Destinations used frequently.
|
||||
/// </summary>
|
||||
Frequent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The event arguments for the event that occurs
|
||||
/// when the user removes items from the application's
|
||||
/// jump list.
|
||||
/// </summary>
|
||||
public class UserRemovedItemsEventArgs : EventArgs
|
||||
{
|
||||
readonly string[] _removedItems;
|
||||
|
||||
internal UserRemovedItemsEventArgs(string[] removedItems)
|
||||
{
|
||||
_removedItems = removedItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The collection of removed items. Each item is the path.
|
||||
/// </summary>
|
||||
public string[] RemovedItems
|
||||
{
|
||||
get
|
||||
{
|
||||
return _removedItems;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set to <b>true</b> if the current operation
|
||||
/// should be cancelled. Should be used by the application
|
||||
/// if because of the items the user has removed
|
||||
/// there is no real work to do with the jump list.
|
||||
/// </summary>
|
||||
public bool CancelCurrentOperation { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using TaskbarLib.Interop;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a taskbar thumbnail button in the thumbnail toolbar.
|
||||
/// </summary>
|
||||
public sealed class ThumbButton
|
||||
{
|
||||
private ThumbButtonManager _manager;
|
||||
|
||||
internal ThumbButton(ThumbButtonManager manager, uint id, Icon icon, string tooltip)
|
||||
{
|
||||
_manager = manager;
|
||||
|
||||
Id = id;
|
||||
Icon = icon;
|
||||
Tooltip = tooltip;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The event that occurs when the taskbar thumbnail button
|
||||
/// is clicked.
|
||||
/// </summary>
|
||||
public event EventHandler Clicked;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets thumbnail button's id.
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the thumbnail button's icon.
|
||||
/// </summary>
|
||||
public Icon Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the thumbnail button's tooltip.
|
||||
/// </summary>
|
||||
public string Tooltip { get; set; }
|
||||
|
||||
internal THBFLAGS Flags { get; set; }
|
||||
|
||||
internal THUMBBUTTON Win32ThumbButton
|
||||
{
|
||||
get
|
||||
{
|
||||
THUMBBUTTON win32ThumbButton = new THUMBBUTTON();
|
||||
win32ThumbButton.iId = Id;
|
||||
win32ThumbButton.szTip = Tooltip;
|
||||
win32ThumbButton.hIcon = Icon.Handle;
|
||||
win32ThumbButton.dwFlags = Flags;
|
||||
|
||||
win32ThumbButton.dwMask = THBMASK.THB_FLAGS;
|
||||
if (Tooltip != null)
|
||||
win32ThumbButton.dwMask |= THBMASK.THB_TOOLTIP;
|
||||
if (Icon != null)
|
||||
win32ThumbButton.dwMask |= THBMASK.THB_ICON;
|
||||
|
||||
return win32ThumbButton;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the thumbnail button's visibility.
|
||||
/// </summary>
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.Flags & THBFLAGS.THBF_HIDDEN) == 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
this.Flags &= ~(THBFLAGS.THBF_HIDDEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Flags |= THBFLAGS.THBF_HIDDEN;
|
||||
}
|
||||
_manager.RefreshThumbButtons();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the thumbnail button's enabled state.
|
||||
/// </summary>
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.Flags & THBFLAGS.THBF_DISABLED) == 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
this.Flags &= ~(THBFLAGS.THBF_DISABLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Flags |= THBFLAGS.THBF_DISABLED;
|
||||
}
|
||||
_manager.RefreshThumbButtons();
|
||||
}
|
||||
}
|
||||
|
||||
internal void FireClick()
|
||||
{
|
||||
if (Clicked != null)
|
||||
Clicked(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using TaskbarLib.Interop;
|
||||
using System.Collections;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages a set of taskbar thumbnail buttons in an application.
|
||||
/// </summary>
|
||||
public sealed class ThumbButtonManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new manager with the specified window handle.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
public ThumbButtonManager(IntPtr hwnd)
|
||||
{
|
||||
_hwnd = hwnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new taskbar thumbnail button.
|
||||
/// </summary>
|
||||
/// <param name="id">The button's id.</param>
|
||||
/// <param name="icon">The button's icon.</param>
|
||||
/// <param name="tooltip">The button's tooltip.</param>
|
||||
/// <returns>An object of type <see cref="ThumbButton"/>
|
||||
/// representing the newly created thumbnail button.</returns>
|
||||
public ThumbButton CreateThumbButton(uint id, Icon icon, string tooltip)
|
||||
{
|
||||
return new ThumbButton(this, id, icon, tooltip);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a Windows message to the thumbnail button event
|
||||
/// handlers if appropriate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is intended for infrastructure use only.
|
||||
/// </remarks>
|
||||
/// <param name="message">The message.</param>
|
||||
public void DispatchMessage(ref Message message)
|
||||
{
|
||||
UInt64 wparam = (UInt64)message.WParam.ToInt64();
|
||||
UInt32 wparam32 = (UInt32) (wparam & 0xffffffff); //Clear top 32 bits
|
||||
|
||||
if (message.Msg == SafeNativeMethods.WM_COMMAND && (wparam32 >> 16 == SafeNativeMethods.THBN_CLICKED))
|
||||
{
|
||||
uint id = wparam32 & 0xffff; //Bottom 16 bits
|
||||
_thumbButtons[id].FireClick();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified taskbar thumbnail buttons to the application's
|
||||
/// thumbnail toolbar.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Thumbnail buttons can only be added once - after being added,
|
||||
/// they cannot be removed or deleted. However, they can be shown,
|
||||
/// hidden, enabled and disabled.
|
||||
/// </remarks>
|
||||
/// <param name="buttons">The buttons to add.</param>
|
||||
public void AddThumbButtons(params ThumbButton[] buttons)
|
||||
{
|
||||
Array.ForEach(buttons, b => _thumbButtons.Add(b.Id, b));
|
||||
|
||||
RefreshThumbButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific thumbnail button by its id.
|
||||
/// </summary>
|
||||
/// <param name="id">The thumbnail button's id.</param>
|
||||
/// <returns>An object of type <see cref="ThumbButton"/>
|
||||
/// with the specified id.</returns>
|
||||
public ThumbButton this[uint id]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _thumbButtons[id];
|
||||
}
|
||||
}
|
||||
|
||||
#region Implementation
|
||||
|
||||
private bool _buttonsLoaded;
|
||||
internal void RefreshThumbButtons()
|
||||
{
|
||||
THUMBBUTTON[] win32Buttons = (from thumbButton in _thumbButtons.Values select thumbButton.Win32ThumbButton).ToArray();
|
||||
|
||||
if (_buttonsLoaded)
|
||||
{
|
||||
Windows7Taskbar.TaskbarList.ThumbBarUpdateButtons(_hwnd, (uint)win32Buttons.Length, win32Buttons);
|
||||
}
|
||||
else //First time
|
||||
{
|
||||
Windows7Taskbar.TaskbarList.ThumbBarAddButtons(_hwnd, (uint)win32Buttons.Length, win32Buttons);
|
||||
_buttonsLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<uint, ThumbButton> _thumbButtons = new Dictionary<uint, ThumbButton>();
|
||||
private IntPtr _hwnd;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using TaskbarLib.Interop;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration
|
||||
{
|
||||
/// <summary>
|
||||
/// The primary coordinator of the Windows 7 taskbar-related activities.
|
||||
/// For additional functionality, see the JumpListManager
|
||||
/// and ThumbButtonManager classes.
|
||||
/// </summary>
|
||||
public static class Windows7Taskbar
|
||||
{
|
||||
#region Infrastructure
|
||||
|
||||
/// <summary>
|
||||
/// The WM_TaskbarButtonCreated message number.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Gets a window's application id by its window handle.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <returns>The application id of that window.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the window's application id by its window handle.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="appId">The application id.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current process' explicit application user model id.
|
||||
/// </summary>
|
||||
/// <param name="appId">The application id.</param>
|
||||
public static void SetCurrentProcessAppId(string appId)
|
||||
{
|
||||
UnsafeNativeMethods.SetCurrentProcessExplicitAppUserModelID(appId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current process' explicit application user model id.
|
||||
/// </summary>
|
||||
/// <returns>The application id.</returns>
|
||||
public static string GetCurrentProcessAppId()
|
||||
{
|
||||
string appId;
|
||||
UnsafeNativeMethods.GetCurrentProcessExplicitAppUserModelID(out appId);
|
||||
return appId;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DWM Iconic Thumbnail and Peek Bitmap
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the specified window requests the DWM
|
||||
/// to demand live preview (thumbnail and peek) mode when necessary
|
||||
/// instead of relying on default preview.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
public static void EnableCustomWindowPreview(IntPtr hwnd)
|
||||
{
|
||||
InternalEnableCustomWindowPreview(hwnd, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
public static void DisableCustomWindowPreview(IntPtr hwnd)
|
||||
{
|
||||
InternalEnableCustomWindowPreview(hwnd, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified iconic thumbnail for the specified window.
|
||||
/// This is typically done in response to a DWM message.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="bitmap">The thumbnail bitmap.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified peek (live preview) bitmap for the specified
|
||||
/// window. This is typically done in response to a DWM message.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="bitmap">The thumbnail bitmap.</param>
|
||||
/// <param name="displayFrame">Whether to display a standard window
|
||||
/// frame around the bitmap.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified peek (live preview) bitmap for the specified
|
||||
/// window. This is typically done in response to a DWM message.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="bitmap">The thumbnail bitmap.</param>
|
||||
/// <param name="offset">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.</param>
|
||||
/// <param name="displayFrame">Whether to display a standard window
|
||||
/// frame around the bitmap.</param>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Draws the specified overlay icon on the specified window's
|
||||
/// taskbar button.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="icon">The overlay icon.</param>
|
||||
/// <param name="description">The overlay icon description.</param>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Represents the thumbnail progress bar state.
|
||||
/// </summary>
|
||||
public enum ThumbnailProgressState
|
||||
{
|
||||
/// <summary>
|
||||
/// No progress is displayed.
|
||||
/// </summary>
|
||||
NoProgress = 0,
|
||||
/// <summary>
|
||||
/// The progress is indeterminate (marquee).
|
||||
/// </summary>
|
||||
Indeterminate = 0x1,
|
||||
/// <summary>
|
||||
/// Normal progress is displayed.
|
||||
/// </summary>
|
||||
Normal = 0x2,
|
||||
/// <summary>
|
||||
/// An error occurred (red).
|
||||
/// </summary>
|
||||
Error = 0x4,
|
||||
/// <summary>
|
||||
/// The operation is paused (yellow).
|
||||
/// </summary>
|
||||
Paused = 0x8
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress state of the specified window's
|
||||
/// taskbar button.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="state">The progress state.</param>
|
||||
public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state)
|
||||
{
|
||||
TaskbarList.SetProgressState(hwnd, (TBPFLAG)state);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the progress value of the specified window's
|
||||
/// taskbar button.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle.</param>
|
||||
/// <param name="current">The current value.</param>
|
||||
/// <param name="maximum">The maximum value.</param>
|
||||
public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum)
|
||||
{
|
||||
TaskbarList.SetProgressValue(hwnd, current, maximum);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Taskbar Thumbnails
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that only a portion of the window's client area
|
||||
/// should be used in the window's thumbnail.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window.</param>
|
||||
/// <param name="clipRect">The rectangle that specifies the clipped region.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified window's thumbnail tooltip.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window.</param>
|
||||
/// <param name="tooltip">The tooltip text.</param>
|
||||
public static void SetThumbnailTooltip(IntPtr hwnd, string tooltip)
|
||||
{
|
||||
TaskbarList.SetThumbnailTooltip(hwnd, tooltip);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Miscellaneous
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TaskbarLib.DesktopIntegration.WindowsForms
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for easier Windows Forms interop.
|
||||
/// </summary>
|
||||
public static class WindowsFormsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets this form's application id.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="appId">The application id.</param>
|
||||
public static void SetAppId(this Form form, string appId)
|
||||
{
|
||||
Windows7Taskbar.SetWindowAppId(form.Handle, appId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this form's application id.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <returns>The form's application id.</returns>
|
||||
public static string GetAppId(this Form form)
|
||||
{
|
||||
return Windows7Taskbar.GetWindowAppId(form.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables custom window preview on this form, meaning that
|
||||
/// the DWM will send messages when a live thumbnail preview
|
||||
/// or a live peek will be necessary.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
public static void EnableCustomWindowPreview(this Form form)
|
||||
{
|
||||
Windows7Taskbar.EnableCustomWindowPreview(form.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables custom window preview on this form, meaning that
|
||||
/// the DWM will not send messages when a live thumbnail preview
|
||||
/// or a live peek will be necessary, but instead rely on its
|
||||
/// default rendering.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
public static void DisableCustomWindowPreview(this Form form)
|
||||
{
|
||||
Windows7Taskbar.DisableCustomWindowPreview(form.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets this form's iconic thumbnail to the specified bitmap.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
public static void SetIconicThumbnail(this Form form, Bitmap bitmap)
|
||||
{
|
||||
Windows7Taskbar.SetIconicThumbnail(form.Handle, bitmap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets this form's peek (live preview) bitmap.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
/// <param name="displayFrame">Whether to display a standard window
|
||||
/// frame around the bitmap.</param>
|
||||
public static void SetPeekBitmap(this Form form, Bitmap bitmap, bool displayFrame)
|
||||
{
|
||||
Windows7Taskbar.SetPeekBitmap(form.Handle, bitmap, displayFrame);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the specified overlay icon over this form's taskbar button.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="icon">The overlay icon.</param>
|
||||
/// <param name="description">The overlay icon's description.</param>
|
||||
public static void SetTaskbarOverlayIcon(this Form form, Icon icon, string description)
|
||||
{
|
||||
Windows7Taskbar.SetTaskbarOverlayIcon(form.Handle, icon, description);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress bar in the containing form's taskbar button
|
||||
/// to this progress bar's progress.
|
||||
/// </summary>
|
||||
/// <param name="progressBar">The progress bar.</param>
|
||||
public static void SetTaskbarProgress(ProgressBar progressBar)
|
||||
{
|
||||
Form form = (Form)progressBar.TopLevelControl;
|
||||
|
||||
//Approximation:
|
||||
ulong maximum = (ulong)(progressBar.Maximum - progressBar.Minimum);
|
||||
ulong progress = (ulong)(progressBar.Value - progressBar.Minimum);
|
||||
|
||||
Windows7Taskbar.SetProgressState(form.Handle, Windows7Taskbar.ThumbnailProgressState.Normal);
|
||||
Windows7Taskbar.SetProgressValue(form.Handle, progress, maximum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress bar in the containing form's taskbar button
|
||||
/// to this toolstrip progress bar's progress.
|
||||
/// </summary>
|
||||
/// <param name="progressBar">The progress bar.</param>
|
||||
public static void SetTaskbarProgress(ToolStripProgressBar progressBar)
|
||||
{
|
||||
Form form = (Form)progressBar.Control.TopLevelControl;
|
||||
|
||||
//Approximation:
|
||||
ulong maximum = (ulong)(progressBar.Maximum - progressBar.Minimum);
|
||||
ulong progress = (ulong)(progressBar.Value - progressBar.Minimum);
|
||||
|
||||
Windows7Taskbar.SetProgressState(form.Handle, Windows7Taskbar.ThumbnailProgressState.Normal);
|
||||
Windows7Taskbar.SetProgressValue(form.Handle, progress, maximum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress bar of this form's taskbar button to the
|
||||
/// specified percentage.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="percent">The progress percentage.</param>
|
||||
public static void SetTaskbarProgress(this Form form, float percent)
|
||||
{
|
||||
Windows7Taskbar.SetProgressState(form.Handle, Windows7Taskbar.ThumbnailProgressState.Normal);
|
||||
Windows7Taskbar.SetProgressValue(form.Handle, (ulong)percent, 100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the progress bar of this form's taskbar button to the
|
||||
/// specified state.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="state">The taskbar progress state.</param>
|
||||
public static void SetTaskbarProgressState(this Form form, Windows7Taskbar.ThumbnailProgressState state)
|
||||
{
|
||||
Windows7Taskbar.SetProgressState(form.Handle, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a taskbar thumbnail button manager for this form.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <returns>An object of type <see cref="ThumbButtonManager"/>
|
||||
/// that can be used to add and manage thumbnail toolbar buttons.</returns>
|
||||
public static ThumbButtonManager CreateThumbButtonManager(this Form form)
|
||||
{
|
||||
return new ThumbButtonManager(form.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a jump list manager for this form.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <returns>An object of type <see cref="JumpListManager"/>
|
||||
/// that can be used to manage the application's jump list.</returns>
|
||||
public static JumpListManager CreateJumpListManager(this Form form)
|
||||
{
|
||||
return new JumpListManager(form.Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that only a portion of the form's client area
|
||||
/// should be used in the form's thumbnail.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="clipRect">The rectangle that specifies the clipped region.</param>
|
||||
public static void SetThumbnailClip(this Form form, Rectangle clipRect)
|
||||
{
|
||||
Windows7Taskbar.SetThumbnailClip(form.Handle, clipRect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the specified form's thumbnail tooltip.
|
||||
/// </summary>
|
||||
/// <param name="form">The form.</param>
|
||||
/// <param name="tooltip">The tooltip text.</param>
|
||||
public static void SetThumbnailTooltip(this Form form, string tooltip)
|
||||
{
|
||||
Windows7Taskbar.SetThumbnailTooltip(form.Handle, tooltip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -416,6 +416,14 @@
|
||||
<Compile Include="Components\TargetWindowButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Components\TaskbarLib\Interop\COMTypes.cs" />
|
||||
<Compile Include="Components\TaskbarLib\Interop\Interop.cs" />
|
||||
<Compile Include="Components\TaskbarLib\JumpLists\JumpListImpl.cs" />
|
||||
<Compile Include="Components\TaskbarLib\JumpLists\JumpListManager.cs" />
|
||||
<Compile Include="Components\TaskbarLib\ThumbnailButtons\ThumbButton.cs" />
|
||||
<Compile Include="Components\TaskbarLib\ThumbnailButtons\ThumbButtonManager.cs" />
|
||||
<Compile Include="Components\TaskbarLib\Windows7Taskbar.cs" />
|
||||
<Compile Include="Components\TaskbarLib\WindowsFormsExtensions.cs" />
|
||||
<Compile Include="Components\TimerProperties.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
|
||||
Reference in New Issue
Block a user