Boîte de dialogue Élément commun

À compter de Windows Vista, la boîte de dialogue Élément commun remplace l’ancienne boîte de dialogue Fichier commun lorsqu’elle est utilisée pour ouvrir ou enregistrer un fichier. La boîte de dialogue Élément commun est utilisée dans deux variantes : la boîte de dialogue Ouvrir et la boîte de dialogue Enregistrer. Ces deux boîtes de dialogue on quasiment les mêmes fonctionnalités, mais chacune possède ses propres méthodes uniques.

Bien que cette version plus récente soit appelée Boîte de dialogue Élément commun, elle continue d’être appelée Boîte de dialogue Fichier commun dans la plupart des documents. À moins que vous n’utilisiez spécifiquement une version antérieure de Windows, considérez que toute mention de la boîte de dialogue Fichier commun fait référence à cette boîte de dialogue Élément commun.

Les rubriques suivantes sont présentées ici :

IFileDialog, IFileOpenDialog et IFileSaveDialog

Windows Vista fournit des implémentations des boîtes de dialogue Ouvrir et Enregistrer : CLSID_FileOpenDialog et CLSID_FileSaveDialog. Ces boîtes de dialogue sont affichées ici.

screen shot of the open dialog box

screen shot of the save as dialog box

IFileOpenDialog et IFileSaveDialog héritent deIFileDialog et partagent presque toutes les mêmes fonctionnalités. En outre, la boîte de dialogue Ouvrir prend en charge IFileOpenDialog et la boîte de dialogue Enregistrer prend en charge IFileSaveDialog.

L’implémentation de la boîte de dialogue Élément commun trouvée dans Windows Vista offre plusieurs avantages par rapport à l’implémentation fournie dans les versions antérieures :

  • Elle prend en charge l’utilisation directe de l’espace de noms Shell via IShellItem au lieu d’utiliser des chemins de système de fichiers.
  • Elle permet une personnalisation simple de la boîte de dialogue, telle que la définition de l’étiquette du bouton OK, sans nécessiter de procédure de raccordement.
  • Elle permet une personnalisation plus étendue de la boîte de dialogue en ajoutant un ensemble de contrôles pilotés par les données qui fonctionnent sans modèle de boîte de dialogue Win32. Ce schéma de personnalisation libère le processus appelant de la disposition de l’interface utilisateur. Étant donné que les modifications apportées à la conception de la boîte de dialogue continuent d’utiliser ce modèle de données, l’implémentation de la boîte de dialogue n’est pas liée à la version actuelle spécifique cette dernière.
  • Elle prend en charge la notification de l’appelant des événements dans la boîte de dialogue, telles que la modification de la sélection ou le changement de type de fichier. Elle permet également au processus appelant de raccorder certains événements dans la boîte de dialogue, tels que l’analyse.
  • Elle présente de nouvelles fonctionnalités de boîte de dialogue, telles que l’ajout d’emplacements spécifiés par l’appelant à la barre Lieux.
  • Dans la boîte de dialogue Enregistrer, les développeurs peuvent tirer parti des nouvelles fonctionnalités de métadonnées du Shell Windows Vista.

En outre, les développeurs peuvent choisir d’implémenter les interfaces suivantes :

La boîte de dialogue Ouvrir ou Enregistrer renvoie un objet IShellItem ou IShellItemArray au processus appelant. L’appelant peut ensuite utiliser un objet IShellItem individuel pour obtenir un chemin d’accès au système de fichiers ou ouvrir un flux sur l’élément pour lire ou écrire des informations.

