Dialogfeld „Allgemeines Element“

Ab Windows Vista ersetzt das Dialogfeld „Allgemeines Element“ das ältere Dialogfeld „Gemeinsame Datei“, wenn sie zum Öffnen oder Speichern einer Datei verwendet wird. Das Dialogfeld „Allgemeines Element“ wird in zwei Variationen verwendet: Das Dialogfeld Öffnen und das Diaglogfeld Speichern. Diese beiden Dialoge haben den größten Teil ihrer Funktionalität gemeinsam, aber jeder hat seine eigenen Methoden.

Während diese neuere Version als Dialogfeld „Gemeinsames Element“ bezeichnet wird, wird sie in den meisten Dokumentationen weiterhin als „Gemeinsames Dateidialogfeld“ bezeichnet. Sofern Sie sich nicht speziell mit einer älteren Version von Windows befassen, sollten Sie davon ausgehen, dass sich jede Erwähnung des Dialogfelds „Gemeinsame Datei“ auf dieses Dialogfeld für allgemeine Elemente bezieht.

Die folgenden Themen werden hier erörtert:

IFileDialog, IFileOpenDialog und IFileSaveDialog

Windows Vista bietet Implementierungen der Dialogfelder Öffnen und Speichern: CLSID_FileOpenDialog und CLSID_FileSaveDialog. Diese Dialogfelder werden hier angezeigt.

screen shot of the open dialog box

screen shot of the save as dialog box

IFileOpenDialog und IFileSaveDialog erben von IFileDialog und teilen einen Großteil ihrer Funktionalität. Darüber hinaus unterstützt das Dialogfeld Öffnen IFileOpenDialog und das Dialogfeld Speichern unterstützt IFileSaveDialog.

Die Implementierung des allgemeinen Elementdialogfelds in Windows Vista bietet mehrere Vorteile gegenüber der Implementierung, die in früheren Versionen bereitgestellt wird:

  • Unterstützt die direkte Verwendung des Shell-Namespace über IShellItem anstelle von Dateisystempfaden.
  • Ermöglicht eine einfache Anpassung des Dialogfelds, z. B. das Festlegen der Beschriftung auf der Schaltfläche OK, ohne dass eine Hook-Prozedur erforderlich ist.
  • Unterstützt eine umfassendere Anpassung des Dialogfelds durch das Hinzufügen einer Reihe von datengesteuerten Steuerelementen, die ohne Win32-Dialogfeldvorlage funktionieren. Dieses Anpassungsschema gibt den Aufrufvorgang aus dem Benutzeroberflächenlayout frei. Da alle Änderungen am Dialogdesign weiterhin dieses Datenmodell verwenden, ist die Dialogimplementierung nicht an die spezifische aktuelle Version des Dialogs gebunden.
  • Unterstützt die Benachrichtigung des Anrufers über Ereignisse innerhalb des Dialogs, wie z. B. die Änderung der Auswahl oder des Dateityps. Ermöglicht es dem aufrufenden Prozess auch, bestimmte Ereignisse im Dialog, wie z. B. das Parsen, zu aktivieren.
  • Führt neue Dialogfeldfunktionen ein, z. B. das Hinzufügen von anruferspezifischen Stellen zur Leiste Orte.
  • Im Dialogfeld Speichern können Entwickler neue Metadatenfunktionen der Windows Vista-Shell nutzen.

Darüber hinaus können Entwickler die folgenden Schnittstellen implementieren:

Das Dialogfeld Öffnen oder Speichern gibt einIShellItem- oderIShellItemArray-Objekt an den aufrufenden Prozess zurück. Der Aufrufer kann dann ein einzelnes IShellIten-Objekt verwenden, um einen Dateisystempfad abzurufen oder einen Datenstrom für das Element zu öffnen, um Informationen zu lesen oder zu schreiben.

