Bagikan melalui


Dialog Item Umum

Dimulai dengan Windows Vista, Dialog Item Umum menggantikan Dialog File Umum yang lebih lama ketika digunakan untuk membuka atau menyimpan file. Dialog Item Umum digunakan dalam dua variasi: dialog Buka dan dialog Simpan . Kedua dialog ini berbagi sebagian besar fungsionalitasnya, tetapi masing-masing memiliki metode uniknya sendiri.

Meskipun versi yang lebih baru ini diberi nama Dialog Item Umum, versi ini terus disebut Dialog File Umum di sebagian besar dokumentasi. Kecuali Anda berurusan secara khusus dengan versi Windows yang lebih lama, Anda harus berasumsi bahwa penyebutan Dialog File Umum mengacu pada Dialog Item Umum ini.

Topik berikut dibahas di sini:

IFileDialog, IFileOpenDialog, dan IFileSaveDialog

Windows Vista menyediakan implementasi dialog Buka dan Simpan : CLSID_FileOpenDialog dan CLSID_FileSaveDialog. Kotak dialog tersebut diperlihatkan di sini.

screen shot of the open dialog box

screen shot of the save as dialog box

IFileOpenDialog dan IFileSaveDialog mewarisi dari IFileDialog dan berbagi banyak fungsionalitas mereka. Selain itu, dialog Buka mendukung IFileOpenDialog, dan dialog Simpan mendukung IFileSaveDialog.

Implementasi Common Item Dialog yang ditemukan di Windows Vista memberikan beberapa keuntungan atas implementasi yang disediakan dalam versi sebelumnya:

  • Mendukung penggunaan namespace Shell secara langsung melalui IShellItem alih-alih menggunakan jalur sistem file.
  • Mengaktifkan penyesuaian dialog sederhana, seperti mengatur label pada tombol OK , tanpa memerlukan prosedur kait.
  • Mendukung penyesuaian dialog yang lebih luas dengan penambahan sekumpulan kontrol berbasis data yang beroperasi tanpa templat dialog Win32. Skema kustomisasi ini membebaskan proses panggilan dari tata letak UI. Karena setiap perubahan pada desain dialog terus menggunakan model data ini, implementasi dialog tidak terkait dengan versi dialog tertentu saat ini.
  • Mendukung pemberitahuan penelepon peristiwa dalam dialog, seperti perubahan pilihan atau perubahan jenis file. Juga memungkinkan proses panggilan untuk mengaitkan peristiwa tertentu dalam dialog, seperti penguraian.
  • Memperkenalkan fitur dialog baru seperti menambahkan tempat yang ditentukan pemanggil ke bilah Tempat .
  • Dalam dialog Simpan, pengembang dapat memanfaatkan fitur metadata baru Windows Vista Shell.

Selain itu, pengembang dapat memilih untuk mengimplementasikan antarmuka berikut:

Dialog Buka atau Simpan mengembalikan objek IShellItem atau IShellItemArray ke proses panggilan. Pemanggil kemudian dapat menggunakan objek IShellItem individual untuk mendapatkan jalur sistem file atau untuk membuka aliran pada item untuk membaca atau menulis informasi.

