Share via


如何實作 ICoNtextMenu 介面

ICoNtextMenu 是最強大的,也是實作的最複雜介面。 強烈建議您使用其中一個靜態動詞方法來實作動詞。 如需詳細資訊,請參閱 選擇靜態或動態快捷方式功能表方法ICoNtextMenu 有三種方法: GetCommandStringInvokeCommandQueryCoNtextMenu,詳細討論在這裡。

您所需了解的事情

技術

  • C++

必要條件

  • 靜態動詞
  • 快速鍵功能表

指示

ICoNtextMenu::GetCommandString 方法

處理常式的 ICoNtextMenu::GetCommandString 方法可用來傳回動詞的正式名稱。 這個方法是一個選擇項目。 在 Windows XP 和舊版 Windows 中,當 Windows 檔案總管具有 [狀態] 欄時,這個方法可用來擷取功能表項目之 [狀態] 欄中所顯示的解說文字。

idCmd參數會保存呼叫ICoNtextMenu::QueryCoNtextMenu時所定義的命令識別碼位移。 如果要求說明字串, uFlags 將會設定為 GCS_HELPTEXTW。 將說明字串複製到 pszName 緩衝區,並將其轉換成 PWSTR。 藉由將 uFlags 設定為 GCS_VERBW,要求動詞字串。 將適當的字串複製到 pszName,就像說明字串一樣。 快顯功能表處理常式不會使用 GCS_VALIDATEAGCS_VALIDATEW 旗標。

下列範例顯示與本主題之 ICoNtextMenu::QueryCoNtextMenu 方法一節中所指定之 QueryCoNtextMenu範例對應的GetCommandString簡單實作。 因為處理常式只會新增一個功能表項目,所以只能傳回一組字串。 方法會測試 idCmd 是否有效,如果為 ,則會傳回要求的字串。

StringCchCopy函式可用來將要求的字串複製到pszName,以確保複製的字串不會超過cchName所指定的緩衝區大小。 此範例只會實作 uFlags Unicode 值的支援,因為只有 Windows 2000 以來已在 Windows 檔案總管中使用。

IFACEMETHODIMP CMenuExtension::GetCommandString(UINT idCommand, 
                                                UINT uFlags, 
                                                UINT *pReserved, 
                                                PSTR pszName, 
                                                UINT cchName)
{
    HRESULT hr = E_INVALIDARG;

    if (idCommand == IDM_DISPLAY)
    {
        switch (uFlags)
        {
            case GCS_HELPTEXTW:
                // Only useful for pre-Vista versions of Windows that 
                // have a Status bar.
                hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), 
                                    cchName, 
                                    L"Display File Name");
                break; 

            case GCS_VERBW:
                // GCS_VERBW is an optional feature that enables a caller
                // to discover the canonical name for the verb that is passed in
                // through idCommand.
                hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), 
                                    cchName, 
                                    L"DisplayFileName");
                break; 
        }
    }
    return hr;
}

ICoNtextMenu::InvokeCommand 方法

當使用者按一下功能表項目以告知處理常式執行相關聯的命令時,會呼叫這個方法。 pici參數指向結構,其中包含執行命令所需的資訊。

雖然 pici 在 Shlobj.h 中宣告為 CMINVOKECOMMANDINFO 結構,但實際上通常會指向 CMINVOKECOMMANDINFOEX 結構。 此結構是 CMINVOKECOMMANDINFO 的擴充版本,而且有數個額外的成員,可讓您傳遞 Unicode 字串。

檢查picicbSize成員,以判斷傳入哪一個結構。 如果它是 CMINVOKECOMMANDINFOEX 結構, 且 fMask 成員已設定 CMIC_MASK_UNICODE 旗標,請將 pici 轉換成 CMINVOKECOMMANDINFOEX。 這可讓您的應用程式使用結構最後五個成員中包含的 Unicode 資訊。

結構的lpVerb 或 lpVerbW成員用來識別要執行的命令。 命令會以下列兩種方式之一來識別:

  • 依命令的動詞字串
  • 由命令的識別碼位移

若要區分這兩個案例,請檢查 ANSI 大小寫的 lpVerb 高序字或 Unicode 案例的 lpVerbW 。 如果高序字是非零字, lpVerblpVerbW 會保留動詞字串。 如果高序單字為零,則命令位移為 lpVerb的低序字。

下列範例示範ICoNtextMenu::InvokeCommand的簡單實作,對應至本節前後指定的ICoNtextMenu::QueryCoNtextMenu::GetCommandString範例。 方法會先判斷傳入哪一個結構。 然後,它會判斷命令是由其位移或其動詞所識別。 如果lpVerb 或 lpVerbW保留有效的動詞或位移,則方法會顯示訊息方塊。