Flags und Optionen, die den neuen Dialogfeldmethoden zur Verfügung stehen, sind den älteren OFN-Flags in der OPENFILENAME-Struktur sehr ähnlich und werden in GetOpenFileName und GetSaveFileName verwendet. Viele davon sind identisch, außer dass sie mit einem FOS-Präfix beginnen. Die vollständige Liste finden Sie in den Themen IFileDialog::GetOptions undIFileDialog::SetOptions. Dialogfelder Öffnen und Speichern werden standardmäßig mit den am häufigsten verwendeten Flags erstellt. Für das Dialogfeld Öffnen lautet dies (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) und für das Dialogfeld Speichern ist dies (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

IFileDialog und seine untergeordneten Schnittstellen erben und erweiternIModalWindow. Show verwendet als einzigen Parameter den Ziehpunkt des übergeordneten Fensters. Wenn Show erfolgreich zurückgegeben wird, gibt es ein gültiges Ergebnis. Wenn HRESULT_FROM_WIN32(ERROR_CANCELLED) zurückgegeben wird, bedeutet dies, dass der Benutzer das Dialogfeld abgebrochen hat. Es könnte auch legitimerweise einen anderen Fehlercode wie E_OUTOFMEMORY zurückgeben.

Beispielverwendung

Die folgenden Abschnitte zeigen Beispielcode für eine Vielzahl von Dialogfeldaufgaben.

Den Großteil des Beispielcodes finden Sie im Windows SDK Common File Dialog Sample.

Grundlegende Verwendung

Im folgenden Beispiel wird veranschaulicht, wie ein Dialogfeld Öffnen gestartet wird. In diesem Beispiel ist sie auf Microsoft Word-Dokumente beschränkt.

Hinweis

Mehrere Beispiele in diesem Thema verwenden die CDialogEventHandler_CreateInstance-Hilfsfunktion, um eine Instanz der IFileDialogEvents-Implementierung zu erstellen. Um diese Funktion in Ihrem eigenen Code zu verwenden, kopieren Sie den Quellcode für die CDialogEventHandler_CreateInstance-Funktion aus dem Common File Dialog Sample, aus dem alle Beispiele in diesem Thema entnommen werden.

 

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

Einschränken der Ergebnisse auf Dateisystemelemente

Das folgende Beispiel, das von oben entnommen wurde, veranschaulicht, wie Ergebnisse auf Dateisystemelemente beschränkt werden. Beachten Sie, dass IFileDialog::SetOptions das neue Flag zu einem Wert hinzufügt, der über IFileDialog::GetOptions abgerufen wird. Dies ist die empfohlene 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);

Angeben von Dateitypen für ein Dialogfeld

Verwenden Sie die IFileDialog::SetFileTypes-Methode, um bestimmte Dateitypen festzulegen, die vom Dialogfeld behandelt werden können. Diese Methode akzeptiert ein Array von COMDLG_FILTERSPEC-Strukturen, die jeweils einen Dateityp darstellen.

Der Standarderweiterungsmechanismus in einem Dialogfeld ist von GetOpenFileName undGetSaveFileName unverändert. Die Dateinamenerweiterung, die an den Text angefügt wird, den der Benutzer im Bearbeitungsfeld des Dateinamens eingibt, wird initialisiert, wenn das Dialogfeld geöffnet wird. Er sollte mit dem Standarddateityp übereinstimmen (der beim Öffnen des Dialogfelds ausgewählt wurde). Wenn der Standarddateityp „*.*“ (alle Dateien) lautet, kann die Datei eine Erweiterung Ihrer Wahl sein. Wenn der Benutzer einen anderen Dateityp auswählt, wird die Erweiterung automatisch auf die Dateierweiterung aktualisiert, die diesem Dateityp zugeordnet ist. Wenn der Benutzer „*.*“ (alle Dateien) auswählt, wird die Erweiterung auf den ursprünglichen Wert zurückgesetzt.

Im folgenden Beispiel wird veranschaulicht, wie dies oben gemacht wurde.

                        // 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");

Steuern des Standardordners

Fast jeder Ordner im Shell-Namespace kann als Standardordner für das Dialogfeld verwendet werden (der Ordner, der angezeigt wird, wenn der Benutzer eine Datei öffnen oder speichern möchte). Rufen Sie dazu IFileDialog::SetDefaultFolder vor dem Aufruf von Show auf.

Der Standardordner ist der Ordner, in dem das Dialogfeld beim ersten Öffnen eines Benutzers aus Ihrer Anwendung gestartet wird. Danach öffnet sich das Dialogfeld in dem Ordner, den ein Benutzer zuletzt geöffnet hat oder in dem er zuletzt ein Objekt gespeichert hat. Weitere Informationen finden Sie unter Statuspersistenz.

Sie können erzwingen, dass das Dialogfeld immer denselben Ordner anzeigt, wenn er geöffnet wird, unabhängig von der vorherigen Benutzeraktion, indem Sie IFileDialog::SetFolder aufrufen. Dies wird jedoch nicht empfohlen. Wenn Sie SetFolder aufrufen, bevor Sie das Dialogfeld anzeigen, wird der zuletzt gespeicherte oder geöffnete Speicherort nicht angezeigt. Wenn es keinen besonderen Grund für dieses Verhalten gibt, ist es keine gute oder erwartete Benutzererfahrung und sollte vermieden werden. In fast allen Instanzen ist IFileDialog::SetDefaultFolder die bessere Methode.

