You need to use COM interfaces to create a shell menu item handler. The interfaces you'll need are
[ComImport(),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
GuidAttribute("000214e8-0000-0000-c000-000000000046")]
internal interface IShellExtInit
{
[PreserveSig()]
int Initialize (IntPtr pidlFolder, IntPtr lpdobj, uint hKeyProgID);
}
[ComImport(),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
GuidAttribute("000214e4-0000-0000-c000-000000000046")]
internal interface IContextMenu
{
[PreserveSig()]
int QueryContextMenu(HMenu hmenu, int iMenu, int idCmdFirst, int idCmdLast, CMF uFlags);
[PreserveSig()]
void InvokeCommand (IntPtr pici);
[PreserveSig()]
void GetCommandString(int idcmd, uint uflags, int reserved, StringBuilder commandstring, int cch);
}
You'll create a class that implements both interfaces. Your class will need a Guid attribute so it can be registered as a COM object with the shell.
The menu code you'll need will be similar to this
int IContextMenu.QueryContextMenu(HMenu hMenu, int iMenu, int idCmdFirst, int idCmdLast, CMF uFlags)
{
StringBuilder sb = new StringBuilder(1024);
uint selected = Helpers.DragQueryFile(_hDrop, 0xffffffff, null, 0);
if(selected > 0)
{
_fileArray = new string[(int)selected];
for(uint i = 0; i < selected; i++)
{
Helpers.DragQueryFile(_hDrop, i, sb, sb.Capacity + 1);
fileArray[i] = sb.ToString();
}
}
int id = 1;
if ( (uFlags & (CMF.CMF_VERBSONLY | CMF.CMF_DEFAULTONLY | CMF.CMF_NOVERBS)) == 0 || (uFlags & CMF.CMF_EXPLORE) != 0)
{
HMenu submenu = Helpers.CreatePopupMenu();
Helpers.AppendMenu(submenu, MFMENU.MF_STRING | MFMENU.MF_ENABLED, new IntPtr(idCmdFirst + id++), "Custom Sub Item 1");
Helpers.AppendMenu(submenu, MFMENU.MF_STRING | MFMENU.MF_ENABLED, new IntPtr(idCmdFirst + id++), "Custom Sub Item 2");
Helpers.InsertMenu(hMenu, 7, MFMENU.MF_BYPOSITION | MFMENU.MF_POPUP | MFMENU.MF_ENABLED, submenu.handle, "My Item");
}
return id;
}
void IContextMenu.GetCommandString(int idCmd, uint uFlags, int pwReserved, StringBuilder commandString, int cchMax)
{
switch((GCS)uFlags)
{
default:
break;
}
}
void IContextMenu.InvokeCommand(IntPtr pici)
{
try
{
Type typINVOKECOMMANDINFO = Type.GetType("My.Full.Namespace.INVOKECOMMANDINFO");
INVOKECOMMANDINFO ici = (INVOKECOMMANDINFO)Marshal.PtrToStructure(pici, typINVOKECOMMANDINFO);
switch (ici.verb - 1)
{
case 0:
MyMethod();
break;
case 1:
MyOtherMethod();
break;
}
}
catch
{
}
}
int IShellExtInit.Initialize(IntPtr pidlFolder, IntPtr lpdobj, uint hKeyProgID)
{
try
{
_dataObject = null;
if (lpdobj != (IntPtr)0)
{
_dataObject = (IDataObject)Marshal.GetObjectForIUnknown(lpdobj);
FORMATETC fmt = new FORMATETC();
fmt.cfFormat = CLIPFORMAT.CF_HDROP;
fmt.ptd = 0;
fmt.dwAspect = DVASPECT.DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.tymed = TYMED.TYMED_HGLOBAL;
STGMEDIUM medium = new STGMEDIUM();
_dataObject.GetData(ref fmt, ref medium);
_hDrop = medium.hGlobal;
}
}
catch(Exception)
{
}
return 0;
}
#region MIIM
internal enum MIIM : uint
{
STATE = 0x00000001,
ID = 0x00000002,
SUBMENU = 0x00000004,
CHECKMARKS = 0x00000008,
TYPE = 0x00000010,
DATA = 0x00000020,
STRING = 0x00000040,
BITMAP = 0x00000080,
FTYPE = 0x00000100
}
#endregion
#region MF
internal enum MF : uint
{
INSERT = 0x00000000,
CHANGE = 0x00000080,
APPEND = 0x00000100,
DELETE = 0x00000200,
REMOVE = 0x00001000,
BYCOMMAND = 0x00000000,
BYPOSITION = 0x00000400,
SEPARATOR = 0x00000800,
ENABLED = 0x00000000,
GRAYED = 0x00000001,
DISABLED = 0x00000002,
UNCHECKED = 0x00000000,
CHECKED = 0x00000008,
USECHECKBITMAPS=0x00000200,
STRING = 0x00000000,
BITMAP = 0x00000004,
OWNERDRAW = 0x00000100,
POPUP = 0x00000010,
MENUBARBREAK = 0x00000020,
MENUBREAK = 0x00000040,
UNHILITE = 0x00000000,
HILITE = 0x00000080,
DEFAULT = 0x00001000,
SYSMENU = 0x00002000,
HELP = 0x00004000,
RIGHTJUSTIFY = 0x00004000,
MOUSESELECT = 0x00008000
}
#endregion
#region CLIPFORMAT
internal enum CLIPFORMAT : uint
{
CF_TEXT = 1,
CF_BITMAP = 2,
CF_METAFILEPICT = 3,
CF_SYLK = 4,
CF_DIF = 5,
CF_TIFF = 6,
CF_OEMTEXT = 7,
CF_DIB = 8,
CF_PALETTE = 9,
CF_PENDATA = 10,
CF_RIFF = 11,
CF_WAVE = 12,
CF_UNICODETEXT = 13,
CF_ENHMETAFILE = 14,
CF_HDROP = 15,
CF_LOCALE = 16,
CF_MAX = 17,
CF_OWNERDISPLAY = 0x0080,
CF_DSPTEXT = 0x0081,
CF_DSPBITMAP = 0x0082,
CF_DSPMETAFILEPICT =0x0083,
CF_DSPENHMETAFILE = 0x008E,
CF_PRIVATEFIRST = 0x0200,
CF_PRIVATELAST = 0x02FF,
CF_GDIOBJFIRST = 0x0300,
CF_GDIOBJLAST = 0x03FF
}
#endregion
#region DVASPECT
internal enum DVASPECT: uint
{
DVASPECT_CONTENT = 1,
DVASPECT_THUMBNAIL = 2,
DVASPECT_ICON = 4,
DVASPECT_DOCPRINT = 8
}
#endregion
#region TYMED
internal enum TYMED: uint
{
TYMED_HGLOBAL = 1,
TYMED_FILE = 2,
TYMED_ISTREAM = 4,
TYMED_ISTORAGE= 8,
TYMED_GDI = 16,
TYMED_MFPICT = 32,
TYMED_ENHMF = 64,
TYMED_NULL= 0
}
#endregion
#region CMF
internal enum CMF: uint
{
CMF_NORMAL = 0x00000000,
CMF_DEFAULTONLY = 0x00000001,
CMF_VERBSONLY = 0x00000002,
CMF_EXPLORE = 0x00000004,
CMF_NOVERBS = 0x00000008,
CMF_CANRENAME = 0x00000010,
CMF_NODEFAULT = 0x00000020,
CMF_INCLUDESTATIC= 0x00000040,
CMF_RESERVED = 0xffff0000
}
#endregion
#region GCS
internal enum GCS: uint
{
VERBA = 0x00000000,
HELPTEXTA = 0x00000001,
VALIDATEA = 0x00000002,
VERBW = 0x00000004,
HELPTEXTW = 0x00000005,
VALIDATEW = 0x00000006,
UNICODE = 0x00000004,
VERB = GCS.VERBA,
HELPTEXT = GCS.HELPTEXTA,
VALIDATE = GCS.VALIDATEA
}
#endregion
#region MENUITEMINFO
[StructLayout(LayoutKind.Sequential)]
internal struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public int wID;
public int hSubMenu;
public int hbmpChecked;
public int hbmpUnchecked;
public int dwItemData;
public String dwTypeData;
public uint cch;
public int hbmpItem;
}
#endregion
#region FORMATETC
[StructLayout(LayoutKind.Sequential)]
internal struct FORMATETC
{
public CLIPFORMAT cfFormat;
public uint ptd;
public DVASPECT dwAspect;
public int lindex;
public TYMED tymed;
}
#endregion
#region STGMEDIUM
[StructLayout(LayoutKind.Sequential)]
internal struct STGMEDIUM
{
public uint tymed;
public uint hGlobal;
public uint pUnkForRelease;
}
#endregion
#region INVOKECOMMANDINFO
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct INVOKECOMMANDINFO
{
public uint cbSize;
public uint fMask;
public uint wnd;
public int verb;
[MarshalAs(UnmanagedType.LPStr)]
public string parameters;
[MarshalAs(UnmanagedType.LPStr)]
public string directory;
public int Show;
public uint HotKey;
public uint hIcon;
}
#endregion
#region IDataObject
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute("0000010e-0000-0000-C000-000000000046")]
internal interface IDataObject
{
[PreserveSig()]
int GetData(ref FORMATETC a, ref STGMEDIUM b);
[PreserveSig()]
void GetDataHere(int a, ref STGMEDIUM b);
[PreserveSig()]
int QueryGetData(int a);
[PreserveSig()]
int GetCanonicalFormatEtc(int a, ref int b);
[PreserveSig()]
int SetData(int a, int b, int c);
[PreserveSig()]
int EnumFormatEtc(uint a, ref Object b);
[PreserveSig()]
int DAdvise(int a, uint b, Object c, ref uint d);
[PreserveSig()]
int DUnadvise(uint a);
[PreserveSig()]
int EnumDAdvise(ref Object a);
}
#endregion
|