diff --git a/docs/changes.txt b/docs/changes.txt index 9fb88e28ad..fda8bba530 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -154,6 +154,7 @@ wxGTK: wxMSW: - Add support for building with Microsoft Visual Studio 2017 (Tobias Taschner). +- Allow loading icons from resources in wxIconBundle (PB). - Enable wxStackWalker in MinGW64 builds. - Fix crash when using wxCHMHelpController() in 64 bit builds (Xlord2). - Fix wxSpinCtrl appearance: show arrows inside the control (Catalin Raceanu). diff --git a/include/wx/iconbndl.h b/include/wx/iconbndl.h index 704c58f248..b1501c324f 100644 --- a/include/wx/iconbndl.h +++ b/include/wx/iconbndl.h @@ -21,9 +21,7 @@ class WXDLLIMPEXP_FWD_BASE wxInputStream; WX_DECLARE_EXPORTED_OBJARRAY(wxIcon, wxIconArray); -// this class can't load bitmaps of type wxBITMAP_TYPE_ICO_RESOURCE, -// if you need them, you have to load them manually and call -// wxIconCollection::AddIcon +// Load icons of multiple sizes from files or resources (MSW-only). class WXDLLIMPEXP_CORE wxIconBundle : public wxGDIObject { public: @@ -58,6 +56,11 @@ public: // initializes the bundle with a single icon wxIconBundle(const wxIcon& icon); +#if defined(__WINDOWS__) && wxUSE_ICO_CUR + // 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 +73,11 @@ public: void AddIcon(wxInputStream& stream, wxBitmapType type = wxBITMAP_TYPE_ANY); #endif // wxUSE_STREAMS && wxUSE_IMAGE +#if defined(__WINDOWS__) && wxUSE_ICO_CUR + // 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/include/wx/private/icondir.h b/include/wx/private/icondir.h new file mode 100644 index 0000000000..30cba3ae10 --- /dev/null +++ b/include/wx/private/icondir.h @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/icondir.h +// Purpose: Declarations of structs used for loading MS icons +// Author: wxWidgets team +// Created: 2017-05-19 +// Copyright: (c) 2017 wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_ICONDIR_H_ +#define _WX_PRIVATE_ICONDIR_H_ + +#include "wx/defs.h" // wxUint* declarations + + +// Structs declared here are used for loading group icons from +// .ICO files or MS Windows resources. +// Icon entry and directory structs for .ICO files and +// MS Windows resources are very similar but not identical. + +#if wxUSE_ICO_CUR + +#if wxUSE_STREAMS + +// icon entry in .ICO files +struct ICONDIRENTRY +{ + wxUint8 bWidth; // Width of the image + wxUint8 bHeight; // Height of the image (times 2) + wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp) + wxUint8 bReserved; // Reserved + + // these two are different in icons and cursors: + // icon or cursor + wxUint16 wPlanes; // Color Planes or XHotSpot + wxUint16 wBitCount; // Bits per pixel or YHotSpot + + wxUint32 dwBytesInRes; // how many bytes in this resource? + wxUint32 dwImageOffset; // where in the file is this image +}; + +// icon directory in .ICO files +struct ICONDIR +{ + wxUint16 idReserved; // Reserved + wxUint16 idType; // resource type (1 for icons, 2 for cursors) + wxUint16 idCount; // how many images? +}; + +#endif // wxUSE_STREAMS + + +#ifdef __WINDOWS__ + +#pragma pack(push) +#pragma pack(2) + +// icon entry in MS Windows resources +struct GRPICONDIRENTRY +{ + wxUint8 bWidth; // Width of the image + wxUint8 bHeight; // Height of the image (times 2) + wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp) + wxUint8 bReserved; // Reserved + + // these two are different in icons and cursors: + // icon or cursor + wxUint16 wPlanes; // Color Planes or XHotSpot + wxUint16 wBitCount; // Bits per pixel or YHotSpot + + wxUint32 dwBytesInRes; // how many bytes in this resource? + + wxUint16 nID; // actual icon resource ID +}; + +// icon directory in MS Windows resources +struct GRPICONDIR +{ + wxUint16 idReserved; // Reserved + wxUint16 idType; // resource type (1 for icons, 2 for cursors) + wxUint16 idCount; // how many images? + GRPICONDIRENTRY idEntries[1]; // The entries for each image +}; + +#pragma pack(pop) + +#endif // __WINDOWS__ + +#endif // wxUSE_ICO_CUR + +#endif // _WX_PRIVATE_ICONDIR_H_ diff --git a/interface/wx/iconbndl.h b/interface/wx/iconbndl.h index 217adb464a..ef1fdd9023 100644 --- a/interface/wx/iconbndl.h +++ b/interface/wx/iconbndl.h @@ -68,6 +68,19 @@ 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 +111,17 @@ 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..0cb757dc60 100644 --- a/src/common/iconbndl.cpp +++ b/src/common/iconbndl.cpp @@ -17,16 +17,24 @@ #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" +#ifdef __WINDOWS__ + #include "wx/private/icondir.h" +#endif + #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxIconArray) @@ -89,6 +97,16 @@ wxIconBundle::wxIconBundle(const wxIcon& icon) AddIcon(icon); } +#if defined(__WINDOWS__) && wxUSE_ICO_CUR + +wxIconBundle::wxIconBundle(const wxString& resourceName, WXHINSTANCE module) + : wxGDIObject() +{ + AddIcon(resourceName, module); +} + +#endif // defined(__WINDOWS__) && wxUSE_ICO_CUR + wxGDIRefData *wxIconBundle::CreateGDIRefData() const { return new wxIconBundleRefData; @@ -192,6 +210,49 @@ void wxIconBundle::AddIcon(wxInputStream& stream, wxBitmapType type) #endif // wxUSE_STREAMS && wxUSE_IMAGE +#if defined(__WINDOWS__) && wxUSE_ICO_CUR + +// 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) ) + { + wxLogError(_("Failed to load icons from resource '%s'."), resourceName); + 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("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, resourceName); + } + } +} + +#endif // defined(__WINDOWS__) && wxUSE_ICO_CUR + wxIcon wxIconBundle::GetIcon(const wxSize& size, int flags) const { wxASSERT( size == wxDefaultSize || (size.x >= 0 && size.y > 0) ); diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index fd129e47e1..ff2d8976a2 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -36,6 +36,7 @@ #include "wx/scopedarray.h" #include "wx/scopedptr.h" #include "wx/anidecod.h" +#include "wx/private/icondir.h" // For memcpy #include @@ -1241,30 +1242,6 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxICOHandler, wxBMPHandler); #if wxUSE_STREAMS -struct ICONDIRENTRY -{ - wxUint8 bWidth; // Width of the image - wxUint8 bHeight; // Height of the image (times 2) - wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp) - wxUint8 bReserved; // Reserved - - // these two are different in icons and cursors: - // icon or cursor - wxUint16 wPlanes; // Color Planes or XHotSpot - wxUint16 wBitCount; // Bits per pixel or YHotSpot - - wxUint32 dwBytesInRes; // how many bytes in this resource? - wxUint32 dwImageOffset; // where in the file is this image -}; - -struct ICONDIR -{ - wxUint16 idReserved; // Reserved - wxUint16 idType; // resource type (1 for icons, 2 for cursors) - wxUint16 idCount; // how many images? -}; - - bool wxICOHandler::SaveFile(wxImage *image, wxOutputStream& stream, bool verbose)