LoginSignup
6
3

More than 1 year has passed since last update.

【Delphi】Explorer を開く

Last updated at Posted at 2022-08-16

はじめに

Delphi から Windows の Explorer を開いてみる記事です。

Explorer を開く

何はともあれ Explorer を Delphi から開いてみます。

ShellExecute() API

Explorer を開くには ShellExecute() API を使うのが簡単です。

Delphi の場合、Winapi.ShellAPIuses に加える事で使えるようになります。

  ShellExecute(0, 'open', 'explorer.exe', nil, nil, SW_SHOWNORMAL);

定数 SW_SHOWNORMALWinapi.Windows で定義されています。

Explorer の起動時オプション

Explorer には起動時オプションがあるのですが、もはや動作しなくなったものもあり、Microsoft のドキュメントからは消えています。

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 レコードを実装してみました。

uExplorer.pas
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 を選択状態にする。

PathRootDirSelectObject には特殊フォルダを表す 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() メソッドの実装はこのようになりました。

uExplorer.pas
    /// <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: でも可) というプロトコルでファイル検索を行う事ができます。

uExplorer.pas
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 エンコード しなくてはならないようなので、usesSystem.NetEncoding を追加し、TNetEncoding.URL.Encode() メソッドを使って URL エンコードしています。

次のコードは C:\WORK の中から *.pas を検索し、検索結果に ソースファイル という名前を付けて表示します。

  TExplorer.Search('C:\WORK', '*.pas', 'ソースファイル');

XP では正しく動作しない (環境がある) かもしれません。

おわりに

整理したソースコードを掲載しておきます。

uExplorer.pas
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:

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3