【C++/MFC】ファイル/フォルダーの選択ダイアログを表示する

 ファイル/フォルダーを選択する、「開く」「名前を付けて保存」「フォルダーの選択」ダイアログを表示する方法を以下に示す。

開発環境Visual Studio 2022
言語C++
フレームワークMFC
動作確認Windows 11
Windows 10
Windows 7
ファイル選択ダイアログ

「開く」ダイアログ表示

(1) 1個のファイルのみ選択可能

 CFileDialogクラスのコンストラクターの引数にtrueを指定する。ただし、この場合は存在しないファイルもファイル名欄に入力できる。


    CFileDialog fileDialog(true);

    // 上記と同じ動作
    // CFileDialog fileDialog(true, nullptr, nullptr, 0);

    // ダイアログ表示
    if (fileDialog.DoModal() == IDOK)
    {
        // [開く]ボタン押下

        // フルパス取得
        std::wstring fullPathName = fileDialog.GetPathName();

        // ここでfullPathNameに格納されたフルパスを使用する
        //
        //
        //
    }

 拡張子を省略してファイル名欄に入力した場合、自動的に補完するには、2番目の引数に拡張子を設定する。


    CFileDialog fileDialog(true, L"txt");

 存在しないファイルを入力した場合、[開く]ボタン押下後に警告ダイアログを表示するには、4番目の引数にOFN_FILEMUSTEXISTを設定する。 2番目の引数と同時に設定した場合、補完前後の両方のファイルが存在しないときのみ警告ダイアログを表示する。

警告ダイアログ

    CFileDialog fileDialog(true, nullptr, nullptr, OFN_FILEMUSTEXIST);

 特定の拡張子のファイルのみ表示するフィルターは、5番目の引数に設定する(細かい書式は後述)。

フィルター

    CFileDialog fileDialog(true, nullptr, nullptr, 0, L"テキスト ドキュメント (*.txt)|*.txt||");

(2) 複数ファイル選択可能

 4番目の引数に、OFN_ALLOWMULTISELECTを設定する。


    CFileDialog fileDialog(true, nullptr, nullptr, OFN_ALLOWMULTISELECT);

    // 警告ダイアログ表示
    // CFileDialog fileDialog(true, nullptr, nullptr, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT);

    // 選択可能なファイル数の最大値
    // (数値は任意)
    const unsigned long iCount = 100;

    // 選択ファイルのフルパスを格納するバッファーのサイズ
    // (1ファイル毎にnull終端、バッファー最後のnull終端を考慮)
    const unsigned long iLength = (MAX_PATH + 1) * iCount + 1;

    // バッファーの変数を初期化
    wchar_t *fullPathBuffer = new wchar_t[iLength]{};

    // バッファーをOPENFILENAME構造体に登録
    fileDialog.GetOFN().lpstrFile = fullPathBuffer;
    fileDialog.GetOFN().nMaxFile = iLength;

    // ダイアログ表示
    if (fileDialog.DoModal() == IDOK)
    {
        // [開く]ボタン押下

        // バッファーの先頭を取得
        POSITION pos = fileDialog.GetStartPosition();

        while(pos != nullptr)
        {
            // 選択したファイル数ループする

            // フルパス取得
            std::wstring fullPathName = fileDialog.GetNextPathName(pos);

            // ここでfullPathNameに格納されたフルパスを使用する
            //
            //
            //
        }
    }

    // 変数の解放
    delete[] fullPathBuffer;

「名前を付けて保存」ダイアログ表示

 CFileDialogクラスのコンストラクターの引数にfalseを指定する。デフォルトにて、存在するファイルの上書き警告ダイアログを表示する。

上書き警告ダイアログ

    CFileDialog fileDialog(false);

    // 上記と同じ動作
    // CFileDialog fileDialog(false, nullptr, nullptr, OFN_OVERWRITEPROMPT);

    // ダイアログ表示
    if (fileDialog.DoModal() == IDOK)
    {
        // [保存]ボタン押下

        // フルパス取得
        std::wstring fullPathName = fileDialog.GetPathName();

        // ここでfullPathNameに格納されたフルパスを使用する
        //
        //
        //
    }

 拡張子を省略してファイル名欄に入力した場合、自動的に補完するには、2番目の引数に拡張子を設定する。


    CFileDialog fileDialog(false, L"txt");

 存在するファイルを入力した場合、[保存]ボタン押下後に上書き警告ダイアログを表示しないようにするには、4番目の引数にゼロを設定する。


    CFileDialog fileDialog(false, nullptr, nullptr, 0);

 特定の拡張子のファイルのみ表示するフィルターは、5番目の引数に設定する。


    CFileDialog fileDialog(false, nullptr, nullptr, OFN_OVERWRITEPROMPT,
        L"テキスト ドキュメント (*.txt)|*.txt||");

フィルターの書式

 以下の書式をファイルの種類だけ繰り返して、最後に縦棒を追加する。


// 書式
ドロップダウンリストに表示するテキスト 縦棒 ワイルドカード 縦棒

// 例1
L"テキスト ドキュメント (*.txt)|*.txt||"

// 例2
L"テキスト ドキュメント (*.txt)|*.txt|すべてのファイル (*.*)|*.*||"

// 例3
L"CSVファイル (*.csv)|*.csv|テキスト ドキュメント (*.txt)|*.txt|すべてのファイル (*.*)|*.*||"

 フィルターのデフォルト表示、および、どのフィルターを選択したかは、GetOFN().nFilterIndexにて設定・取得できる。 ただし、フィルターの選択と入力した拡張子が異なる場合、どう処理するかは自分で決める必要がある。


    CFileDialog fileDialog(略);

    // フィルターの何番目をデフォルト表示するかの指定(1開始)
    // 省略した場合、先頭を表示する
    fileDialog.GetOFN().nFilterIndex = インデックス;

    // ダイアログ表示
    if (fileDialog.DoModal() == IDOK)
    {
        // ボタン押下

        // フルパス取得
        std::wstring fullPathName = fileDialog.GetPathName();

        // フィルターの選択を取得(1開始)
        unsigned long i = fileDialog.GetOFN().nFilterIndex;

        if (fileDialog.GetFileExt().IsEmpty())
        {
            // 拡張子の入力が無い場合
            //
            //
            //
        }

        // 以下、ファイルを開く、または、保存する
        //
        //
        //
    }

「フォルダーの選択」ダイアログ表示

 CFileDialogクラスの派生クラスである、CFolderPickerDialogクラスを使用する。


    CFolderPickerDialog folderDialog;

    // ダイアログ表示
    if (folderDialog.DoModal() == IDOK)
    {
        // [フォルダーの選択]ボタン押下

        // フルパス取得
        std::wstring fullPathName = folderDialog.GetPathName();

        // ここでfullPathNameに格納されたフルパスを使用する
        //
        //
        //
    }

リファレンス

CFileDialog Class
https://learn.microsoft.com/en-us/cpp/mfc/reference/cfiledialog-class

CFolderPickerDialog Class
https://learn.microsoft.com/en-us/cpp/mfc/reference/cfolderpickerdialog-class