# 【Delphi】Explorer を開く --- tags: Windows Delphi programming Explorer objectpascal created_at: 2022-08-17 updated_at: 2022-09-13 --- # はじめに Delphi から Windows の Explorer を開いてみる記事です。 # Explorer を開く 何はともあれ Explorer を Delphi から開いてみます。 ## ShellExecute() API Explorer を開くには `ShellExecute()` API を使うのが簡単です。 - [ShellExecuteW function (shellapi.h) (docs.microsoft.com)](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew) Delphi の場合、`Winapi.ShellAPI` を **uses** に加える事で使えるようになります。 ```pascal ShellExecute(0, 'open', 'explorer.exe', nil, nil, SW_SHOWNORMAL); ``` 定数 `SW_SHOWNORMAL` は `Winapi.Windows` で定義されています。 ## Explorer の起動時オプション Explorer には起動時オプションがあるのですが、もはや動作しなくなったものもあり、Microsoft のドキュメントからは消えています。 - [Explorer.exe Command-Line Options for Windows XP (support.microsoft.com)](http://web.archive.org/web/20140823211915/http://support.microsoft.com/kb/314853) - [Windowsのエクスプローラで目的のフォルダだけを開く (@IT)](https://atmarkit.itmedia.co.jp/ait/articles/0404/03/news019.html) | Option | Function | |:---|:---| | /n | Opens a new single-pane window for the default selection. This is usually the root of the drive that Windows is installed on. If the window is already open, a duplicate opens. | | /e | Opens Windows Explorer in its default view. | | /root,\ | Opens a window view of the specified object. | | /select,\ | Opens a window view with the specified folder, file, or program selected. | ## TExplorer レコード Explorer の起動時オプションを指定して開ける TExprorer レコードを実装してみました。 ```pascal:uExplorer.pas unit uExplorer; interface uses Winapi.Windows, Winapi.ShellAPI; type TExplorerOpenStyle = (eosNone, eosSinglePane, eosDefaultView); TExplorer = record public /// /// Explorer を開く /// /// /// 開く場所。 /// /// /// Explorer の表示スタイル。 /// eosNone /// 指定なし。 /// eosSinglePane /// Windows XP だとシングルペインウィンドウで開く。 /// eosDefaultView /// エクスプローラーバーの `フォルダ` が有効の状態で開く。 /// /// /// ルートフォルダ。Windows XP だとルートフォルダよりも上の階層に移動する事はできない。 /// /// /// 選択するオブジェクト。オブジェクトが選択された状態で Explorer が開く。 /// /// /// ShellExecute() API の戻り値 /// class function Open(Path: string = ''; OpenStyle: TExplorerOpenStyle = eosNone; RootDir: string = ''; SelectObject: string = ''): HINST; static; end; implementation { TExplorer } class function TExplorer.Open(Path: string; OpenStyle: TExplorerOpenStyle; RootDir, SelectObject: string): HINST; var Param: string; procedure AddDelimiter; begin if Param <> '' then Param := Param + ','; end; begin case OpenStyle of eosSinglePane: Param := '/n'; eosDefaultView: Param := '/e'; else Param := ''; end; if (Path <> '') and (RootDir = '') and (SelectObject = '') then case OpenStyle of eosSinglePane, eosDefaultView: begin AddDelimiter; Param := Param + Path; end; else Param := Path; end; if RootDir <> '' then begin AddDelimiter; Param := Param + '/root'; AddDelimiter; Param := Param + RootDir; end; if SelectObject <> '' then begin AddDelimiter; Param := Param + '/select'; AddDelimiter; Param := Param + SelectObject; end; result := ShellExecute(0, 'open', 'explorer.exe', PChar(Param), nil, SW_SHOWNORMAL); end; end. ``` `Open()` メソッドで Explorer を開けます。 ```pascal class function TExplorer.Open(Path: string; OpenStyle: TExplorerOpenStyle; RootDir, SelectObject: string): HINST; ``` | コード |起動時オプション| 動作 | |:---|:---|:---| | TExplorer.Open; | (なし)| Windows 11 だと `クイックアクセス` が開く。単純に `Explorer.exe` を起動した状態| | TExplorer.Open('C:\WORK'); | C:\WORK | 'C:\WORK' が開く| | TExplorer.Open('C:\WORK', eosNone); | C:\WORK | 'TExplorer.Open('C:\WORK');' と同じ| | TExplorer.Open('C:\WORK', eosSinglePane); | /n,C:\WORK| Windows XP だと 'C:\WORK' がシングルペインウィンドウで開く| | TExplorer.Open('C:\WORK', eosDefaultView); |/e,C:\WORK| Windows XP だと 'C:\WORK' がエクスプローラーバーの `フォルダ` が有効の状態で開く| | TExplorer.Open('', eosDefaultView, 'C:\WORK'); | /e,/root,C:\WORK| 'C:\WORK' をルートフォルダとして開く。 Windows XP だとルートフォルダよりも上の階層に移動する事はできない。 | | TExplorer.Open('', eosDefaultView, '', 'C:\WORK\TEST.EXE'); | /e,/select,C:\WORK\TEST.EXE| 'C:\WORK' フォルダを開き、そこにある `TEST.EXE` を選択状態にする。 | `Path` や `RootDir`、`SelectObject` には特殊フォルダを表す **CLSID** を指定する事もできます。CLSID を指定する場合には先頭にコロンを 2 つ並べます。 ``` :: ``` 例えば次のコードはデスクトップフォルダが開き、ごみ箱が選択状態になります。 ```pascal TExplorer.Open('', eosDefaultView, '', '::{645FF040-5081-101B-9F08-00AA002F954E}'); ``` :::note info 「長いパラメータの書式の方がよく使う!」という方はパラメータの並びを変更するか、オーバーロードメソッドを追加してください。 ::: ## Shell() メソッドの実装 Explorer や `ファイル名を指定して実行` では **shell:** というプロトコルが使えます。 例えば `shell:C:\WORK` は Explorer で `C:\WORK` を開きますし、`shell:::{645FF040-5081-101B-9F08-00AA002F954E}` はゴミ箱を開きます。 `Shell()` メソッドの実装はこのようになりました。 ```pascal:uExplorer.pas /// /// Explorer を開く /// /// /// shell: コマンドに渡すパラメータ。 /// /// /// ShellExecute() API の戻り値 /// class function Shell(Param: string): HINST; static; ... class function TExplorer.Shell(Param: string): HINST; begin Param := 'shell:' + Param; result := ShellExecute(0, 'open', PChar(Param), nil, nil, SW_SHOWNORMAL); end; ``` `Param` には**ロケーション名**を渡す事もできます。例えば次のコードはコントロールパネルを開きます。 ```pascal TExplorer.Shell('ControlPanelFolder'); ``` :::note info ロケーション名はレジストリの `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\FolderDescriptions` から取得する事ができます。 ::: ## Search() メソッドの実装 Explorer や ファイル名を指定して実行 では **search-ms:** (Vista 以降では **search:** でも可) というプロトコルでファイル検索を行う事ができます。 - [検索プロトコルの使用 (docs.microsoft.com)](https://docs.microsoft.com/ja-jp/windows/win32/shell/search-protocol) ```pascal:uExplorer.pas uses ..., System.NetEncoding; ... /// /// Explorer を開く /// /// /// 検索する場所。 /// /// /// 検索文字列。 /// /// /// [省略可能] 検索結果に付ける表示名。 /// /// /// ShellExecute() API の戻り値 /// class function Search(Location: string; Query: string; DisplayName: string = ''): HINST; static; ... class function TExplorer.Search(Location, Query, DisplayName: string): HINST; var Param: string; begin Param := 'search-ms:'; Param := Param + 'query=' + Query + '&'; Param := Param + 'location=' + TNetEncoding.URL.Encode(Location); if DisplayName <> '' then Param := Param + '&' + 'displayName=' + Location; result := ShellExecute(0, 'open', PChar(Param), nil, nil, SW_SHOWNORMAL); end; ``` `location=` に渡す文字列は **URL エンコード** しなくてはならないようなので、**uses** に `System.NetEncoding` を追加し、`TNetEncoding.URL.Encode()` メソッドを使って URL エンコードしています。 次のコードは `C:\WORK` の中から `*.pas` を検索し、検索結果に `ソースファイル` という名前を付けて表示します。 ```pascal TExplorer.Search('C:\WORK', '*.pas', 'ソースファイル'); ``` :::note warn XP では正しく動作しない (環境がある) かもしれません。 ::: # おわりに 整理したソースコードを掲載しておきます。 ```pascal:uExplorer.pas unit uExplorer; interface uses Winapi.Windows, Winapi.ShellAPI, System.NetEncoding; type TExplorerOpenStyle = (eosNone, eosSinglePane, eosDefaultView); TExplorer = record public /// /// Explorer を開く /// /// /// 開く場所。 /// /// /// Explorer の表示スタイル。 /// eosNone /// 指定なし。 /// eosSinglePane /// Windows XP だとシングルペインウィンドウで開く。 /// eosDefaultView /// エクスプローラーバーの `フォルダ` が有効の状態で開く。 /// /// /// ルートフォルダ。Windows XP だとルートフォルダよりも上の階層に移動する事はできない。 /// /// /// 選択するオブジェクト。オブジェクトが選択された状態で Explorer が開く。 /// /// /// ShellExecute() API の戻り値 /// class function Open(Path: string = ''; OpenStyle: TExplorerOpenStyle = eosNone; RootDir: string = ''; SelectObject: string = ''): HINST; static; /// /// Explorer を開く /// /// /// shell: コマンドに渡すパラメータ。 /// /// /// ShellExecute() API の戻り値 /// class function Shell(Param: string): HINST; static; /// /// Explorer を開く /// /// /// 検索する場所。 /// /// /// 検索文字列。 /// /// /// [省略可能] 検索結果に付ける表示名。 /// /// /// ShellExecute() API の戻り値 /// class function Search(Location: string; Query: string; DisplayName: string = ''): HINST; static; end; implementation { TExplorer } class function TExplorer.Open(Path: string; OpenStyle: TExplorerOpenStyle; RootDir, SelectObject: string): HINST; var Param: string; procedure AddDelimiter; begin if Param <> '' then Param := Param + ','; end; begin case OpenStyle of eosSinglePane: Param := '/n'; eosDefaultView: Param := '/e'; else Param := ''; end; if (Path <> '') and (RootDir = '') and (SelectObject = '') then case OpenStyle of eosSinglePane, eosDefaultView: begin AddDelimiter; Param := Param + Path; end; else Param := Path; end; if RootDir <> '' then begin AddDelimiter; Param := Param + '/root'; AddDelimiter; Param := Param + RootDir; end; if SelectObject <> '' then begin AddDelimiter; Param := Param + '/select'; AddDelimiter; Param := Param + SelectObject; end; result := ShellExecute(0, 'open', 'explorer.exe', PChar(Param), nil, SW_SHOWNORMAL); end; class function TExplorer.Search(Location, Query, DisplayName: string): HINST; var Param: string; begin Param := 'search-ms:'; Param := Param + 'query=' + Query + '&'; Param := Param + 'location=' + TNetEncoding.URL.Encode(Location); if DisplayName <> '' then Param := Param + '&' + 'displayName=' + Location; result := ShellExecute(0, 'open', PChar(Param), nil, nil, SW_SHOWNORMAL); end; class function TExplorer.Shell(Param: string): HINST; begin Param := 'shell:' + Param; result := ShellExecute(0, 'open', PChar(Param), nil, nil, SW_SHOWNORMAL); end; end. ``` アプリケーションから Explorer の検索結果を表示する事はあまりないかもしれませんが、アプリケーションが出力したファイルを選択状態にして Explorer を開く事はあるかもしれませんね。 **See also:** - [945_エクスプローラのテスト (Mr.XRAY)](http://mrxray.on.coocan.jp/Delphi/plSamples/945_ExplorerTest.htm)