Share via


일반 항목 대화 상자

Windows Vista부터 공통 항목 대화 상자는 파일을 열거나 저장하는 데 사용되는 경우 이전 일반 파일 대화 상자를 대체합니다. 공통 항목 대화 상자는 열기 대화 상자와 저장 대화 상자의 두 가지 변형으로 사용됩니다. 이 두 대화 상자는 대부분의 기능을 공유하지만 각각 고유한 메서드가 있습니다.

이 최신 버전의 이름은 공통 항목 대화 상자이지만 대부분의 설명서에서 공통 파일 대화 상자라고 합니다. 이전 버전의 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

IFileOpenDialogIFileSaveDialog는 IFileDialog에서 상속되며 대부분의 기능을 공유합니다. 또한 열기 대화 상자는 IFileOpenDialog를 지원하고 저장 대화 상자는 IFileSaveDialog를 지원합니다.

Windows Vista에 있는 공통 항목 대화 상자 구현은 이전 버전에서 제공된 구현보다 몇 가지 이점을 제공합니다.

  • 파일 시스템 경로를 사용하는 대신 IShellItem을 통해 셸 네임스페이스를 직접 사용할 수 있습니다.
  • 후크 프로시저를 요구하지 않고 OK 단추에 레이블을 설정하는 등 대화 상자를 간단하게 사용자 지정할 수 있습니다.
  • Win32 대화 상자 템플릿 없이 작동하는 데이터 기반 컨트롤 집합을 추가하여 대화 상자의 보다 광범위한 사용자 지정을 지원합니다. 이 사용자 지정 체계는 호출 프로세스를 UI 레이아웃에서 해제합니다. 대화 상자 디자인에 대한 변경 내용이 이 데이터 모델을 계속 사용하므로 대화 상자 구현은 대화의 특정 현재 버전에 연결되지 않습니다.
  • 선택 변경 또는 파일 형식 변경과 같은 대화 상자 내의 이벤트에 대한 호출자 알림을 지원합니다. 또한 호출 프로세스에서 구문 분석과 같은 대화 상자의 특정 이벤트를 후크할 수 있습니다.
  • 위치 표시줄에 호출자 지정 위치를 추가하는 것과 같은 새로운 대화 상자를 소개합니다.
  • 저장 대화 상자에서 개발자는 Windows Vista Shell의 새로운 메타데이터 기능을 활용할 수 있습니다.

또한 개발자는 다음 인터페이스를 구현하도록 선택할 수 있습니다.

열기 또는 저장 대화 상자는 호출 프로세스에 IShellItem 또는 IShellItemArray 개체를 반환합니다. 그런 다음 호출자는 개별 IShellItem 개체를 사용하여 파일 시스템 경로를 얻거나 항목에서 스트림을 열어 정보를 읽거나 쓸 수 있습니다.

새 대화 메서드에 사용할 수 있는 플래그 및 옵션은 OPENFILENAME 구조체에 있는 이전 OFN 플래그와 매우 유사하며 GetOpenFileName GetSaveFileName에서 사용됩니다. FOS 접두사로 시작한다는 점을 제외하고, 그들 중 대부분은 정확히 동일합니다. 전체 목록은 IFileDialog::GetOptionsIFileDialog::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 같은 다른 오류 코드를 합법적으로 반환할 수도 있습니다.

Sample Usage

다음 섹션에서는 다양한 대화 작업에 대한 예제 코드를 보여 줍니다.

대부분의 샘플 코드는 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");

기본 폴더 제어

셸 네임스페이스의 거의 모든 폴더를 대화 상자의 기본 폴더(사용자가 파일을 열거나 저장하도록 선택할 때 표시되는 폴더)로 사용할 수 있습니다. Show를 호출하기 전에 IFileDialog::SetDefaultFolder를 호출합니다.

기본 폴더는 사용자가 애플리케이션에서 처음으로 대화 상자를 열 때 대화 상자가 시작되는 폴더입니다. 그런 다음 사용자가 연 마지막 폴더 또는 항목을 저장하는 데 사용한 마지막 폴더에서 대화 상자가 열립니다. 자세한 내용은 상태 지속성을 참조하세요.

IFileDialog::SetFolder를 호출하여 이전 사용자 작업에 관계없이 대화 상자가 열릴 때 항상 동일한 폴더를 표시하도록 강제할 수 있습니다. 그러나 이 작업은 권장하지 않습니다. 대화 상자를 표시하기 전에 SetFolder를 호출하면 사용자가 저장하거나 연 가장 최근 위치가 표시되지 않습니다. 이 동작에 대한 매우 구체적인 이유가 없는 한 좋은 사용자 환경이나 예상 사용자 환경이 아니고 피해야 합니다. 거의 모든 인스턴스 에서 IFileDialog::SetDefaultFolder 가 더 나은 방법입니다.

