Dialoogvenster voor algemene items

Vanaf Windows Vista vervangt het dialoogvenster Algemeen item het oudere dialoogvenster Algemeen bestand bij het openen of opslaan van een bestand. Het dialoogvenster Algemeen item wordt in twee variaties gebruikt: het dialoogvenster Openen en het dialoogvenster Opslaan . Deze twee dialoogvensters delen het grootste deel van hun functionaliteit, maar elk heeft zijn eigen unieke methoden.

Important

IFileDialog is de moderne dialoogvenster-API voor bestanden (Windows Vista en hoger). De oudere functies GetOpenFileName en GetSaveFileName zijn verouderd en mogen niet worden gebruikt in nieuwe toepassingen. De verouderde API's bieden geen ondersteuning voor de Shell-naamruimte, moderne dialoogvensteraanpassing of bestandsmetagegevensfuncties.

Wanneer u het volgende gebruikt IFileDialog:

  • U moetCoInitializeEx aanroepen voordat u CoCreateInstance aanroept om het dialoogvenster te maken. Gebruiken COINIT_APARTMENTTHREADED voor UI-threads.
  • Gebruik CLSID_FileOpenDialog of CLSID_FileSaveDialog met CLSCTX_INPROC_SERVER.
  • Moderne alternatieven: Gebruik voor UWP-/WinUI-apps Windows.Storage.Pickers. Voor .NET desktop-apps leveren WPF en WinForms OpenFileDialog/SaveFileDialog wrappers die intern gebruikmaken van IFileDialog.

Hoewel deze nieuwere versie het dialoogvenster Algemene items heet, wordt het in de meeste documentatie nog steeds het dialoogvenster Algemene bestanden genoemd. Tenzij u specifiek te maken hebt met een oudere versie van Windows, moet u ervan uitgaan dat elke verwijzing naar het algemene bestandsdialoogvenster verwijst naar dit algemene itemdialoogvenster.

De volgende onderwerpen worden hier besproken:

IFileDialog, IFileOpenDialog en IFileSaveDialog

Windows Vista biedt implementaties van de dialoogvensters Openen en Opslaan: CLSID_FileOpenDialog en CLSID_FileSaveDialog. Deze dialoogvensters worden hier weergegeven.

schermafbeelding van het geopende dialoogvenster

schermafbeelding van het dialoogvenster Opslaan als

IFileOpenDialog en IFileSaveDialog nemen het over van IFileDialog en delen veel van hun functionaliteit. Daarnaast ondersteunt het dialoogvenster OpenenIFileOpenDialog en het dialoogvenster Opslaan ondersteunt IFileSaveDialog.

De implementatie van het dialoogvenster voor algemene items in Windows Vista biedt verschillende voordelen ten opzichte van de implementatie in eerdere versies:

  • Ondersteunt direct gebruik van de Shell-naamruimte via IShellItem in plaats van bestandssysteempaden te gebruiken.
  • Hiermee kunt u eenvoudig het dialoogvenster aanpassen, zoals het instellen van het label op de knop OK , zonder dat hiervoor een haakprocedure is vereist.
  • Ondersteunt uitgebreidere aanpassingen van het dialoogvenster door een set gegevensgestuurde besturingselementen toe te passen die werken zonder een Win32-dialoogvenstersjabloon. Met dit aanpassingsschema wordt het aanroepende proces losgekoppeld van de lay-out van de gebruikersinterface. Aangezien wijzigingen in het dialoogvensterontwerp dit gegevensmodel blijven gebruiken, is de implementatie van het dialoogvenster niet gekoppeld aan de specifieke huidige versie van het dialoogvenster.
  • Ondersteunt aanroepermeldingen van gebeurtenissen in het dialoogvenster, zoals selectiewijziging of wijziging van bestandstype. Hiermee kan het aanroepende proces bepaalde gebeurtenissen in het dialoogvenster koppelen, zoals het parseren.
  • Introduceert nieuwe dialoogvensterfuncties, zoals het toevoegen van door de beller opgegeven plaatsen aan de balk Plaatsen .
  • In het dialoogvenster Opslaan kunnen ontwikkelaars profiteren van nieuwe metagegevensfuncties van de Windows Vista Shell.

Daarnaast kunnen ontwikkelaars ervoor kiezen om de volgende interfaces te implementeren:

