SelectDirectory と特殊フォルダ

タイムラインに「SelectDirectoryでルートをデスクトップからコンピュータに変更したい」ってのが流れてきたので調べた事のメモ。

SelectDirectoryは内部でSHBrowseForFolderを呼んでる。

SHBrowseForFolderのルートの指定は、BROWSEINFO構造体のpidlRootに値を指定します。このpidlRootがNilの場合はデスクトップがルートとして表示されます。

SelectDirectory関数の内部でどういう処理になっているかと言うと引数Rootに値が渡された場合DesktopのIShellFolderインターフェースを取得して、そのParseDisplayNameメソッドに引数Rootを渡してITEMIDLISTを取得しています。

ParseDisplayNameのヘルプによると、引数pszDisplayNameに「::{GUID}」の形で値を渡すことで特殊フォルダのITEMIDLISTを取得出来るようです。
SelectDirectoryの引数RootがpszDisplayNameに渡されるのでRootに「::{GUID}」を渡す事でフォルダ選択ダイアログのルートに特殊フォルダが指定出来るようです。

DelphiXE以降(2010は確認していないので不明)だと、ShlObj.pasにマイコンピュータ等のGUIDが定義されています。という事で下記のようにSelectDirectoryを呼ぶ事でコンピューターをルートとしてフォルダ選択ダイアログが表示されます。その他マイドキュメント(CLSID_MyDocuments)やコントロールパネル(CLSID_ControlPanel)なんかも定義されています。

ルートの指定を文字列でしないとダメなので色々調べましたが、ITEMIDLISTを引数に取るバージョンの関数とかをコピーして作った方が後々便利かもなーとか思いました。

uses
  FileCtrl, ShlObj;
procedure TForm1.Button1Click(Sender: TObject);
var
  SelectDir: String;
begin
  SelectDirectory('', '::' + GUIDToString(CLSID_MyComputer), SelectDir);
end;