将自定义横幅添加到命名空间扩展

时间:2017-10-10 21:50:27

标签: c++ windows-shell shell-namespace-extension

Windows资源管理器可以在执行搜索时显示自定义横幅并禁用索引:

Explorer indexing not running image

我想在自定义命名空间扩展中显示类似的横幅,其中包含自定义消息和自定义链接处理程序。是否有我可以实现的命名空间扩展接口,这将允许我提供此功能?我在namespace extension documentation 中搜索过各种字词,但我无法确定要使用的正确字词。

1 个答案:

答案 0 :(得分:0)

Microsft没有记录该功能。我发现了如何显示来自名称空间扩展的信息栏。

Picture

首先,您需要声明3个未公开的接口

IInfobarHost

MIDL_INTERFACE("e38fe0f3-3db0-47ee-a314-25cf7f4bf521")
IInfoBarHost : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE Inform(IInfoBarMessage* msg) = 0;
    virtual HRESULT STDMETHODCALLTYPE CancelInform(GUID guid) = 0;
};

IInfobarMessage

MIDL_INTERFACE("819d1334-9d74-4254-9ac8-dc745ebc5386")
IInfoBarMessage : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetMessageID(GUID* guid,INT* intVal) = 0;
    virtual HRESULT STDMETHODCALLTYPE GetMessageW(LPWSTR* message) = 0;
    virtual HRESULT STDMETHODCALLTYPE CreateMenu(HMENU* pMwnu) = 0;
    virtual HRESULT STDMETHODCALLTYPE HandleMenu(HWND hwnd,int intVal) = 0;
};

IBrowserProgressSessionProvider

MIDL_INTERFACE("18140CBD-AA23-4384-A38D-6A8D3E2BE505")
IBrowserProgressSessionProvider : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE BeginSession() = 0; //Unknown
    virtual HRESULT STDMETHODCALLTYPE EndSession() = 0;//Unknown
    virtual HRESULT STDMETHODCALLTYPE GetCurrentSession(PDWORD sessionId) = 0;
    virtual HRESULT STDMETHODCALLTYPE ActivateSession() = 0;//Unknown
};

IID_IInfoBarHost:e38fe0f3-3db0-47ee-a314-25cf7f4bf521
IID_IBrowserProgressConnection:20174539-B2C7-4EC7-970B-04201F9CDBAD
IID_IBrowserProgressAggregator:5EA8EEC4-C34B-4DE0-9B56-0E15FD8C8F80
IID_IBrowserProgressSessionProvider:18140CBD-AA23-4384-A38D-6A8D3E2BE505

2。创建一个类并实现IInfoBarMessage。
GetMessageID(GUID * guid,INT * pIntVal)
获取信息栏向导。为当前信息栏消息生成自己的随机Guid。

HRESULT STDMETHODCALLTYPE CInfoBarMessageImpl::GetMessageID(GUID* guid, INT* intVal) {
    //Our InformationBar GUID (generated in constructor)
    *guid = this->guid;
    return S_OK;
}

GetMessageW(LPWSTR *消息)
获取InformationBar消息
分配内存并将unicode字符串复制到参数(使用CoTaskMemAlloc)

HRESULT STDMETHODCALLTYPE CInfoBarMessageImpl::GetMessageW(LPWSTR* message) {
    if (!this->message) { //message set at constructor or set at our own initialize function
        return E_FAIL;
    }
    *message = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (this->messageLen + 1));
    wcscpy_s(*message, this->messageLen + 1, this->message);
    return S_OK;
}
  1. 从ShellView(IShellView)获取IServiceProvider并获取IBrowserProgressSessionProvider接口以获取dwCookie值。
    之后,使用“ GetCurrentSession”中的“ dwCookie”从GIT(GlobalInterfaceTable)中获取IBrowserProgressConnection,并从BrowserProgressConnection中获取IInfoBarHost接口
//CInfobarManger is own class (does not implement anyone)
void CInfoBarManager::ShowInfoBar(IShellView* shview) {
    HRESULT hr;
    DWORD dwCookie = 0;

    if (!this->sprovider) {
        hr = shview->QueryInterface(IID_IServiceProvider, (PVOID*)&sprovider);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    if (!this->sessionProvider) {
        hr = this->sprovider->QueryService(IID_IBrowserProgressAggregator, IID_IBrowserProgressSessionProvider, (PVOID*)&this->sessionProvider);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    hr = sessionProvider->GetCurrentSession(&dwCookie);
    if (FAILED(hr)) {
        goto escapeArea;
    }

    //Get GIT
    if (!this->git) {
        hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER,
            IID_IGlobalInterfaceTable, (PVOID*)&this->git);
        if (FAILED(hr)) {
            goto escapeArea;
        }
    }

    hr = this->git->GetInterfaceFromGlobal(dwCookie, IID_IBrowserProgressConnecion, (PVOID*)&this->browserProgress);
    if (hr == S_OK) {
        hr = this->browserProgress->QueryInterface(IID_IInfoBarHost, (PVOID*)&this->host);
        if (hr == S_OK) {
            //Call Relase in explorer inside
            this->infoMsg->AddRef();
            this->host->Inform(this->infoMsg);
        }
    }
escapeArea:
    return;
}
  1. 如果uMsg为17(刷新),则在MessageSFVCB上显示信息栏。
//in MessageSFVCB
else if (uMsg == 17) { //OnRefresh
    if (!this->infobar) {
        this->infobar = new CInfoBarManager();
        infobar->InitializeSimple(L"NSE Information Bar Message");
    }
    infobar->ShowInfoBar(this->shview); //IShellView
}

示例代码:https://github.com/bho3538/NSEInformationBar