Het dialoogvenster Openen of Opslaan retourneert een IShellItem - of IShellItemArray-object voor het aanroepen. De beller kan vervolgens een afzonderlijk IShellItem-object gebruiken om een bestandssysteempad op te halen of om een stream op het item te openen om informatie te lezen of te schrijven.

Vlaggen en opties die beschikbaar zijn voor de nieuwe dialoogvenstermethoden zijn vergelijkbaar met de oudere OFN-vlaggen in de STRUCTUUR OPENFILENAME en worden gebruikt in GetOpenFileName en GetSaveFileName. Veel van hen zijn precies hetzelfde, behalve dat ze beginnen met een FOS-voorvoegsel. De volledige lijst vindt u in de onderwerpen IFileDialog::GetOptions en IFileDialog::SetOptions . Dialoogvensters openen en opslaan worden standaard gemaakt met de meest voorkomende vlaggen. Voor het dialoogvenster Openen is dit (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) en voor het dialoogvenster Opslaan is dit (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

IFileDialog en de onderliggende interfaces nemen IModalWindow over en breiden deze uit. Show neemt als enige parameter de handle van het bovenliggende venster. Als Weergeven is gelukt, is er een geldig resultaat. Als het HRESULT_FROM_WIN32(ERROR_CANCELLED) retourneert, betekent dat dat de gebruiker het dialoogvenster heeft geannuleerd. Het kan ook legitiem een andere foutcode retourneren, zoals E_OUTOFMEMORY.

Voorbeeld van gebruik

In de volgende secties ziet u voorbeeldcode voor verschillende dialoogvenstertaken.

De meeste voorbeeldcode vindt u in het algemene dialoogvenster Windows SDK.

Basisgebruik

In het volgende voorbeeld ziet u hoe u een dialoogvenster Openen start. In dit voorbeeld is het beperkt tot Microsoft Word documenten.

Note

In verschillende voorbeelden in dit onderwerp wordt de CDialogEventHandler_CreateInstance helperfunctie gebruikt om een exemplaar van de IFileDialogEvents-implementatie te maken. Als u deze functie in uw eigen code wilt gebruiken, kopieert u de broncode voor de CDialogEventHandler_CreateInstance functie uit het dialoogvenster Common File Sample, waaruit alle voorbeelden in dit onderwerp worden genomen.

 

HRESULT BasicFileOpen()
{
    // CoCreate the File Open Dialog object.
    IFileDialog *pfd = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 
                      NULL, 
                      CLSCTX_INPROC_SERVER, 
                      IID_PPV_ARGS(&pfd));
    if (SUCCEEDED(hr))
    {
        // Create an event handling object, and hook it up to the dialog.
        IFileDialogEvents *pfde = NULL;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
        if (SUCCEEDED(hr))
        {
            // Hook up the event handler.
            DWORD dwCookie;
            hr = pfd->Advise(pfde, &dwCookie);
            if (SUCCEEDED(hr))
            {
                // Set the options on the dialog.
                DWORD dwFlags;

                // Before setting, always get the options first in order 
                // not to override existing options.
                hr = pfd->GetOptions(&dwFlags);
                if (SUCCEEDED(hr))
                {
                    // In this case, get shell items only for file system items.
                    hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
                    if (SUCCEEDED(hr))
                    {
                        // Set the file types to display only. 
                        // Notice that this is a 1-based array.
                        hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);
                        if (SUCCEEDED(hr))
                        {
                            // Set the selected file type index to Word Docs for this example.
                            hr = pfd->SetFileTypeIndex(INDEX_WORDDOC);
                            if (SUCCEEDED(hr))
                            {
                                // Set the default extension to be ".doc" file.
                                hr = pfd->SetDefaultExtension(L"doc;docx");
                                if (SUCCEEDED(hr))
                                {
                                    // Show the dialog
                                    hr = pfd->Show(NULL);
                                    if (SUCCEEDED(hr))
                                    {
                                        // Obtain the result once the user clicks 
                                        // the 'Open' button.
                                        // The result is an IShellItem object.
                                        IShellItem *psiResult;
                                        hr = pfd->GetResult(&psiResult);
                                        if (SUCCEEDED(hr))
                                        {
                                            // We are just going to print out the 
                                            // name of the file for sample sake.
                                            PWSTR pszFilePath = NULL;
                                            hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, 
                                                               &pszFilePath);
                                            if (SUCCEEDED(hr))
                                            {
                                                TaskDialog(NULL,
                                                           NULL,
                                                           L"CommonFileDialogApp",
                                                           pszFilePath,
                                                           NULL,
                                                           TDCBF_OK_BUTTON,
                                                           TD_INFORMATION_ICON,
                                                           NULL);
                                                CoTaskMemFree(pszFilePath);
                                            }
                                            psiResult->Release();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // Unhook the event handler.
                pfd->Unadvise(dwCookie);
            }
            pfde->Release();
        }
        pfd->Release();
    }
    return hr;
}

Resultaten beperken tot bestandssysteemitems

In het volgende voorbeeld, dat hierboven is genomen, ziet u hoe u resultaten kunt beperken tot bestandssysteemitems. Houd er rekening mee dat IFileDialog::SetOptions de nieuwe vlag toevoegt aan een waarde die is verkregen via IFileDialog::GetOptions. Dit is de aanbevolen methode.

                // Set the options on the dialog.
                DWORD dwFlags;

                // Before setting, always get the options first in order 
                // not to override existing options.
                hr = pfd->GetOptions(&dwFlags);
                if (SUCCEEDED(hr))
                {
                    // In this case, get shell items only for file system items.
                    hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);

Bestandstypen voor een dialoogvenster opgeven

Als u specifieke bestandstypen wilt instellen die in het dialoogvenster kunnen worden verwerkt, gebruikt u de methode IFileDialog::SetFileTypes . Deze methode accepteert een matrix van COMDLG_FILTERSPEC structuren, die elk een bestandstype vertegenwoordigen.

Het standaarduitbreidingsmechanisme in een dialoogvenster is ongewijzigd van GetOpenFileName en GetSaveFileName. De bestandsnaamextensie die wordt toegevoegd aan de tekst die de gebruiker typt in het invoervak bestandsnaam wordt geïnitialiseerd wanneer het dialoogvenster wordt geopend. Dit moet overeenkomen met het standaardbestandstype (dat is geselecteerd als het dialoogvenster wordt geopend). Als het standaardbestandstype '*.*' (alle bestanden) is, kan het bestand een extensie van uw keuze zijn. Als de gebruiker een ander bestandstype kiest, wordt de extensie automatisch bijgewerkt naar de voornaamextensie die aan dat bestandstype is gekoppeld. Als de gebruiker '*.*' (alle bestanden) kiest, wordt de oorspronkelijke waarde van de extensie hersteld.

In het volgende voorbeeld ziet u hoe dit hierboven is gedaan.

                        // Set the file types to display only. 
                        // Notice that this is a 1-based array.
                        hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);
                        if (SUCCEEDED(hr))
                        {
                            // Set the selected file type index to Word Docs for this example.
                            hr = pfd->SetFileTypeIndex(INDEX_WORDDOC);
                            if (SUCCEEDED(hr))
                            {
                                // Set the default extension to be ".doc" file.
                                hr = pfd->SetDefaultExtension(L"doc;docx");

De standaardmap beheren

Bijna elke map in de Shell-naamruimte kan worden gebruikt als de standaardmap voor het dialoogvenster (de map die wordt weergegeven wanneer de gebruiker ervoor kiest een bestand te openen of op te slaan). Roep IFileDialog::SetDefaultFolder aan voordat u Show aanroept om dit te doen.

De standaardmap is de map waarin het dialoogvenster wordt gestart wanneer een gebruiker het voor het eerst opent vanuit uw toepassing. Daarna wordt het dialoogvenster geopend in de laatste map die een gebruiker heeft geopend of de laatste map die ze hebben gebruikt om een item op te slaan. Zie Statuspersistentie voor meer informatie.

U kunt afdwingen dat het dialoogvenster altijd dezelfde map weergeeft wanneer deze wordt geopend, ongeacht de vorige gebruikersactie, door IFileDialog::SetFolder aan te roepen. We raden u echter niet aan dit te doen. Als u SetFolder aanroept voordat u het dialoogvenster weergeeft, wordt de meest recente locatie waarnaar de gebruiker is opgeslagen of geopend, niet weergegeven. Tenzij er een zeer specifieke reden voor dit gedrag is, is het geen goede of verwachte gebruikerservaring en moet worden vermeden. In bijna alle gevallen is IFileDialog::SetDefaultFolder de betere methode.

Wanneer u een document voor het eerst opslaat in het dialoogvenster Opslaan, moet u dezelfde richtlijnen volgen om de eerste map te bepalen als in het dialoogvenster Openen . Als de gebruiker een eerder bestaand document bewerkt, opent u het dialoogvenster in de map waarin dat document is opgeslagen en vult u het invoervak in met de naam van dat document. Roep IFileSaveDialog::SetSaveAsItem aan met het huidige item voordat u Show aanroept.

Items toevoegen aan de balk Plaatsen

In het volgende voorbeeld ziet u hoe items worden toegevoegd aan de balk Locaties :

HRESULT AddItemsToCommonPlaces()
{
    // CoCreate the File Open Dialog object.
    IFileDialog *pfd = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 
                      NULL, 
                      CLSCTX_INPROC_SERVER, 
                      IID_PPV_ARGS(&pfd));
    if (SUCCEEDED(hr))
    {
        // Always use known folders instead of hard-coding physical file paths.
        // In this case we are using Public Music KnownFolder.
        IKnownFolderManager *pkfm = NULL;
        hr = CoCreateInstance(CLSID_KnownFolderManager, 
                      NULL, 
                      CLSCTX_INPROC_SERVER, 
                      IID_PPV_ARGS(&pkfm));
        if (SUCCEEDED(hr))
        {
            // Get the known folder.
            IKnownFolder *pKnownFolder = NULL;
            hr = pkfm->GetFolder(FOLDERID_PublicMusic, &pKnownFolder);
            if (SUCCEEDED(hr))
            {
                // File Dialog APIs need an IShellItem that represents the location.
                IShellItem *psi = NULL;
                hr = pKnownFolder->GetShellItem(0, IID_PPV_ARGS(&psi));
                if (SUCCEEDED(hr))
                {
                    // Add the place to the bottom of default list in Common File Dialog.
                    hr = pfd->AddPlace(psi, FDAP_BOTTOM);
                    if (SUCCEEDED(hr))
                    {
                        // Show the File Dialog.
                        hr = pfd->Show(NULL);
                        if (SUCCEEDED(hr))
                        {
                            //
                            // You can add your own code here to handle the results.
                            //
                        }
                    }
                    psi->Release();
                }
                pKnownFolder->Release();
            }
            pkfm->Release();
        }
        pfd->Release();
    }
    return hr;
}

Statuspersistentie

Vóór Windows Vista werd een status, zoals de laatst bezochte map, per proces opgeslagen. Deze informatie werd echter gebruikt, ongeacht de specifieke actie. Een toepassing voor het bewerken van video's zou bijvoorbeeld dezelfde map in het dialoogvenster Weergeven als presenteren als in het dialoogvenster Media importeren . In Windows Vista kunt u specifieker zijn via het gebruik van GUID's. Als u een GUID wilt toewijzen aan het dialoogvenster, roept u iFileDialog::SetClientGuid aan.

Mogelijkheden voor meervoudige selectie

Multiselect-functionaliteit is beschikbaar in het dialoogvenster Openen met behulp van de methode GetResults , zoals hier wordt weergegeven.

HRESULT MultiselectInvoke()
{
    IFileOpenDialog *pfd;
    
    // CoCreate the dialog object.
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 
                                  NULL, 
                                  CLSCTX_INPROC_SERVER, 
                                  IID_PPV_ARGS(&pfd));

    if (SUCCEEDED(hr))
    {
        DWORD dwOptions;
        // Specify multiselect.
        hr = pfd->GetOptions(&dwOptions);
        
        if (SUCCEEDED(hr))
        {
            hr = pfd->SetOptions(dwOptions | FOS_ALLOWMULTISELECT);
        }

        if (SUCCEEDED(hr))
        {
            // Show the Open dialog.
            hr = pfd->Show(NULL);

            if (SUCCEEDED(hr))
            {
                // Obtain the result of the user interaction.
                IShellItemArray *psiaResults;
                hr = pfd->GetResults(&psiaResults);
                
                if (SUCCEEDED(hr))
                {
                    //
                    // You can add your own code here to handle the results.
                    //
                    psiaResults->Release();
                }
            }
        }
        pfd->Release();
    }
    return hr;
}

Luisteren naar gebeurtenissen vanuit het dialoogvenster

Een aanroepproces kan een IFileDialogEvents-interface met het dialoogvenster registreren met behulp van de IFileDialog::Advise and IFileDialog::Unadvise methods zoals hier wordt weergegeven.

Dit is afkomstig uit het voorbeeld basisgebruik .

        // Create an event handling object, and hook it up to the dialog.
        IFileDialogEvents *pfde = NULL;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
        if (SUCCEEDED(hr))
        {
            // Hook up the event handler.
            DWORD dwCookie;
            hr = pfd->Advise(pfde, &dwCookie);

Het grootste deel van de dialoogvensterverwerking wordt hier geplaatst.

                // Unhook the event handler.
                pfd->Unadvise(dwCookie);
            }
            pfde->Release();
        }
        pfd->Release();
    }
    return hr;
}

Het aanroepende proces kan gebeurtenissen gebruiken voor meldingen wanneer de gebruiker de map, het bestandstype of de selectie wijzigt. Deze gebeurtenissen zijn met name handig wanneer het aanroepende proces besturingselementen heeft toegevoegd aan het dialoogvenster (zie Het dialoogvenster aanpassen) en de status van deze besturingselementen moet wijzigen als reactie op deze gebeurtenissen. Handig in alle gevallen is de mogelijkheid van het aanroepende proces om aangepaste code te bieden voor situaties zoals het delen van schendingen, het overschrijven van bestanden of het bepalen of een bestand geldig is voordat het dialoogvenster wordt gesloten. Sommige van deze gevallen worden beschreven in deze sectie.

OnFileOk

Deze methode wordt aangeroepen nadat de gebruiker een item heeft gekozen, net voordat het dialoogvenster wordt gesloten. De toepassing kan vervolgens IFileDialog::GetResult of IFileOpenDialog::GetResults aanroepen zoals zou worden gedaan zodra het dialoogvenster was gesloten. Als het gekozen item acceptabel is, kunnen ze S_OK retourneren. Anders retourneren ze S_FALSE en geven ze de gebruikersinterface weer die de gebruiker vertelt waarom het gekozen item niet geldig is. Als S_FALSE wordt geretourneerd, wordt het dialoogvenster niet gesloten.

Het aanroepende proces kan de venstergreep van het dialoogvenster zelf gebruiken als het bovenliggende element van de gebruikersinterface. Deze ingang kan worden verkregen door eerst IOleWindow::QueryInterface aan te roepen en vervolgens IOleWindow::GetWindow aan te roepen met de ingang, zoals wordt weergegeven in dit voorbeeld.

HRESULT CDialogEventHandler::OnFileOk(IFileDialog *pfd) 
{ 
    IShellItem *psiResult;
    HRESULT hr = pfd->GetResult(&psiResult);
    
    if (SUCCEEDED(hr))
    {
        SFGAOF attributes;
        hr = psiResult->GetAttributes(SFGAO_COMPRESSED, &attributes);
    
        if (SUCCEEDED(hr))
        {
            if (attributes & SFGAO_COMPRESSED)
            {
                // Accept the file.
                hr = S_OK;
            }
            else
            {
                // Refuse the file.
                hr = S_FALSE;
                
                _DisplayMessage(pfd, L"Not a compressed file.");
            }
        }
        psiResult->Release();
    }
    return hr;
};

HRESULT CDialogEventHandler::_DisplayMessage(IFileDialog *pfd, PCWSTR pszMessage)
{
    IOleWindow *pWindow;
    HRESULT hr = pfd->QueryInterface(IID_PPV_ARGS(&pWindow));
    
    if (SUCCEEDED(hr))
    {
        HWND hwndDialog;
        hr = pWindow->GetWindow(&hwndDialog);
    
        if (SUCCEEDED(hr))
        {
            MessageBox(hwndDialog, pszMessage, L"An error has occurred", MB_OK);
        }
        pWindow->Release();
    }
    return hr;
}

OnShareViolation en OnOverwrite

Als de gebruiker ervoor kiest een bestand te overschrijven in het dialoogvenster Opslaan of als een bestand dat wordt opgeslagen of vervangen, wordt gebruikt en niet kan worden weggeschreven naar (een schending van delen), kan de toepassing aangepaste functionaliteit bieden om het standaardgedrag van het dialoogvenster te overschrijven. Bij het overschrijven van een bestand wordt in het dialoogvenster standaard een prompt weergegeven waarmee de gebruiker deze actie kan verifiëren. Bij conflicten bij gedeeld gebruik wordt standaard in het dialoogvenster een foutbericht weergegeven, sluit het niet en moet de gebruiker een andere keuze maken. Het aanroepende proces kan deze standaardinstellingen overschrijven en desgewenst een eigen gebruikersinterface weergeven. Het dialoogvenster kan worden geïnstrueerd om het bestand te weigeren en open te blijven of het bestand te accepteren en te sluiten.

Het dialoogvenster aanpassen

Er kunnen verschillende besturingselementen aan het dialoogvenster worden toegevoegd zonder een Win32-dialoogvenstersjabloon op te geven. Deze besturingselementen zijn onder andere PushButton, ComboBox, EditBox, CheckButton, RadioButton-lijsten, Groepen, Scheidingstekens en Statische tekst. Roep QueryInterface aan op het dialoogvensterobject (IFileDialog, IFileOpenDialog of IFileSaveDialog) om een aanwijzer voor IFileDialogCustomize te verkrijgen. Gebruik die interface om besturingselementen toe te voegen. Elk besturingselement heeft een door de beller opgegeven id en een zichtbare en ingeschakelde status die kan worden ingesteld door het aanroepende proces. Sommige besturingselementen, zoals PushButton, hebben ook tekst die eraan gekoppeld is.

Er kunnen meerdere besturingselementen worden toegevoegd aan een 'visuele groep' die wordt verplaatst als één eenheid in de indeling van het dialoogvenster. Aan groepen kan een label zijn gekoppeld.

Besturingselementen kunnen alleen worden toegevoegd voordat het dialoogvenster wordt weergegeven. Zodra het dialoogvenster wordt weergegeven, kunnen besturingselementen echter worden verborgen of naar wens worden weergegeven, mogelijk in reactie op gebruikersactie. In de volgende voorbeelden wordt getoond hoe u een keuzerondjeslijst aan het dialoogvenster toevoegt.

// Controls
#define CONTROL_GROUP           2000
#define CONTROL_RADIOBUTTONLIST 2
#define CONTROL_RADIOBUTTON1    1
#define CONTROL_RADIOBUTTON2    2       // It is OK for this to have the same ID
                    // as CONTROL_RADIOBUTTONLIST, because it 
                    // is a child control under CONTROL_RADIOBUTTONLIST


// This code snippet demonstrates how to add custom controls in the Common File Dialog.
HRESULT AddCustomControls()
{
    // CoCreate the File Open Dialog object.
    IFileDialog *pfd = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 
                                  NULL, 
                                  CLSCTX_INPROC_SERVER, 
                                  IID_PPV_ARGS(&pfd));
    if (SUCCEEDED(hr))
    {
        // Create an event handling object, and hook it up to the dialog.
        IFileDialogEvents   *pfde       = NULL;
        DWORD               dwCookie    = 0;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
        if (SUCCEEDED(hr))
        {
            // Hook up the event handler.
            hr = pfd->Advise(pfde, &dwCookie);
            if (SUCCEEDED(hr))
            {
                // Set up a Customization.
                IFileDialogCustomize *pfdc = NULL;
                hr = pfd->QueryInterface(IID_PPV_ARGS(&pfdc));
                if (SUCCEEDED(hr))
                {
                    // Create a Visual Group.
                    hr = pfdc->StartVisualGroup(CONTROL_GROUP, L"Sample Group");
                    if (SUCCEEDED(hr))
                    {
                        // Add a radio-button list.
                        hr = pfdc->AddRadioButtonList(CONTROL_RADIOBUTTONLIST);
                        if (SUCCEEDED(hr))
                        {
                            // Set the state of the added radio-button list.
                            hr = pfdc->SetControlState(CONTROL_RADIOBUTTONLIST, 
                                               CDCS_VISIBLE | CDCS_ENABLED);
                            if (SUCCEEDED(hr))
                            {
                                // Add individual buttons to the radio-button list.
                                hr = pfdc->AddControlItem(CONTROL_RADIOBUTTONLIST,
                                                          CONTROL_RADIOBUTTON1,
                                                          L"Change Title to ABC");
                                if (SUCCEEDED(hr))
                                {
                                    hr = pfdc->AddControlItem(CONTROL_RADIOBUTTONLIST,
                                                              CONTROL_RADIOBUTTON2,
                                                              L"Change Title to XYZ");
                                    if (SUCCEEDED(hr))
                                    {
                                        // Set the default selection to option 1.
                                        hr = pfdc->SetSelectedControlItem(CONTROL_RADIOBUTTONLIST,
                                                                          CONTROL_RADIOBUTTON1);
                                    }
                                }
                            }
                        }
                        // End the visual group.
                        pfdc->EndVisualGroup();
                    }
                    pfdc->Release();
                }

                if (FAILED(hr))
                {
                    // Unadvise here in case we encounter failures 
                    // before we get a chance to show the dialog.
                    pfd->Unadvise(dwCookie);
                }
            }
            pfde->Release();
        }

        if (SUCCEEDED(hr))
        {
            // Now show the dialog.
            hr = pfd->Show(NULL);
            if (SUCCEEDED(hr))
            {
                //
                // You can add your own code here to handle the results.
                //
            }
            // Unhook the event handler.
            pfd->Unadvise(dwCookie);
        }
        pfd->Release();
    }
    return hr;
}

