Trouble loading multiple size ICO embedded resource  [SOLVED]

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.
fishnet37222
In need of some credit
In need of some credit
Posts: 6
Joined: Sat May 06, 2017 1:40 pm

Trouble loading multiple size ICO embedded resource

Postby fishnet37222 » Tue May 16, 2017 11:17 am

I'm using wxWidgets 3.1.0 on Windows 10 using Visual C++. I have a multiple size .ico file included as a resource in my project. I'm using the following code to set my frame's icon in the constructor.

Code: Select all

wxInitAllImageHandlers();
this->SetIcon(wxICON(IDI_ICON1));


The code compiles and runs without any errors, however, I only see the correct icon in the taskbar and not in the window's title bar.

Below is the resource configuration for my project:
2017-05-16_7-15-23.png
2017-05-16_7-15-23.png (15.96 KiB) Viewed 274 times


Thanks in advance for any help.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 1698
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Trouble loading multiple size ICO embedded resource

Postby ONEEYEMAN » Tue May 16, 2017 2:00 pm

Hi,
How do you load the icon? Did you make sure the bitmap is loaded properly and IsOk() return true? How did you set it up?

Please show some code so that we can look at it.

Thank you.

PB
wxWorld Domination!
wxWorld Domination!
Posts: 1185
Joined: Sun Jan 03, 2010 5:45 pm

Re: Trouble loading multiple size ICO embedded resource

Postby PB » Tue May 16, 2017 2:31 pm

I believe that a wxIcon can contain just one icon (size).

Have you tried SetIcons(), which passes a wxIconBundle which can contain several icons (with different sizes)?

User avatar
doublemax
Moderator
Moderator
Posts: 10923
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Trouble loading multiple size ICO embedded resource

Postby doublemax » Tue May 16, 2017 5:23 pm

Which icon sizes are needed depends on several factors, e.g. Windows version, Window scheme (height of window caption), screen dpi, etc.

Try adding a 48x48 and 64x64 version to the icon.

If that doesn't work, what's the exact line in the .rc file for this icon?
Use the source, Luke!

PB
wxWorld Domination!
wxWorld Domination!
Posts: 1185
Joined: Sun Jan 03, 2010 5:45 pm

Re: Trouble loading multiple size ICO embedded resource  [SOLVED]

Postby PB » Tue May 16, 2017 8:26 pm

I do not have Windows 10, the following test was conducted on Windows 7 Pro with Aero.

The test icon (obtained from wxWidgets.org where I added text displaying its size to individual icons) had 6 sizes (output from the attached program):
22:05:03: Icon bundle contains 6 icons.
22:05:03: Icon 0: width 16, height 16.
22:05:03: Icon 1: width 32, height 32.
22:05:03: Icon 2: width 48, height 48.
22:05:03: Icon 3: width 64, height 64.
22:05:03: Icon 4: width 96, height 96.
22:05:03: Icon 5: width 128, height 128.


I observed a difference between SetIcon() and SetIcons():
SetIcon()
In frame title bar: 32x32
When <Alt+Tab>bing between applications: 32x32
In taskbar: 32x32, regardless its "Use small icons" setting.

SetIcons()
In frame title bar: 16x16
When <Alt+Tab>bing between applications: 32x32
In taskbar: 16x16 with "Use small icons" on, 32x32 with "Use small icons" off

Code I tested the above with is attached below, including the icon and resource file.

As wxWidgets cannot load wxIconBundle from a Windows resource, I mashed up the resource loading code (wxIconBundleResLoader.{h|cpp}), basically a copy&paste of a StackOverflow answer. I have also included project and solution files for VS Express 2015 for Desktop, but they would have to be adapted (at least include and lib paths vc14_lib -> vc_lib) to build on someone else's computer.
Attachments
IconBundle.zip
(26.31 KiB) Downloaded 9 times

fishnet37222
In need of some credit
In need of some credit
Posts: 6
Joined: Sat May 06, 2017 1:40 pm

Re: Trouble loading multiple size ICO embedded resource

Postby fishnet37222 » Wed May 17, 2017 1:09 am

Thanks for the replies guys. Once I modified my .rc file to remove all the extra stuff that Visual Studio added and put "#define wxUSE_NO_MANIFEST 1" at the top, PB's solution worked like a charm.

PB
wxWorld Domination!
wxWorld Domination!
Posts: 1185
Joined: Sun Jan 03, 2010 5:45 pm

Re: Trouble loading multiple size ICO embedded resource

Postby PB » Wed May 17, 2017 3:50 pm

I believe that loading wxIconBundle from an MS Windows resource can be useful. I cleaned the code up and I will try to submit it (modified, as a wxIconBundle method) to wxWidgets.

