ぴぐノート

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, プログラミング言語

執筆者:

関連記事

【Boost】Boostライブラリの日付を使ってみよう!

先日の記事でBoostをインストールできたのでBoostのライブラリを使って遊んでみましょう。 今回は日付に関する情報をBoostから取得・表示したり、〇月〇日~□月□日が何日間あるか(期間)取得して …

【Boost】boost::property_treeの例外処理を考えよう!

ライブラリなどを使用していると、「使い方は大体分かった!使ってみよう!」とすると微妙にはまってしまうことがあります。 前回・前々回でお話しした文字コードもその一つですが今回は例外処理について考えてみま …

C++のプリプロセッサの復習をしよう その2 【#defineの活用】

前回に引き続き、C++のプリプロセッサの復習です。 前回は#includeと#defineについて記事にしましたが、【まとめ】にも記載の通り、#defineと関連するプリプロセッサは多くあります。 今 …

【MFC入門】MFCについて知ろう【Visual C++】

Windowsのアプリ開発で最もポピュラーな開発環境はやはりMFCでしょうか。 MFC(Microsoft Foundation Class)とはVisual Studioに組み込まれているアプリケー …

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

前回の記事でEclipseにCDTを追加インストールすることができました。 今回はMinGWとMSYSをインストールし、Eclipse上でC++プロジェクトを実行してみましょう。 この際に必要なダウン …