Finestra di dialogo Elemento comune

A partire da Windows Vista, la finestra di dialogo Elemento comune sostituisce la finestra di dialogo file comune precedente quando viene usata per aprire o salvare un file. La finestra di dialogo Elemento comune viene utilizzata in due varianti: la finestra di dialogo Apri e la finestra di dialogo Salva . Queste due finestre di dialogo condividono la maggior parte delle relative funzionalità, ma ognuna ha metodi univoci.

Anche se questa versione più recente è denominata Finestra di dialogo elemento comune, continua a essere chiamata finestra di dialogo File comune nella maggior parte della documentazione. A meno che non si abbia a che fare in modo specifico con una versione precedente di Windows, è consigliabile presupporre che qualsiasi menzione della finestra di dialogo file comune faccia riferimento a questa finestra di dialogo elemento comune.

Di seguito sono illustrati gli argomenti seguenti:

IFileDialog, IFileOpenDialog e IFileSaveDialog

Windows Vista fornisce implementazioni delle finestre di dialogo Apri e Salva : CLSID_FileOpenDialog e CLSID_FileSaveDialog. Queste finestre di dialogo sono visualizzate qui.

screen shot of the open dialog box

screen shot of the save as dialog box

IFileOpenDialog e IFileSaveDialog ereditano da IFileDialog e condividono gran parte delle funzionalità. Inoltre, la finestra di dialogo Apri supporta IFileOpenDialog e la finestra di dialogo Salva supporta IFileSaveDialog.

L'implementazione della finestra di dialogo elementi comuni disponibile in Windows Vista offre diversi vantaggi rispetto all'implementazione fornita nelle versioni precedenti:

  • Supporta l'uso diretto dello spazio dei nomi shell tramite IShellItem invece di usare i percorsi del file system.
  • Abilita la semplice personalizzazione della finestra di dialogo, ad esempio l'impostazione dell'etichetta sul pulsante OK , senza richiedere una procedura hook.
  • Supporta una personalizzazione più estesa del dialogo tramite l'aggiunta di un set di controlli basati sui dati che operano senza un modello di finestra di dialogo Win32. Questo schema di personalizzazione libera il processo chiamante dal layout dell'interfaccia utente. Poiché le modifiche apportate alla progettazione della finestra di dialogo continuano a usare questo modello di dati, l'implementazione del dialogo non è associata alla versione corrente specifica del dialogo.
  • Supporta la notifica del chiamante degli eventi all'interno della finestra di dialogo, ad esempio la modifica del tipo di selezione o il tipo di file. Consente inoltre al processo chiamante di associare determinati eventi nella finestra di dialogo, ad esempio l'analisi.
  • Introduce nuove funzionalità della finestra di dialogo, ad esempio l'aggiunta di posizioni specificate dal chiamante alla barra Posizioni .
  • Nella finestra di dialogo Salva gli sviluppatori possono sfruttare le nuove funzionalità dei metadati della shell di Windows Vista.

Inoltre, gli sviluppatori possono scegliere di implementare le interfacce seguenti:

La finestra di dialogo Apri o Salva restituisce un oggetto IShellItem o IShellItemArray al processo chiamante. Il chiamante può quindi usare un singolo oggetto IShellItem per ottenere un percorso del file system o per aprire un flusso sull'elemento per leggere o scrivere informazioni.

I flag e le opzioni disponibili per i nuovi metodi di dialogo sono molto simili ai flag OFN precedenti disponibili nella struttura OPENFILENAME e usati in GetOpenFileName e GetSaveFileName. Molti di essi sono esattamente gli stessi, ad eccezione del fatto che iniziano con un prefisso FOS. L'elenco completo è disponibile negli argomenti IFileDialog::GetOptions e IFileDialog::SetOptions. Le finestre di dialogo Apri e Salva vengono create per impostazione predefinita con i flag più comuni. Per la finestra di dialogo Apri , si tratta di (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) e per la finestra di dialogo Salva si tratta di (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

IFileDialog e le relative interfacce discendenti ereditano da ed estendono IModalWindow. Show accetta come unico parametro l'handle della finestra padre. Se Show restituisce correttamente, viene restituito un risultato valido. Se restituisce HRESULT_FROM_WIN32(ERROR_CANCELLED), significa che l'utente ha annullato la finestra di dialogo. Potrebbe anche restituire legittimamente un altro codice di errore, ad esempio E_OUTOFMEMORY.

Utilizzo di esempio

Le sezioni seguenti illustrano il codice di esempio per un'ampia gamma di attività di dialogo.

La maggior parte del codice di esempio è disponibile nell'esempio di finestra di dialogo File comuni di Windows SDK.

Utilizzo di base

Nell'esempio seguente viene illustrato come avviare una finestra di dialogo Apri . In questo esempio è limitato ai documenti di Microsoft Word.

Nota

