Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Snelmenuhandlers worden ook wel contextmenuhandlers of werkwoordhandlers genoemd. Een snelmenuhandler is een type handler voor bestandstypen.
Dit onderwerp is als volgt ingedeeld:
- Over statische en dynamische werkwoorden
- hoe snelmenuhandlers werken met dynamische werkwoorden
- Botsingen vermijden door ongespecificeerde werkwoordnamen
- Een snelmenu-handler registreren met een dynamisch werkwoord
- De interface IContextMenu implementeren
- Verwante onderwerpen
Over statische en dynamische werkwoorden
We raden u ten zeerste aan een snelmenu te implementeren met behulp van een van de statische werkwoordmethoden. U wordt aangeraden de instructies te volgen in de sectie 'Een snelmenu aanpassen met behulp van statische werkwoorden' van Contextmenu-handlers maken. Zie "Dynamisch gedrag voor statische werkwoorden verkrijgen" in Contextmenuhandlers makenvoor hoe je dynamisch gedrag kunt verkrijgen voor statische werkwoorden in Windows 7 en hoger. Zie Een statisch of dynamisch werkwoord kiezen voor uw snelmenuvoor meer informatie over de implementatie van statische werkwoorden en welke dynamische werkwoorden u wilt vermijden.
Als u het snelmenu voor een bestandstype moet uitbreiden door een dynamisch werkwoord voor het bestandstype te registreren, volgt u de instructies verderop in dit onderwerp.
Notitie
Er zijn speciale overwegingen voor 64-bit Windows bij het registreren van handlers die werken in de context van 32-bit toepassingen: wanneer Shell-werkwoorden worden aangeroepen in de context van een 32-bit toepassing, leidt het WOW64-subsysteem besturingssysteemtoegang om naar bepaalde paden. Als uw .exe handler is opgeslagen in een van deze paden, is deze niet toegankelijk in deze context. Sla uw .exe daarom op in een pad dat niet wordt omgeleid, of sla een stub-versie van uw .exe op waarmee de echte versie wordt gestart.
Hoe handlers van snelmenu's werken met dynamische werkwoorden
Naast IUnknown,,exporteren contextmenuhandlers de volgende extra interfaces om de berichten te verwerken die nodig zijn bij het implementeren van door de eigenaar getekende menu-items:
- IShellExtInit (verplicht)
- IContextMenu (verplicht)
- IContextMenu2 (optioneel)
- IContextMenu3 (optioneel)
Zie de sectie Menu-items maken Owner-Drawn in Menumenu'svoor meer informatie over door de eigenaar getekende menu-items.
Shell maakt gebruik van de interface IShellExtInit om de handler te initialiseren. Wanneer de Shell IShellExtInit::Initializeaanroept, wordt een gegevensobject doorgegeven met de naam van het object en een aanwijzer naar een lijst met item-id's (PIDL) van de map die het bestand bevat. De parameter hkeyProgID is de registerlocatie waaronder de snelmenugreep is geregistreerd. De methode IShellExtInit::Initialize moet de bestandsnaam uit het gegevensobject extraheren en de naam en de aanwijzer van de map opslaan in een lijst met item-id's (PIDL) voor later gebruik. Zie IShellExtInit-implementeren voor meer informatie over de initialisatie van handler.
Wanneer werkwoorden worden weergegeven in een snelmenu, worden ze eerst gedetecteerd, vervolgens aan de gebruiker gepresenteerd en ten slotte aangeroepen. In de volgende lijst worden deze drie stappen gedetailleerder beschreven:
- De Shell roept IContextMenu::QueryContextMenuaan, waarmee een set werkwoorden wordt geretourneerd die kan worden gebaseerd op de status van de items of het systeem.
- Het systeem geeft een HMENU- handle door die de methode kan gebruiken om items toe te voegen aan het snelmenu.
- Als de gebruiker op een van de items van de handler klikt, roept de Shell IContextMenu::InvokeCommandaan. De handler kan vervolgens de juiste opdracht uitvoeren.
Conflicten voorkomen vanwege niet-gekwalificeerde werkwoordnamen
Omdat werkwoorden per type zijn geregistreerd, kan dezelfde werkwoordnaam worden gebruikt voor werkwoorden op verschillende items. Hierdoor kunnen toepassingen verwijzen naar algemene werkwoorden die onafhankelijk zijn van het itemtype. Hoewel deze functionaliteit nuttig is, kan het gebruik van niet-gekwalificeerde namen leiden tot conflicten met meerdere onafhankelijke softwareleveranciers (ISV's) die dezelfde werkwoordnaam kiezen. U kunt dit voorkomen door altijd voorvoegsels met de ISV-naam als volgt te gebruiken:
ISV_Name.verb
Gebruik altijd een toepassingsspecifieke ProgID. Het aannemen van de conventie om de bestandsnaamextensie toe te wijzen aan een door een ISV verstrekte ProgID vermijdt mogelijke conflicten. Sommige itemtypen gebruiken echter deze toewijzing niet, waardoor er behoefte is aan specifieke leveranciersnamen. Wanneer u een werkwoord toevoegt aan een bestaande ProgID die mogelijk al dat werkwoord heeft geregistreerd, moet u eerst de registersleutel voor het oude werkwoord verwijderen voordat u uw eigen werkwoord toevoegt. U moet dit doen om te voorkomen dat de werkwoordgegevens van de twee werkwoorden worden samengevoegd. Als u dit niet doet, resulteert dit in onvoorspelbaar gedrag.
Een snelmenuhandler registreren met een dynamisch werkwoord
Snelmenuhandlers zijn gekoppeld aan een bestandstype of een map. Voor bestandstypen wordt de handler geregistreerd onder de volgende subsleutel.
HKEY_CLASSES_ROOT
Program ID
shellex
ContextMenuHandlers
Als u een snelmenuhandler wilt koppelen aan een bestandstype of een map, maakt u eerst een subsleutel onder de ContextMenuHandlers subsleutel. Geef de subsleutel voor de handler een naam en stel de standaardwaarde van de subsleutel in op de tekenreeks van de class identifier (CLSID) GUID van de handler.
Als u vervolgens een snelmenuhandler wilt koppelen aan verschillende soorten mappen, moet u de handler op dezelfde manier registreren als voor een bestandstype, maar onder de subsleutel FolderType subsleutel, zoals wordt weergegeven in het volgende voorbeeld.
HKEY_CLASSES_ROOT
FolderType
shellex
ContextMenuHandlers
Zie Shell-extensiehandlers registrerenvoor meer informatie over de maptypen waarvoor u handlers kunt registreren.
Als aan een bestandstype een snelmenu is gekoppeld, voert dubbelklikken op een object normaal gesproken de standaardopdracht uit en wordt de methode IContextMenu::QueryContextMenu niet aangeroepen. Om op te geven dat de IContextMenu::QueryContextMenu-methode van de handler moet worden aangeroepen wanneer een object wordt dubbelgeklikt, maakt u een subsleutel aan onder de CLSID-subsleutel van de handler, zoals hier wordt weergegeven.
HKEY_CLASSES_ROOT
CLSID
{00000000-1111-2222-3333-444444444444}
shellex
MayChangeDefaultMenu
Wanneer op een object dat is gekoppeld aan de handler dubbelklikt wordt, wordt de IContextMenu::QueryContextMenu aangeroepen met de vlag CMF_DEFAULTONLY ingesteld in de parameter uFlags.
Snelmenuhandlers moeten de subsleutel MayChangeDefaultMenu alleen instellen als zij mogelijk de standaardopdracht van het snelmenu moeten wijzigen. Als u deze subsleutel instelt, wordt het systeem gedwongen om het DLL-bestand van de handler te laden wanneer er op een gekoppeld item wordt gedubbelklikt. Als uw handler het standaardwerkwoord niet wijzigt, moet u deze subsleutel niet instellen omdat dit ervoor zorgt dat het systeem uw DLL onnodig laadt.
In het volgende voorbeeld ziet u registervermeldingen die een snelmenuhandler inschakelen voor een MYP-bestandstype. De subsleutel van de handler's CLSID bevat een MayChangeDefaultMenu subsleutel om te garanderen dat de handler wordt aangeroepen wanneer de gebruiker dubbelklikt op een gerelateerd object.
HKEY_CLASSES_ROOT
.myp
(Default) = MyProgram.1
CLSID
{00000000-1111-2222-3333-444444444444}
InProcServer32
(Default) = C:\MyDir\MyCommand.dll
ThreadingModel = Apartment
shellex
MayChangeDefaultMenu
MyProgram.1
(Default) = MyProgram Application
shellex
ContextMenuHandler
MyCommand = {00000000-1111-2222-3333-444444444444}
De interface IContextMenu implementeren
IContextMenu is de krachtigste maar ook de meest gecompliceerde methode om te implementeren. We raden u ten zeerste aan een werkwoord te implementeren met behulp van een van de statische werkwoordmethoden. Zie Een statisch of dynamisch werkwoord kiezen voor uw snelmenuvoor meer informatie. IContextMenu heeft drie methoden, GetCommandString, InvokeCommanden QueryContextMenu, die hier in detail worden besproken.
Methode IContextMenu::GetCommandString
De handler's IContextMenu::GetCommandString methode wordt gebruikt om de canonieke naam voor een werkwoord te retourneren. Deze methode is optioneel. In Windows XP en eerdere versies van Windows, wanneer Windows Verkenner een statusbalk heeft, wordt deze methode gebruikt om de Help-tekst op te halen die wordt weergegeven op de statusbalk voor een menu-item.
De parameter idCmd bevat de offset van de identifier van de opdracht die werd gedefinieerd toen IContextMenu::QueryContextMenu werd aangeroepen. Als een helptekenreeks wordt aangevraagd, wordt uFlags ingesteld op GCS_HELPTEXTW. Kopieer de helptekenreeks naar de pszName buffer door het te converteren naar een PWSTR. De reeks van werkwoorden wordt aangevraagd door uFlags in te stellen op GCS_VERBW. Kopieer de juiste tekenreeks naar pszName, net als bij de Help-tekenreeks. De GCS_VALIDATEA en GCS_VALIDATEW vlaggen worden niet gebruikt door snelmenuhandlers.
In het volgende voorbeeld ziet u een eenvoudige implementatie van IContextMenu::GetCommandString die overeenkomt met de IContextMenu::QueryContextMenu voorbeeld in de IContextMenu::QueryContextMenu Method sectie van dit onderwerp. Omdat de handler slechts één menu-item toevoegt, is er slechts één set tekenreeksen die kunnen worden geretourneerd. De methode test of idCmd- geldig is en, als dat het is, de aangevraagde tekenreeks retourneert.
De functie StringCchCopy wordt gebruikt om de aangevraagde tekenreeks te kopiëren naar pszName om ervoor te zorgen dat de gekopieerde tekenreeks niet groter is dan de grootte van de buffer die is opgegeven door cchName. In dit voorbeeld wordt alleen ondersteuning geïmplementeerd voor de Unicode-waarden van uFlags, omdat alleen die zijn gebruikt in Windows Verkenner sinds 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 passed in
// through idCommand.
hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName),
cchName,
L"DisplayFileName");
break;
}
}
return hr;
}
Methode IContextMenu::InvokeCommand
Deze methode wordt aangeroepen wanneer een gebruiker op een menu-item klikt om de handler te laten weten dat de bijbehorende opdracht moet worden uitgevoerd. De parameter pici verwijst naar een structuur die de vereiste informatie bevat.
Hoewel pici in Shlobj.h wordt aangegeven als een CMINVOKECOMMANDINFO structuur, verwijst het in de praktijk vaak naar een CMINVOKECOMMANDINFOEX structuur. Deze structuur is een uitgebreide versie van CMINVOKECOMMANDINFO en heeft verschillende extra leden waarmee Unicode-tekenreeksen kunnen worden doorgegeven.
Controleer het cbSize lid van pici om te bepalen welke structuur is doorgegeven. Als het een CMINVOKECOMMANDINFOEX structuur is en het fMask lid de CMIC_MASK_UNICODE vlag heeft, cast dan pici naar CMINVOKECOMMANDINFOEX. Hierdoor kan uw toepassing gebruikmaken van de Unicode-informatie in de laatste vijf leden van de structuur.
Het lpVerb- of lpVerbW-lid van de structuur wordt gebruikt om de opdracht te identificeren die moet worden uitgevoerd. Opdrachten worden op een van de volgende twee manieren geïdentificeerd:
- Via de werkwoordreeks van de opdracht
- Door de offset van de ID van het commando
Als u onderscheid wilt maken tussen deze twee gevallen, controleert u het woord in hoge volgorde van lpVerb- voor de ANSI-case of lpVerbW- voor de Unicode-case. Als het woord in hoge volgorde niet-nul is, bevat lpVerb of lpVerbW een werkwoordtekenreeks. Als het hoog-ordewoord nul is, bevindt de commando-offset zich in het laag-ordewoord van lpVerb.
In het volgende voorbeeld ziet u een eenvoudige implementatie van IContextMenu::InvokeCommand- die overeenkomt met het IContextMenu::QueryContextMenu en IContextMenu::GetCommandString voorbeelden gegeven vóór en na deze sectie. De methode bepaalt eerst welke structuur wordt doorgegeven. Vervolgens wordt bepaald of de opdracht wordt geïdentificeerd door de offset of het werkwoord. Als lpVerb of lpVerbW een geldig werkwoord of een geldige offset bevat, wordt er een berichtvak weergegeven.
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;
}
Methode IContextMenu::QueryContextMenu
De Shell roept IContextMenu::QueryContextMenu aan om de snelmenu-handler in staat te stellen zijn menu-items aan het menu toe te voegen. Het geeft de HMENU handle door in de parameter hmenu. De parameter indexMenu is ingesteld op de index die moet worden gebruikt voor het eerste menu-item dat moet worden toegevoegd.
Menu-items die door de handler worden toegevoegd, moeten id's hebben die tussen de waarden in de parameters idCmdFirst en idCmdLast vallen. Normaal gesproken wordt de eerste opdracht-id ingesteld op idCmdFirst-, die wordt verhoogd met één (1) voor elke extra opdracht. Deze procedure helpt u te voorkomen dat u idCmdLast overschrijdt en het aantal beschikbare id's maximaliseert als de Shell meer dan één handler aanroept.
Het commando-offset van een item-identifier is het verschil tussen de identifier en de waarde in idCmdFirst. Sla de verschuiving op van elk item dat uw handler toevoegt aan het snelmenu, omdat de Shell dit kan gebruiken om het item te identificeren als het vervolgens IContextMenu::GetCommandString of IContextMenu::InvokeCommandaanroept.
U moet ook aan elke opdracht die u toevoegt een werkwoord toewijzen. Een werkwoord is een tekenreeks die kan worden gebruikt in plaats van de offset om de opdracht te identificeren wanneer IContextMenu::InvokeCommand wordt aangeroepen. Het wordt ook gebruikt door functies zoals ShellExecuteEx om snelmenuopdrachten uit te voeren.
Er zijn drie vlaggen die kunnen worden doorgegeven via de uFlags parameter die relevant zijn voor snelmenu-handlers. Ze worden beschreven in de volgende tabel.
| Vlag | Beschrijving |
|---|---|
| CMF_DEFAULTONLY | De gebruiker heeft de standaardopdracht geselecteerd, meestal door te dubbelklikken op het object. IContextMenu::QueryContextMenu moet besturing teruggeven aan de Shell zonder het menu te wijzigen. |
| CMF_NODEFAULT | Geen item in het menu moet het standaarditem zijn. De methode moet zijn opdrachten aan het menu toevoegen. |
| CMF_NORMAL | Het snelmenu wordt normaal weergegeven. De methode moet de opdrachten toevoegen aan het menu. |
Gebruik InsertMenu of InsertMenuItem om menu-items toe te voegen aan de lijst. Retourneer vervolgens een HRESULT--waarde met het ernstniveau ingesteld op SEVERITY_SUCCESS. Stel de codewaarde in op de offset van de hoogste opdracht-id die is toegewezen, vermeerderd met één (1). Stel dat idCmdFirst is ingesteld op 5 en u drie items toevoegt aan het menu met opdracht-id's van 5, 7 en 8. De retourwaarde moet MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 - 5 + 1)zijn.
In het volgende voorbeeld ziet u een eenvoudige implementatie van IContextMenu::QueryContextMenu waarmee één opdracht wordt ingevoegd. De identificatie-offset voor de opdracht is IDM_DISPLAY, dat is ingesteld op nul. De variabelen m_pszVerb en m_pwszVerb zijn privévariabelen die worden gebruikt voor het opslaan van de bijbehorende taalonafhankelijke werkwoordreeks in zowel ANSI- als Unicode-indelingen.
#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));
}
Zie Contextmenu-handlers makenvoor andere implementatietaken voor werkwoorden.
Verwante onderwerpen
-
een statisch of dynamisch werkwoord kiezen voor het snelmenu
-
Aanbevolen procedures voor snelmenuhandlers en meerdere selectiewerkwoorden