using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using SystemTrayMenu.Helper; namespace SystemTrayMenu.Utilities { /// /// "Stand-alone" shell context menu /// /// It isn't really debugged but is mostly working. /// Create an instance and call ShowContextMenu with a list of FileInfo for the files. /// Limitation is that it only handles files in the same directory but it can be fixed /// by changing the way files are translated into PIDLs. /// /// Based on FileBrowser in C# from CodeProject /// http://www.codeproject.com/useritems/FileBrowser.asp /// /// Hooking class taken from MSDN Magazine Cutting Edge column /// http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/ /// /// Andreas Johansson /// afjohansson@hotmail.com /// http://afjohansson.spaces.live.com /// /// /// ShellContextMenu scm = new ShellContextMenu(); /// FileInfo[] files = new FileInfo[1]; /// files[0] = new FileInfo(@"c:\windows\notepad.exe"); /// scm.ShowContextMenu(this.Handle, files, Cursor.Position); /// public class ShellContextMenu : NativeWindow { #region Constructor /// Default constructor public ShellContextMenu() { CreateHandle(new CreateParams()); } #endregion #region Destructor /// Ensure all resources get released ~ShellContextMenu() { ReleaseAll(); } #endregion #region GetContextMenuInterfaces() /// Gets the interfaces to the context menu /// Parent folder /// PIDLs /// true if it got the interfaces, otherwise false private bool GetContextMenuInterfaces(IShellFolder oParentFolder, IntPtr[] arrPIDLs, out IntPtr ctxMenuPtr) { int nResult = oParentFolder.GetUIObjectOf( IntPtr.Zero, (uint)arrPIDLs.Length, arrPIDLs, ref IID_IContextMenu, IntPtr.Zero, out ctxMenuPtr); if (S_OK == nResult) { _oContextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(ctxMenuPtr, typeof(IContextMenu)); /*IntPtr pUnknownContextMenu2 = IntPtr.Zero; if (S_OK == Marshal.QueryInterface(pUnknownContextMenu, ref IID_IContextMenu2, out pUnknownContextMenu2)) { _oContextMenu2 = (IContextMenu2)Marshal.GetTypedObjectForIUnknown(pUnknownContextMenu2, typeof(IContextMenu2)); } IntPtr pUnknownContextMenu3 = IntPtr.Zero; if (S_OK == Marshal.QueryInterface(pUnknownContextMenu, ref IID_IContextMenu3, out pUnknownContextMenu3)) { _oContextMenu3 = (IContextMenu3)Marshal.GetTypedObjectForIUnknown(pUnknownContextMenu3, typeof(IContextMenu3)); }*/ return true; } else { ctxMenuPtr = IntPtr.Zero; _oContextMenu = null; return false; } } #endregion #region Override /// /// This method receives WindowMessages. It will make the "Open With" and "Send To" work /// by calling HandleMenuMsg and HandleMenuMsg2. It will also call the OnContextMenuMouseHover /// method of Browser when hovering over a ContextMenu item. /// /// the Message of the Browser's WndProc /// true if the message has been handled, false otherwise protected override void WndProc(ref Message m) { #region IContextMenu if (_oContextMenu != null && m.Msg == (int)WM.MENUSELECT && ((int)ShellHelper.HiWord(m.WParam) & (int)MFT.SEPARATOR) == 0 && ((int)ShellHelper.HiWord(m.WParam) & (int)MFT.POPUP) == 0) { string info = string.Empty; if (ShellHelper.LoWord(m.WParam) == (int)CMD_CUSTOM.ExpandCollapse) { info = "Expands or collapses the current selected item"; } else { info = "";/* ContextMenuHelper.GetCommandString( _oContextMenu, ShellHelper.LoWord(m.WParam) - CMD_FIRST, false);*/ } //br.OnContextMenuMouseHover(new ContextMenuMouseHoverEventArgs(info.ToString())); } #endregion #region IContextMenu2 if (_oContextMenu2 != null && (m.Msg == (int)WM.INITMENUPOPUP || m.Msg == (int)WM.MEASUREITEM || m.Msg == (int)WM.DRAWITEM)) { if (_oContextMenu2.HandleMenuMsg( (uint)m.Msg, m.WParam, m.LParam) == S_OK) { return; } } #endregion #region IContextMenu3 if (_oContextMenu3 != null && m.Msg == (int)WM.MENUCHAR) { if (_oContextMenu3.HandleMenuMsg2( (uint)m.Msg, m.WParam, m.LParam, IntPtr.Zero) == S_OK) { return; } } #endregion base.WndProc(ref m); } #endregion #region InvokeCommand private static void InvokeCommand(IContextMenu contextMenu, uint nCmd, string strFolder, Point pointInvoke) { CMINVOKECOMMANDINFOEX invoke = new CMINVOKECOMMANDINFOEX { cbSize = cbInvokeCommand, lpVerb = (IntPtr)(nCmd - CMD_FIRST), lpDirectory = strFolder, lpVerbW = (IntPtr)(nCmd - CMD_FIRST), lpDirectoryW = strFolder, fMask = CMIC.UNICODE | CMIC.PTINVOKE | ((Control.ModifierKeys & Keys.Control) != 0 ? CMIC.CONTROL_DOWN : 0) | ((Control.ModifierKeys & Keys.Shift) != 0 ? CMIC.SHIFT_DOWN : 0), ptInvoke = new POINT(pointInvoke.X, pointInvoke.Y), nShow = SW.SHOWNORMAL }; _ = contextMenu.InvokeCommand(ref invoke); } #endregion #region ReleaseAll() /// /// Release all allocated interfaces, PIDLs /// private void ReleaseAll() { if (null != _oContextMenu) { Marshal.ReleaseComObject(_oContextMenu); _oContextMenu = null; } if (null != _oContextMenu2) { Marshal.ReleaseComObject(_oContextMenu2); _oContextMenu2 = null; } if (null != _oContextMenu3) { Marshal.ReleaseComObject(_oContextMenu3); _oContextMenu3 = null; } if (null != _oDesktopFolder) { Marshal.ReleaseComObject(_oDesktopFolder); _oDesktopFolder = null; } if (null != _oParentFolder) { Marshal.ReleaseComObject(_oParentFolder); _oParentFolder = null; } if (null != _arrPIDLs) { FreePIDLs(_arrPIDLs); _arrPIDLs = null; } } #endregion #region GetDesktopFolder() /// /// Gets the desktop folder /// /// IShellFolder for desktop folder private IShellFolder GetDesktopFolder() { IntPtr pUnkownDesktopFolder = IntPtr.Zero; if (null == _oDesktopFolder) { // Get desktop IShellFolder int nResult = DllImports.NativeMethods.Shell32SHGetDesktopFolder(out pUnkownDesktopFolder); if (S_OK != nResult) { #pragma warning disable CA1303 // Do not pass literals as localized parameters throw new ShellContextMenuException("Failed to get the desktop shell folder"); #pragma warning restore CA1303 //=> Exceptions not translated in logfile => OK } _oDesktopFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pUnkownDesktopFolder, typeof(IShellFolder)); } return _oDesktopFolder; } #endregion #region GetParentFolder() /// /// Gets the parent folder /// /// Folder path /// IShellFolder for the folder (relative from the desktop) private IShellFolder GetParentFolder(string folderName) { if (null == _oParentFolder) { IShellFolder oDesktopFolder = GetDesktopFolder(); if (null == oDesktopFolder) { return null; } // Get the PIDL for the folder file is in IntPtr pPIDL = IntPtr.Zero; uint pchEaten = 0; SFGAO pdwAttributes = 0; int nResult = oDesktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, folderName, ref pchEaten, out pPIDL, ref pdwAttributes); if (S_OK != nResult) { return null; } IntPtr pStrRet = Marshal.AllocCoTaskMem(MAX_PATH * 2 + 4); Marshal.WriteInt32(pStrRet, 0, 0); nResult = _oDesktopFolder.GetDisplayNameOf(pPIDL, SHGNO.FORPARSING, pStrRet); StringBuilder strFolder = new StringBuilder(MAX_PATH); _ = DllImports.NativeMethods.ShlwapiStrRetToBuf(pStrRet, pPIDL, strFolder, MAX_PATH); Marshal.FreeCoTaskMem(pStrRet); pStrRet = IntPtr.Zero; _strParentFolder = strFolder.ToString(); // Get the IShellFolder for folder IntPtr pUnknownParentFolder = IntPtr.Zero; nResult = oDesktopFolder.BindToObject(pPIDL, IntPtr.Zero, ref IID_IShellFolder, out pUnknownParentFolder); // Free the PIDL first Marshal.FreeCoTaskMem(pPIDL); if (S_OK != nResult) { return null; } _oParentFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pUnknownParentFolder, typeof(IShellFolder)); } return _oParentFolder; } #endregion #region GetPIDLs() /// /// Get the PIDLs /// /// Array of FileInfo /// Array of PIDLs protected IntPtr[] GetPIDLs(FileInfo[] arrFI) { if (null == arrFI || 0 == arrFI.Length) { return null; } IShellFolder oParentFolder = GetParentFolder(arrFI[0].DirectoryName); if (null == oParentFolder) { return null; } IntPtr[] arrPIDLs = new IntPtr[arrFI.Length]; int n = 0; foreach (FileInfo fi in arrFI) { // Get the file relative to folder uint pchEaten = 0; SFGAO pdwAttributes = 0; IntPtr pPIDL = IntPtr.Zero; int nResult = oParentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, fi.Name, ref pchEaten, out pPIDL, ref pdwAttributes); if (S_OK != nResult) { FreePIDLs(arrPIDLs); return null; } arrPIDLs[n] = pPIDL; n++; } return arrPIDLs; } /// /// Get the PIDLs /// /// Array of DirectoryInfo /// Array of PIDLs protected IntPtr[] GetPIDLs(DirectoryInfo[] arrFI) { if (null == arrFI || 0 == arrFI.Length) { return null; } IShellFolder oParentFolder = GetParentFolder(arrFI[0].Parent.FullName); if (null == oParentFolder) { return null; } IntPtr[] arrPIDLs = new IntPtr[arrFI.Length]; int n = 0; foreach (DirectoryInfo fi in arrFI) { // Get the file relative to folder uint pchEaten = 0; SFGAO pdwAttributes = 0; IntPtr pPIDL = IntPtr.Zero; int nResult = oParentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, fi.Name, ref pchEaten, out pPIDL, ref pdwAttributes); if (S_OK != nResult) { FreePIDLs(arrPIDLs); return null; } arrPIDLs[n] = pPIDL; n++; } return arrPIDLs; } #endregion #region FreePIDLs() /// /// Free the PIDLs /// /// Array of PIDLs (IntPtr) protected static void FreePIDLs(IntPtr[] arrPIDLs) { if (null != arrPIDLs) { for (int n = 0; n < arrPIDLs.Length; n++) { if (arrPIDLs[n] != IntPtr.Zero) { Marshal.FreeCoTaskMem(arrPIDLs[n]); arrPIDLs[n] = IntPtr.Zero; } } } } #endregion #region InvokeContextMenuDefault private void InvokeContextMenuDefault(FileInfo[] arrFI) { // Release all resources first. ReleaseAll(); IntPtr pMenu = IntPtr.Zero, iContextMenuPtr = IntPtr.Zero; try { _arrPIDLs = GetPIDLs(arrFI); if (null == _arrPIDLs) { ReleaseAll(); return; } if (false == GetContextMenuInterfaces(_oParentFolder, _arrPIDLs, out iContextMenuPtr)) { ReleaseAll(); return; } pMenu = DllImports.NativeMethods.User32CreatePopupMenu(); int nResult = _oContextMenu.QueryContextMenu( pMenu, 0, CMD_FIRST, CMD_LAST, CMF.DEFAULTONLY | ((Control.ModifierKeys & Keys.Shift) != 0 ? CMF.EXTENDEDVERBS : 0)); uint nDefaultCmd = (uint)DllImports.NativeMethods.User32GetMenuDefaultItem(pMenu, false, 0); if (nDefaultCmd >= CMD_FIRST) { InvokeCommand(_oContextMenu, nDefaultCmd, arrFI[0].DirectoryName, Control.MousePosition); } DllImports.NativeMethods.User32DestroyMenu(pMenu); pMenu = IntPtr.Zero; } catch { throw; } finally { if (pMenu != IntPtr.Zero) { DllImports.NativeMethods.User32DestroyMenu(pMenu); } ReleaseAll(); } } #endregion #region ShowContextMenu() /// /// Shows the context menu /// /// FileInfos (should all be in same directory) /// Where to show the menu public void ShowContextMenu(FileInfo[] files, Point pointScreen) { // Release all resources first. ReleaseAll(); _arrPIDLs = GetPIDLs(files); ShowContextMenu(pointScreen); } /// /// Shows the context menu /// /// DirectoryInfos (should all be in same directory) /// Where to show the menu public void ShowContextMenu(DirectoryInfo[] dirs, Point pointScreen) { // Release all resources first. ReleaseAll(); _arrPIDLs = GetPIDLs(dirs); ShowContextMenu(pointScreen); } /// /// Shows the context menu /// /// FileInfos (should all be in same directory) /// Where to show the menu public void ShowContextMenu(Point pointScreen) { IntPtr pMenu = IntPtr.Zero, iContextMenuPtr = IntPtr.Zero, iContextMenuPtr2 = IntPtr.Zero, iContextMenuPtr3 = IntPtr.Zero; //LocalWindowsHook hook = new LocalWindowsHook(HookType.WH_CALLWNDPROC); //hook.HookInvoked += new LocalWindowsHook.HookEventHandler(WindowsHookInvoked); try { //Application.AddMessageFilter(this); //_arrPIDLs = GetPIDLs(arrFI); if (null == _arrPIDLs) { ReleaseAll(); return; } if (false == GetContextMenuInterfaces(_oParentFolder, _arrPIDLs, out iContextMenuPtr)) { ReleaseAll(); return; } pMenu = DllImports.NativeMethods.User32CreatePopupMenu(); int nResult = _oContextMenu.QueryContextMenu( pMenu, 0, CMD_FIRST, CMD_LAST, CMF.EXPLORE | CMF.NORMAL | ((Control.ModifierKeys & Keys.Shift) != 0 ? CMF.EXTENDEDVERBS : 0)); Marshal.QueryInterface(iContextMenuPtr, ref IID_IContextMenu2, out iContextMenuPtr2); Marshal.QueryInterface(iContextMenuPtr, ref IID_IContextMenu3, out iContextMenuPtr3); _oContextMenu2 = (IContextMenu2)Marshal.GetTypedObjectForIUnknown(iContextMenuPtr2, typeof(IContextMenu2)); _oContextMenu3 = (IContextMenu3)Marshal.GetTypedObjectForIUnknown(iContextMenuPtr3, typeof(IContextMenu3)); //hook.Install(); uint nSelected = DllImports.NativeMethods.User32TrackPopupMenuEx( pMenu, DllImports.NativeMethods.TPM.RETURNCMD, pointScreen.X, pointScreen.Y, Handle, IntPtr.Zero); DllImports.NativeMethods.User32DestroyMenu(pMenu); pMenu = IntPtr.Zero; if (nSelected != 0) { InvokeCommand(_oContextMenu, nSelected, _strParentFolder, pointScreen); } } catch { throw; } finally { //hook.Uninstall(); if (pMenu != IntPtr.Zero) { DllImports.NativeMethods.User32DestroyMenu(pMenu); } if (iContextMenuPtr != IntPtr.Zero) { Marshal.Release(iContextMenuPtr); } if (iContextMenuPtr2 != IntPtr.Zero) { Marshal.Release(iContextMenuPtr2); } if (iContextMenuPtr3 != IntPtr.Zero) { Marshal.Release(iContextMenuPtr3); } ReleaseAll(); } } #endregion #region Local variabled private IContextMenu _oContextMenu; private IContextMenu2 _oContextMenu2; private IContextMenu3 _oContextMenu3; private IShellFolder _oDesktopFolder; private IShellFolder _oParentFolder; private IntPtr[] _arrPIDLs; private string _strParentFolder; #endregion #region Variables and Constants private const int MAX_PATH = 260; private const uint CMD_FIRST = 1; private const uint CMD_LAST = 30000; private const int S_OK = 0; private static readonly int cbMenuItemInfo = Marshal.SizeOf(typeof(MENUITEMINFO)); private static readonly int cbInvokeCommand = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)); #endregion #region Shell GUIDs private static Guid IID_IShellFolder = new Guid("{000214E6-0000-0000-C000-000000000046}"); private static Guid IID_IContextMenu = new Guid("{000214e4-0000-0000-c000-000000000046}"); private static Guid IID_IContextMenu2 = new Guid("{000214f4-0000-0000-c000-000000000046}"); private static Guid IID_IContextMenu3 = new Guid("{bcfce0a0-ec17-11d0-8d10-00a0c90f2719}"); #endregion #region Structs [StructLayout(LayoutKind.Sequential)] private struct CWPSTRUCT { public IntPtr lparam; public IntPtr wparam; public int message; public IntPtr hwnd; } // Contains extended information about a shortcut menu command [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct CMINVOKECOMMANDINFOEX { public int cbSize; public CMIC fMask; public IntPtr hwnd; public IntPtr lpVerb; [MarshalAs(UnmanagedType.LPStr)] public string lpParameters; [MarshalAs(UnmanagedType.LPStr)] public string lpDirectory; public SW nShow; public int dwHotKey; public IntPtr hIcon; [MarshalAs(UnmanagedType.LPStr)] public string lpTitle; public IntPtr lpVerbW; [MarshalAs(UnmanagedType.LPWStr)] public string lpParametersW; [MarshalAs(UnmanagedType.LPWStr)] public string lpDirectoryW; [MarshalAs(UnmanagedType.LPWStr)] public string lpTitleW; public POINT ptInvoke; } // Contains information about a menu item [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct MENUITEMINFO { public MENUITEMINFO(string text) { cbSize = cbMenuItemInfo; dwTypeData = text; cch = text.Length; fMask = 0; fType = 0; fState = 0; wID = 0; hSubMenu = IntPtr.Zero; hbmpChecked = IntPtr.Zero; hbmpUnchecked = IntPtr.Zero; dwItemData = IntPtr.Zero; hbmpItem = IntPtr.Zero; } public int cbSize; public MIIM fMask; public MFT fType; public MFS fState; public uint wID; public IntPtr hSubMenu; public IntPtr hbmpChecked; public IntPtr hbmpUnchecked; public IntPtr dwItemData; [MarshalAs(UnmanagedType.LPTStr)] public string dwTypeData; public int cch; public IntPtr hbmpItem; } // A generalized global memory handle used for data transfer operations by the // IAdviseSink, IDataObject, and IOleCache interfaces [StructLayout(LayoutKind.Sequential)] private struct STGMEDIUM { public TYMED tymed; public IntPtr hBitmap; public IntPtr hMetaFilePict; public IntPtr hEnhMetaFile; public IntPtr hGlobal; public IntPtr lpszFileName; public IntPtr pstm; public IntPtr pstg; public IntPtr pUnkForRelease; } // Defines the x- and y-coordinates of a point [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct POINT { public POINT(int x, int y) { this.x = x; this.y = y; } public int x; public int y; } #endregion #region Enums // Defines the values used with the IShellFolder::GetDisplayNameOf and IShellFolder::SetNameOf // methods to specify the type of file or folder names used by those methods [Flags] private enum SHGNO { NORMAL = 0x0000, INFOLDER = 0x0001, FOREDITING = 0x1000, FORADDRESSBAR = 0x4000, FORPARSING = 0x8000 } // The attributes that the caller is requesting, when calling IShellFolder::GetAttributesOf [Flags] private enum SFGAO : uint { BROWSABLE = 0x8000000, CANCOPY = 1, CANDELETE = 0x20, CANLINK = 4, CANMONIKER = 0x400000, CANMOVE = 2, CANRENAME = 0x10, CAPABILITYMASK = 0x177, COMPRESSED = 0x4000000, CONTENTSMASK = 0x80000000, DISPLAYATTRMASK = 0xfc000, DROPTARGET = 0x100, ENCRYPTED = 0x2000, FILESYSANCESTOR = 0x10000000, FILESYSTEM = 0x40000000, FOLDER = 0x20000000, GHOSTED = 0x8000, HASPROPSHEET = 0x40, HASSTORAGE = 0x400000, HASSUBFOLDER = 0x80000000, HIDDEN = 0x80000, ISSLOW = 0x4000, LINK = 0x10000, NEWCONTENT = 0x200000, NONENUMERATED = 0x100000, READONLY = 0x40000, REMOVABLE = 0x2000000, SHARE = 0x20000, STORAGE = 8, STORAGEANCESTOR = 0x800000, STORAGECAPMASK = 0x70c50008, STREAM = 0x400000, VALIDATE = 0x1000000 } // Determines the type of items included in an enumeration. // These values are used with the IShellFolder::EnumObjects method [Flags] private enum SHCONTF { FOLDERS = 0x0020, NONFOLDERS = 0x0040, INCLUDEHIDDEN = 0x0080, INIT_ON_FIRST_NEXT = 0x0100, NETPRINTERSRCH = 0x0200, SHAREABLE = 0x0400, STORAGE = 0x0800, } // Specifies how the shortcut menu can be changed when calling IContextMenu::QueryContextMenu [Flags] private enum CMF : uint { NORMAL = 0x00000000, DEFAULTONLY = 0x00000001, VERBSONLY = 0x00000002, EXPLORE = 0x00000004, NOVERBS = 0x00000008, CANRENAME = 0x00000010, NODEFAULT = 0x00000020, INCLUDESTATIC = 0x00000040, EXTENDEDVERBS = 0x00000100, RESERVED = 0xffff0000 } // Flags specifying the information to return when calling IContextMenu::GetCommandString [Flags] private enum GCS : uint { VERBA = 0, HELPTEXTA = 1, VALIDATEA = 2, VERBW = 4, HELPTEXTW = 5, VALIDATEW = 6 } // The cmd for a custom added menu item private enum CMD_CUSTOM { ExpandCollapse = (int)CMD_LAST + 1 } // Flags used with the CMINVOKECOMMANDINFOEX structure [Flags] private enum CMIC : uint { HOTKEY = 0x00000020, ICON = 0x00000010, FLAG_NO_UI = 0x00000400, UNICODE = 0x00004000, NO_CONSOLE = 0x00008000, ASYNCOK = 0x00100000, NOZONECHECKS = 0x00800000, SHIFT_DOWN = 0x10000000, CONTROL_DOWN = 0x40000000, FLAG_LOG_USAGE = 0x04000000, PTINVOKE = 0x20000000 } // Specifies how the window is to be shown [Flags] private enum SW { HIDE = 0, SHOWNORMAL = 1, NORMAL = 1, SHOWMINIMIZED = 2, SHOWMAXIMIZED = 3, MAXIMIZE = 3, SHOWNOACTIVATE = 4, SHOW = 5, MINIMIZE = 6, SHOWMINNOACTIVE = 7, SHOWNA = 8, RESTORE = 9, SHOWDEFAULT = 10, } // Window message flags [Flags] private enum WM : uint { ACTIVATE = 0x6, ACTIVATEAPP = 0x1C, AFXFIRST = 0x360, AFXLAST = 0x37F, APP = 0x8000, ASKCBFORMATNAME = 0x30C, CANCELJOURNAL = 0x4B, CANCELMODE = 0x1F, CAPTURECHANGED = 0x215, CHANGECBCHAIN = 0x30D, CHAR = 0x102, CHARTOITEM = 0x2F, CHILDACTIVATE = 0x22, CLEAR = 0x303, CLOSE = 0x10, COMMAND = 0x111, COMPACTING = 0x41, COMPAREITEM = 0x39, CONTEXTMENU = 0x7B, COPY = 0x301, COPYDATA = 0x4A, CREATE = 0x1, CTLCOLORBTN = 0x135, CTLCOLORDLG = 0x136, CTLCOLOREDIT = 0x133, CTLCOLORLISTBOX = 0x134, CTLCOLORMSGBOX = 0x132, CTLCOLORSCROLLBAR = 0x137, CTLCOLORSTATIC = 0x138, CUT = 0x300, DEADCHAR = 0x103, DELETEITEM = 0x2D, DESTROY = 0x2, DESTROYCLIPBOARD = 0x307, DEVICECHANGE = 0x219, DEVMODECHANGE = 0x1B, DISPLAYCHANGE = 0x7E, DRAWCLIPBOARD = 0x308, DRAWITEM = 0x2B, DROPFILES = 0x233, ENABLE = 0xA, ENDSESSION = 0x16, ENTERIDLE = 0x121, ENTERMENULOOP = 0x211, ENTERSIZEMOVE = 0x231, ERASEBKGND = 0x14, EXITMENULOOP = 0x212, EXITSIZEMOVE = 0x232, FONTCHANGE = 0x1D, GETDLGCODE = 0x87, GETFONT = 0x31, GETHOTKEY = 0x33, GETICON = 0x7F, GETMINMAXINFO = 0x24, GETOBJECT = 0x3D, GETSYSMENU = 0x313, GETTEXT = 0xD, GETTEXTLENGTH = 0xE, HANDHELDFIRST = 0x358, HANDHELDLAST = 0x35F, HELP = 0x53, HOTKEY = 0x312, HSCROLL = 0x114, HSCROLLCLIPBOARD = 0x30E, ICONERASEBKGND = 0x27, IME_CHAR = 0x286, IME_COMPOSITION = 0x10F, IME_COMPOSITIONFULL = 0x284, IME_CONTROL = 0x283, IME_ENDCOMPOSITION = 0x10E, IME_KEYDOWN = 0x290, IME_KEYLAST = 0x10F, IME_KEYUP = 0x291, IME_NOTIFY = 0x282, IME_REQUEST = 0x288, IME_SELECT = 0x285, IME_SETCONTEXT = 0x281, IME_STARTCOMPOSITION = 0x10D, INITDIALOG = 0x110, INITMENU = 0x116, INITMENUPOPUP = 0x117, INPUTLANGCHANGE = 0x51, INPUTLANGCHANGEREQUEST = 0x50, KEYDOWN = 0x100, KEYFIRST = 0x100, KEYLAST = 0x108, KEYUP = 0x101, KILLFOCUS = 0x8, LBUTTONDBLCLK = 0x203, LBUTTONDOWN = 0x201, LBUTTONUP = 0x202, LVM_GETEDITCONTROL = 0x1018, LVM_SETIMAGELIST = 0x1003, MBUTTONDBLCLK = 0x209, MBUTTONDOWN = 0x207, MBUTTONUP = 0x208, MDIACTIVATE = 0x222, MDICASCADE = 0x227, MDICREATE = 0x220, MDIDESTROY = 0x221, MDIGETACTIVE = 0x229, MDIICONARRANGE = 0x228, MDIMAXIMIZE = 0x225, MDINEXT = 0x224, MDIREFRESHMENU = 0x234, MDIRESTORE = 0x223, MDISETMENU = 0x230, MDITILE = 0x226, MEASUREITEM = 0x2C, MENUCHAR = 0x120, MENUCOMMAND = 0x126, MENUDRAG = 0x123, MENUGETOBJECT = 0x124, MENURBUTTONUP = 0x122, MENUSELECT = 0x11F, MOUSEACTIVATE = 0x21, MOUSEFIRST = 0x200, MOUSEHOVER = 0x2A1, MOUSELAST = 0x20A, MOUSELEAVE = 0x2A3, MOUSEMOVE = 0x200, MOUSEWHEEL = 0x20A, MOVE = 0x3, MOVING = 0x216, NCACTIVATE = 0x86, NCCALCSIZE = 0x83, NCCREATE = 0x81, NCDESTROY = 0x82, NCHITTEST = 0x84, NCLBUTTONDBLCLK = 0xA3, NCLBUTTONDOWN = 0xA1, NCLBUTTONUP = 0xA2, NCMBUTTONDBLCLK = 0xA9, NCMBUTTONDOWN = 0xA7, NCMBUTTONUP = 0xA8, NCMOUSEHOVER = 0x2A0, NCMOUSELEAVE = 0x2A2, NCMOUSEMOVE = 0xA0, NCPAINT = 0x85, NCRBUTTONDBLCLK = 0xA6, NCRBUTTONDOWN = 0xA4, NCRBUTTONUP = 0xA5, NEXTDLGCTL = 0x28, NEXTMENU = 0x213, NOTIFY = 0x4E, NOTIFYFORMAT = 0x55, NULL = 0x0, PAINT = 0xF, PAINTCLIPBOARD = 0x309, PAINTICON = 0x26, PALETTECHANGED = 0x311, PALETTEISCHANGING = 0x310, PARENTNOTIFY = 0x210, PASTE = 0x302, PENWINFIRST = 0x380, PENWINLAST = 0x38F, POWER = 0x48, PRINT = 0x317, PRINTCLIENT = 0x318, QUERYDRAGICON = 0x37, QUERYENDSESSION = 0x11, QUERYNEWPALETTE = 0x30F, QUERYOPEN = 0x13, QUEUESYNC = 0x23, QUIT = 0x12, RBUTTONDBLCLK = 0x206, RBUTTONDOWN = 0x204, RBUTTONUP = 0x205, RENDERALLFORMATS = 0x306, RENDERFORMAT = 0x305, SETCURSOR = 0x20, SETFOCUS = 0x7, SETFONT = 0x30, SETHOTKEY = 0x32, SETICON = 0x80, SETMARGINS = 0xD3, SETREDRAW = 0xB, SETTEXT = 0xC, SETTINGCHANGE = 0x1A, SHOWWINDOW = 0x18, SIZE = 0x5, SIZECLIPBOARD = 0x30B, SIZING = 0x214, SPOOLERSTATUS = 0x2A, STYLECHANGED = 0x7D, STYLECHANGING = 0x7C, SYNCPAINT = 0x88, SYSCHAR = 0x106, SYSCOLORCHANGE = 0x15, SYSCOMMAND = 0x112, SYSDEADCHAR = 0x107, SYSKEYDOWN = 0x104, SYSKEYUP = 0x105, TCARD = 0x52, TIMECHANGE = 0x1E, TIMER = 0x113, TVM_GETEDITCONTROL = 0x110F, TVM_SETIMAGELIST = 0x1109, UNDO = 0x304, UNINITMENUPOPUP = 0x125, USER = 0x400, USERCHANGED = 0x54, VKEYTOITEM = 0x2E, VSCROLL = 0x115, VSCROLLCLIPBOARD = 0x30A, WINDOWPOSCHANGED = 0x47, WINDOWPOSCHANGING = 0x46, WININICHANGE = 0x1A, SH_NOTIFY = 0x0401 } // Specifies the content of the new menu item [Flags] private enum MFT : uint { GRAYED = 0x00000003, DISABLED = 0x00000003, CHECKED = 0x00000008, SEPARATOR = 0x00000800, RADIOCHECK = 0x00000200, BITMAP = 0x00000004, OWNERDRAW = 0x00000100, MENUBARBREAK = 0x00000020, MENUBREAK = 0x00000040, RIGHTORDER = 0x00002000, BYCOMMAND = 0x00000000, BYPOSITION = 0x00000400, POPUP = 0x00000010 } // Specifies the state of the new menu item [Flags] private enum MFS : uint { GRAYED = 0x00000003, DISABLED = 0x00000003, CHECKED = 0x00000008, HILITE = 0x00000080, ENABLED = 0x00000000, UNCHECKED = 0x00000000, UNHILITE = 0x00000000, DEFAULT = 0x00001000 } // Specifies the content of the new menu item [Flags] private enum MIIM : uint { BITMAP = 0x80, CHECKMARKS = 0x08, DATA = 0x20, FTYPE = 0x100, ID = 0x02, STATE = 0x01, STRING = 0x40, SUBMENU = 0x04, TYPE = 0x10 } // Indicates the type of storage medium being used in a data transfer [Flags] private enum TYMED { ENHMF = 0x40, FILE = 2, GDI = 0x10, HGLOBAL = 1, ISTORAGE = 8, ISTREAM = 4, MFPICT = 0x20, NULL = 0 } #endregion #region IShellFolder [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214E6-0000-0000-C000-000000000046")] private interface IShellFolder { // Translates a file object's or folder's display name into an item identifier list. // Return value: error code, if any [PreserveSig] int ParseDisplayName( IntPtr hwnd, IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, ref uint pchEaten, out IntPtr ppidl, ref SFGAO pdwAttributes); // Allows a client to determine the contents of a folder by creating an item // identifier enumeration object and returning its IEnumIDList interface. // Return value: error code, if any [PreserveSig] int EnumObjects( IntPtr hwnd, SHCONTF grfFlags, out IntPtr enumIDList); // Retrieves an IShellFolder object for a subfolder. // Return value: error code, if any [PreserveSig] int BindToObject( IntPtr pidl, IntPtr pbc, ref Guid riid, out IntPtr ppv); // Requests a pointer to an object's storage interface. // Return value: error code, if any [PreserveSig] int BindToStorage( IntPtr pidl, IntPtr pbc, ref Guid riid, out IntPtr ppv); // Determines the relative order of two file objects or folders, given their // item identifier lists. Return value: If this method is successful, the // CODE field of the HRESULT contains one of the following values (the code // can be retrived using the helper function GetHResultCode): Negative A // negative return value indicates that the first item should precede // the second (pidl1 < pidl2). // Positive A positive return value indicates that the first item should // follow the second (pidl1 > pidl2). Zero A return value of zero // indicates that the two items are the same (pidl1 = pidl2). [PreserveSig] int CompareIDs( IntPtr lParam, IntPtr pidl1, IntPtr pidl2); // Requests an object that can be used to obtain information from or interact // with a folder object. // Return value: error code, if any [PreserveSig] int CreateViewObject( IntPtr hwndOwner, Guid riid, out IntPtr ppv); // Retrieves the attributes of one or more file objects or subfolders. // Return value: error code, if any [PreserveSig] int GetAttributesOf( uint cidl, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, ref SFGAO rgfInOut); // Retrieves an OLE interface that can be used to carry out actions on the // specified file objects or folders. // Return value: error code, if any [PreserveSig] int GetUIObjectOf( IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, ref Guid riid, IntPtr rgfReserved, out IntPtr ppv); // Retrieves the display name for the specified file object or subfolder. // Return value: error code, if any [PreserveSig()] int GetDisplayNameOf( IntPtr pidl, SHGNO uFlags, IntPtr lpName); // Sets the display name of a file object or subfolder, changing the item // identifier in the process. // Return value: error code, if any [PreserveSig] int SetNameOf( IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGNO uFlags, out IntPtr ppidlOut); } #endregion #region IContextMenu [ComImport()] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [GuidAttribute("000214e4-0000-0000-c000-000000000046")] private interface IContextMenu { // Adds commands to a shortcut menu [PreserveSig()] int QueryContextMenu( IntPtr hmenu, uint iMenu, uint idCmdFirst, uint idCmdLast, CMF uFlags); // Carries out the command associated with a shortcut menu item [PreserveSig()] int InvokeCommand( ref CMINVOKECOMMANDINFOEX info); // Retrieves information about a shortcut menu command, // including the help string and the language-independent, // or canonical, name for the command [PreserveSig()] int GetCommandString( uint idcmd, GCS uflags, uint reserved, [MarshalAs(UnmanagedType.LPArray)] byte[] commandstring, int cch); } [ComImport, Guid("000214f4-0000-0000-c000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IContextMenu2 { // Adds commands to a shortcut menu [PreserveSig()] int QueryContextMenu( IntPtr hmenu, uint iMenu, uint idCmdFirst, uint idCmdLast, CMF uFlags); // Carries out the command associated with a shortcut menu item [PreserveSig()] int InvokeCommand( ref CMINVOKECOMMANDINFOEX info); // Retrieves information about a shortcut menu command, // including the help string and the language-independent, // or canonical, name for the command [PreserveSig()] int GetCommandString( uint idcmd, GCS uflags, uint reserved, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder commandstring, int cch); // Allows client objects of the IContextMenu interface to // handle messages associated with owner-drawn menu items [PreserveSig] int HandleMenuMsg( uint uMsg, IntPtr wParam, IntPtr lParam); } [ComImport, Guid("bcfce0a0-ec17-11d0-8d10-00a0c90f2719")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IContextMenu3 { // Adds commands to a shortcut menu [PreserveSig()] int QueryContextMenu( IntPtr hmenu, uint iMenu, uint idCmdFirst, uint idCmdLast, CMF uFlags); // Carries out the command associated with a shortcut menu item [PreserveSig()] int InvokeCommand( ref CMINVOKECOMMANDINFOEX info); // Retrieves information about a shortcut menu command, // including the help string and the language-independent, // or canonical, name for the command [PreserveSig()] int GetCommandString( uint idcmd, GCS uflags, uint reserved, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder commandstring, int cch); // Allows client objects of the IContextMenu interface to // handle messages associated with owner-drawn menu items [PreserveSig] int HandleMenuMsg( uint uMsg, IntPtr wParam, IntPtr lParam); // Allows client objects of the IContextMenu3 interface to // handle messages associated with owner-drawn menu items [PreserveSig] int HandleMenuMsg2( uint uMsg, IntPtr wParam, IntPtr lParam, IntPtr plResult); } #endregion } }