STDMETHODIMP CShellExtension::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
    BOOL fEx = FALSE;
    BOOL fUnicode = FALSE;

    if(lpcmi->cbSize == sizeof(CMINVOKECOMMANDINFOEX))
    {
        fEx = TRUE;
        if((lpcmi->fMask & CMIC_MASK_UNICODE))
        {
            fUnicode = TRUE;
        }
    }

    if( !fUnicode && HIWORD(lpcmi->lpVerb))
    {
        if(StrCmpIA(lpcmi->lpVerb, m_pszVerb))
        {
            return E_FAIL;
        }
    }

    else if( fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX *) lpcmi)->lpVerbW))
    {
        if(StrCmpIW(((CMINVOKECOMMANDINFOEX *)lpcmi)->lpVerbW, m_pwszVerb))
        {
            return E_FAIL;
        }
    }

    else if(LOWORD(lpcmi->lpVerb) != IDM_DISPLAY)
    {
        return E_FAIL;
    }

    else
    {
        MessageBox(lpcmi->hwnd,
                   "The File Name",
                   "File Name",
                   MB_OK|MB_ICONINFORMATION);
    }

    return S_OK;
}

ICoNtextMenu::QueryCoNtextMenu 方法

Shell 會呼叫 ICoNtextMenu::QueryCoNtextMenu ,讓快捷方式功能表處理常式將其功能表項目新增至功能表。 它會傳入hmenu參數中的HMENU控制碼。 indexMenu參數會設定為要用於要加入之第一個功能表項目的索引。

處理常式新增的任何功能表項目都必須具有 idCmdFirstidCmdLast 參數中值之間的識別碼。 一般而言,第一個命令識別碼會設定為 idCmdFirst,其會針對每個額外的命令遞增一 (1) 。 此做法可協助您避免超過 idCmdLast ,並在 Shell 呼叫多個處理常式時最大化可用的識別碼數目。

專案識別碼的 命令位移識別碼與 idCmdFirst中的值之間的差異。 儲存處理常式新增至快捷方式功能表的每個專案的位移,因為 Shell 可能會使用位移來識別專案,如果後續呼叫 ICoNtextMenu::GetCommandStringICoNtextMenu::InvokeCommand

您也應該將 動詞 指派給您新增的每個命令。 動詞是字串,可在呼叫 InvokeCommand 時用來識別命令的位移。 它也會由 ShellExecuteEx 等函式用來執行快捷方式功能表命令。

有三個旗標可以透過與快捷方式功能表處理常式相關的 uFlags 參數傳入。 如下表中所述。

旗標 描述
CMF_DEFAULTONLY 使用者已選取預設命令,通常是按兩下 物件。 ICoNtextMenu::QueryCoNtextMenu 應該將控制項傳回殼層,而不需修改功能表。
CMF_NODEFAULT 功能表中沒有專案應該是預設專案。 方法應該將其命令新增至功能表。
CMF_NORMAL 快捷方式功能表通常會顯示。 方法應該將其命令新增至功能表。

 

使用 InsertMenu 或InsertMenuItem 將功能表項目新增至清單。 然後傳回 HRESULT 值,並將嚴重性設定為 SEVERITY_SUCCESS。 將程式碼值設定為指派的最大命令識別碼位移,加上一個 (1) 。 例如,假設 idCmdFirst 設定為 5,而且您會將三個專案新增至具有 5、7 和 8 命令識別碼的功能表。 傳回值應該MAKE_HRESULT (SEVERITY_SUCCESS、0、8 + 1) 。

下列範例示範插入單一命令的 QueryCoNtextMenu 簡單實作。 命令的識別碼位移IDM_DISPLAY,其設定為零。 m_pszVerbm_pwszVerb變數是私用變數,用來以 ANSI 和 Unicode 格式儲存與語言無關的動詞字串。

#define IDM_DISPLAY 0

STDMETHODIMP CMenuExtension::QueryContextMenu(HMENU hMenu,
                                              UINT indexMenu,
                                              UINT idCmdFirst,
                                              UINT idCmdLast,
                                              UINT uFlags)
{
    HRESULT hr;
    
    if(!(CMF_DEFAULTONLY & uFlags))
    {
        InsertMenu(hMenu, 
                   indexMenu, 
                   MF_STRING | MF_BYPOSITION, 
                   idCmdFirst + IDM_DISPLAY, 
                   "&Display File Name");

    
        
        hr = StringCbCopyA(m_pszVerb, sizeof(m_pszVerb), "display");
        hr = StringCbCopyW(m_pwszVerb, sizeof(m_pwszVerb), L"display");

        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_DISPLAY + 1));
    }

    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));}

備註

如需其他動詞實作工作,請參閱 建立快捷方式功能表處理常式