Bendera dan opsi yang tersedia untuk metode dialog baru sangat mirip dengan bendera OFN yang lebih lama yang ditemukan dalam struktur OPENFILENAME dan digunakan di GetOpenFileName dan GetSaveFileName. Banyak dari mereka persis sama, kecuali bahwa mereka mulai dengan awalan FOS. Daftar lengkap dapat ditemukan di topik IFileDialog::GetOptions dan IFileDialog::SetOptions. Dialog Buka dan Simpan dibuat secara default dengan bendera yang paling umum. Untuk dialog Buka, ini adalah (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) dan untuk dialog Simpan ini adalah (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

IFileDialog dan antarmuka turunannya mewarisi dan memperluas IModalWindow. Tampilkan mengambil sebagai satu-satunya parameter handel jendela induk. Jika Tampilkan berhasil ditampilkan, ada hasil yang valid. Jika mengembalikan HRESULT_FROM_WIN32(ERROR_CANCELLED), itu berarti pengguna membatalkan dialog. Ini mungkin juga secara sah mengembalikan kode kesalahan lain seperti E_OUTOFMEMORY.

Penggunaan sampel

Bagian berikut ini memperlihatkan contoh kode untuk berbagai tugas dialog.

Sebagian besar kode sampel dapat ditemukan di Sampel Dialog File Umum Windows SDK.

Penggunaan Dasar

Contoh berikut mengilustrasikan cara meluncurkan dialog Buka . Dalam contoh ini, dibatasi untuk dokumen Microsoft Word.

Catatan

Beberapa contoh dalam topik ini menggunakan CDialogEventHandler_CreateInstance fungsi pembantu untuk membuat instans implementasi IFileDialogEvents . Untuk menggunakan fungsi ini dalam kode Anda sendiri, salin kode sumber untuk CDialogEventHandler_CreateInstance fungsi dari Sampel Dialog File Umum, dari mana semua contoh dalam topik ini diambil.

 

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

Membatasi Hasil ke Item Sistem File

Contoh berikut, yang diambil dari atas, menunjukkan cara membatasi hasil ke item sistem file. Perhatikan bahwa IFileDialog::SetOptions menambahkan bendera baru ke nilai yang diperoleh melalui IFileDialog::GetOptions. Ini adalah metode yang direkomendasikan.

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

Menentukan Tipe File untuk Dialog

Untuk mengatur jenis file tertentu yang dapat ditangani dialog, gunakan metode IFileDialog::SetFileTypes. Metode tersebut menerima array struktur COMDLG_FILTERSPEC , yang masing-masing mewakili jenis file.

Mekanisme ekstensi default dalam dialog tidak berubah dari GetOpenFileName dan GetSaveFileName. Ekstensi nama file yang ditambahkan ke teks jenis pengguna dalam kotak edit nama file diinisialisasi saat dialog terbuka. Ini harus cocok dengan jenis file default (yang dipilih saat dialog terbuka). Jika jenis file default adalah "*.*" (semua file), file dapat menjadi ekstensi pilihan Anda. Jika pengguna memilih jenis file yang berbeda, ekstensi secara otomatis diperbarui ke ekstensi nama file pertama yang terkait dengan jenis file tersebut. Jika pengguna memilih "*.*" (semua file), maka ekstensi kembali ke nilai aslinya.

Contoh berikut menggambarkan bagaimana hal ini dilakukan di atas.

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

Mengontrol Folder Default

Hampir semua folder di namespace Shell dapat digunakan sebagai folder default untuk dialog (folder yang disajikan ketika pengguna memilih untuk membuka atau menyimpan file). Panggil IFileDialog::SetDefaultFolder sebelum memanggil Tampilkan untuk melakukannya.

Folder default adalah folder tempat dialog dimulai pertama kali pengguna membukanya dari aplikasi Anda. Setelah itu, dialog akan terbuka di folder terakhir yang dibuka pengguna atau folder terakhir yang mereka gunakan untuk menyimpan item. Lihat Persistensi Status untuk detail selengkapnya.

Anda dapat memaksa dialog untuk selalu menampilkan folder yang sama saat terbuka, terlepas dari tindakan pengguna sebelumnya, dengan memanggil IFileDialog::SetFolder. Namun, kami tidak merekomendasikan untuk melakukan ini. Jika Anda memanggil SetFolder sebelum menampilkan kotak dialog, lokasi terbaru tempat pengguna disimpan atau dibuka tidak ditampilkan. Kecuali ada alasan yang sangat spesifik untuk perilaku ini, itu bukan pengalaman pengguna yang baik atau diharapkan dan harus dihindari. Dalam hampir semua instans, IFileDialog::SetDefaultFolder adalah metode yang lebih baik.

Saat menyimpan dokumen untuk pertama kalinya dalam dialog Simpan , Anda harus mengikuti panduan yang sama dalam menentukan folder awal seperti yang Anda lakukan dalam dialog Buka . Jika pengguna mengedit dokumen yang sudah ada sebelumnya, buka dialog di folder tempat dokumen tersebut disimpan, dan isi kotak edit dengan nama dokumen tersebut. Panggil IFileSaveDialog::SetSaveAsItem dengan item saat ini sebelum memanggil Tampilkan.

Menambahkan Item ke Bilah Tempat

Contoh berikut menunjukkan penambahan item ke bilah Tempat :

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

Persistensi Status

Sebelum Windows Vista, status, seperti folder terakhir yang dikunjungi, disimpan berdasarkan per proses. Namun, informasi itu digunakan terlepas dari tindakan tertentu. Misalnya, aplikasi pengeditan video akan menyajikan folder yang sama dalam dialog Render As seperti yang ada dalam dialog Impor Media . Di Windows Vista Anda bisa lebih spesifik melalui penggunaan GUID. Untuk menetapkan GUID ke dialog, panggil iFileDialog::SetClientGuid.

Kemampuan Multipilih

Fungsionalitas multipilih tersedia dalam dialog Buka menggunakan metode GetResults seperti yang ditunjukkan di sini.

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

Mendengarkan Peristiwa dari Dialog

Proses panggilan dapat mendaftarkan antarmuka IFileDialogEvents dengan dialog dengan menggunakan metode IFileDialog::Advise and IFileDialog::Unadvise seperti yang ditunjukkan di sini.

Ini diambil dari sampel Penggunaan Dasar.

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

Sebagian besar pemrosesan dialog akan ditempatkan di sini.

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

Proses panggilan dapat menggunakan peristiwa untuk pemberitahuan saat pengguna mengubah folder, jenis file, atau pilihan. Peristiwa ini sangat berguna ketika proses panggilan telah menambahkan kontrol ke dialog (lihat Menyesuaikan Dialog) dan harus mengubah status kontrol tersebut sebagai reaksi terhadap peristiwa ini. Berguna dalam semua kasus adalah kemampuan proses panggilan untuk menyediakan kode kustom untuk menangani situasi seperti berbagi pelanggaran, menimpa file, atau menentukan apakah file valid sebelum dialog ditutup. Beberapa kasus tersebut dijelaskan di bagian ini.

OnFileOk

Metode ini dipanggil setelah pengguna memilih item, tepat sebelum dialog ditutup. Aplikasi kemudian dapat memanggil IFileDialog::GetResult atau IFileOpenDialog::GetResults seperti yang akan dilakukan setelah dialog ditutup. Jika item yang dipilih dapat diterima, item tersebut dapat mengembalikan S_OK. Jika tidak, mereka mengembalikan S_FALSE dan menampilkan UI yang memberi tahu pengguna mengapa item yang dipilih tidak valid. Jika S_FALSE dikembalikan, dialog tidak ditutup.

Proses panggilan dapat menggunakan handel jendela dialog itu sendiri sebagai induk UI. Handel tersebut dapat diperoleh dengan terlebih dahulu memanggil IOleWindow::QueryInterface lalu memanggil IOleWindow::GetWindow dengan handel seperti yang ditunjukkan dalam contoh ini.

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

Jika pengguna memilih untuk menimpa file dalam dialog Simpan , atau jika file yang disimpan atau diganti sedang digunakan dan tidak dapat ditulis ke (pelanggaran berbagi), aplikasi dapat menyediakan fungsionalitas kustom untuk mengambil alih perilaku default dialog. Secara default, saat menimpa file, dialog menampilkan permintaan yang memungkinkan pengguna memverifikasi tindakan ini. Untuk pelanggaran berbagi, secara default dialog menampilkan pesan kesalahan, tidak ditutup, dan pengguna diperlukan untuk membuat pilihan lain. Proses panggilan dapat mengambil alih default ini dan menampilkan UI-nya sendiri jika diinginkan. Dialog dapat diinstruksikan untuk menolak file dan tetap membuka atau menerima file dan berhasil menutup.

Menyesuaikan Dialog

Berbagai kontrol dapat ditambahkan ke dialog tanpa menyediakan templat dialog Win32. Kontrol ini termasuk pushButton, ComboBox, EditBox, CheckButton, daftar RadioButton, Grup, Pemisah, dan kontrol Teks Statis. Panggil QueryInterface pada objek dialog (IFileDialog, IFileOpenDialog, atau IFileSaveDialog) untuk mendapatkan pointer IFileDialogCustomize. Gunakan antarmuka tersebut untuk menambahkan kontrol. Setiap kontrol memiliki ID yang disediakan pemanggil terkait serta status terlihat dan diaktifkan yang dapat diatur oleh proses panggilan. Beberapa kontrol, seperti PushButton, juga memiliki teks yang terkait dengannya.

Beberapa kontrol dapat ditambahkan ke dalam "grup visual" yang bergerak sebagai satu unit dalam tata letak dialog. Grup dapat memiliki label yang terkait dengannya.

Kontrol hanya dapat ditambahkan sebelum dialog ditampilkan. Namun, setelah dialog ditampilkan, kontrol dapat disembunyikan atau ditampilkan sesuai keinginan, mungkin sebagai respons terhadap tindakan pengguna. Contoh berikut menunjukkan cara menambahkan daftar tombol radio ke dialog.

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

Menambahkan Opsi ke Tombol OK

Demikian pula, pilihan dapat ditambahkan ke tombol Buka atau Simpan , yang merupakan tombol OK untuk jenis dialog masing-masing. Opsi dapat diakses melalui kotak daftar drop-down yang dilampirkan ke tombol . Item pertama dalam daftar menjadi teks untuk tombol . Contoh berikut menunjukkan cara menyediakan tombol Buka dengan dua kemungkinan: "Buka" dan "Buka sebagai baca-saja".

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

Pilihan pengguna dapat diverifikasi setelah dialog kembali dari metode Tampilkan seperti yang Anda lakukan untuk ComboBox, atau dapat diverifikasi sebagai bagian dari penanganan oleh IFileDialogEvents::OnFileOk.

Menanggapi Peristiwa di Kontrol yang Ditambahkan

Penanganan aktivitas yang disediakan oleh proses panggilan dapat mengimplementasikan IFileDialogControlEvents selain IFileDialogEvents. IFileDialogControlEvents memungkinkan proses panggilan untuk bereaksi terhadap peristiwa ini:

  • PushButton diklik
  • Status CheckButton berubah
  • Item dipilih dari menu, ComboBox, atau daftar RadioButton
  • Mengontrol aktivasi. Ini dikirim ketika menu akan menampilkan daftar drop-down, jika proses panggilan ingin mengubah item dalam daftar.

Sampel Lengkap

Berikut ini adalah sampel C++ yang lengkap dan dapat diunduh dari Windows Software Development Kit (SDK) yang menunjukkan penggunaan dan interaksi dengan Dialog Item Umum.

IID_PPV_ARGS