Wenn Sie ein Dokument zum ersten Mal im Dialogfeld Speichern speichern, sollten Sie die gleichen Richtlinien befolgen, um den ursprünglichen Ordner wie im Dialogfeld Öffnen zu bestimmen. Wenn der Benutzer ein zuvor vorhandenes Dokument bearbeitet, öffnen Sie das Dialogfeld im Ordner, in dem das Dokument gespeichert ist, und füllen Sie das Bearbeitungsfeld mit dem Namen dieses Dokuments auf. Aufrufen von IFileSaveDialog::SetSaveAsItem mit dem aktuellen Element vor dem Aufrufen von Show.

Hinzufügen von Elementen zur Leiste „Orte“

Im folgenden Beispiel wird das Hinzufügen von Elementen zur Leiste Orte veranschaulicht:

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

Statuspersistenz

Vor Windows Vista wurde ein Zustand, z. B. der zuletzt besuchte Ordner, pro Prozess gespeichert. Diese Informationen wurden jedoch unabhängig von der jeweiligen Aktion verwendet. Beispielsweise würde eine Videobearbeitungsanwendung denselben Ordner im Dialogfeld Render As wie im Dialogfeld Medien importieren darstellen. In Windows Vista können Sie durch die Verwendung von GUIDs spezifischer sein. Um dem Dialogfeld eine GUID zuzuweisen, rufen Sie iFileDialog::SetClientGuid auf.

Mehrfachauswahlfunktionen

Mehrfachauswahlfunktionalität ist im Dialogfeld Öffnen mit der GetResults-Methode verfügbar, wie hier gezeigt.

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

Überwachen von Ereignissen aus dem Dialogfeld

Ein Aufrufvorgang kann eine IFileDialogEvents-Schnittstelle mit dem Dialogfeld registrieren, indem dieIFileDialog::Advise-Methoden und IFileDialog::Unadvise-Methoden verwendet werden, wie hier gezeigt.

Dies wird aus dem Beispiel Grundlegende Verwendung entnommen.

        // 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);

Der Großteil der Dialogverarbeitung würde hier platziert.

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

Der Aufrufvorgang kann Ereignisse für Benachrichtigungen verwenden, wenn der Benutzer den Ordner, den Dateityp oder die Auswahl ändert. Diese Ereignisse sind besonders nützlich, wenn der aufrufende Prozess dem Dialogfeld Steuerelemente hinzugefügt hat (siehe Anpassen des Dialogfelds) und muss den Status dieser Steuerelemente in Reaktion auf diese Ereignisse ändern. Nützlich ist in jedem Fall die Möglichkeit, dass der aufrufende Prozess benutzerdefinierten Code bereitstellen kann, um mit Situationen wie Verletzungen der Freigabe, dem Überschreiben von Dateien oder der Feststellung, ob eine Datei gültig ist, bevor das Dialogfeld geschlossen wird, umzugehen. Einige dieser Fälle werden in diesem Abschnitt beschrieben.

OnFileOk

Diese Methode wird aufgerufen, nachdem der Benutzer ein Element ausgewählt hat, unmittelbar vor dem Schließen des Dialogfelds. Die Anwendung kann dann IFileDialog::GetResult oder IFileOpenDialog::GetResults aufrufen, wie das Dialogfeld geschlossen wurde. Wenn das ausgewählte Element akzeptabel ist, können sie S_OK zurückgeben. Andernfalls geben sie S_FALSE zurück und zeigen die Benutzeroberfläche an, die dem Benutzer angibt, weshalb das ausgewählte Element ungültig ist. Wenn S_FALSE zurückgegeben wird, wird das Dialogfeld nicht geschlossen.

Der aufrufende Prozess kann das Fensterhandle des Dialogfelds selbst als übergeordnetes Element der Benutzeroberfläche verwenden. Dieser Ziehpunkt kann abgerufen werden, indem zuerst IOleWindow::QueryInterface und dann IOleWindow::GetWindow mit dem Ziehpunkt aufgerufen wird, wie in diesem Beispiel gezeigt.

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 und OnOverwrite

