diff --git a/include/wx/iconbndl.h b/include/wx/iconbndl.h index 704c58f248..dee50a4de8 100644 --- a/include/wx/iconbndl.h +++ b/include/wx/iconbndl.h @@ -58,6 +58,11 @@ public: // initializes the bundle with a single icon wxIconBundle(const wxIcon& icon); +#ifdef __WINDOWS__ + // initializes the bundle with the icons from a group icon stored as an MS Windows resource + wxIconBundle(const wxString& resourceName, WXHINSTANCE module); +#endif + // default copy ctor and assignment operator are OK // adds all the icons contained in the file to the collection, @@ -70,6 +75,11 @@ public: void AddIcon(wxInputStream& stream, wxBitmapType type = wxBITMAP_TYPE_ANY); #endif // wxUSE_STREAMS && wxUSE_IMAGE +#ifdef __WINDOWS__ + // loads all the icons from a group icon stored in an MS Windows resource + void AddIcon(const wxString& resourceName, WXHINSTANCE module); +#endif + // adds the icon to the collection, if the collection already // contains an icon with the same width and height, it is // replaced diff --git a/interface/wx/iconbndl.h b/interface/wx/iconbndl.h index 217adb464a..3433663158 100644 --- a/interface/wx/iconbndl.h +++ b/interface/wx/iconbndl.h @@ -68,6 +68,18 @@ public: */ wxIconBundle(const wxIcon& icon); + /** + Initializes the bundle with all sizes of a group icon with @a resourceName + stored as an MS Windows resource in @a module. When @a module is 0, the current + instance is used. + + @see AddIcon(const wxString&, WXHINSTANCE) + + @onlyfor{wxmsw} + @since 3.1.1 + */ + wxIconBundle(const wxString& resourceName, WXHINSTANCE module); + /** Copy constructor. */ @@ -98,6 +110,15 @@ public: */ void AddIcon(wxInputStream& stream, wxBitmapType type = wxBITMAP_TYPE_ANY); + /** + Loads all sizes of a group icon with @a resourceName stored as an MS Windows + resource in @a module. When @a module is 0, the current instance is used. + + @onlyfor{wxmsw} + @since 3.1.1 + */ + void AddIcon(const wxString& resourceName, WXHINSTANCE module); + /** Adds the icon to the collection; if the collection already contains an icon with the same width and height, it is diff --git a/src/common/iconbndl.cpp b/src/common/iconbndl.cpp index 566f1ae813..a51ee3bc52 100644 --- a/src/common/iconbndl.cpp +++ b/src/common/iconbndl.cpp @@ -17,12 +17,16 @@ #include "wx/iconbndl.h" #ifndef WX_PRECOMP + #ifdef __WINDOWS__ + #include "wx/msw/wrapwin.h" + #endif #include "wx/settings.h" #include "wx/log.h" #include "wx/intl.h" #include "wx/bitmap.h" #include "wx/image.h" #include "wx/stream.h" + #include "wx/utils.h" #endif #include "wx/wfstream.h" @@ -89,6 +93,16 @@ wxIconBundle::wxIconBundle(const wxIcon& icon) AddIcon(icon); } +#ifdef __WINDOWS__ + +wxIconBundle::wxIconBundle(const wxString& resourceName, WXHINSTANCE module) + : wxGDIObject() +{ + AddIcon(resourceName, module); +} + +#endif + wxGDIRefData *wxIconBundle::CreateGDIRefData() const { return new wxIconBundleRefData; @@ -192,6 +206,75 @@ void wxIconBundle::AddIcon(wxInputStream& stream, wxBitmapType type) #endif // wxUSE_STREAMS && wxUSE_IMAGE + +#ifdef __WINDOWS__ + +namespace { + +// struct declarations taken from https://msdn.microsoft.com/en-us/library/ms997538.aspx +#pragma pack(push) +#pragma pack(2) + +// individual 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 + +// Loads all the icons for an icon group (i.e., different sizes of one icon) +// stored as an MS Windows resource. +void wxIconBundle::AddIcon(const wxString& resourceName, WXHINSTANCE module) +{ + const void* data = NULL; + size_t outLen = 0; + + // load the icon directory resource + if ( !wxLoadUserResource(&data, &outLen, resourceName, RT_GROUP_ICON, module) ) + return; + + // load the individual icons referred from the icon directory + const GRPICONDIR* grpIconDir = static_cast(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(const_cast(data)), + static_cast(outLen), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR); + wxIcon icon; + + if ( hIcon && icon.CreateFromHICON(hIcon) ) + AddIcon(icon); + else + wxLogDebug(wxS("Could not create icon from resource with id %u."), iconID); + } + } +} + +#endif + wxIcon wxIconBundle::GetIcon(const wxSize& size, int flags) const { wxASSERT( size == wxDefaultSize || (size.x >= 0 && size.y > 0) );