How to properly create a wxIconBundle under Windows?

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
a little bit
In need of some credit
In need of some credit
Posts: 6
Joined: Sat Apr 10, 2021 11:46 am

How to properly create a wxIconBundle under Windows?

Post by a little bit »

I would like to create a wxIconBundle for a given file extension / MIME type under Windows.

I tried the following for a given wxString ext (e.g., "pdf"):

Code: Select all

// simplified; no error checking

if (auto const file_type = wxTheMimeTypesManager::GetFileTypeFromExtension(ext)) {
	if (wxIconLocation icon_loc; file_type->GetIcon(&icon_loc))
		icon_bundle.AddIcon(icon_loc.GetFileName(), /* whatever */);
}
However, this fails if GetIcon(...) returns a so called "indirect string" in icon_loc. It seems that wxWidgets does not properly parse these. I tried to handle them via native function SHLoadIndirectString(...). But then a PNG file is often returned for the icon with improper size. Eventually, I threw the towel and implemented it all natively for that platform:

Code: Select all

void
create_icon_bundle(
    wxIconBundle&   icon_bundle,
    wxFileType&     file_type
) {
    if (wxArrayString file_exts; !file_type.GetExtensions(file_exts)) // XXX: see API doc for potential shortcomings
        ;

    else {
        for (auto const& file_ext: file_exts) {
            SHFILEINFO file_info;

            if (!SUCCEEDED(SHGetFileInfo(file_ext.c_str(), FILE_ATTRIBUTE_NORMAL, &file_info, sizeof(file_info), SHGFI_USEFILEATTRIBUTES|SHGFI_ICON)))
                ;

            else if (wxIcon icon; !icon.CreateFromHICON(static_cast<WXHICON>(file_info.hIcon)))
                DestroyIcon(file_info.hIcon);

            else {
                icon_bundle.AddIcon(icon);
                break;
            }
        }
    }
}
While this works, it is not cross-platform. Now, I find the whole icon-related stuff in wxWidgets a little bit overwhelming, so I might have done it wrong. Hence, my question:

How to create an icon bundle under Windows (or better yet, any platform) containing the same kind of icon but with different sizes for a given file extension / MIME type? My ultimate goal is to retrieve a (native, if possible) icon via wxArtProvider::GetIcon(...) for that extension (= wxArtID), e.g., to be usable in the wxImageList of a wxTreeCtrl.
Post Reply