在从搜索 window 启动的程序中获取资源管理器 shell 搜索的结果

Getting the results of an explorer shell search in a program that was launched from a search window

当用户打开使用资源管理器搜索找到的文件而启动程序时,有没有办法实现有用的 'open next/previous file in folder' 功能?

例如,应用程序与 *.jpg 相关联。用户在资源管理器中搜索 foo*.jpg 并打开 foobar1.jpg。应用程序启动。当用户使用应用程序的 'next file in folder' 命令时,应用程序打开搜索返回的下一个文件,而不是与 foobar1.jpg.

相同文件夹中的下一个文件

这可能吗?

当用户在 Windows 资源管理器中打开文件时 shell 枚举所有可用的上下文菜单命令和 运行 第一个默认命令。因此,只需创建新的上下文菜单 shell 扩展名并将其注册到您的文件扩展名 ProgID 上。您的 shell 扩展必须实现 3 个接口:IObjectWithSite、IShellExtInit 和 IContextMenu。不要忘记创建 MayChangeDefaultMenu 注册表子项。

您的上下文菜单可以在任何程序中使用。如果调用者调用 IObjectWithSite.SetSite,则表示文件已在 Windows 资源管理器中打开。如果未调用 IObjectWithSite.SetSite - 文件是从任何其他应用程序打开的。

当 shell 调用 IShellExtInit 时,从传递的 IDataObject 中提取文件名并存储它们。当 shell 调用 IContextMenu.QueryContextMenu 时,将带有 MFS_DEFAULT 标志的命令添加到菜单。当 shell 调用 IContextMenu.GetCommandString(GCS_VERB) 时,您必须 return "open" 字符串。当 shell 调用 IContextMenu.InvokeCommand 运行 您的应用程序并在参数中传递文件名和 CMINVOKECOMMANDINFO.hwnd 时。

在您的应用程序中分析参数,如果找到 hwnd,则意味着您必须从 hwnd 获取文件列表。

查找资源管理器实例:

OleCheck(CoCreateInstance(CLASS_ShellWindows, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IShellWindows, ShellWindows));
for i := ShellWindows.Count - 1 downto 0 do
  begin
    Dispatch := ShellWindows.Item(i);
    Dispatch.QueryInterface(IServiceProvider, ServiceProvider);
    ServiceProvider.QueryService(SID_STopLevelBrowser, IShellBrowser, ShellBrowser);
    ShellBrowser.GetWindow(Hwnd);
    if Hwnd = HwndFromParams then InstanceFound;
  end;

创建文件列表:

ShellBrowser.QueryActiveShellView(ShellView);
ShellView.QueryInterface(IFolderView, FolderView);
FolderView.Items(SVGIO_ALLVIEW)

现在您拥有 Windows Explorer 实例中的所有文件,您可以在导航中使用它们。