如何告诉 Windows 资源管理器刷新其图标?

发布于 2024-08-12 05:36:56 字数 2805 浏览 10 评论 0原文

一旦我的安装程序完成应用程序 exe 新版本的安装,我想告诉资源管理器使用新 exe 的图标作为其快捷方式。但是,我不知道该怎么做。

从网上阅读来看,问题似乎是 系统映像列表 正在缓存旧版本图标。我尝试使用 调用 SHChangeNotify SHCNE_UPDATEIMAGE 参数。我尝试致电 SHUpdateImage。我什至尝试了广播的大锤方法<代码>WM_SETTINGCHANGE。似乎什么都不起作用。

完全有可能我只是做错了什么。任何帮助将不胜感激。

警告:下面是非常丑陋的测试代码。

#if 1
    // First attempt: using shell functions
    wchar_t icon_path[MAX_PATH];
    int icon_index;
    UINT icon_flags;

    IShellFolder *desktop_folder;
    IShellFolder *sub_folder;
    IExtractIcon *extract_icon;
    LPITEMIDLIST pidl;

    SHGetDesktopFolder(&desktop_folder);

    wchar_t *folder_path = L"C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\MyCompany\\";
    desktop_folder->ParseDisplayName(NULL, NULL, folder_path, NULL, &pidl,
        NULL);
    desktop_folder->BindToObject(pidl, NULL, IID_IShellFolder,
        (void**) &sub_folder);
    sub_folder->ParseDisplayName(NULL, NULL, L"MyApp.lnk", NULL, &pidl,
        NULL);

    sub_folder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*) &pidl,
        IID_IExtractIcon, NULL, (void**) &extract_icon);

    extract_icon->GetIconLocation(0, icon_path, MAX_PATH,
        &icon_index, &icon_flags);

    SHFILEINFO sfi;
    DWORD_PTR result = SHGetFileInfo(shortcut_path, 0, &sfi, sizeof(sfi), 
        SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
    SHUpdateImage(icon_path, icon_index, icon_flags, sfi.iIcon);
    // sfi.iIcon should be correct, but we'll try both, just for fun...
    SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD, NULL,
        (LPCVOID) icon_index);
    SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD, NULL,
        (LPCVOID) sfi.iIcon);
#else
    // Second attempt: broadcasting a settings change
    HKEY reg;
    RegCreateKeyEx(HKEY_CURRENT_USER,
        L"Control Panel\\Desktop\\WindowMetrics", 0, NULL, 0,
        KEY_SET_VALUE, NULL, &reg, NULL);
    DWORD value;
    value = 33;
    RegSetValueEx(reg, L"Shell Icon Size", 0, REG_DWORD, (BYTE*) &value,
        sizeof(value));
    value = 32;
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
        (int) L"WindowMetrics");
    RegSetValueEx(reg, L"Shell Icon Size", 0, REG_DWORD, (BYTE*) &value,
        sizeof(value));
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
        (int) L"WindowMetrics");
#endif

Once my installer finishes installing new versions of my application's exe, I'd like to tell Explorer to use the new exe's icons for its shortcuts. However, I cannot figure out how to do this.

From reading online, it looks like the problem is that the system image list is caching an old version of the icon. I tried calling SHChangeNotify with a SHCNE_UPDATEIMAGE parameter. I tried calling SHUpdateImage. I even tried the sledgehammer approach of broadcasting WM_SETTINGCHANGE. Nothing seems to work.

It's entirely possible that I'm just doing something wrong. Any help would be appreciated.

Warning: Very ugly test code follows.

#if 1
    // First attempt: using shell functions
    wchar_t icon_path[MAX_PATH];
    int icon_index;
    UINT icon_flags;

    IShellFolder *desktop_folder;
    IShellFolder *sub_folder;
    IExtractIcon *extract_icon;
    LPITEMIDLIST pidl;

    SHGetDesktopFolder(&desktop_folder);

    wchar_t *folder_path = L"C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\MyCompany\\";
    desktop_folder->ParseDisplayName(NULL, NULL, folder_path, NULL, &pidl,
        NULL);
    desktop_folder->BindToObject(pidl, NULL, IID_IShellFolder,
        (void**) &sub_folder);
    sub_folder->ParseDisplayName(NULL, NULL, L"MyApp.lnk", NULL, &pidl,
        NULL);

    sub_folder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*) &pidl,
        IID_IExtractIcon, NULL, (void**) &extract_icon);

    extract_icon->GetIconLocation(0, icon_path, MAX_PATH,
        &icon_index, &icon_flags);

    SHFILEINFO sfi;
    DWORD_PTR result = SHGetFileInfo(shortcut_path, 0, &sfi, sizeof(sfi), 
        SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
    SHUpdateImage(icon_path, icon_index, icon_flags, sfi.iIcon);
    // sfi.iIcon should be correct, but we'll try both, just for fun...
    SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD, NULL,
        (LPCVOID) icon_index);
    SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD, NULL,
        (LPCVOID) sfi.iIcon);
#else
    // Second attempt: broadcasting a settings change
    HKEY reg;
    RegCreateKeyEx(HKEY_CURRENT_USER,
        L"Control Panel\\Desktop\\WindowMetrics", 0, NULL, 0,
        KEY_SET_VALUE, NULL, ®, NULL);
    DWORD value;
    value = 33;
    RegSetValueEx(reg, L"Shell Icon Size", 0, REG_DWORD, (BYTE*) &value,
        sizeof(value));
    value = 32;
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
        (int) L"WindowMetrics");
    RegSetValueEx(reg, L"Shell Icon Size", 0, REG_DWORD, (BYTE*) &value,
        sizeof(value));
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS,
        (int) L"WindowMetrics");
#endif

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

童话里做英雄 2024-08-19 05:36:56

我见过你用大锤的方法来完成这件事。不过,在您的代码中,“Shell Icon Size”值是 REG_SZ,而不是 REG_DWORD。始终 VERIFY() API 函数返回值...

Your sledge-hammer approach is the one I've seen used to get this done. An oops in your code though, the "Shell Icon Size" value is a REG_SZ, not a REG_DWORD. Always VERIFY() the API function return values...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文