Diversi esempi in questo argomento usano la CDialogEventHandler_CreateInstance funzione helper per creare un'istanza dell'implementazione IFileDialogEvents . Per usare questa funzione nel proprio codice, copiare il codice sorgente per la CDialogEventHandler_CreateInstance funzione dall'esempio di finestra di dialogo file comune, da cui vengono acquisiti tutti gli esempi in questo argomento.

 

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

Limitazione dei risultati agli elementi del file system

Nell'esempio seguente, tratto in precedenza, viene illustrato come limitare i risultati agli elementi del file system. Si noti che IFileDialog::SetOptions aggiunge il nuovo flag a un valore ottenuto tramite IFileDialog::GetOptions. Questo è il metodo consigliato.

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

Specifica dei tipi di file per una finestra di dialogo

Per impostare tipi di file specifici che il dialogo può gestire, usare il metodo IFileDialog::SetFileTypes. Questo metodo accetta una matrice di strutture COMDLG_FILTERSPEC , ognuna delle quali rappresenta un tipo di file.

Il meccanismo di estensione predefinito in una finestra di dialogo è invariato da GetOpenFileName e GetSaveFileName. L'estensione del nome file aggiunta al testo digitati dall'utente nella casella di modifica del nome file viene inizializzata quando viene visualizzata la finestra di dialogo. Deve corrispondere al tipo di file predefinito (selezionato durante l'apertura della finestra di dialogo). Se il tipo di file predefinito è "*.*" (tutti i file), il file può essere un'estensione di propria scelta. Se l'utente sceglie un tipo di file diverso, l'estensione viene aggiornata automaticamente alla prima estensione di file associata a tale tipo di file. Se l'utente sceglie "*.*" (tutti i file), l'estensione ripristina il valore originale.

L'esempio seguente illustra come questa operazione è stata eseguita in precedenza.

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

Controllo della cartella predefinita

Quasi tutte le cartelle nello spazio dei nomi shell possono essere usate come cartella predefinita per la finestra di dialogo (la cartella presentata quando l'utente sceglie di aprire o salvare un file). Chiamare IFileDialog::SetDefaultFolder prima di chiamare Show a tale scopo.

La cartella predefinita è la cartella in cui viene avviata la prima volta che un utente lo apre dall'applicazione. Successivamente, la finestra di dialogo verrà aperta nell'ultima cartella che un utente ha aperto o l'ultima cartella usata per salvare un elemento. Per altri dettagli, vedere State Persistence .See State Persistence for more details.

È possibile forzare la finestra di dialogo a visualizzare sempre la stessa cartella all'apertura, indipendentemente dall'azione precedente dell'utente, chiamando IFileDialog::SetFolder. Tuttavia, non è consigliabile eseguire questa operazione. Se si chiama SetFolder prima di visualizzare la finestra di dialogo, il percorso più recente da cui l'utente è stato salvato o aperto non viene visualizzato. A meno che non esista un motivo molto specifico per questo comportamento, non è un'esperienza utente valida o prevista e deve essere evitata. In quasi tutte le istanze, IFileDialog::SetDefaultFolder è il metodo migliore.

Quando si salva un documento per la prima volta nella finestra di dialogo Salva , è necessario seguire le stesse linee guida per determinare la cartella iniziale come si è fatto nella finestra di dialogo Apri . Se l'utente sta modificando un documento esistente in precedenza, aprire la finestra di dialogo nella cartella in cui è archiviato il documento e popolare la casella di modifica con il nome del documento. Chiamare IFileSaveDialog::SetSaveAsItem con l'elemento corrente prima di chiamare Show.

Aggiunta di elementi alla barra Delle posizioni

Nell'esempio seguente viene illustrata l'aggiunta di elementi alla barra Places :

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

Persistenza dello stato

Prima di Windows Vista, uno stato, ad esempio l'ultima cartella visitata, è stato salvato in base al processo. Tuttavia, tali informazioni sono state utilizzate indipendentemente dall'azione specifica. Ad esempio, un'applicazione di modifica video presenterebbe la stessa cartella nella finestra di dialogo Esegui rendering come nella finestra di dialogo Importa file multimediali . In Windows Vista è possibile essere più specifici tramite l'uso di GUID. Per assegnare un GUID alla finestra di dialogo, chiamare iFileDialog::SetClientGuid.

Funzionalità di selezione multipla

La funzionalità di selezione multipla è disponibile nella finestra di dialogo Apri usando il metodo GetResults , come illustrato di seguito.

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

Ascolto di eventi dal dialogo

Un processo chiamante può registrare un'interfaccia IFileDialogEvents con la finestra di dialogo usando i metodi IFileDialog::Advise e IFileDialog::Unadvise, come illustrato di seguito.

Questo è tratto dall'esempio di utilizzo di 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 maggior parte dell'elaborazione dei dialoghi verrà inserita qui.

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

Il processo chiamante può usare eventi per la notifica quando l'utente modifica la cartella, il tipo di file o la selezione. Questi eventi sono particolarmente utili quando il processo chiamante ha aggiunto controlli alla finestra di dialogo (vedere Personalizzazione del dialogo) e deve modificare lo stato di tali controlli in reazione a questi eventi. Utile in tutti i casi è la possibilità del processo chiamante di fornire codice personalizzato per gestire situazioni come la condivisione di violazioni, la sovrascrittura dei file o la determinazione della validità di un file prima della chiusura della finestra di dialogo. Alcuni di questi casi sono descritti in questa sezione.

OnFileOk

Questo metodo viene chiamato dopo che l'utente sceglie un elemento, subito prima della chiusura della finestra di dialogo. L'applicazione può quindi chiamare IFileDialog::GetResult o IFileOpenDialog::GetResults come sarebbe stato fatto dopo la chiusura della finestra di dialogo. Se l'elemento scelto è accettabile, può restituire S_OK. In caso contrario, restituiscono S_FALedizione Standard e visualizzano l'interfaccia utente che indica all'utente perché l'elemento scelto non è valido. Se viene restituito S_FALedizione Standard, la finestra di dialogo non viene chiusa.

Il processo chiamante può usare l'handle della finestra del dialogo stesso come elemento padre dell'interfaccia utente. Tale handle può essere ottenuto chiamando prima IOleWindow::QueryInterface e quindi chiamando IOleWindow::GetWindow con l'handle come illustrato in questo esempio.

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

Se l'utente sceglie di sovrascrivere un file nella finestra di dialogo Salva o se un file salvato o sostituito è in uso e non può essere scritto in (violazione di condivisione), l'applicazione può fornire funzionalità personalizzate per ignorare il comportamento predefinito della finestra di dialogo. Per impostazione predefinita, quando si sovrascrive un file, nella finestra di dialogo viene visualizzata una richiesta che consente all'utente di verificare questa azione. Per le violazioni di condivisione, per impostazione predefinita nella finestra di dialogo viene visualizzato un messaggio di errore, non viene chiuso e l'utente deve effettuare un'altra scelta. Il processo chiamante può eseguire l'override di queste impostazioni predefinite e visualizzare la propria interfaccia utente, se necessario. Il dialogo può essere richiesto di rifiutare il file e rimanere aperto o accettare il file e chiudere correttamente.

Personalizzazione del dialogo

È possibile aggiungere un'ampia gamma di controlli alla finestra di dialogo senza fornire un modello di finestra di dialogo Win32. Questi controlli includono PushButton, ComboBox, EditBox, CheckButton, elenchi RadioButton, Gruppi, Separatori e Controlli Testo statico. Chiamare QueryInterface sull'oggetto finestra di dialogo (IFileDialog, IFileOpenDialog o IFileSaveDialog) per ottenere un puntatore IFileDialogCustomize. Usare tale interfaccia per aggiungere controlli. Ogni controllo ha un ID fornito dal chiamante associato, nonché uno stato visibile e abilitato che può essere impostato dal processo chiamante. Alcuni controlli, ad esempio PushButton, dispongono anche di testo associato.

È possibile aggiungere più controlli in un "gruppo visivo" che si sposta come singola unità nel layout del dialogo. Ai gruppi può essere associata un'etichetta.

I controlli possono essere aggiunti solo prima che venga visualizzata la finestra di dialogo. Tuttavia, una volta visualizzata la finestra di dialogo, i controlli possono essere nascosti o visualizzati come desiderato, ad esempio in risposta all'azione dell'utente. Negli esempi seguenti viene illustrato come aggiungere un elenco di pulsanti di opzione alla finestra di dialogo.

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

Aggiunta di opzioni al pulsante OK

Analogamente, le scelte possono essere aggiunte ai pulsanti Apri o Salva , ovvero il pulsante OK per i rispettivi tipi di dialogo. Le opzioni sono accessibili tramite una casella di riepilogo a discesa collegata al pulsante. Il primo elemento dell'elenco diventa il testo del pulsante. Nell'esempio seguente viene illustrato come fornire un pulsante Apri con due possibilità: "Apri" e "Apri come di sola lettura".

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

La scelta dell'utente può essere verificata dopo che la finestra di dialogo viene restituita dal metodo Show come si farebbe per un controllo ComboBox oppure può essere verificata come parte della gestione da IFileDialogEvents::OnFileOk.

Risposta agli eventi nei controlli aggiunti

Il gestore eventi fornito dal processo chiamante può implementare IFileDialogControlEvents oltre a IFileDialogEvents. IFileDialogControlEvents consente al processo chiamante di reagire a questi eventi:

  • Pulsante di scelta rapida
  • Stato checkbutton modificato
  • Elemento selezionato da un menu, un controllo ComboBox o un elenco di pulsanti di opzione
  • Controllare l'attivazione. Questo viene inviato quando un menu sta per visualizzare un elenco a discesa, nel caso in cui il processo chiamante voglia modificare gli elementi nell'elenco.

Esempi completi

Di seguito sono riportati esempi C++ scaricabili da Windows Software Development Kit (SDK) che illustrano l'uso e l'interazione con la finestra di dialogo elementi comuni.

IID_PPV_ARGS