The approach is not always satisfying and primarily depends on your ico-files.
In my case, I started off with the attached ico-file containing three images with 16x16, 24x24 and 32x32 sizes.
These are the images of the ico-file placed next to each other:
- stop.png (328 Bytes) Viewed 3712 times
And that's how it's rendered, when trying to get the 32x32 image:
- rendered result
- stop-result.png (282 Bytes) Viewed 3712 times
The top image is loaded from file system by index.
Code: Select all
wxImage img;
img.LoadFile("icons\\stop.ico", wxBITMAP_TYPE_ICO, 2);
The bottom image is loaded from resource by wxIcon constructor.
Code: Select all
wxIcon icon = wxIcon(L"ICON_STOP", wxBITMAP_TYPE_ICO_RESOURCE, 32, 32);
What happens?
I created the ico-file with Gimp and exported it with different bits per pixel (at this point I wasn't aware of the trouble it makes):
16x16 => 32bpp, 8-Bit Alpha, no palette
24x24 => 32bpp, 8-Bit Alpha, no palette
32x32 => 4bpp, 1-Bit Alpha, 16 slot palette.
The ico-file then contains the images in the following order:
24x24 - 32bit
16x16 - 32bit
32x32 - 4bit
At some point under the hood of the wxIcon constructor the function
LoadIcon of Winapi is called, which selects the best fitting image, which turns out to be the 24x24 32bit image and not the one with fitting size. And then it gets rescaled to 32x32. In total it leads to a bad result.
There are three options to get desired results.
1. Do not embed ico files and provide them with your application on release.
2. Do not mix up the bits per pixel of your icons and stick with Kerry's solution.
3. If you can't change your icons anymore and have the problem, I struggled with, you can use following approach, which allows to load embedded icons from resource by index:
I copied the code from
https://wiki.wxwidgets.org/Embedding_PN ... ource_file and adjusted it a little bit.
At the end it looks like this:
The resource entry in your_app.rc:
Code: Select all
ICON_STOP RCDATA "icons\\stop.ico"
The modified code from the above mentioned wiki:
Code: Select all
bool LoadDataFromResource(char*& t_data, DWORD& t_dataSize, const wxString& t_name)
{
bool r_result = false;
HGLOBAL a_resHandle = 0;
HRSRC a_resource;
a_resource = FindResource(0, t_name.wchar_str(), RT_RCDATA);
if (0 != a_resource) {
a_resHandle = LoadResource(NULL, a_resource);
if (0 != a_resHandle) {
t_data = (char*)LockResource(a_resHandle);
t_dataSize = SizeofResource(NULL, a_resource);
r_result = true;
}
}
return r_result;
}
wxImage* GetImageFromMemory(const char* t_data, const DWORD t_size, int index = -1)
{
wxMemoryInputStream a_is(t_data, t_size); // requires #include <wx/mstream.h>
return new wxImage(a_is, wxBITMAP_TYPE_ICO, index);
}
wxImage* CreateImageFromIcoResource(const wxString& t_name, int index = -1)
{
wxImage* r_bitmapPtr = 0;
char* a_data = 0;
DWORD a_dataSize = 0;
if (LoadDataFromResource(a_data, a_dataSize, t_name)) {
r_bitmapPtr = GetImageFromMemory(a_data, a_dataSize, index);
}
return r_bitmapPtr;
}
Usage:
Code: Select all
wxImage* iconStop = CreateImageFromIcoResource(L"ICON_STOP", 2);
toolbar->AddTool(ID_TOOLBAR_BTN_STOP, wxEmptyString, *iconStop, _(L"Stop"));
delete iconStop;
The code just loads the ico resource as RC_DATA instead of RC_ICON and allows to use the ico data in an input stream. And this allows using wxImage as if it was loading up a file from the file system, as you see in the wxImage instantiation with wxBITMAP_TYPE_ICO instead of wxBITMAP_TYPE_ICO_RESOURCE.
For now, I will export my icons with consistent bits per pixel and use Kerry's solution, which seems the appropriate way. Wish, I had figured it out earlier.