Диалоговое окно "Общий элемент"

Начиная с Windows Vista, диалоговое окно "Общий элемент" заменяет более старое диалоговое окно "Общий файл" при открытии или сохранении файла. Диалоговое окно "Общий элемент" используется в двух вариантах: диалоговое окно "Открыть " и "Сохранить ". Эти два диалога используют большую часть своих функциональных возможностей, но каждый из них имеет свои собственные уникальные методы.

Хотя эта более новая версия называется диалогом общих элементов, в большинстве документации она по-прежнему называется диалогом с общими файлами. Если вы не используете более раннюю версию Windows, следует предположить, что любая упоминание диалогового окна "Общий файл" относится к этому диалогу общих элементов.

Здесь рассматриваются следующие темы:

IFileDialog, IFileOpenDialog и IFileSaveDialog

Windows Vista предоставляет реализации диалоговых окон Открытие и Сохранение : CLSID_FileOpenDialog и CLSID_FileSaveDialog. Эти диалоговые окна показаны здесь.

Снимок экрана: открытое диалоговое окно

Снимок экрана: диалоговое окно

IFileOpenDialog и IFileSaveDialog наследуются от IFileDialog и используют большую часть их функциональных возможностей. Кроме того, диалоговое окно "Открыть " поддерживает IFileOpenDialog, а диалоговое окно "Сохранить " поддерживает IFileSaveDialog.

Реализация диалогового окна общих элементов в Windows Vista предоставляет несколько преимуществ по сравнению с реализацией, предоставляемой в более ранних версиях:

  • Поддерживает прямое использование пространства имен оболочки через IShellItem вместо использования путей файловой системы.
  • Включает простую настройку диалогового окна, например установку метки на кнопке ОК , не требуя процедуры перехватчика.
  • Поддерживает более обширную настройку диалога путем добавления набора управляемых данными элементов управления, которые работают без шаблона диалогового окна Win32. Эта схема настройки освобождает вызывающий процесс от макета пользовательского интерфейса. Так как все изменения в структуре диалога по-прежнему используют эту модель данных, реализация диалога не привязана к конкретной текущей версии диалога.
  • Поддерживает уведомление вызывающей стороны о событиях в диалоговом окне, таких как изменение выбора или изменение типа файла. Кроме того, позволяет вызывающей процедуре перехватывать определенные события в диалоговом окне, например синтаксический анализ.
  • Новые возможности диалога, такие как добавление мест, указанных вызывающим абонентом, на панель "Места ".
  • В диалоговом окне Сохранить разработчики могут воспользоваться новыми функциями метаданных оболочки Windows Vista.

Кроме того, разработчики могут реализовать следующие интерфейсы:

  • IFileDialogEvents для получения уведомлений о событиях в диалоговом окне.
  • IFileDialogНастройка для добавления элементов управления в диалоговое окно.
  • IFileDialogControlEvents для уведомления о событиях в добавленных элементах управления.

Диалоговое окно Открыть или Сохранить возвращает объект IShellItem или IShellItemArray вызывающей процедуре. Затем вызывающий объект может использовать отдельный объект IShellItem , чтобы получить путь к файловой системе или открыть поток в элементе для чтения или записи сведений.

Флаги и параметры, доступные для новых методов диалога, очень похожи на старые флаги OFN в структуре OPENFILENAME и используются в GetOpenFileName и GetSaveFileName. Многие из них точно такие же, за исключением того, что они начинаются с префикса FOS. Полный список можно найти в разделах IFileDialog::GetOptions и IFileDialog::SetOptions . Диалоговые окна "Открыть" и "Сохранить" создаются по умолчанию с наиболее распространенными флагами. Для диалогового окна Открыть это (FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR) и для диалогового окна Сохранить это значение (FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR).

Интерфейсы IFileDialog и его потомков наследуют от IModalWindow и расширяют их. Show принимает в качестве единственного параметра дескриптор родительского окна. Если значение Show возвращается успешно, имеется допустимый результат. Если возвращается HRESULT_FROM_WIN32(ERROR_CANCELLED)значение , это означает, что пользователь отменил диалоговое окно. Он также может вернуть другой код ошибки, например E_OUTOFMEMORY.

Пример использования

В следующих разделах показаны примеры кода для различных задач диалога.

Большую часть примера кода можно найти в примере диалогового окна общих файлов пакета Windows SDK.

Основное использование

В следующем примере показано, как запустить диалоговое окно "Открыть ". В этом примере он ограничен документами Microsoft Word.

