はじめに
Delphi から Windows の Explorer を開いてみる記事です。
Explorer を開く
何はともあれ Explorer を Delphi から開いてみます。
ShellExecute() API
Explorer を開くには ShellExecute()
API を使うのが簡単です。
Delphi の場合、Winapi.ShellAPI
を uses に加える事で使えるようになります。
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)
- Windowsのエクスプローラで目的のフォルダだけを開く (@IT)
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,<object> | Opens a window view of the specified object. |
/select,<object> | Opens a window view with the specified folder, file, or program selected. |
TExplorer レコード
Explorer の起動時オプションを指定して開ける TExprorer レコードを実装してみました。
unit uExplorer;
interface
uses
Winapi.Windows, Winapi.ShellAPI;
type
TExplorerOpenStyle = (eosNone, eosSinglePane, eosDefaultView);
TExplorer = record
public
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Path">
/// 開く場所。
/// </param>
/// <param name="OpenStyle">
/// Explorer の表示スタイル。
/// eosNone
/// 指定なし。
/// eosSinglePane
/// Windows XP だとシングルペインウィンドウで開く。
/// eosDefaultView
/// エクスプローラーバーの `フォルダ` が有効の状態で開く。
/// </param>
/// <param name="RootDir">
/// ルートフォルダ。Windows XP だとルートフォルダよりも上の階層に移動する事はできない。
/// </param>
/// <param name="SelectObject">
/// 選択するオブジェクト。オブジェクトが選択された状態で Explorer が開く。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
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 を開けます。
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 つ並べます。
::<CLSID>
例えば次のコードはデスクトップフォルダが開き、ごみ箱が選択状態になります。
TExplorer.Open('', eosDefaultView, '', '::{645FF040-5081-101B-9F08-00AA002F954E}');
「長いパラメータの書式の方がよく使う!」という方はパラメータの並びを変更するか、オーバーロードメソッドを追加してください。
Shell() メソッドの実装
Explorer や ファイル名を指定して実行
では shell: というプロトコルが使えます。
例えば shell:C:\WORK
は Explorer で C:\WORK
を開きますし、shell:::{645FF040-5081-101B-9F08-00AA002F954E}
はゴミ箱を開きます。
Shell()
メソッドの実装はこのようになりました。
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Param">
/// shell: コマンドに渡すパラメータ。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
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
にはロケーション名を渡す事もできます。例えば次のコードはコントロールパネルを開きます。
TExplorer.Shell('ControlPanelFolder');
ロケーション名はレジストリの HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\FolderDescriptions
から取得する事ができます。
Search() メソッドの実装
Explorer や ファイル名を指定して実行 では search-ms: (Vista 以降では search: でも可) というプロトコルでファイル検索を行う事ができます。
uses
..., System.NetEncoding;
...
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Location">
/// 検索する場所。
/// </param>
/// <param name="Query">
/// 検索文字列。
/// </param>
/// <param name="DisplayName">
/// [省略可能] 検索結果に付ける表示名。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
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
を検索し、検索結果に ソースファイル
という名前を付けて表示します。
TExplorer.Search('C:\WORK', '*.pas', 'ソースファイル');
XP では正しく動作しない (環境がある) かもしれません。
おわりに
整理したソースコードを掲載しておきます。
unit uExplorer;
interface
uses
Winapi.Windows, Winapi.ShellAPI, System.NetEncoding;
type
TExplorerOpenStyle = (eosNone, eosSinglePane, eosDefaultView);
TExplorer = record
public
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Path">
/// 開く場所。
/// </param>
/// <param name="OpenStyle">
/// Explorer の表示スタイル。
/// eosNone
/// 指定なし。
/// eosSinglePane
/// Windows XP だとシングルペインウィンドウで開く。
/// eosDefaultView
/// エクスプローラーバーの `フォルダ` が有効の状態で開く。
/// </param>
/// <param name="RootDir">
/// ルートフォルダ。Windows XP だとルートフォルダよりも上の階層に移動する事はできない。
/// </param>
/// <param name="SelectObject">
/// 選択するオブジェクト。オブジェクトが選択された状態で Explorer が開く。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
class function Open(Path: string = ''; OpenStyle: TExplorerOpenStyle = eosNone; RootDir: string = ''; SelectObject: string = ''): HINST; static;
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Param">
/// shell: コマンドに渡すパラメータ。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
class function Shell(Param: string): HINST; static;
/// <summary>
/// Explorer を開く
/// </summary>
/// <param name="Location">
/// 検索する場所。
/// </param>
/// <param name="Query">
/// 検索文字列。
/// </param>
/// <param name="DisplayName">
/// [省略可能] 検索結果に付ける表示名。
/// </param>
/// <returns>
/// ShellExecute() API の戻り値
/// </returns>
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: