使用 Windows 资源管理器进行开发

Windows 资源管理器是一个功能强大的资源浏览和管理应用程序。 可以通过 Explorer.exe 或 IExplorerBrowser 接口作为集成整体访问 Windows 资源管理器。 Windows 资源管理器 (Explorer.exe) 可以使用 ShellExecuteExecuteEx 或类似函数作为单独的进程生成。

可以使用 IShellWindows (CLSID_ShellWindows) 发现和编程打开的资源管理器窗口,并且可以使用 IWebBrowser2 (CLSID_ShellBrowserWindow) 创建新的 Windows 资源管理器实例。

以下代码示例演示了如何使用 Windows 资源管理器自动化模型来创建和发现正在运行的资源管理器窗口。

#define _WIN32_WINNT 0x0600
#define _WIN32_IE 0x0700
#define _UNICODE

#include <windows.h>
#include <shobjidl.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <propvarutil.h>
 
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "propsys.lib")
 
// Use the Shell Windows object to find all of the explorer and IExplorer 
// windows and close them.
 
void CloseExplorerWindows()
{
    IShellWindows* psw;
    
    if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, 
                                   NULL,  
                                   CLSCTX_LOCAL_SERVER, 
                                   IID_PPV_ARGS(&psw))))
    {
        VARIANT v = { VT_I4 };
        if (SUCCEEDED(psw->get_Count(&v.lVal)))
        {
            // Walk backward to make sure that the windows that close
            // do not cause the array to be reordered.
            while (--v.lVal >= 0)
            {
                IDispatch *pdisp;
                
                if (S_OK == psw->Item(v, &pdisp))
                {
                    IWebBrowser2 *pwb;
                    if (SUCCEEDED(pdisp->QueryInterface(IID_PPV_ARGS(&pwb))))
                    {
                        pwb->Quit();
                        pwb->Release();
                    }
                    pdisp->Release();
                }
            }
        }
        psw->Release();
    }
}
 
// Convert an IShellItem or IDataObject into a VARIANT that holds an IDList
// suitable for use with IWebBrowser2::Navigate2.
 
HRESULT InitVariantFromObject(IUnknown *punk, VARIANT *pvar)
{
    VariantInit(pvar);
 
    PIDLIST_ABSOLUTE pidl;
    HRESULT hr = SHGetIDListFromObject(punk, &pidl);
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromBuffer(pidl, ILGetSize(pidl), pvar);
        CoTaskMemFree(pidl);
    }
    return hr;
}
 
HRESULT ParseItemAsVariant(PCWSTR pszItem, IBindCtx *pbc, VARIANT *pvar)
{
    VariantInit(pvar);
 
    IShellItem *psi;
    HRESULT hr = SHCreateItemFromParsingName(pszItem, NULL, IID_PPV_ARGS(&psi));
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromObject(psi, pvar);
        psi->Release();
    }
    return hr;
}

HRESULT GetKnownFolderAsVariant(REFKNOWNFOLDERID kfid, VARIANT *pvar)
{
    VariantInit(pvar);
 
    PIDLIST_ABSOLUTE pidl;
    HRESULT hr = SHGetKnownFolderIDList(kfid, 0, NULL, &pidl);
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromBuffer(pidl, ILGetSize(pidl), pvar);
        CoTaskMemFree(pidl);
    }
    return hr;
}

HRESULT GetShellItemFromCommandLine(REFIID riid, void **ppv)
{
    *ppv = NULL;
    HRESULT hr = E_FAIL;

    int cArgs;
    PWSTR *ppszCmd = CommandLineToArgvW(GetCommandLineW(), &cArgs);
    if (ppszCmd && cArgs > 1)
    {
        WCHAR szSpec[MAX_PATH];
        StringCchCopyW(szSpec, ARRAYSIZE(szSpec), ppszCmd[1]);
        PathUnquoteSpacesW(szSpec);

        hr = szSpec[0] ? S_OK : E_FAIL;   // Protect against empty data
        if (SUCCEEDED(hr))
        {
            hr = SHCreateItemFromParsingName(szSpec, NULL, riid, ppv);
            if (FAILED(hr))
            {
                WCHAR szFolder[MAX_PATH];
                GetCurrentDirectoryW(ARRAYSIZE(szFolder), szFolder);

                hr = PathAppendW(szFolder, szSpec) ? S_OK : E_FAIL;
                if (SUCCEEDED(hr))
                {
                    hr = SHCreateItemFromParsingName(szFolder, NULL, riid, ppv);
                }
            }
        }
    }
    return hr;
}