Edit: Deleted the code from this post, the updated version is here.
Last edited by PB on Sat May 20, 2017 3:40 pm, edited 1 time in total.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 1698
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Trouble loading multiple size ICO embedded resource

Postby ONEEYEMAN » Wed May 17, 2017 4:04 pm

Hi,
You should check the PB' second post as defining NO_MANIFEST is wise - you will need it for HighDPI machines at least.

Thank you.

PB
wxWorld Domination!
wxWorld Domination!
Posts: 1185
Joined: Sun Jan 03, 2010 5:45 pm

Re: Trouble loading multiple size ICO embedded resource

Postby PB » Sat May 20, 2017 3:38 pm

Support for loading icons from MSW resources has been added to wxIconBundle:
https://github.com/wxWidgets/wxWidgets/commit/66865ed7145dbfa9c90fa0b77764cd60605b77f4

Here (and attached) is the updated standalone code that can be used to achieve that with older wxWidgets versions:

wxIconBundleResLoader.h

Code: Select all

#ifndef WXICONBUNDLE_RESLOADER_H_DEFINED
#define WXICONBUNDLE_RESLOADER_H_DEFINED

#include <wx/iconbndl.h>

/*
    MS Windows only: Loads all icon sizes
    for an icon stored in an MS Windows resource file.
    When module is 0, the current instance is used.
*/
bool LoadwxIconBundleFromWindowsResource(wxIconBundle& bundle, const wxString& name, WXHINSTANCE module = 0);

#endif // #ifndef WXICONBUNDLE_RESLOADER_H_DEFINED


wxIconBundleResLoader.cpp

Code: Select all

##include "wxIconBundleResLoader.h"

#ifdef __WINDOWS__

#include <wx/log.h>
#include <wx/intl.h>
#include <wx/msw/wrapwin.h>
#include <wx/utils.h>


namespace {
   
// struct declarations taken from https://msdn.microsoft.com/en-us/library/ms997538.aspx
// More information about icon resources is available at https://blogs.msdn.microsoft.com/oldnewthing/20120720-00/?p=7083

#pragma pack(push)
#pragma pack(2)

// icon entry in the icon directory resource
typedef struct
{
    BYTE   bWidth;               // Width, in pixels, of the image
    BYTE   bHeight;              // Height, in pixels, of the image
    BYTE   bColorCount;          // Number of colors in image (0 if >=8bpp)
    BYTE   bReserved;            // Reserved
    WORD   wPlanes;              // Color Planes
    WORD   wBitCount;            // Bits per pixel
    DWORD  dwBytesInRes;         // how many bytes in this resource?
    WORD   nID;                  // the ID
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;

// icon directory resource
typedef struct
{
    WORD            idReserved;   // Reserved (must be 0)
    WORD            idType;       // Resource type (1 for icons)
    WORD            idCount;      // How many images?
    GRPICONDIRENTRY idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;

#pragma pack(pop)

} // anonymous namespace

bool LoadwxIconBundleFromWindowsResource(wxIconBundle& bundle, const wxString& name, WXHINSTANCE module)
{
    const void* data = NULL;
    size_t outLen = 0;

    // load the icon directory resource
    if ( !wxLoadUserResource(&data, &outLen, name, RT_GROUP_ICON, module) )
    {
        wxLogError(_("Failed to load icons from resource '%s'."), name);
        return false;
    }

    // load the individual icons referred from the icon directory
    const GRPICONDIR* grpIconDir = static_cast<const GRPICONDIR*>(data);
   
    for ( WORD i = 0; i < grpIconDir->idCount; i++ )
    {
        const WORD iconID = grpIconDir->idEntries[i].nID;

        if ( wxLoadUserResource(&data, &outLen, wxString::Format(wxS("#%u"), iconID), RT_ICON, module) )
        {
            HICON hIcon = ::CreateIconFromResourceEx(static_cast<PBYTE>(const_cast<void*>(data)),
                                static_cast<DWORD>(outLen), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR);
            wxIcon icon;

            if ( hIcon && icon.CreateFromHICON(hIcon) )
                bundle.AddIcon(icon);
            else
                wxLogDebug(wxS("Failed to create icon from resource with id %u."), iconID);
        }
        else
        {
            wxLogDebug(wxS("Failed to load icon with id %u for group icon resource '%s'."), iconID, name);
        }
    }
    return true;
}

#else

bool LoadwxIconBundleFromWindowsResource(wxIconBundle&, const wxString&, WXHINSTANCE)
{   
    return false;
}

#endif // __WINDOWS__
Attachments
wxIconBundleResLoader.zip
(1.68 KiB) Downloaded 6 times


Return to “Platform Related Issues”

Who is online

Users browsing this forum: No registered users and 1 guest