/// <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) == this._verb) { return; } 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) == this._verb) { return; } 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? int Count = NativeMethods.LowWord(ici.verb.ToInt32()); if (0 <= Count && Count < _printerList.Count) { ExecuteCommand(ici.verb.ToInt32()); } 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); } } }