Como implementar a interface IContextMenu
IContextMenu é a interface mais poderosa, mas também a mais complicada a ser implementada. É altamente recomendável que você implemente um verbo usando um dos métodos de verbo estático. Para obter mais informações, consulte Escolhendo um método de menu de atalho estático ou dinâmico. IContextMenu tem três métodos, GetCommandString, InvokeCommand e QueryContextMenu, que são discutidos aqui em detalhes.
O que você precisa saber
Tecnologias
- C++
Pré-requisitos
- Verbo Estático
- Menu de atalho
Instruções
Método IContextMenu::GetCommandString
O método IContextMenu::GetCommandString do manipulador é usado para retornar o nome canônico de um verbo. Esse método é opcional. No Windows XP e em versões anteriores do Windows, quando o Windows Explorer tem uma barra status, esse método é usado para recuperar o texto de ajuda exibido na barra Status de um item de menu.
O parâmetro idCmd contém o deslocamento do identificador do comando que foi definido quando IContextMenu::QueryContextMenu foi chamado. Se uma cadeia de caracteres de ajuda for solicitada, uFlags será definido como GCS_HELPTEXTW. Copie a cadeia de caracteres de ajuda para o buffer pszName , convertendo-a em um PWSTR. A cadeia de caracteres de verbo é solicitada definindo uFlags como GCS_VERBW. Copie a cadeia de caracteres apropriada para pszName, assim como com a cadeia de caracteres de ajuda. Os sinalizadores de GCS_VALIDATEA e GCS_VALIDATEW não são usados por manipuladores de menu de atalho.
O exemplo a seguir mostra uma implementação simples de GetCommandString que corresponde ao exemplo QueryContextMenu dado na seção Método IContextMenu::QueryContextMenu deste tópico. Como o manipulador adiciona apenas um item de menu, há apenas um conjunto de cadeias de caracteres que podem ser retornadas. O método testa se idCmd é válido e, se for, retorna a cadeia de caracteres solicitada.
A função StringCchCopy é usada para copiar a cadeia de caracteres solicitada para pszName para garantir que a cadeia de caracteres copiada não exceda o tamanho do buffer especificado por cchName. Este exemplo implementa o suporte apenas para os valores Unicode de uFlags, pois somente aqueles foram usados no Windows Explorer desde o Windows 2000.
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;
}
Método IContextMenu::InvokeCommand
Esse método é chamado quando um usuário clica em um item de menu para informar o manipulador para executar o comando associado. O parâmetro pici aponta para uma estrutura que contém as informações necessárias para executar o comando.
Embora pici seja declarado em Shlobj.h como uma estrutura CMINVOKECOMMANDINFO , na prática, geralmente aponta para uma estrutura CMINVOKECOMMANDINFOEX . Essa estrutura é uma versão estendida de CMINVOKECOMMANDINFO e tem vários membros adicionais que possibilitam passar cadeias de caracteres Unicode.
Verifique o membro cbSize do pici para determinar em qual estrutura foi passada. Se for uma estrutura CMINVOKECOMMANDINFOEX e o membro fMask tiver o sinalizador CMIC_MASK_UNICODE definido, converta pici em CMINVOKECOMMANDINFOEX. Isso permite que seu aplicativo use as informações Unicode contidas nos últimos cinco membros da estrutura.
O membro lpVerb ou lpVerbW da estrutura é usado para identificar o comando a ser executado. Os comandos são identificados de uma das duas maneiras a seguir:
- Pela cadeia de caracteres de verbo do comando
- Pelo deslocamento do identificador do comando
Para distinguir entre esses dois casos, marcar a palavra de alta ordem de lpVerb para o caso ANSI ou lpVerbW para o caso Unicode. Se a palavra de alta ordem for diferente de zero, lpVerb ou lpVerbW conterá uma cadeia de caracteres de verbo. Se a palavra de alta ordem for zero, o deslocamento de comando estará na palavra de baixa ordem lpVerb.
O exemplo a seguir mostra uma implementação simples de IContextMenu::InvokeCommand que corresponde aos exemplos IContextMenu::QueryContextMenu e IContextMenu::GetCommandString dados antes e depois desta seção. Primeiro, o método determina em qual estrutura está sendo passada. Em seguida, ele determina se o comando é identificado por seu deslocamento ou seu verbo. Se lpVerb ou lpVerbW mantiver um verbo ou deslocamento válido, o método exibirá uma caixa de mensagem.
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;
}
Método IContextMenu::QueryContextMenu
O Shell chama IContextMenu::QueryContextMenu para habilitar o manipulador de menu de atalho para adicionar seus itens de menu ao menu. Ele passa o identificador HMENU no parâmetro hmenu . O parâmetro indexMenu é definido como o índice a ser usado para o primeiro item de menu a ser adicionado.
Todos os itens de menu adicionados pelo manipulador devem ter identificadores que se enquadram entre os valores nos parâmetros idCmdFirst e idCmdLast . Normalmente, o primeiro identificador de comando é definido como idCmdFirst, que é incrementado por um (1) para cada comando adicional. Essa prática ajuda você a evitar exceder idCmdLast e maximiza o número de identificadores disponíveis caso o Shell chame mais de um manipulador.
O deslocamento de comando de um identificador de item é a diferença entre o identificador e o valor em idCmdFirst. Armazene o deslocamento de cada item que seu manipulador adiciona ao menu de atalho, pois o Shell pode usar o deslocamento para identificar o item se ele chamar posteriormente IContextMenu::GetCommandString ou IContextMenu::InvokeCommand.
Você também deve atribuir um verbo a cada comando adicionado. Um verbo é uma cadeia de caracteres que pode ser usada em vez do deslocamento para identificar o comando quando InvokeCommand é chamado. Ele também é usado por funções como ShellExecuteEx para executar comandos de menu de atalho.
Há três sinalizadores que podem ser passados por meio do parâmetro uFlags relevantes para manipuladores de menu de atalho. Eles são descritos na tabela a seguir.
Sinalizador | Descrição |
---|---|
CMF_DEFAULTONLY | O usuário selecionou o comando padrão, geralmente clicando duas vezes no objeto . IContextMenu::QueryContextMenu deve retornar o controle para o Shell sem modificar o menu. |
CMF_NODEFAULT | Nenhum item no menu deve ser o item padrão. O método deve adicionar seus comandos ao menu. |
CMF_NORMAL | O menu de atalho será exibido normalmente. O método deve adicionar seus comandos ao menu. |
Use InsertMenu ou InsertMenuItem para adicionar itens de menu à lista. Em seguida, retorne um valor HRESULT com a severidade definida como SEVERITY_SUCCESS. Defina o valor do código como o deslocamento do maior identificador de comando atribuído, mais um (1). Por exemplo, suponha que idCmdFirst esteja definido como 5 e adicione três itens ao menu com identificadores de comando de 5, 7 e 8. O valor retornado deve ser MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 + 1).
O exemplo a seguir mostra uma implementação simples de QueryContextMenu que insere um único comando. O deslocamento do identificador para o comando é IDM_DISPLAY, que é definido como zero. As variáveis m_pszVerb e m_pwszVerb são variáveis privadas usadas para armazenar a cadeia de caracteres de verbo independente de linguagem associada nos formatos ANSI e 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));}
Comentários
Para outras tarefas de implementação de verbo, consulte Criando manipuladores de menu de atalho.