/// <summary> /// Invokes the Delete command on the shell item. /// </summary> public void InvokeDelete() { CMINVOKECOMMANDINFO invoke = new CMINVOKECOMMANDINFO(); invoke.cbSize = Marshal.SizeOf(invoke); invoke.lpVerb = "delete"; try { m_ComInterface.InvokeCommand(ref invoke); } catch (COMException e) { // Ignore the exception raised when the user cancels // a delete operation. if (e.ErrorCode != unchecked ((int)0x800704C7)) { throw; } } }
/// <summary> /// Saves the invoke command information. /// </summary> /// <param name="isUnicode">if set to <c>true</c> the unicode structure is used.</param> /// <param name="ici">The ici.</param> /// <param name="iciex">The iciex.</param> private void SaveInvokeCommandInfo(bool isUnicode, CMINVOKECOMMANDINFO ici, CMINVOKECOMMANDINFOEX iciex) { if (isUnicode) { // Create command info from the Unicode structure. currentInvokeCommandInfo = new InvokeCommandInfo { WindowHandle = iciex.hwnd, ShowCommand = iciex.nShow }; } else { // Create command info from the ANSI structure. currentInvokeCommandInfo = new InvokeCommandInfo { WindowHandle = ici.hwnd, ShowCommand = ici.nShow }; } }
/// <summary> /// Carry out the command associated with a shortcut menu item. /// </summary> /// <param name="pici"> /// A pointer to a CMINVOKECOMMANDINFO or CMINVOKECOMMANDINFOEX structure /// containing information about the command. /// </param> public void InvokeCommand(IntPtr pici) { bool isUnicode = false; // Determine which structure is being passed in, CMINVOKECOMMANDINFO or // CMINVOKECOMMANDINFOEX based on the cbSize member of lpcmi. Although // the lpcmi parameter is declared in Shlobj.h as a CMINVOKECOMMANDINFO // structure, in practice it often points to a CMINVOKECOMMANDINFOEX // structure. This struct is an extended version of CMINVOKECOMMANDINFO // and has additional members that allow Unicode strings to be passed. CMINVOKECOMMANDINFO ici = (CMINVOKECOMMANDINFO)Marshal.PtrToStructure( pici, typeof(CMINVOKECOMMANDINFO)); CMINVOKECOMMANDINFOEX iciex = new CMINVOKECOMMANDINFOEX(); if (ici.cbSize == Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX))) { if ((ici.fMask & CMIC.CMIC_MASK_UNICODE) != 0) { isUnicode = true; iciex = (CMINVOKECOMMANDINFOEX)Marshal.PtrToStructure(pici, typeof(CMINVOKECOMMANDINFOEX)); } } // Determines whether the command is identified by its offset or verb. // There are two ways to identify commands: // // 1) The command's verb string // 2) The command's identifier offset // // If the high-order word of lpcmi->lpVerb (for the ANSI case) or // lpcmi->lpVerbW (for the Unicode case) is nonzero, lpVerb or lpVerbW // holds a verb string. If the high-order word is zero, the command // offset is in the low-order word of lpcmi->lpVerb. // For the ANSI case, if the high-order word is not zero, the command's // verb string is in lpcmi->lpVerb. if (!isUnicode && NativeMethods.HighWord(ici.verb.ToInt32()) != 0) { // Is the verb supported by this context menu extension? if (Marshal.PtrToStringAnsi(ici.verb) == verb) { OnVerbDisplayFileName(ici.hwnd); } else { // If the verb is not recognized by the context menu handler, it // must return E_FAIL to allow it to be passed on to the other // context menu handlers that might implement that verb. Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } // For the Unicode case, if the high-order word is not zero, the // command's verb string is in lpcmi->lpVerbW. else if (isUnicode && NativeMethods.HighWord(iciex.verbW.ToInt32()) != 0) { // Is the verb supported by this context menu extension? if (Marshal.PtrToStringUni(iciex.verbW) == verb) { OnVerbDisplayFileName(ici.hwnd); } else { // If the verb is not recognized by the context menu handler, it // must return E_FAIL to allow it to be passed on to the other // context menu handlers that might implement that verb. Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } // If the command cannot be identified through the verb string, then // check the identifier offset. else { // Is the command identifier offset supported by this context menu // extension? if (NativeMethods.LowWord(ici.verb.ToInt32()) == IDM_DISPLAY) { OnVerbDisplayFileName(ici.hwnd); } else { // If the verb is not recognized by the context menu handler, it // must return E_FAIL to allow it to be passed on to the other // context menu handlers that might implement that verb. Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } }
/// <summary> /// Displays shell shortcut menu. /// </summary> /// <param name="idlw">IDLWrapper object that specifies shell item</param> /// <param name="pntShow">location of the shortcut menu, in screen coordinates.</param> /// <param name="hwndParent">Handle of parent control. Parent control will get focus, and receives the messages about drawing 'Send to' submenues.</param> /// <param name="fCanRemove">set true to add 'remove this' menu item.</param> /// <returns> /// 0xFFFF user selected "Remove this item from menu". /// 0xFFFE user selected "Open containing folder". /// 0xFFFD If the user cancels the menu without making a selection, or if an error occurs /// </returns> public int Open(IDLWrapper idlw, Point pntShow, IntPtr hwndParent, bool fCanRemove) { const uint MF_STRING = 0x00000000; const uint MF_SEPARATOR = 0x00000800; const uint CMF_NORMAL = 0x00000000; const uint CMF_EXTENDEDVERBS = 0x00000100; const uint TPM_RETURNCMD = 0x0100; const uint S_OK = 0; const int COMMANDID_REMOVEITEM = 0xffff; // todo: move to const class const int COMMANDID_OPENPARENT = 0xfffe; const int COMMANDID_USERCANCEL = 0xfffd; IShellFolder shellFolderParent = null; try { // get IShellFolder IntPtr pIDLRelative; if (idlw.Available && S_OK == PInvoke.SHBindToParent(idlw.PIDL, ExplorerGUIDs.IID_IShellFolder, out shellFolderParent, out pIDLRelative) && shellFolderParent != null) { // get IContextMenu2 IntPtr[] pIDLs = new IntPtr[] { pIDLRelative }; uint reserved = 0; object oUnk; if (S_OK == shellFolderParent.GetUIObjectOf(IntPtr.Zero, (uint)pIDLs.Length, pIDLs, ExplorerGUIDs.IID_IContextMenu, ref reserved, out oUnk)) { pIContextMenu2 = oUnk as IContextMenu2; if (pIContextMenu2 != null) { using (ContextMenu contextMenu = new ContextMenu()) { int nResult = -1; uint uFlags = CMF_NORMAL; if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { uFlags |= CMF_EXTENDEDVERBS; } pIContextMenu2.QueryContextMenu(contextMenu.Handle, 0, 1, 0xffff, uFlags); // append optional menus if (fCanRemove) { // "Remove this item from menu" PInvoke.AppendMenu(contextMenu.Handle, MF_SEPARATOR, IntPtr.Zero, null); PInvoke.AppendMenu(contextMenu.Handle, MF_STRING, new IntPtr(COMMANDID_REMOVEITEM), QTUtility.ResMain[25]); } if (idlw.HasPath && idlw.Path.Length > 3 && idlw.IsFileSystem /*&& ( idlw.IsFileSystemFolder || idlw.IsFileSystemFile )*/) { // "Open containing folder" if (!fCanRemove) { // separator PInvoke.AppendMenu(contextMenu.Handle, MF_SEPARATOR, IntPtr.Zero, null); } PInvoke.AppendMenu(contextMenu.Handle, MF_STRING, new IntPtr(COMMANDID_OPENPARENT), QTUtility.ResMain[26]); } uint commandID = PInvoke.TrackPopupMenu(contextMenu.Handle, TPM_RETURNCMD, pntShow.X, pntShow.Y, 0, hwndParent, IntPtr.Zero); if (commandID != 0) { if (commandID == COMMANDID_REMOVEITEM) { return(COMMANDID_REMOVEITEM); } else if (commandID == COMMANDID_OPENPARENT) { if (idlw.HasPath) { try { QTTabBarClass tabbar = InstanceManager.GetThreadTabBar(); if (tabbar != null) { using (IDLWrapper idlwParent = idlw.GetParent()) { if (idlwParent.Available) { tabbar.OpenNewTabOrWindow(idlwParent); } } } // DesktopTool will handle it by itself nResult = COMMANDID_OPENPARENT; } catch { System.Media.SystemSounds.Asterisk.Play(); } } } else { CMINVOKECOMMANDINFO cmInfo = new CMINVOKECOMMANDINFO { cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)), fMask = 0, hwnd = hwndParent, lpVerb = (IntPtr)((commandID - 1) & 0xFFFF), lpParameters = IntPtr.Zero, lpDirectory = IntPtr.Zero, nShow = 1, //SW_SHOWNORMAL; dwHotKey = 0, hIcon = IntPtr.Zero }; // returns S_OK if successful, or an error value otherwise. // E_ABORT when user clicked "Open folder link target exists" of link file...( E_ABORT _HRESULT_TYPEDEF_(0x80004004L) ) nResult = pIContextMenu2.InvokeCommand(ref cmInfo); } } else { // 'if the user cancels the menu without making a selection, or if an error occurs' (MSDN) nResult = COMMANDID_USERCANCEL; } return(nResult); } } } } // if failed to create shell context menu, show 'remove this' menu instead if (fCanRemove) { using (ContextMenu contextMenu = new ContextMenu()) { PInvoke.AppendMenu(contextMenu.Handle, MF_STRING, new IntPtr(COMMANDID_REMOVEITEM), QTUtility.ResMain[25]); if (COMMANDID_REMOVEITEM == PInvoke.TrackPopupMenu(contextMenu.Handle, TPM_RETURNCMD, pntShow.X, pntShow.Y, 0, hwndParent, IntPtr.Zero)) { return(COMMANDID_REMOVEITEM); } } } return(COMMANDID_USERCANCEL); } catch { } finally { if (shellFolderParent != null) { Marshal.ReleaseComObject(shellFolderParent); } if (pIContextMenu2 != null) { Marshal.ReleaseComObject(pIContextMenu2); pIContextMenu2 = null; } } return(-1); }
/// <summary> /// Displays shell shortcut menu for multiple items. Paths must be sub items of one directory. /// </summary> /// <param name="lstIDLs"></param> /// <param name="pntShow"></param> /// <param name="hwndParent"></param> /// <returns></returns> public int Open(List <byte[]> lstIDLs, Point pntShow, IntPtr hwndParent) { // All lstIDLs members must share the same parent, for compatibility. const uint S_OK = 0; if (lstIDLs == null || lstIDLs.Count == 0) { return(-1); } IShellFolder shellFolder = null; List <IntPtr> lstRltvPIDLs = new List <IntPtr>(); IntPtr pIDLFirst = IntPtr.Zero; try { // build array of relative idls for (int i = 0; i < lstIDLs.Count; i++) { if (i == 0) { pIDLFirst = ShellMethods.CreateIDL(lstIDLs[0]); } using (IDLWrapper idlw = new IDLWrapper(lstIDLs[i])) { if (!idlw.Available) { continue; } IntPtr p = PInvoke.ILClone(PInvoke.ILFindLastID(idlw.PIDL)); if (p != IntPtr.Zero) { lstRltvPIDLs.Add(p); } } } IntPtr[] apidl = lstRltvPIDLs.ToArray(); if (apidl.Length > 0) { IntPtr pIDLRltv1st; if (S_OK == PInvoke.SHBindToParent(pIDLFirst, ExplorerGUIDs.IID_IShellFolder, out shellFolder, out pIDLRltv1st)) { // get IContextMenu2 uint rsv = 0; object oUnk; if (S_OK == shellFolder.GetUIObjectOf(IntPtr.Zero, (uint)apidl.Length, apidl, ExplorerGUIDs.IID_IContextMenu, ref rsv, out oUnk)) { pIContextMenu2 = oUnk as IContextMenu2; if (pIContextMenu2 != null) { using (ContextMenu contextMenu = new ContextMenu()) { const uint CMF_EXTENDEDVERBS = 0x00000100; const uint TPM_RETURNCMD = 0x0100; uint uFlags = 0; if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { uFlags |= CMF_EXTENDEDVERBS; } pIContextMenu2.QueryContextMenu(contextMenu.Handle, 0, 1, 0xffff, uFlags); uint commandID = PInvoke.TrackPopupMenu(contextMenu.Handle, TPM_RETURNCMD, pntShow.X, pntShow.Y, 0, hwndParent, IntPtr.Zero); if (commandID != 0) { CMINVOKECOMMANDINFO cmInfo = new CMINVOKECOMMANDINFO { cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)), fMask = 0, hwnd = hwndParent, lpVerb = (IntPtr)((commandID - 1) & 0xFFFF), lpParameters = IntPtr.Zero, lpDirectory = IntPtr.Zero, nShow = 1, //SW_SHOWNORMAL dwHotKey = 0, hIcon = IntPtr.Zero }; // this returns E_ABORT when user clicked "Open folder link target exists" of link file... pIContextMenu2.InvokeCommand(ref cmInfo); return(0); } } } } } } } catch { } finally { if (shellFolder != null) { Marshal.ReleaseComObject(shellFolder); } if (pIDLFirst != IntPtr.Zero) { PInvoke.CoTaskMemFree(pIDLFirst); } foreach (IntPtr pIDL in lstRltvPIDLs.Where(pIDL => pIDL != IntPtr.Zero)) { PInvoke.CoTaskMemFree(pIDL); } if (pIContextMenu2 != null) { Marshal.ReleaseComObject(pIContextMenu2); pIContextMenu2 = null; } } return(-1); }
public void InvokeCommand(IntPtr pici) { //bool isUnicode = false; // Determine which structure is being passed in, CMINVOKECOMMANDINFO or // CMINVOKECOMMANDINFOEX based on the cbSize member of lpcmi. Although // the lpcmi parameter is declared in Shlobj.h as a CMINVOKECOMMANDINFO // structure, in practice it often points to a CMINVOKECOMMANDINFOEX // structure. This struct is an extended version of CMINVOKECOMMANDINFO // and has additional members that allow Unicode strings to be passed. CMINVOKECOMMANDINFO ici = (CMINVOKECOMMANDINFO)Marshal.PtrToStructure( pici, typeof(CMINVOKECOMMANDINFO)); #region unicode //CMINVOKECOMMANDINFOEX iciex = new CMINVOKECOMMANDINFOEX(); //if (ici.cbSize == Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX))) //{ // if ((ici.fMask & CMIC.CMIC_MASK_UNICODE) != 0) // { // isUnicode = true; // iciex = (CMINVOKECOMMANDINFOEX)Marshal.PtrToStructure(pici, // typeof(CMINVOKECOMMANDINFOEX)); // } //} #endregion // Is the command identifier offset supported by this context menu // extension? int id = NativeMethods.LowWord(ici.verb.ToInt32()); if (id == MenuConnectWIFI_ID) { string s = ""; string lastipfile = Path.GetTempPath() + "lastip.txt"; if (File.Exists(lastipfile)) { FileStream fs = new FileStream(lastipfile, FileMode.Open); StreamReader sr = new StreamReader(fs); s = sr.ReadLine(); sr.Close(); fs.Close(); } s = Microsoft.VisualBasic.Interaction.InputBox(Properties.Resources.prompt_ConnectViaWIFI, Properties.Resources.menu_ConnectViaWIFI, s); if (!String.IsNullOrEmpty(s)) { if (NativeMethods.isIPAddress(s)) { File.Delete(lastipfile); FileStream fs = new FileStream(lastipfile, FileMode.CreateNew); StreamWriter sw = new StreamWriter(fs); sw.WriteLine(s); sw.Close(); fs.Close(); (new AndroidToolAdb()).Connect(s); } else { System.Windows.Forms.MessageBox.Show(Properties.Resources.prompt_NotAnIP); } } } else { for (int i = 0; i < devices.Count; i++) { AndroidDevice d = (AndroidDevice)devices[i]; AndroidToolAdb adb = new AndroidToolAdb(); if (MenuInstall2Memory_ID[i] == id) { adb.install(d.Serialno, sFileName); } else if (MenuInstall2SD_ID[i] == id) { adb.install(d.Serialno, sFileName, true); } else if (MenuUninstall_ID[i] == id) { if (curApk == null) { curApk = AndroidPackage2.GetAndroidPackage(sFileName); } adb.uninstall(d.Serialno, curApk.PackageName); } else if (MenuDisconnect_ID[i] == id) { adb.Disconnect(d.Serialno); } } } }
/// <summary> /// Called to invoke the comamand. /// </summary> /// <param name="pici">The command info pointer.</param> int IContextMenu.InvokeCommand(IntPtr pici) // ref CMINVOKECOMMANDINFO pici) { // We could have been provided with a CMINVOKECOMMANDINFO or a // CMINVOKECOMMANDINFOEX - cast to the small and then check the size. CMINVOKECOMMANDINFO ici = default(CMINVOKECOMMANDINFO); try { if (pici != IntPtr.Zero) { ici = (CMINVOKECOMMANDINFO)Marshal.PtrToStructure((IntPtr)pici, typeof(CMINVOKECOMMANDINFO)); } } catch { pici = IntPtr.Zero; } if (pici == IntPtr.Zero) { return(WinError.E_NOTIMPL); } var iciex = new CMINVOKECOMMANDINFOEX(); // We'll work out whether the commandis unicode or not... var isUnicode = false; // Is it a CMINVOKECOMMANDINFOEX? if (ici.cbSize == Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX))) { // Check the unicode flag, get the extended command info. if ((ici.fMask & CMIC.CMIC_MASK_UNICODE) != 0) { isUnicode = true; iciex = (CMINVOKECOMMANDINFOEX)Marshal.PtrToStructure((IntPtr)pici, typeof(CMINVOKECOMMANDINFOEX)); } } // The derived class MAY need some of the extended command data, // so we store it now. It can be retrieved and used in the handler // of the menu item. SaveInvokeCommandInfo(isUnicode, ici, iciex); // If we're not unicode and the verb hiword is not zero, // we've got an ANSI verb string. if (!isUnicode && User32.HighWord(ici.verb.ToInt32()) != 0) { // Get the verb. var verb = Marshal.PtrToStringAnsi(ici.verb); // DebugLog this key event. Log(string.Format("Invoke ANSI verb {0}", verb)); // Try and invoke the command. If we don't invoke it, throw // E_FAIL so that other handlers can try. if (!nativeContextMenuWrapper.TryInvokeCommand(verb)) { Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } // If we're unicode, and the verb hiword is not zero, // we've got a unicode command string. else if (isUnicode && User32.HighWord(iciex.verbW.ToInt32()) != 0) { // Get the verb. var verb = Marshal.PtrToStringAnsi(ici.verb); // DebugLog this key event. Log(string.Format("Invoke Unicode verb {0}", verb)); // Try and invoke the command. If we don't invoke it, throw // E_FAIL so that other handlers can try. if (!nativeContextMenuWrapper.TryInvokeCommand(verb)) { Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } // The verb pointer isn't a string at all, it's an index. else { // Get the command index. Logically, we don't actually need to // loword it, as the hiword is zero, but we're following the // documentation rigourously. var index = User32.LowWord(ici.verb.ToInt32()); // DebugLog this key event. Log(string.Format("Invoke command index {0}", index)); // Try and invoke the command. If we don't invoke it, throw // E_FAIL so that other handlers can try. if (!nativeContextMenuWrapper.TryInvokeCommand(index)) { Marshal.ThrowExceptionForHR(WinError.E_FAIL); } } // Return success. return(WinError.S_OK); }