Примечание

В нескольких примерах этого раздела используется CDialogEventHandler_CreateInstance вспомоганная функция для создания экземпляра реализации IFileDialogEvents . Чтобы использовать эту функцию в собственном коде, скопируйте исходный код функции CDialogEventHandler_CreateInstance из примера общего диалогового окна файла, из которого взяты все примеры в этом разделе.

 

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

Ограничение результатов элементами файловой системы

В приведенном выше примере показано, как ограничить результаты элементами файловой системы. Обратите внимание, что IFileDialog::SetOptions добавляет новый флаг к значению, полученному с помощью IFileDialog::GetOptions. Рекомендуем использовать этот метод.

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

Указание типов файлов для диалогового окна

Чтобы задать определенные типы файлов, которые могут обрабатываться диалоговым окном, используйте метод IFileDialog::SetFileTypes . Этот метод принимает массив COMDLG_FILTERSPEC структур, каждая из которых представляет тип файла.

Механизм расширения по умолчанию в диалоговом окне не отличается от GetOpenFileName и GetSaveFileName. Расширение имени файла, добавляемое к тексту, который пользователь вводит в поле ввода имени файла, инициализируется при открытии диалогового окна. Он должен соответствовать типу файла по умолчанию (выбранному при открытии диалогового окна). Если тип файла по умолчанию — "*.*" (все файлы), файл может быть расширением по вашему выбору. Если пользователь выбирает другой тип файла, расширение автоматически обновляется до первого расширения имени файла, связанного с этим типом файлов. Если пользователь выбирает "*.*" (все файлы), расширение возвращается к исходному значению.

В следующем примере показано, как это было сделано выше.

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

Управление папкой по умолчанию

Практически любую папку в пространстве имен оболочки можно использовать в качестве папки по умолчанию для диалогового окна (папка, представленная, когда пользователь выбирает открытие или сохранение файла). Вызовите метод IFileDialog::SetDefaultFolder перед вызовом метода Show .

Папка по умолчанию — это папка, в которой диалоговое окно запускается при первом открытии пользователем из приложения. После этого диалоговое окно откроется в последней папке, открытой пользователем, или в последней папке, которая использовалась для сохранения элемента. Дополнительные сведения см. в разделе Сохраняемость состояния .

Вы можете принудить диалоговое окно всегда отображать одну и ту же папку при его открытии, независимо от предыдущего действия пользователя, вызвав метод IFileDialog::SetFolder. Однако мы не рекомендуем это делать. Если вы вызываете SetFolder перед отображением диалогового окна, последнее расположение, в котором пользователь сохранил или открыл его, не отображается. Если для такого поведения нет особой причины, это не является хорошим или ожидаемым взаимодействием с пользователем, и его следует избегать. Почти во всех экземплярах лучше использовать метод IFileDialog::SetDefaultFolder .

При первом сохранении документа в диалоговом окне Сохранить следует следовать тем же рекомендациям при определении начальной папки, что и в диалоговом окне Открыть . Если пользователь редактирует ранее существующий документ, откройте диалоговое окно в папке, в которой хранится этот документ, и заполните поле редактирования именем этого документа. Вызовите метод IFileSaveDialog::SetSaveAsItem с текущим элементом перед вызовомМетода Show.

Добавление элементов на панель мест

В следующем примере показано добавление элементов на панель Мест :

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

Сохраняемость состояния

До windows Vista состояние, например последняя посещенная папка, сохранялось для каждого процесса. Однако эта информация используется независимо от конкретного действия. Например, приложение для редактирования видео будет отображать ту же папку в диалоговом окне Отрисовка как в диалоговом окне Импорт мультимедиа . В Windows Vista вы можете быть более конкретными с помощью идентификаторов GUID. Чтобы назначить идентификатор GUID диалогу, вызовите метод iFileDialog::SetClientGuid.

Возможности множественного выбора

Функция multiselect доступна в диалоговом окне Открыть с помощью метода GetResults , как показано здесь.

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

Прослушивание событий из диалогового окна

Вызывающий процесс может зарегистрировать интерфейс IFileDialogEvents в диалоговом окне с помощью методов IFileDialog::Advise и IFileDialog::Unadvise , как показано ниже.

Это взято из примера "Базовое использование ".

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

Основная часть обработки диалога будет размещена здесь.

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