Wenn der Benutzer eine Datei im Dialogfeld Speichern überschreiben möchte, oder wenn eine gespeicherte oder ersetzte Datei verwendet wird und nicht in (eine Freigabeverletzung) geschrieben werden kann, kann die Anwendung benutzerdefinierte Funktionen bereitstellen, um das Standardverhalten des Dialogfelds außer Kraft zu setzen. Standardmäßig zeigt das Dialogfeld beim Überschreiben einer Datei eine Eingabeaufforderung an, mit welcher der Benutzer diese Aktion überprüfen kann. Bei Freigabeverstößen zeigt das Dialogfeld standardmäßig eine Fehlermeldung an, es wird nicht geschlossen und der Benutzer muss eine andere Auswahl treffen. Der aufrufende Prozess kann diese Standardwerte überschreiben und bei Bedarf eine eigene Benutzeroberfläche anzeigen. Das Dialogfeld kann angewiesen werden, die Datei abzulehnen und geöffnet zu bleiben oder die Datei zu akzeptieren und erfolgreich zu schließen.

Anpassen des Dialogfelds

Dem Dialogfeld kann eine Vielzahl von Steuerelementen hinzugefügt werden, ohne eine Win32-Dialogfeldvorlage bereitstellen zu müssen. Zu diesen Steuerelementen gehören PushButton-, ComboBox-, EditBox-, CheckButton-, RadioButton-Listen, Gruppen, Trennzeichen und statische Text-Steuerelemente. Rufen Sie QueryInterface am Dialogfeldobjekt (IFileDialog, IFileOpenDialog, oder IFileSaveDialog) auf, um einen IFileDialogCustomize-Zeiger zu erhalten. Verwenden Sie diese Schnittstelle, um Steuerelemente hinzuzufügen. Jedes Steuerelement verfügt über eine zugeordnete, vom Aufrufer bereitgestellte ID sowie einen sichtbaren und aktivierten Zustand, der durch den Aufrufvorgang festgelegt werden kann. Einige Steuerelemente, z. B. PushButton, weisen auch Text zu.

Mehrere Steuerelemente können zu einer „visuellen Gruppe“ hinzugefügt werden, die als einzelne Einheit im Layout des Dialogfelds verschoben wird. Gruppen können ihnen eine Bezeichnung zugeordnet haben.

Steuerelemente können nur hinzugefügt werden, bevor das Dialogfeld angezeigt wird. Sobald das Dialogfeld angezeigt wird, können Steuerelemente jedoch wie gewünscht ausgeblendet oder angezeigt werden, z. B. als Reaktion auf eine Benutzeraktion. Die folgenden Beispiele zeigen, wie Sie dem Dialogfeld eine Optionsfeldliste hinzufügen.

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

Hinzufügen von Optionen zur Schaltfläche „OK“

In ähnlicher Weise können Sie den Schaltflächen Öffnen oder Speichern, welche die OK-Schaltfläche für ihre jeweiligen Dialogfeldtypen sind, Auswahlmöglichkeiten hinzufügen. Auf die Optionen kann über ein Dropdown-Listenfeld zugegriffen werden, das der Schaltfläche zugeordnet ist. Das erste Element in der Liste wird zum Text für die Schaltfläche. Das folgende Beispiel zeigt, wie Sie eine Schaltfläche Öffnen mit zwei Möglichkeiten bereitstellen: „Öffnen“ und „Als schreibgeschützt öffnen“.

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

Die Auswahl des Benutzers kann überprüft werden, nachdem das Dialogfeld von der Show-Methode zurückgegeben wird, wie sie für ein ComboBox-Steuerelement verwendet wird, oder es kann als Teil der Behandlung durch IFileDialogEvents::OnFileOk überprüft werden.

Reagieren auf Ereignisse in hinzugefügten Steuerelementen

Der vom aufrufenden Prozess bereitgestellte Ereignishandler kann zusätzlich zu IFileDialogEventsauch IFileDialogControlEvents implementieren. IFileDialogControlEvents ermöglicht dem aufrufenden Prozess, auf diese Ereignisse zu reagieren:

  • PushButton geklickt
  • CheckButton-Status geändert
  • Element, das aus einer Menü-, ComboBox- oder RadioButton-Liste ausgewählt ist
  • Aktivieren des Steuerelements. Dies wird gesendet, wenn ein Menü eine Dropdownliste anzeigt, falls der aufrufende Prozess die Elemente in der Liste ändern möchte.

Vollständige Beispiele

Im Folgenden finden Sie vollständige, herunterladbare C++-Beispiele aus dem Windows Software Development Kit (SDK), welche die Verwendung und Interaktion mit dem Dialogfeld für allgemeine Elemente veranschaulichen.

IID_PPV_ARGS