我们在GetOverlayInfo()IsMemberOf()方法中读取注册表项,以确定是否显示覆盖图标。如果未设置注册表项,则从这两种方法中返回S_FALSE

问题是调用GetOverlayInfo()时未设置注册表项,但在会话的稍后阶段将其设置。我注意到,一旦GetOverlayInfo()返回S_FALSE,shell便不再调用IsMemberOf()

GetOverlayInfo()IsMemberOf()在资源管理器中运行时(很明显),此注册表项是从其他进程(我们的应用程序)设置/重置的。

我正在寻找使我的方案起作用的想法,即在注册表项切换后,应至少调用一次GetOverlayInfo()。到目前为止,我还没有找到任何在线方法。

我试图删除“ Iconcache.db”文件,但没有强制资源管理器再次调用GetOverlayInfo()

我们可以通过编程方式清除资源管理器的缓存吗?这可能会强制资源管理器再次调用GetOverlayInfo()

编辑1-
我在某处读到,在98期《 Window's Journal》(WDJ)中发表了标题为“重建Internet Shell图标缓存”的文章。也许这篇文章会有所帮助,但我在网上找不到。有人知道吗?

编辑2-这是示例代码。由于我是从S_FALSE方法返回GetOverlayInfo()的,这意味着我们要告诉资源管理器从现在开始在当前会话中忽略此覆盖图标,因此资源管理器不会进一步调用IsMemberOf()。现在,如果以后某个时候注册表值被切换,那么我希望资源管理器再次调用GetOverlayInfo()。那可能吗 ?

STDMETHOD(IsMemberOf)(LPCWSTR path, DWORD attr)
{

     ......
     ......
    // Check if icons are visible...
    if(!s_bOverlay)
    {
        return S_FALSE;
    }

    return S_OK;
}

STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile, int iLength, int* piIndex, DWORD* pdwFlags)
{
    // Check if icons are visible...
    if(!IsHandler(0))
    {
        return S_OK;
    }

    if(g_moduleName[0])
    {
        wcsncpy(pwszIconFile, g_moduleName, iLength - 1);

        // Retrieve the icon index...
        *piIndex  = static_cast<T*>(this)->GetIconIndex();
        *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

        return S_OK;
    }

    return E_FAIL;
}


bool IsHandler(const UINT uiState)
{
    s_bOverlay = true;  // static variable
    if(ERROR_SUCCESS == reg.Open(HKEY_CURRENT_USER, L"SOFTWARE\\XYZ\\ABC", KEY_READ))
    {
        DWORD value = 1;

        reg.QueryDWORDValue(L"PQR", value);

        if(0 == value)
        {
            s_bOverlay = false;
        }
    }
return s_bOverlay;
}

最佳答案

对于那些遵循此主题的人,这是我与Raymond在评论部分进行的讨论的摘要。

在一个会话中,您只会调用一次GetOverlayInfo()方法。如果从中返回一个无效值,则甚至不会调用IsMemberOf()方法。但是,如果您从GetOverlayInfo()返回有效值,则将调用IsMemberOf()。而且我们无法以编程方式重置Icon的缓存。

09-26 23:48