IExplorerBrowser - 在不启动默认应用程序的情况下就地浏览

IExplorerBrowser - Browse in place without starting default application

我正在开发 windows 文件管理器应用程序,本质上它包装 IExplorerBrowser 给我精确的控制,就像在 Windows 资源管理器中一样。

我已经使用 Mutex 和 IPC 实现了单实例传递参数。

所以现在我希望能够在您从 ie 打开目录时将我的文件管理器注册为默认应用程序。桌面

所以我创建了这样的注册表脚本:

REGEDIT4

[HKEY_CURRENT_USER\Software\Classes\Drive\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName\command]
@="\"<app-path>\" %1"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName\command]
@="\"<app-path>\" \"%1\""

它按预期工作,如果我双击目录它会启动我的应用程序,并且由于我实现了单个实例它不会产生多个实例。

由于我的应用程序中有选项卡式界面,每次打开目录时,它都会使用 IExplorerBrowser 控件创建新选项卡。

问题是,现在 IExplorerBrowser 控件的行为已经改变,当我从控件打开目录时,我得到了新的选项卡,而不是在控件内部导航,这是合乎逻辑的(它总是调用注册表命令来启动我的应用程序,并将 direcotry 作为 arg )

TL;博士;

windows 资源管理器如何处理这个问题? windows 资源管理器如何知道目录是否从 ie 打开。桌面,或从 Windows 资源管理器内部,以便它在 "listview" 内部导航,而不是打开新的 window?

我不是 C# 开发人员,我不知道 Windows-API-Code-Pack-1.1 的详细信息。在我的 NSE 项目中,我在当前 Explorer window(IContextMenu 处理程序的一部分)中使用以下导航算法:

Site.QueryInterface(IServiceProvider, ServiceProvider) // Site was received in IObjectWithSite.SetSite
ServiceProvider.QueryService(SID_STopLevelBrowser, IShellBrowser, ShellBrowser)
ShellBrowser.BrowseObject(ChildItem, SBSP_RELATIVE or SBSP_SAMEBROWSER)

也许对你有帮助。

它必须是一个更好的方法来做到这一点,但这个有效:

  HResult ICommDlgBrowser3.OnDefaultCommand(IntPtr ppshv)
    {
        if (SelectedItems.Count > 0)
        {
            var item = SelectedItems[0];

            ShellNativeMethods.ShellFileGetAttributesOptions sfgao;
            item.NativeShellItem2.GetAttributes(ShellNativeMethods.ShellFileGetAttributesOptions.Folder, out sfgao);
            bool isFolder = (sfgao & ShellNativeMethods.ShellFileGetAttributesOptions.Folder) != 0;

            if (isFolder)
            {
                Navigate(SelectedItems[0]);
                return HResult.Ok;
            }
        }
        return HResult.False;
    }