如何實作 ICoNtextMenu 介面
ICoNtextMenu 是最強大的,也是實作的最複雜介面。 強烈建議您使用其中一個靜態動詞方法來實作動詞。 如需詳細資訊,請參閱 選擇靜態或動態快捷方式功能表方法。 ICoNtextMenu 有三種方法: GetCommandString、 InvokeCommand和 QueryCoNtextMenu,詳細討論在這裡。
您所需了解的事情
技術
- C++
必要條件
- 靜態動詞
- 快速鍵功能表
指示
ICoNtextMenu::GetCommandString 方法
處理常式的 ICoNtextMenu::GetCommandString 方法可用來傳回動詞的正式名稱。 這個方法是一個選擇項目。 在 Windows XP 和舊版 Windows 中,當 Windows 檔案總管具有 [狀態] 欄時,這個方法可用來擷取功能表項目之 [狀態] 欄中所顯示的解說文字。
idCmd參數會保存呼叫ICoNtextMenu::QueryCoNtextMenu時所定義的命令識別碼位移。 如果要求說明字串, uFlags 將會設定為 GCS_HELPTEXTW。 將說明字串複製到 pszName 緩衝區,並將其轉換成 PWSTR。 藉由將 uFlags 設定為 GCS_VERBW,要求動詞字串。 將適當的字串複製到 pszName,就像說明字串一樣。 快顯功能表處理常式不會使用 GCS_VALIDATEA 和 GCS_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 字串。
檢查pici的cbSize成員,以判斷傳入哪一個結構。 如果它是 CMINVOKECOMMANDINFOEX 結構, 且 fMask 成員已設定 CMIC_MASK_UNICODE 旗標,請將 pici 轉換成 CMINVOKECOMMANDINFOEX。 這可讓您的應用程式使用結構最後五個成員中包含的 Unicode 資訊。
結構的lpVerb 或 lpVerbW成員用來識別要執行的命令。 命令會以下列兩種方式之一來識別:
- 依命令的動詞字串
- 由命令的識別碼位移
若要區分這兩個案例,請檢查 ANSI 大小寫的 lpVerb 高序字或 Unicode 案例的 lpVerbW 。 如果高序字是非零字, lpVerb 或 lpVerbW 會保留動詞字串。 如果高序單字為零,則命令位移為 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參數會設定為要用於要加入之第一個功能表項目的索引。
處理常式新增的任何功能表項目都必須具有 idCmdFirst 和 idCmdLast 參數中值之間的識別碼。 一般而言,第一個命令識別碼會設定為 idCmdFirst,其會針對每個額外的命令遞增一 (1) 。 此做法可協助您避免超過 idCmdLast ,並在 Shell 呼叫多個處理常式時最大化可用的識別碼數目。
專案識別碼的 命令位移 是 識別碼與 idCmdFirst中的值之間的差異。 儲存處理常式新增至快捷方式功能表的每個專案的位移,因為 Shell 可能會使用位移來識別專案,如果後續呼叫 ICoNtextMenu::GetCommandString 或 ICoNtextMenu::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_pszVerb和m_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));}
備註
如需其他動詞實作工作,請參閱 建立快捷方式功能表處理常式。