Les indicateurs et les options disponibles pour les nouvelles méthodes de boîtes de dialogue sont très similaires aux anciens indicateurs OFN trouvés dans la structure OPENFILENAME et sont utilisés dans GetOpenFileName et GetSaveFileName. Beaucoup d’entre eux sont exactement les mêmes, sauf ceux qui commencent par un préfixe FOS. La liste complète se trouve dans les rubriques IFileDialog::GetOptions et IFileDialog::SetOptions. Les boîtes de dialogue Ouvrir et Enregistrer sont créées par défaut avec les indicateurs les plus courants. Pour la boîte de dialogue Ouvrir, il s’agit de (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) et pour la boîte de dialogue Enregistrer, il s’agit de (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

IFileDialog et ses interfaces descendantes héritent et étendent IModalWindow. Show prend comme seul paramètre le handle de la fenêtre parente. Si Show retourne correctement, il existe un résultat valide. Si elle retourne HRESULT_FROM_WIN32(ERROR_CANCELLED), cela signifie que l’utilisateur a annulé la boîte de dialogue. Il peut également retourner légitimement un autre code d’erreur tel que E_OUTOFMEMORY.

Exemple d’utilisation

Les sections suivantes montrent un exemple de code pour diverses tâches de boîtes de dialogue.

La plupart de l’exemple de code se trouve dans l’exemple de boîte de dialogue Fichier commun du SDK Windows.

Utilisation de base

L’exemple suivant montre comment lancer une boîte de dialogue Ouvrir. Dans cet exemple, il est limité aux documents Microsoft Word.

Remarque

Plusieurs exemples de cette rubrique utilisent la fonction d’assistance CDialogEventHandler_CreateInstance pour créer une instance de l’implémentation IFileDialogEvents. Pour utiliser cette fonction dans votre propre code, copiez le code source de la fonction CDialogEventHandler_CreateInstance à partir de l’exemple de dialogue Fichier commun à partir duquel tous les exemples de cette rubrique sont pris.

 

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

Limitation des résultats aux éléments du système de fichiers

L’exemple suivant, extrait d’au-dessus, montre comment restreindre les résultats aux éléments du système de fichiers. Notez que IFileDialog::SetOptions ajoute le nouvel indicateur à une valeur obtenue via IFileDialog::GetOptions. Il s’agit de la méthode recommandée.

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

Spécification de types de fichiers pour une boîte de dialogue

Pour définir les types de fichiers spécifiques que la boîte de dialogue peut gérer, utilisez la méthode IFileDialog::SetFileTypes. Cette méthode accepte un tableau de structures COMDLG_FILTERSPEC, chacune représentant un type de fichier.

Le mécanisme d’extension par défaut dans une boîte de dialogue est inchangé par rapport à GetOpenFileName et GetSaveFileName. L’extension de nom de fichier ajoutée au texte que l’utilisateur tape dans la zone d’édition du nom de fichier est initialisée lorsque la boîte de dialogue s’ouvre. Il doit correspondre au type de fichier par défaut (sélectionné lors de l’ouverture de la boîte de dialogue). Si le type de fichier par défaut est « *.* » (tous les fichiers), le fichier peut être une extension de votre choix. Si l’utilisateur choisit un autre type de fichier, l’extension est automatiquement mise à jour vers la première extension de nom de fichier associée à ce type de fichier. Si l’utilisateur choisit « *.* » (tous les fichiers), l’extension revient à sa valeur d’origine.

L'exemple suivant illustre la façon dont cela a été fait plus haut.

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

Contrôle du fichier par défaut

Presque tous les dossiers de l’espace de noms Shell peuvent être utilisés comme dossier par défaut pour la boîte de dialogue (le dossier présenté lorsque l’utilisateur choisit d’ouvrir ou d’enregistrer un fichier). Pour ce faire, appelez IFileDialog::SetDefaultFolder avant d’appeler Show.

Le dossier par défaut est le dossier dans lequel la boîte de dialogue démarre la première fois qu’un utilisateur l’ouvre à partir de votre application. Après cela, la boîte de dialogue s’ouvre dans le dernier dossier ouvert par un utilisateur ou le dernier dossier utilisé pour enregistrer un élément. Pour plus d’informations, consultez Persistance de l’état.

Vous pouvez obliger la boîte de dialogue à toujours afficher le même dossier lorsqu’elle s’ouvre, quelle que soit l’action de l’utilisateur précédente, en appelant IFileDialog::SetFolder. Toutefois, nous ne recommandons pas ce procédé. Si vous appelez SetFolder avant d’afficher la boîte de dialogue, l’emplacement le plus récent vers lequel l’utilisateur a enregistré ou à partir duquel il a ouvert n’est pas affiché. À moins qu’il n’existe une raison très spéciale pour ce comportement, ce n’est pas une expérience utilisateur bonne ou attendue. Elle doit être évitée. Dans presque toutes les instances, IFileDialog::SetDefaultFolder est la meilleure méthode.

Lors de l’enregistrement d’un document pour la première fois dans la boîte de dialogue Enregistrer, vous devez suivre les mêmes instructions pour déterminer le dossier initial que pour la boîte de dialogue Ouvrir. Si l’utilisateur modifie un document existant précédemment, ouvrez la boîte de dialogue dans le dossier où ce document est stocké et remplissez la zone d’édition avec le nom de ce document. Appelez IFileSaveDialog::SetSaveAsItem avec l’élément actuel avant d’appeler Show.

Ajout d’éléments à la barre Lieux

L’exemple suivant illustre l’ajout d’éléments à la barre Lieux :

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

Persistance de l’état

Avant Windows Vista, un état, tel que le dernier dossier visité, été enregistré pour chaque processus. Toutefois, ces informations ont été utilisées indépendamment de l’action particulière. Par exemple, une application d’édition de vidéos présenterait le même dossier dans la boîte de dialogue Convertir en que dans la boîte de dialogue Importer un média. Dans Windows Vista, vous pouvez être plus spécifique via l’utilisation des GUID. Pour affecter un GUID à la boîte de dialogue, appelez iFileDialog::SetClientGuid.

Fonctionnalités de sélection multiple

La fonctionnalité de sélection multiple est disponible dans la boîte de dialogue Ouvrir à l’aide de la méthode GetResults, comme illustré ici.

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

Écoute des événements à partir de la boîte de dialogue

Un processus appelant peut inscrire une interface IFileDialogEvents avec la boîte de dialogue à l’aide des méthodes IFileDialog::Advise et IFileDialog::Unadvise, comme illustré ici.

Il s’agit de l’exemple d’Utilisation de base.

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

La majeure partie du traitement de la boîte de dialogue serait placée ici.

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

Le processus appelant peut utiliser des événements pour une notification lorsque l’utilisateur modifie le dossier, le type de fichier ou la sélection. Ces événements sont particulièrement utiles lorsque le processus appelant a ajouté des contrôles à la boîte de dialogue (voir Personnalisation de la boîte de dialogue) et doit modifier l’état de ces contrôles en réaction à ces événements. Ce qui est utile dans tous les cas, c’est la capacité du processus appelant à fournir du code personnalisé pour gérer des situations telles que le partage de violations, le remplacement de fichiers ou pour déterminer si un fichier est valide avant la fermeture de la boîte de dialogue. Certains de ces cas sont décrits dans cette section.

OnFileOk

Cette méthode est appelée une fois que l’utilisateur choisit un élément, juste avant la fermeture de la boîte de dialogue. L’application peut ensuite appeler IFileDialog::GetResult ou IFileOpenDialog::GetResults comme cela serait fait une fois la boîte de dialogue fermée. Si l’élément choisi est acceptable, S_OK est retourné. Sinon, S_FALSE est retourné et l’interface utilisateur s’affiche pour indiquer à l’utilisateur pourquoi l’élément choisi n’est pas valide. Si S_FALSE est retourné, la boîte de dialogue ne se ferme pas.

Le processus appelant peut utiliser le handle de fenêtre de la boîte de dialogue même comme parent de l’interface utilisateur. Ce handle peut être obtenu en appelant d’abord IOleWindow::QueryInterface, puis en appelant IOleWindow::GetWindow avec le handle, comme illustré dans cet exemple.

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

Si l’utilisateur choisit de remplacer un fichier dans la boîte de dialogue Enregistrer, ou si un fichier en cours d’enregistrement ou remplacé est en cours d’utilisation et dans lequel on ne peut écrire (violation de partage), l’application peut fournir des fonctionnalités personnalisées pour remplacer le comportement par défaut de la boîte de dialogue. Par défaut, lorsque vous remplacez un fichier, la boîte de dialogue affiche une invite permettant à l’utilisateur de vérifier cette action. Pour les violations de partage, par défaut, la boîte de dialogue affiche un message d’erreur, elle ne se ferme pas et l’utilisateur doit faire un autre choix. Le processus appelant peut remplacer ces valeurs par défaut et afficher sa propre interface utilisateur si vous le souhaitez. La boîte de dialogue peut être chargée de refuser le fichier et de rester ouverte ou d’accepter le fichier et de fermer correctement.

Personnalisation de la boîte de dialogue

Plusieurs contrôles peuvent être ajoutés à la boîte de dialogue sans fournir de modèle de boîte de dialogue Win32. Ces contrôles incluent PushButton, ComboBox, EditBox, CheckButton, les listes RadioButton, des groupes, des séparateurs et des contrôles de texte statique. Appelez QueryInterface sur l’objet de boîte de dialogue (IFileDialog, IFileOpenDialog ou IFileSaveDialog) pour obtenir un pointeur IFileDialogCustomize. Utilisez cette interface pour ajouter des contrôles. Chaque contrôle a un ID fourni par l’appelant associé, ainsi qu’un état visible et activé qui peut être défini par le processus appelant. Certains contrôles, tels que PushButton, ont également du texte associé.

Plusieurs contrôles peuvent être ajoutés à un « groupe visuel » qui se déplace en tant qu’unité unique dans la disposition de la boîte de dialogue. Les groupes peuvent avoir une étiquette associée.

Les contrôles peuvent être ajoutés uniquement avant l’affichage de la boîte de dialogue. Toutefois, une fois la boîte de dialogue affichée, les contrôles peuvent être masqués ou affichés comme souhaité, en réponse à l’action de l’utilisateur, par exemple. Les exemples suivants montrent comment ajouter une liste de cases d’option à la boîte de dialogue.

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

Ajout d’options au bouton OK

De la même manière, les choix peuvent être ajoutés aux boutons Ouvrir ou Enregistrer, qui sont le bouton OK pour leurs types de dialogue respectifs. Les options sont accessibles via une zone de liste déroulante attachée au bouton. Le premier élément de la liste devient le texte du bouton. L’exemple suivant montre comment fournir deux possibilités à un bouton Ouvrir : « Ouvrir » et « Ouvrir en lecture seule ».

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

Le choix de l’utilisateur peut être vérifié après le retour de la boîte de dialogue de la méthode Show comme vous le feriez pour un ComboBox, ou il peut être vérifié dans le cadre de la gestion par IFileDialogEvents::OnFileOk.

Réponse aux événements dans les contrôles ajoutés

Le gestionnaire d’événements fourni par le processus appelant peut implémenter IFileDialogControlEvents en plus deIFileDialogEvents. IFileDialogControlEvents permet au processus appelant de réagir à ces événements :

  • PushButton cliqué
  • État de CheckButton modifié
  • Élément sélectionné dans un menu, ComboBox ou une liste RadioButton
  • Contrôler l’activation. Ceci est envoyé lorsqu’un menu est sur le point d’afficher une liste déroulante, si le processus appelant souhaite modifier les éléments de la liste.

Exemples complets

Voici des exemples C++ complets et téléchargeables à partir du Kit de développement logiciel (SDK) Windows, qui illustrent l’utilisation et l’interaction avec la boîte de dialogue Élément commun.

IID_PPV_ARGS