HRESULT GetShellItemFromCommandLineAsVariant(VARIANT *pvar)
{
    VariantInit(pvar);

    IShellItem *psi;
    HRESULT hr = GetShellItemFromCommandLine(IID_PPV_ARGS(&psi));
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromObject(psi, pvar);
        psi->Release();
    }
    return hr;
}

void OpenWindow()
{
    IWebBrowser2 *pwb;
    HRESULT hr = CoCreateInstance(CLSID_ShellBrowserWindow, 
                                  NULL,
                                  CLSCTX_LOCAL_SERVER, 
                                  IID_PPV_ARGS(&pwb));
    if (SUCCEEDED(hr))
    {
        CoAllowSetForegroundWindow(pwb, 0);

        pwb->put_Left(100);
        pwb->put_Top(100);
        pwb->put_Height(600);
        pwb->put_Width(800);
 
        VARIANT varTarget = {0};
        hr = GetShellItemFromCommandLineAsVariant(&varTarget);
        if (FAILED(hr))
        {
            hr = GetKnownFolderAsVariant(FOLDERID_UsersFiles, &varTarget);
        }

        if (SUCCEEDED(hr))
        {
            VARIANT vEmpty = {0};
            hr = pwb->Navigate2(&varTarget, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
            if (SUCCEEDED(hr))
            {
                pwb->put_Visible(VARIANT_TRUE);
            }
            VariantClear(&varTarget);
        }
        pwb->Release();
    }
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |  COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr))
    {
        CloseExplorerWindows();

        OpenWindow();

        CoUninitialize();
    }
    return 0;
}

可以使用 IExplorerBrowser 接口托管 Windows 资源管理器工作区。 Windows 资源管理器客户端和命名空间树控件是 Windows Vista 及更高版本的标准组件。 开发人员可以重复使用接口作为生成组件。 这些控件的一个常见用途是创建适合问题域的自定义资源管理器。

Windows 资源管理器中的控件分为以下功能类别:

导航控件可帮助用户确定上下文并导航关联的逻辑域空间(称为页面空间)。 例如,Windows 资源管理器的页面空间是 Shell 命名空间。 页面空间由零页或多页组成。

下表列出了并描述了 Windows Vista 及更高操作系统中 Windows 资源管理器中可用的导航控件。

导航控件 说明
地址栏 (痕迹导航控件) 在 pagespace 中显示当前页的地址。 可以单击痕迹导航按钮以导航到页面空间中的任何上级。 用户还可以键入 URL 和路径进行导航。
文件夹树 提供树控件的新版本,针对大页空间进行了优化。
旅行 通过 Web 样式按钮(如 后退前进)启用相对导航。
Title 显示当前资源管理器名称和上下文。
Pagespace 显示页面空间的当前分支。 页面可以按不同的条件排序。 用户可以单击页面导航到该页面。

 

命令控件

命令控件向用户播发 Windows 资源管理器的特性和功能。 这些控件执行常规操作或特定于一个或多个选定项的操作。

命令控件 说明
工具栏 显示常用命令的按钮 (新版本的命令工具栏) 。 自定义选项包括下拉按钮、拆分按钮、可选描述性文本和溢出区域。
英雄 在工具栏的中心显示为单个可选自定义控件。 它表示当前上下文的主命令。
菜单栏 通过菜单显示命令。
上下文菜单 列出因右键单击项而显示的可用命令的上下文相关子集。

 

属性和预览控件

属性和预览控件用于预览项,以及查看和编辑项属性。

控制 说明
预览 显示所选项的预览,例如缩略图或实时图标。
属性 显示所选项的属性。 对于多个选择,它显示所选项目组的属性摘要。 对于 null 选择,它显示当前页的属性摘要, (listview) 的内容。

 

筛选和查看控件

筛选和视图控件用于操作 listview 中的项集,以及更改 listview 中项的表示形式。

控制 说明
“筛选器” 根据列为列的属性筛选或排列 listview 中的项。 单击列按该属性排序。
Wordwheel 基于输入文本字符串以增量方式筛选 listview 中显示的项目。
视图 使用户能够更改 listview 控件的视图模式。 滑块可用于确定图标大小。

 

Listview 控件

listview 控件用于在以下四种视图模式之一中查看一组项:详细信息、磁贴、图标或全景。 listview 控件还允许用户选择和激活一个或多个项。

注意

尽管其中一些控件的名称和/或功能类似于 System.Windows.Controls 命名空间中的标准Windows Presentation Foundation (WPF) 控件,但它们是不同的类。

 

这些单独的控件主要通过用户交互或控件本身生成的事件协同工作。 下表显示了三个主要事件类别。

事件类别 示例
导航 从一个页面转到另一个页面。
选择 更改 listview 中的当前选择。
查看更改 更改列表视图中的演示顺序或视图模式。