Opties toevoegen aan de knop OK

Op dezelfde manier kunnen opties worden toegevoegd aan de knoppen Openen of Opslaan . Dit zijn de knop OK voor de respectieve dialoogvenstertypen. De opties zijn toegankelijk via een vervolgkeuzelijst die is gekoppeld aan de knop. Het eerste item in de lijst wordt de tekst voor de knop. In het volgende voorbeeld ziet u hoe u een knop Openen met twee mogelijkheden kunt bieden: 'Openen' en 'Openen als alleen-lezen'.

// OpenChoices options
#define OPENCHOICES 0
#define OPEN 0
#define OPEN_AS_READONLY 1


HRESULT AddOpenChoices()
{
    // CoCreate the File Open Dialog object.
    IFileDialog *pfd = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 
                      NULL, 
                      CLSCTX_INPROC_SERVER, 
                      IID_PPV_ARGS(&pfd));
    if (SUCCEEDED(hr))
    {
        // Create an event handling object, and hook it up to the dialog.
        IFileDialogEvents   *pfde       = NULL;
        DWORD               dwCookie    = 0;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
        if (SUCCEEDED(hr))
        {
            // Hook up the event handler.
            hr = pfd->Advise(pfde, &dwCookie);
            if (SUCCEEDED(hr))
            {
                // Set up a Customization.
                IFileDialogCustomize *pfdc = NULL;
                hr = pfd->QueryInterface(IID_PPV_ARGS(&pfdc));
                if (SUCCEEDED(hr))
                {
                    hr = pfdc->EnableOpenDropDown(OPENCHOICES);
                    if (SUCCEEDED(hr))
                    {
                        hr = pfdc->AddControlItem(OPENCHOICES, OPEN, L"&Open");
                    }                    
                    if (SUCCEEDED(hr))
                    {
                        hr = pfdc->AddControlItem(OPENCHOICES, 
                                                OPEN_AS_READONLY, 
                                                L"Open as &read-only");
                    }
                    if (SUCCEEDED(hr))
                    {
                        pfd->Show(NULL);
                    }
                }
                pfdc->Release();
            }
            pfd->Unadvise(dwCookie);
        }
        pfde->Release();
    }
    pfd->Release();
    return hr;
}

De keuze van de gebruiker kan worden geverifieerd nadat het dialoogvenster wordt geretourneerd uit de methode Weergeven zoals u dat zou doen voor een keuzelijst met invoervak of kan worden geverifieerd als onderdeel van de verwerking door IFileDialogEvents::OnFileOk.

Reageren op gebeurtenissen in toegevoegde besturingselementen

De gebeurtenishandler die door het aanroepproces wordt geleverd, kan IFileDialogControlEvents naast IFileDialogEvents implementeren. Met IFileDialogControlEvents kan het aanroepende proces reageren op deze gebeurtenissen:

  • Drukknop erop geklikt
  • Status van CheckButton is gewijzigd
  • Item geselecteerd uit een menu, keuzelijst met invoervak of lijst met keuzerondjes
  • Besturing wordt geactiveerd. Dit wordt verzonden wanneer een menu op het punt staat een vervolgkeuzelijst weer te geven, voor het geval het oproepproces de items in de lijst wil wijzigen.

Volledige voorbeelden

Hier volgen volledige, downloadbare C++-voorbeelden van de Windows Software Development Kit (SDK) die het gebruik van en interactie met het dialoogvenster Common Item demonstreren.

IID_PPV_ARGS