Вызывающий процесс может использовать события для уведомления при изменении пользователем папки, типа файла или выбора. Эти события особенно полезны, если вызывающий процесс добавил элементы управления в диалог (см. раздел Настройка диалогового окна) и должен изменить состояние этих элементов управления в ответ на эти события. Полезной во всех случаях является возможность вызывающего процесса предоставлять пользовательский код для решения таких ситуаций, как нарушения общего доступа, перезапись файлов или определение допустимости файла до закрытия диалогового окна. Некоторые из этих случаев описаны в этом разделе.

OnFileOk

Этот метод вызывается после выбора пользователем элемента непосредственно перед закрытием диалогового окна. Затем приложение может вызвать IFileDialog::GetResult или IFileOpenDialog::GetResults , как это будет сделано после закрытия диалогового окна. Если выбранный элемент является приемлемым, они могут вернуть S_OK. В противном случае они возвращают S_FALSE и отображают пользовательский интерфейс, который сообщает пользователю, почему выбранный элемент является недопустимым. Если возвращается S_FALSE, диалоговое окно не закрывается.

Вызывающий процесс может использовать дескриптор окна самого диалога в качестве родительского элемента пользовательского интерфейса. Этот дескриптор можно получить, сначала вызвав IOleWindow::QueryInterface , а затем вызвав IOleWindow::GetWindow с дескриптором, как показано в этом примере.

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

Если пользователь решит перезаписать файл в диалоговом окне Сохранить или если сохраненный или заменяемый файл используется и не может быть записан в (нарушение общего доступа), приложение может предоставить пользовательские функции для переопределения поведения диалога по умолчанию. По умолчанию при перезаписи файла в диалоговом окне отображается запрос, позволяющий пользователю проверить это действие. Для нарушений общего доступа диалоговое окно по умолчанию отображает сообщение об ошибке, оно не закрывается, и пользователь должен сделать другой выбор. Вызывающий процесс может переопределить эти значения по умолчанию и при необходимости отобразить собственный пользовательский интерфейс. В диалоговом окне можно указать отказаться от файла и оставаться открытым или принять файл и успешно закрыть его.

Настройка диалогового окна

В диалоговое окно можно добавить различные элементы управления, не предоставляя шаблон диалогового окна Win32. К этим элементам управления относятся PushButton, ComboBox, EditBox, CheckButton, Списки RadioButton, Группы, Разделители и Статический текст. Вызовите QueryInterface для объекта диалогового окна (IFileDialog, IFileOpenDialog или IFileSaveDialog), чтобы получить указатель IFileDialogCustomize . Используйте этот интерфейс для добавления элементов управления. Каждый элемент управления имеет связанный идентификатор, предоставленный вызывающей стороны, а также видимое и включенное состояние, которое может быть задано вызывающим процессом. Некоторые элементы управления, такие как PushButton, также имеют связанный с ними текст.

Несколько элементов управления можно добавить в "визуальную группу", которая перемещается как единое целое в макете диалогового окна. С группами может быть связана метка.

Элементы управления можно добавлять только до отображения диалогового окна. Однако после отображения диалогового окна элементы управления можно скрыть или отобразить по желанию, возможно, в ответ на действия пользователя. В следующих примерах показано, как добавить список переключателей в диалоговое окно.

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

Добавление параметров на кнопку ОК

Аналогичным образом можно добавить параметры к кнопкам Открыть или Сохранить , которые являются кнопкой ОК для соответствующих типов диалогов. Параметры доступны через раскрывающийся список, подключенный к кнопке. Первым элементом в списке становится текст кнопки. В следующем примере показано, как предоставить кнопку Открыть с двумя возможностями: "Открыть" и "Открыть как доступный только для чтения".

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

Выбор пользователя можно проверить после возврата диалогового окна из метода Show так же, как для ComboBox, или его можно проверить в рамках обработки с помощью IFileDialogEvents::OnFileOk.

Реагирование на события в добавленных элементах управления

Обработчик событий, предоставляемый вызывающим процессом, может реализовывать IFileDialogControlEvents в дополнение к IFileDialogEvents. IFileDialogControlEvents позволяет вызывающей процедуре реагировать на следующие события:

  • PushButton clicked
  • Состояние CheckButton изменено
  • Элемент, выбранный в меню, списке ComboBox или RadioButton
  • Активация элемента управления. Он отправляется, когда меню собирается отобразить раскрывающийся список, если вызывающий процесс хочет изменить элементы в списке.

Полные примеры

Ниже приведены полные загружаемые примеры C++ из пакета sdk для Windows, демонстрирующие использование и взаимодействие с диалоговым окном общих элементов.

IID_PPV_ARGS