Диалоговое окно "Распространенный элемент"

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

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

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

IFileDialog, IFileOpenDialog и IFileSaveDialog

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

screen shot of the open dialog box

screen shot of the save as dialog box

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

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

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

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

  • IFileDialogEvents для получения уведомлений о событиях в диалоговом окне.
  • IFileDialogCustomize для добавления элементов управления в диалоговое окно.
  • 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 возвращается успешно, имеется допустимый результат. Если он возвращается HRESULT_FROM_WIN32(ERROR_CANCELLED), это означает, что пользователь отменил диалоговое окно. Он также может законно возвращать другой код ошибки, например E_OUTOFMEMORY.

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

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

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

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

В следующем примере показано, как запустить диалоговое окно "Открыть ". В этом примере он ограничен документами 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 щелкнул
  • Изменено состояние CheckButton
  • Элемент, выбранный из меню, ComboBox или RadioButton
  • Активация элемента управления. Это отправляется, когда меню собирается отобразить раскрывающийся список, если вызывающий процесс хочет изменить элементы в списке.

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

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

IID_PPV_ARGS