フォルダ指定ダイアログを表示する
※フォルダ選択が行われない不具合が発生していたため、サンプル&解説をを修正しました。(2004/2/26)
コモンダイアログのフォルダ指定ダイアログを表示するテクニックです。
また、表示時に指定したフォルダを選択している状態にもしています。※VB6から追加されたAddressOfを指定しているので下記サンプルは旧VBでは動作しません。
旧VBでの動作については「旧VBでの使用について」をご覧ください。
サンプル(32bit) ダウンロード
' フォルダ指定ダイアログを表示するAPI Public Declare Function SHBrowseForFolder Lib "shell32.dll" (lpBrowseInfo As BROWSEINFO) As Long ' アイテム識別子のリストをシステムパスへ変換するAPI Public Declare Function SHGetPathFromIDList Lib "shell32.dll" (ByVal pidl As Long, ByVal pszPath As String) As Long ' メッセージの送信API Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Public Type BROWSEINFO hwndOwner As Long pidlRoot As Long pszDisplayName As String lpszTitle As String ulFlags As Long lpfn As Long lParam As String iImage As Long End Type Public Const MAX_PATH As Long = 260 Public Const BIF_RETURNONLYFSDIRS As Long = &H1 Public Const BIF_DONTGOBELOWDOMAIN As Long = &H2 Public Const BIF_STATUSTEXT As Long = &H4 Public Const BIF_RETURNFSANCESTORS As Long = &H8 Public Const BIF_EDITBOX As Long = &H10 Public Const BIF_VALIDATE As Long = &H20 Public Const BIF_BROWSEFORCOMPUTER As Long = &H1000 Public Const BIF_BROWSEFORPRINTER As Long = &H2000 Public Const BIF_BROWSEINCLUDEFILES As Long = &H4000 Public Const WM_USER = &H400 Public Const BFFM_INITIALIZED = 1 Public Const BFFM_SETSELECTIONA = (WM_USER + 102) Public Function GetPointer(lngAddressOf As Long) As Long 'コールバック関数のアドレスを返す GetPointer = lngAddressOf End Function Public Function BFFCallback(ByVal hwnd As Long, ByVal uMsg As Long, ByVal lParam As Long, ByVal lpData As Long) As Long 'フォルダを指定のメッセージをダイアログへ送信 If uMsg = BFFM_INITIALIZED Then Call SendMessage(hwnd, BFFM_SETSELECTIONA, True, ByVal lpData) End If End Function '================================================================================================== ' 概要 : フォルダ選択ダイアログの表示 ' 引数 : hwnd : 呼び出すフォームのハンドル ' : strTitle : フォルダ選択ダイアログのウィンドタイトル ' : strPath : 初期選択フォルダ名 ' 戻値 : [OK]クリック時:指定されたフォルダ名 [キャンセル]クリック時:strPathと同じ内容 '================================================================================================== Public Function ShowFolders(hwnd As Long, strTitle As String, strPath As String) As String 'BROWSEINFO構造体 Dim udtBrows As BROWSEINFO Dim nRC As Long Dim DataPath As String 'とりあえず指定されたフォルダを戻り値にセット ShowFolders = strPath 'BROWSEINFO構造体設定 With udtBrows .hwndOwner = hwnd .pidlRoot = 0 .pszDisplayName = String(MAX_PATH, vbNullChar) .lpszTitle = strTitle .ulFlags = BIF_RETURNONLYFSDIRS .lpfn = GetPointer(AddressOf BFFCallback) .lParam = strPath & vbNullChar .iImage = 0 End With 'フォルダ選択ダイアログ表示 nRC = SHBrowseForFolder(udtBrows) 'キャンセルされた場合は終了 If nRC = 0 Then Exit Function End If 'システムパスへ変換 DataPath = String(MAX_PATH, vbNullChar) Call SHGetPathFromIDList(nRC, DataPath) 'NUll除去 DataPath = Left(DataPath, InStr(DataPath, vbNullChar) - 1) 'フォルダ名を戻り値にセット ShowFolders = DataPath End Function
サンプル解説
ShowFoldersプロシージャでフォルダ指定ダイアログを表示しています。
フォルダ指定ダイアログはSHBrowseForFolder関数にBROWSEINFO構造体を渡して表示します。
BROWSEINFO構造体の内容は次の通りです。
メンバー I/O 説明 hwndOwner In 表示するウィンドウのハンドル pidlRoot In アイテム識別子リストのルートフォルダIDのポインタを指定します。指定するとそのフォルダ以下が表示されます。
サンプルでは0を指定してデスクトップを指定しています。pszDisplayName I/O ユーザが選択したフォルダ名を受け取るバッファ(ココに入ってくるのはフルパスではありません) lpszTitle In フォルダ指定ダイアログのタイトル ulFlags In 動作フラグ。
サンプルではBIF_RETURNONLYFSDIRSを指定してファイルシステムのディレクトリのみを返すように指定しています。lpfn In フォルダ指定ダイアログでイベントが起きたときに実行するコールバック関数のポインタを指定します。 lParam In lpfnへのパラメータ。サンプルでは選択するフォルダを指定しています。 iImage In ユーザが選択したフォルダに関連するイメージを受け取る変数のポインタを指定します。
サンプルでは必要がないので0を指定しています。
ここでミソになるのが、lpfnとlParamです。
この2つはフォルダ指定ダイアログ表示時に指定されたフォルダを選択状態にする「初期選択フォルダ指定機能」を実現するためのものです。lpfnにはフォルダ指定ダイアログでイベントが起きたときに実行するコールバック関数のポインタを指定していますが、実際にコールバック関数として動くのはBFFCallback関数です。
この、BFFCallback関数を示すポインタをlpfnにセットする訳ですが・・・関数のポインタ(アドレス)なんて分かるわけがありません。
そこで、VB6で追加されたAddressOfを使用してBFFCallback関数を示すポインタを取得します。
しかしAddressOfは引数リスト内しか使えないのでダミーの関数GetPointerを中継してセットしています。
(AddressOfを使用しているため各関数はパブリックとなります)そしてlParamにはBFFCallback関数に渡すパラメータをセットします。
パラメータには選択状態にしたいフォルダ名(フルパス)をセットしているんですが、Nullでタミネートしないと空白を含むフォルダ名の場合、正常に動作しません。
そのため、サンプルでは、末尾にNullを追加しています。ちなみにコールバック関数のBFFCallback関数の内容ですがフォルダ指定ダイアログの初期化が完了したらパラメータにセットされているフォルダ名をを選択するようにフォルダ指定ダイアログにメッセージを送っています。
SHBrowseForFolder関数の戻り値ですが、ユーザが[キャンセル]ボタンをクリックした場合はゼロが返ってきます。
逆にユーザがフォルダを選択した場合はアイテム識別子のリストのポインタが返ってきます。
このままでは選択されたフォルダ名が分かりませんので、SHGetPathFromIDList関数でアイテム識別子のリストから選択したフォルダ(フルパス)を取得しています。取得したフォルダ名の末尾にはNullがセットされているのでLeft関数で除去しています。
AddressOfはVB6で追加された演算子のため旧バージョンのVBでは実行できません。
しかし、初期選択フォルダ指定の機能さえ削れば旧VBでも使用できます。
具体的にはBROWSEINFO構造体の「lpfn」にゼロ、「lParam」に長さゼロの文字列を指定すればOKです。
同時にGetPointer関数・BFFCallback関数は使用しなくなるのでコーディングする必要はありません。
[ Window Close ]