ぴぐノート

Good code is its own best documentation.

C/C++ MFC プログラミング言語

【MFC】フォルダー選択ダイアログの表示【Visual C++】

投稿日:

出力先の指定などフォルダー選択のダイアログを表示させたいことがあります。
フォルダー選択ダイアログを表示させるためには、SHBrowseForFolder関数を使います。

SHBrowseForFolder関数は、BROWSEINFO構造体を引数に取るので構造体に値をセットしなければいけません。
またSHBrowseForFolder関数の戻り値である、ITEMIDLIST構造体は取得したのち解放が必要なので、IMallocインターフェイスを用意したりと結構手間がかかります。

冒頭から見慣れない関数、構造体などがたくさん出てくるかもしれませんが、要点さえ押さえていれば簡単に実装できるので、ボタンを押下するとフォルダー選択ダイアログを表示させるサンプルプログラムを作成してみましょう。

サンプルプログラム

リソースエディター

ダイアログベースのプロジェクトを作成し、以下の手順で作成します。

関連リンク:無料のVisual StudioをインストールしてMFCを動かそう

  • リソースエディターで以下のようなダイアログを作成します。
    browse_for_folder_001
  • [Button1]を右クリックし、[イベントハンドラーの追加]をクリックして、OnBnClickedButton1関数を作成します。

コーディング

まずは、フォルダー選択ダイアログを表示させる関数を作成します。

フォルダー選択ダイアログを表示させる、SHBrowseForFolder関数の戻り値、ITEMIDLIST構造体は取得したのち必ず解放しなければいけません
ITEMIDLIST構造体を解放させるためには、IMallocインターフェイスのポインタが必要となるため、関数冒頭で宣言、SHGetMalloc関数にて作成します。

IMallocインターフェースの作成が成功すれば、今回作成するフォルダー選択ダイアログの構造を規定していきます。(BROWSEINFO構造体)

hWndOwner フォルダー選択ダイアログのオーナーウィンドウのハンドル。
pidRoot ルートフォルダを表すITEMIDLISTへのポインタ。
NULLを指定した場合には”デスクトップ”がルートフォルダに設定される。
pszDisplayName 選択されたアイテムの表示名を格納するバッファへのアドレスを指定。
lpszTitle フォルダー選択ダイアログのツリービュー上部に表示される文字列のアドレス。
ulFlags フォルダー選択ダイアログのオプションフラグ。後述。
lpfn イベント発生時にフォルダー選択ダイアログが呼び出すコールバック関数のアドレス。
必要なければNULL指定可能。
lParam コールバック関数に渡されるアプリケーション定義値。
iImage 選択されたフォルダと関連付けられるシステムイメージリストのインデックス。
ulFlags(オプションフラグ)

選択可能なフォルダーの指定や、ユーザーが指定できるエディットボックスの有無、新しいフォルダー作成ボタンなど、フォルダー選択ダイアログのオプションが指定できます。

  • BIF_RETURNONLYFSDIRS
    ファイルシステムディレクトリ以外が選択されている場合は[OK]ボタンがグレーアウトします。
  • BIF_DONTGOBELOWDOMAIN
    ダイアログのツリービューコントロールにドメインレベルのネットワークフォルダーを含めない。
  • BIF_EDITBOX
    アイテム名を書き込むことができるエディットボックスを作成します。
  • BIF_VALIDATE
    上記エディットボックスに無効な名前を入力した場合、コールバック関数にBFFM_VALIDATEFAILEDメッセージを送ります。
  • BIF_NEWDIALOGSTYLE
    リサイズなどが可能な新しいユーザーインターフェイスを使用します。
    [新しいフォルダー]ボタンやフォルダーの削除などが追加されます。

他にもいくつか定義されていますが、頻繁に使用するのはこのあたりでしょうか。

関連リンク:BROWSEINFO structure (Windows)

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

BROWSEINFO構造体に値をセットしたら、SHBrowseForFolder関数を呼び出して、フォルダー選択ダイアログを表示させることができます。

呼び出しに成功すれば、SHGetPathFromIDList関数にITEMIDLIST構造体と、フルパスを格納するバッファを指定してフルパスを取得します。

関連リンク:SHBrowseForFolder function (Windows)

ITEMIDLIST構造体とIMallocインターフェイスの解放

最後に、IMallocインターフェイスのFree関数でITEMIDLIST構造体を解放、そしてIMallocインターフェイス自体を解放して完了です。

コールバック関数定義

さて、フォルダー選択ダイアログの設定を行う際、ダイアログが呼び出すコールバック関数のポインタが必要でした。

  • BFFM_INITIALIZED
    ダイアログの初期化が完了したときにメッセージが送られます。
  • BFFM_IUNKNOWN
    IUNNOWNインターフェイスを使用時にメッセージが送られます。
  • BFFM_SELCHANGED
    ダイアログで選択が変更された場合にメッセージが送られます。
  • BFFM_VALIDATEFAILED
    ダイアログ内のエディットボックスに存在しないフォルダーなど、無効な名前を入力した場合にメッセージが送られます。

特にコールバック関数が必要でない場合はBROWSEINFO構造体にNULLを指定することもできます。

関連リンク:BFFCALLBACK function pointer (Windows)

Button1のイベントハンドラー

ボタンのイベントハンドラーとして作成した、OnBnClickedButton1関数を編集します。

選択したフォルダーのフルパスを格納するバッファを用意して、作成したSelectFolder関数を呼び出すだけです。

実行し、ボタンを押下するとフォルダー選択ダイアログが表示され、選択したフォルダーのフルパスをメッセージボックスで表示できていると思います。

まとめ

うまく実行できたでしょうか。
そんなに難しい実装ではなかったと思いますが、見慣れない構造体などの定義があると少し躊躇してしまう人もいるのではないでしょうか。

設定する項目をしっかり理解して使い方に慣れていくことが肝要ですね。

スポンサーリンク

スポンサーリンク

-C/C++, MFC, プログラミング言語

執筆者:

関連記事

Eclipse NeonとCDT/MinGWでC++開発環境を作成しよう!(1)

MFCなどを利用する場合にはほぼVisualStudio一択ですが、簡単なコンソールアプリケーションを作る場合にはEclipseのほうが便利な場合も多いです。 特に「普段はJavaで開発を行っているけ …

【MFC】マルチスレッドでプログレスバーを実装しよう その3

プログレスバーをマルチスレッドを用いた実装について最後の記事です。 引き続き作成の目的は、 スレッド実行中はモーダルダイアログを表示させること。 モーダルダイアログではプログレスバーを表示し進捗が分か …

【C++11】後処理が必要なリソースはスマートポインタを使おう

オープンソースのライブラリのソースコードを呼んでいるとC++11で追加されたunique_ptrを使用しているところもちらほらと見られるようになってきています。 MFCなどを利用していれば動的確保した …

【MFC】マルチスレッドでプログレスバーを実装しよう その2

昨日に続き、プログレスバーをマルチスレッドを用いて実装してみましょう。 作成の目的は、 スレッド実行中はモーダルダイアログを表示させること。 モーダルダイアログではプログレスバーを表示し進捗が分かるこ …

【MFC入門】メッセージボックスにエラーコードを表示させよう

ライブラリなどを使用していると、戻り値にエラーコードを返す関数は比較的多いです。 GetLastError関数(最新のエラーコードを取得する関数)がライブラリに含まれていることもありますが、そうでない …