저장 대화 상자에서 처음으로 문서를 저장할 때 열기 대화 상자에서마찬가지로 초기 폴더를 결정하는 것과 동일한 지침을 따라야 합니다. 사용자가 기존 문서를 편집하는 경우 해당 문서가 저장된 폴더에서 대화 상자를 열고 편집 상자를 해당 문서의 이름으로 채웁다. Show를 호출하기 전에 현재 항목으로 IFileSaveDialog::SetSaveAsItem을 호출합니다.

위치 표시줄에 항목 추가

다음 예제에서는 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;
}

상태 지속성

Windows Vista 이전에는 마지막으로 방문한 폴더와 같은 상태가 프로세스별로 저장되었습니다. 그러나 해당 정보는 특정 작업에 관계없이 사용되었습니다. 예를 들어 비디오 편집 애플리케이션은 미디어 가져오기 대화 상자와 동일한 폴더를 렌더링 대화 상자에 표시합니다. Windows Vista에서는 GUID를 사용하여 보다 구체적으로 지정할 수 있습니다. 대화 상자에 GUID를 할당하려면 iFileDialog::SetClientGuid를 호출합니다.

다중 선택 기능

다중 선택 기능은 다음과 같이 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;
}

대화 상자에서 이벤트 수신 대기

호출 프로세스는 여기에 표시된 대로 IFileDialog::Advise IFileDialog::Unadvise 메서드를 사용하여 IFileDialogEvents 인터페이스를 대화 상자에 등록할 수 있습니다.

기본 사용 샘플에서 가져옵니다.

        // 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 반환하고 선택한 항목이 유효하지 않은 이유를 사용자에게 알려주는 UI를 표시합니다. S_FALSE 반환되면 대화 상자가 닫히지 않습니다.

호출 프로세스는 대화 상자 자체의 창 핸들을 UI의 부모로 사용할 수 있습니다. 이 핸들은 먼저 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

사용자가 저장 대화 상자에서 파일을 덮어쓰도록 선택하거나 저장 또는 교체 중인 파일이 사용 중이고 쓸 수 없는 경우(공유 위반) 애플리케이션은 대화 상자의 기본 동작을 재정의하는 사용자 지정 기능을 제공할 수 있습니다. 기본적으로 파일을 덮어쓸 때 대화 상자에는 사용자가 이 작업을 확인할 수 있는 프롬프트가 표시됩니다. 공유 위반의 경우 기본적으로 대화 상자에 오류 메시지가 표시되고 닫히지 않으며 사용자가 다른 선택을 해야 합니다. 호출 프로세스는 이러한 기본값을 재정의하고 원하는 경우 자체 UI를 표시할 수 있습니다. 대화 상자는 파일을 거부하고 파일을 다시 열거나 수락하고 성공적으로 닫을 기본 지시할 수 있습니다.

대화 상자 사용자 지정

Win32 대화 상자 템플릿을 제공하지 않고 대화 상자에 다양한 컨트롤을 추가할 수 있습니다. 이러한 컨트롤에는 PushButton, ComboBox, EditBox, CheckButton, RadioButton 목록, 그룹, 구분 기호 및 정적 텍스트 컨트롤이 포함됩니다. 대화 상자 개체(IFileDialog, IFileOpenDialog 또는 IFileSaveDialog)에서 QueryInterface를 호출하여 IFileDialogCustomize 포인터를 가져옵니다. 해당 인터페이스를 사용하여 컨트롤을 추가합니다. 각 컨트롤에는 호출 프로세스에서 설정할 수 있는 표시되고 활성화된 상태뿐만 아니라 연결된 호출자 제공 ID가 있습니다. 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;
}

대화 상자가 ComboBox와 마찬가지로 Show 메서드에서 반환된 후 사용자의 선택을 확인하거나 IFileDialogEvents::OnFileOk에서 처리의 일부로 확인할 수 있습니다.

추가된 컨트롤의 이벤트에 응답

호출 프로세스에서 제공하는 이벤트 처리기는 IFileDialogEvents 외에도 IFileDialogControlEvents를 구현수 있습니다. IFileDialogControlEvents 를 사용하면 호출 프로세스가 다음 이벤트에 대응할 수 있습니다.

  • PushButton을 클릭했습니다.
  • CheckButton 상태가 변경됨
  • 메뉴, ComboBox 또는 RadioButton 목록에서 선택한 항목
  • 활성화를 제어합니다. 호출 프로세스에서 목록의 항목을 변경하려는 경우 메뉴가 드롭다운 목록을 표시하려고 할 때 전송됩니다.

전체 샘플

다음은 일반 항목 대화 상자의 사용 및 상호 작용을 보여 주는 Windows SDK(소프트웨어 개발 키트)에서 다운로드 가능한 완전한 C++ 샘플입니다.

IID_PPV_ARGS