打开Windows资源管理器目录,在Delphi中选择特定文件

21

我有一个在Windows资源管理器中打开文件夹的程序,需要传递一个目录路径:

procedure TfrmAbout.ShowFolder(strFolder: string);
begin
   ShellExecute(Application.Handle,PChar('explore'),PChar(strFolder),nil,nil,SW_SHOWNORMAL);
end;

有没有办法传递一个文件名(包括完整的文件名路径或只是名称+扩展名),打开 Windows Explorer 中的文件夹,但也要突出/选择该文件? 我要去的位置有很多文件,我需要在 Windows 中操作那个文件。


使用 Andreas Rejbrand 下面提供的方法,我在 Win7 Pro 32 位上遇到了一些奇怪的问题,有时候使用它会打开目录但是不会突出显示文件,或者会打开一些非常普通的目录并且会突出显示完全不相关的内容。例如,刚刚我使用它来选择一个文件,但它却打开了我的个人用户文件夹并突出显示了“我的文档”文件夹,而我要让它定位的文件甚至不在同一个硬盘驱动器上。 - Jerry Dodge
我刚刚注意到了这个问题的一个趋势,当文件名中有某些字符时,例如逗号,会使命令出错。 - Jerry Dodge
注意:我之前的问题已经通过Andreas的更新得到解决,其中包括另一个更具体和可靠的解决方案。 - Jerry Dodge
2个回答

54

是的,当您调用explorer.exe时,可以使用/select标志

ShellExecute(0, nil, 'explorer.exe', '/select,C:\WINDOWS\explorer.exe', nil,
  SW_SHOWNORMAL)

一种更加高端(也许更加可靠)的方法(使用ShellAPI、ShlObj):

const
  OFASI_EDIT = $0001;
  OFASI_OPENDESKTOP = $0002;

{$IFDEF UNICODE}
function ILCreateFromPath(pszPath: PChar): PItemIDList stdcall; external shell32
  name 'ILCreateFromPathW';
{$ELSE}
function ILCreateFromPath(pszPath: PChar): PItemIDList stdcall; external shell32
  name 'ILCreateFromPathA';
{$ENDIF}
procedure ILFree(pidl: PItemIDList) stdcall; external shell32;
function SHOpenFolderAndSelectItems(pidlFolder: PItemIDList; cidl: Cardinal;
  apidl: pointer; dwFlags: DWORD): HRESULT; stdcall; external shell32;

function OpenFolderAndSelectFile(const FileName: string): boolean;
var
  IIDL: PItemIDList;
begin
  result := false;
  IIDL := ILCreateFromPath(PChar(FileName));
  if IIDL <> nil then
    try
      result := SHOpenFolderAndSelectItems(IIDL, 0, nil, 0) = S_OK;
    finally
      ILFree(IIDL);
    end;
end;

1
请注意:https://dev59.com/fW855IYBdhLWcg3whExL?rq=1 这个并不总是有效,我自己也亲眼见过它失效。 - Jerry Dodge
3
我已经为您实现了这个。 - Andreas Rejbrand
谢谢Andreas,这种“高端方法”可靠性要高得多。 - Jerry Dodge
1
对于那些使用 Delphi XE 及以上版本的人来说:您不必声明 ILCreateFromPath 等函数。 - Gabriel
1
我写了一个程序,用户可以打开/选择数十个不同的文件。我不想运行数十次explorer.exe。这段代码不会实例化一个新的explorer.exe实例。太棒了! - James L.
显示剩余7条评论

2
这段文本的意思是:“delphi.lonzu.netswissdelphicenter上的答案提供了一个更简单的解决方案。我只在Windows 10,1909上测试过它,但其要点是:”
uses ShellApi, ...
...
var
   FileName : TFileName;
begin
  FileName := 'c:\temp\somefile.html';

  ShellExecute(Handle, 'OPEN', 
    pchar('explorer.exe'), 
    pchar('/select, "' + FileName + '"'), 
    nil, 
    SW_NORMAL);
end;

这很简单易用。至于它是否适用于旧版Windows,我不知道。

2
它甚至可以在Windows XP上运行,所以对于大多数人来说这应该是可以的。 - dummzeuch
我创建了一个空的单元,需要更多的用途,比如Winapi.Windows、Winapi.Messages和Forms。 - Márcio Rossato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接