Condividi tramite


Come implementare l'interfaccia IContextMenu

IContextMenu è la più potente ma anche l'interfaccia più complessa da implementare. È consigliabile implementare un verbo usando uno dei metodi dei verbi statici. Per altre informazioni, vedere Scelta di un metodo di menu di scelta rapida statico o dinamico. IContextMenu include tre metodi, GetCommandString, InvokeCommand e QueryContextMenu, descritti qui in dettaglio.

Informazioni importanti

Tecnologie

  • C++

Prerequisiti

  • Verbo statico
  • Menu di scelta rapida

Istruzioni

Metodo IContextMenu::GetCommandString

Il metodo IContextMenu::GetCommandString del gestore viene usato per restituire il nome canonico per un verbo. È facoltativo. In Windows XP e nelle versioni precedenti di Windows, quando Esplora risorse dispone di una barra di stato, questo metodo viene utilizzato per recuperare il testo della Guida visualizzato nella barra di stato per una voce di menu.

Il parametro idCmd contiene l'offset dell'identificatore del comando definito quando è stato chiamato IContextMenu::QueryContextMenu . Se viene richiesta una stringa della Guida, uFlags verrà impostato su GCS_HELPTEXTW. Copiare la stringa della Guida nel buffer pszName , eseguendo il cast in un oggetto PWSTR. La stringa verbo viene richiesta impostando uFlags su GCS_VERBW. Copiare la stringa appropriata in pszName, esattamente come per la stringa della Guida. I flag GCS_VALIDATEA e GCS_VALIDATEW non vengono usati dai gestori di menu di scelta rapida.

Nell'esempio seguente viene illustrata una semplice implementazione di GetCommandString che corrisponde all'esempio QueryContextMenu fornito nella sezione Metodo IContextMenu::QueryContextMenu di questo argomento. Poiché il gestore aggiunge una sola voce di menu, è possibile restituire un solo set di stringhe. Il metodo verifica se idCmd è valido e, in caso affermativo, restituisce la stringa richiesta.

La funzione StringCchCopy viene usata per copiare la stringa richiesta in pszName per assicurarsi che la stringa copiata non superi le dimensioni del buffer specificato da cchName. Questo esempio implementa il supporto solo per i valori Unicode di uFlags, perché solo quelli sono stati usati in Esplora risorse a partire da 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;
}

Metodo IContextMenu::InvokeCommand

Questo metodo viene chiamato quando un utente fa clic su una voce di menu per indicare al gestore di eseguire il comando associato. Il parametro pici punta a una struttura contenente le informazioni necessarie per eseguire il comando.

Sebbene pici sia dichiarato in Shlobj.h come struttura CMINVOKECOMMANDINFO , in pratica punta spesso a una struttura CMINVOKECOMMANDINFOEX . Questa struttura è una versione estesa di CMINVOKECOMMANDINFO e include diversi membri aggiuntivi che consentono di passare stringhe Unicode.

Controllare il membro cbSize di pici per determinare la struttura passata. Se si tratta di una struttura CMINVOKECOMMANDINFOEX e il membro fMask ha il flag CMIC_MASK_UNICODE impostato, eseguire il cast pici in CMINVOKECOMMANDINFOEX. In questo modo l'applicazione può usare le informazioni Unicode contenute negli ultimi cinque membri della struttura.

Il membro lpVerb o lpVerbW della struttura viene usato per identificare il comando da eseguire. I comandi vengono identificati in uno dei due modi seguenti:

  • In base alla stringa verbo del comando
  • Offset dell'identificatore del comando

Per distinguere tra questi due casi, controllare la parola dell'ordine elevato di lpVerb per il caso ANSI o lpVerbW per il caso Unicode. Se la parola di ordine elevato è diversa da zero, lpVerb o lpVerbW contiene una stringa verbo. Se la parola di ordine elevato è zero, l'offset del comando si trova nella parola in ordine basso di lpVerb.

L'esempio seguente illustra una semplice implementazione di IContextMenu::InvokeCommand che corrisponde agli esempi IContextMenu::QueryContextMenu e IContextMenu::GetCommandString specificati prima e dopo questa sezione. Il metodo determina innanzitutto la struttura passata. Determina quindi se il comando è identificato dal relativo offset o dal relativo verbo. Se lpVerb o lpVerbW contiene un verbo o un offset valido, il metodo visualizza una finestra di messaggio.

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;
}

Metodo IContextMenu::QueryContextMenu

Shell chiama IContextMenu::QueryContextMenu per consentire al gestore di menu di scelta rapida di aggiungere le voci di menu al menu. Passa l'handle HMENU nel parametro hmenu . Il parametro indexMenu è impostato sull'indice da utilizzare per la prima voce di menu da aggiungere.

Le voci di menu aggiunte dal gestore devono avere identificatori che rientrano tra i valori nei parametri idCmdFirst e idCmdLast . In genere, il primo identificatore di comando è impostato su idCmdFirst, che viene incrementato di uno (1) per ogni comando aggiuntivo. Questa procedura consente di evitare di superare idCmdLast e massimizzare il numero di identificatori disponibili nel caso in cui shell chiami più di un gestore.

L'offset del comando di un identificatore di elemento è la differenza tra l'identificatore e il valore in idCmdFirst. Archiviare l'offset di ogni elemento aggiunto dal gestore al menu di scelta rapida, perché shell potrebbe usare l'offset per identificare l'elemento se successivamente chiama IContextMenu::GetCommandString o IContextMenu::InvokeCommand.

È anche necessario assegnare un verbo a ogni comando aggiunto. Un verbo è una stringa che può essere usata anziché l'offset per identificare il comando quando viene chiamato InvokeCommand . Viene usato anche da funzioni come ShellExecuteEx per eseguire i comandi di menu di scelta rapida.

Esistono tre flag che possono essere passati tramite il parametro uFlags rilevanti per i gestori di menu di scelta rapida. descritti nella tabella seguente.

Flag Descrizione
CMF_DEFAULTONLY L'utente ha selezionato il comando predefinito, in genere facendo doppio clic sull'oggetto. IContextMenu::QueryContextMenu deve restituire il controllo alla shell senza modificare il menu.
CMF_NODEFAULT Nessuna voce nel menu deve essere la voce predefinita. Il metodo deve aggiungere i comandi al menu.
CMF_NORMAL Il menu di scelta rapida verrà visualizzato normalmente. Il metodo deve aggiungere i comandi al menu.

 

Utilizzare InsertMenu o InsertMenuItem per aggiungere voci di menu all'elenco. Restituire quindi un valore HRESULT con la gravità impostata su SEVERITY_SUCCESS. Impostare il valore del codice sull'offset dell'identificatore di comando più grande assegnato, più uno (1). Si supponga, ad esempio, che idCmdFirst sia impostato su 5 e si aggiungono tre voci al menu con identificatori di comando di 5, 7 e 8. Il valore restituito deve essere MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 + 1).

Nell'esempio seguente viene illustrata una semplice implementazione di QueryContextMenu che inserisce un singolo comando. L'offset dell'identificatore per il comando è IDM_DISPLAY, che è impostato su zero. Le variabili m_pszVerb e m_pwszVerb sono variabili private usate per archiviare la stringa verbo indipendente dal linguaggio associata in formati 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));}

Commenti

Per altre attività di implementazione verbo, vedere Creazione di gestori di menu di scelta rapida.