From cb8b6009d590ae9c72d97fc6fb1abb538638dc34 Mon Sep 17 00:00:00 2001 From: Markus Juergens Date: Sun, 18 Nov 2018 20:49:34 +0100 Subject: [PATCH 01/12] Add a size selection choice to the "artprov" sample This will allow to test support for larger icons when it is added in the upcoming commits. --- samples/artprov/artbrows.cpp | 45 ++++++++++++++++++++++++++++++++---- samples/artprov/artbrows.h | 7 ++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/samples/artprov/artbrows.cpp b/samples/artprov/artbrows.cpp index 93e0f9f638..8cefcd5e19 100644 --- a/samples/artprov/artbrows.cpp +++ b/samples/artprov/artbrows.cpp @@ -126,8 +126,13 @@ static void FillBitmaps(wxImageList *images, wxListCtrl *list, #include "null.xpm" +const int SIZE_CHOICE_ID = ::wxNewId(); + +int wxArtBrowserDialog::m_bitmap_sizes[] = { -1, 16, 32, 64, 128, 256, 0 }; + wxBEGIN_EVENT_TABLE(wxArtBrowserDialog, wxDialog) EVT_LIST_ITEM_SELECTED(wxID_ANY, wxArtBrowserDialog::OnSelectItem) + EVT_CHOICE(SIZE_CHOICE_ID, wxArtBrowserDialog::OnChangeSize) EVT_CHOICE(wxID_ANY, wxArtBrowserDialog::OnChooseClient) wxEND_EVENT_TABLE() @@ -136,6 +141,8 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { + m_current_artid = wxART_ERROR; + wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxSizer *subsizer; @@ -152,16 +159,31 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) m_list = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(250, 300), wxLC_REPORT | wxSUNKEN_BORDER); m_list->AppendColumn("wxArtID"); - subsizer->Add(m_list, 1, wxEXPAND | wxRIGHT, 10); + subsizer->Add(m_list, 0, wxEXPAND | wxRIGHT, 10); wxSizer *subsub = new wxBoxSizer(wxVERTICAL); + + m_sizes = new wxChoice( this, SIZE_CHOICE_ID ); + int size_index = 0; + while( m_bitmap_sizes[size_index] != 0 ) + { + if( m_bitmap_sizes[size_index] == -1 ) + m_sizes->Append( "Default" ); + else + m_sizes->Append( wxString::Format("%d x %d", m_bitmap_sizes[size_index], m_bitmap_sizes[size_index] ) ); + + size_index++; + } + m_sizes->SetSelection(0); + subsub->Add(m_sizes, 0, wxALL, 4); + m_text = new wxStaticText(this, wxID_ANY, "Size: 333x333"); - subsub->Add(m_text); + subsub->Add(m_text, 0, wxALL, 4); m_canvas = new wxStaticBitmap(this, wxID_ANY, wxBitmap(null_xpm)); subsub->Add(m_canvas); - subsub->Add(100, 100); - subsizer->Add(subsub); + subsub->Add(256, 256); + subsizer->Add(subsub, 1, wxLEFT, 4 ); sizer->Add(subsizer, 1, wxEXPAND | wxLEFT|wxRIGHT, 10); @@ -176,6 +198,13 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) } +wxSize wxArtBrowserDialog::GetSelectedBitmapSize() const +{ + int size = m_bitmap_sizes[ m_sizes->GetSelection() ]; + return wxSize( size, size ); +} + + void wxArtBrowserDialog::SetArtClient(const wxArtClient& client) { wxBusyCursor bcur; @@ -201,7 +230,13 @@ void wxArtBrowserDialog::SetArtClient(const wxArtClient& client) void wxArtBrowserDialog::OnSelectItem(wxListEvent &event) { const char *data = (const char*)event.GetData(); - SetArtBitmap(data, m_client, wxDefaultSize); + m_current_artid = wxString( data ); + SetArtBitmap(data, m_client, GetSelectedBitmapSize()); +} + +void wxArtBrowserDialog::OnChangeSize(wxCommandEvent &event) +{ + SetArtBitmap(m_current_artid, m_client, GetSelectedBitmapSize() ); } void wxArtBrowserDialog::OnChooseClient(wxCommandEvent &event) diff --git a/samples/artprov/artbrows.h b/samples/artprov/artbrows.h index 977dce30f3..4c794834b1 100644 --- a/samples/artprov/artbrows.h +++ b/samples/artprov/artbrows.h @@ -28,12 +28,19 @@ public: private: void OnSelectItem(wxListEvent &event); + void OnChangeSize(wxCommandEvent &event); void OnChooseClient(wxCommandEvent &event); + wxSize GetSelectedBitmapSize() const; + wxListCtrl *m_list; wxStaticBitmap *m_canvas; wxStaticText *m_text; wxString m_client; + wxChoice *m_sizes; + wxString m_current_artid; + + static int m_bitmap_sizes[7]; wxDECLARE_EVENT_TABLE(); }; From 303fa4b3ef632a5a9e887c416d56028a90b2c643 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2018 20:55:09 +0100 Subject: [PATCH 02/12] Minor cleanup in the "artprov" sample after the previous commit Use the standard wxWidgets camelCase naming convention instead of snake_case and fix some style inconsistencies. No real changes. --- samples/artprov/artbrows.cpp | 24 +++++++++++------------- samples/artprov/artbrows.h | 4 +--- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/samples/artprov/artbrows.cpp b/samples/artprov/artbrows.cpp index 8cefcd5e19..ea0b9944da 100644 --- a/samples/artprov/artbrows.cpp +++ b/samples/artprov/artbrows.cpp @@ -128,7 +128,8 @@ static void FillBitmaps(wxImageList *images, wxListCtrl *list, const int SIZE_CHOICE_ID = ::wxNewId(); -int wxArtBrowserDialog::m_bitmap_sizes[] = { -1, 16, 32, 64, 128, 256, 0 }; +// Bitmap sizes that can be chosen in the size selection wxChoice. +static const int bitmapSizes[] = { -1, 16, 32, 64, 128, 256, 0 }; wxBEGIN_EVENT_TABLE(wxArtBrowserDialog, wxDialog) EVT_LIST_ITEM_SELECTED(wxID_ANY, wxArtBrowserDialog::OnSelectItem) @@ -141,7 +142,7 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { - m_current_artid = wxART_ERROR; + m_currentArtId = wxART_ERROR; wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxSizer *subsizer; @@ -164,15 +165,12 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) wxSizer *subsub = new wxBoxSizer(wxVERTICAL); m_sizes = new wxChoice( this, SIZE_CHOICE_ID ); - int size_index = 0; - while( m_bitmap_sizes[size_index] != 0 ) + for ( const int* p = bitmapSizes; *p; ++p ) { - if( m_bitmap_sizes[size_index] == -1 ) + if ( *p == -1 ) m_sizes->Append( "Default" ); else - m_sizes->Append( wxString::Format("%d x %d", m_bitmap_sizes[size_index], m_bitmap_sizes[size_index] ) ); - - size_index++; + m_sizes->Append( wxString::Format("%d x %d", *p, *p ) ); } m_sizes->SetSelection(0); subsub->Add(m_sizes, 0, wxALL, 4); @@ -200,8 +198,8 @@ wxArtBrowserDialog::wxArtBrowserDialog(wxWindow *parent) wxSize wxArtBrowserDialog::GetSelectedBitmapSize() const { - int size = m_bitmap_sizes[ m_sizes->GetSelection() ]; - return wxSize( size, size ); + const int size = bitmapSizes[m_sizes->GetSelection()]; + return wxSize(size, size); } @@ -230,13 +228,13 @@ void wxArtBrowserDialog::SetArtClient(const wxArtClient& client) void wxArtBrowserDialog::OnSelectItem(wxListEvent &event) { const char *data = (const char*)event.GetData(); - m_current_artid = wxString( data ); + m_currentArtId = wxString( data ); SetArtBitmap(data, m_client, GetSelectedBitmapSize()); } -void wxArtBrowserDialog::OnChangeSize(wxCommandEvent &event) +void wxArtBrowserDialog::OnChangeSize(wxCommandEvent& WXUNUSED(event)) { - SetArtBitmap(m_current_artid, m_client, GetSelectedBitmapSize() ); + SetArtBitmap(m_currentArtId, m_client, GetSelectedBitmapSize() ); } void wxArtBrowserDialog::OnChooseClient(wxCommandEvent &event) diff --git a/samples/artprov/artbrows.h b/samples/artprov/artbrows.h index 4c794834b1..e1dbb093b5 100644 --- a/samples/artprov/artbrows.h +++ b/samples/artprov/artbrows.h @@ -38,9 +38,7 @@ private: wxStaticText *m_text; wxString m_client; wxChoice *m_sizes; - wxString m_current_artid; - - static int m_bitmap_sizes[7]; + wxString m_currentArtId; wxDECLARE_EVENT_TABLE(); }; From d5cd939db73854469f7ff8e0d699f15fea6ec8db Mon Sep 17 00:00:00 2001 From: Markus Juergens Date: Sun, 18 Nov 2018 20:58:57 +0100 Subject: [PATCH 03/12] Use native art for PRINT and XXX_FILE art IDs under MSW These art IDs have natural native equivalents, so do use them. --- src/msw/artmsw.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index eb7a6c4ec8..8c4c5612b0 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -51,6 +51,9 @@ SHSTOCKICONID MSWGetStockIconIdForArtProviderId(const wxArtID& art_id) else if ( art_id == wxART_FLOPPY ) return SIID_DRIVE35; else if ( art_id == wxART_CDROM ) return SIID_DRIVECD; else if ( art_id == wxART_REMOVABLE ) return SIID_DRIVEREMOVE; + else if ( art_id == wxART_PRINT ) return SIID_PRINTER; + else if ( art_id == wxART_EXECUTABLE_FILE ) return SIID_APPLICATION; + else if ( art_id == wxART_NORMAL_FILE ) return SIID_DOCNOASSOC; return SIID_INVALID; }; From 880b2b0a460cd0c52838910683d53fdfedf211c0 Mon Sep 17 00:00:00 2001 From: Markus Juergens Date: Sun, 18 Nov 2018 21:16:00 +0100 Subject: [PATCH 04/12] Use icons of correct sizes for wxART_FOLDER in wxMSW Don't restrict the sizes to just small or large icons but extract the icon closest to the requested size using SHDefExtractIcon(). --- src/msw/artmsw.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 8c4c5612b0..329dfbd7b7 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -25,6 +25,7 @@ #include "wx/volume.h" #include "wx/msw/private.h" #include "wx/msw/wrapwin.h" +#include "wx/msw/wrapshl.h" #ifdef SHGSI_ICON #define wxHAS_SHGetStockIconInfo @@ -90,24 +91,22 @@ MSWGetBitmapForPath(const wxString& path, const wxSize& size, DWORD uFlags = 0) SHFILEINFO fi; wxZeroMemory(fi); - uFlags |= SHGFI_USEFILEATTRIBUTES | SHGFI_ICON; - if ( size != wxDefaultSize ) - { - if ( size.x <= 16 ) - uFlags |= SHGFI_SMALLICON; - else if ( size.x >= 64 ) - uFlags |= SHGFI_LARGEICON; - } + uFlags |= SHGFI_USEFILEATTRIBUTES | SHGFI_ICONLOCATION; if ( !SHGetFileInfo(path.t_str(), FILE_ATTRIBUTE_DIRECTORY, &fi, sizeof(SHFILEINFO), uFlags) ) + return wxNullBitmap; + + HICON hIcon = NULL; + if ( !SHDefExtractIcon(fi.szDisplayName, fi.iIcon, 0, + &hIcon, NULL, size.x) ) return wxNullBitmap; wxIcon icon; - icon.CreateFromHICON((WXHICON)fi.hIcon); + icon.CreateFromHICON((WXHICON)hIcon); wxBitmap bitmap(icon); - ::DestroyIcon(fi.hIcon); + ::DestroyIcon(hIcon); return bitmap; } From 8698d69c77b37aded54a6f8b69b6184abf2a5813 Mon Sep 17 00:00:00 2001 From: Markus Juergens Date: Sun, 18 Nov 2018 22:34:40 +0100 Subject: [PATCH 05/12] Return the best-sized icons from wxWindowsArtProvider Use SHDefExtractIcon() to retrieve the most appropriately-sized icon instead of always getting either the small or the large icon and then scaling it ourselves to make it of the right size. This results in incomparably better results for large icon sizes, e.g. 256*256, as can be seen in the artprov sample. --- src/msw/artmsw.cpp | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 329dfbd7b7..afc90823a9 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -180,38 +180,37 @@ wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id, { WinStruct sii; - UINT uFlags = SHGSI_ICON; - if ( size != wxDefaultSize ) - { - if ( size.x <= 16 ) - uFlags |= SHGSI_SMALLICON; - else if ( size.x >= 64 ) - uFlags |= SHGSI_LARGEICON; - } + UINT uFlags = SHGSI_ICONLOCATION | SHGSI_SYSICONINDEX; HRESULT res = MSW_SHGetStockIconInfo(stockIconId, uFlags, &sii); if ( res == S_OK ) { - wxIcon icon; - icon.CreateFromHICON( (WXHICON)sii.hIcon ); + const wxSize + sizeNeeded = size.IsFullySpecified() + ? size + : wxArtProvider::GetNativeSizeHint(client); - bitmap = wxBitmap(icon); - ::DestroyIcon(sii.hIcon); - - if ( bitmap.IsOk() ) + HICON hIcon = NULL; + res = SHDefExtractIcon(sii.szPath, sii.iIcon, 0, + &hIcon, NULL, sizeNeeded.x); + if ( res == S_OK ) { - const wxSize - sizeNeeded = size.IsFullySpecified() - ? size - : wxArtProvider::GetNativeSizeHint(client); + wxIcon icon; + icon.CreateFromHICON((WXHICON)hIcon); - if ( sizeNeeded.IsFullySpecified() && - bitmap.GetSize() != sizeNeeded ) + bitmap = wxBitmap(icon); + ::DestroyIcon(hIcon); + + if ( bitmap.IsOk() ) { - wxArtProvider::RescaleBitmap(bitmap, sizeNeeded); - } + if ( sizeNeeded.IsFullySpecified() && + bitmap.GetSize() != sizeNeeded ) + { + wxArtProvider::RescaleBitmap(bitmap, sizeNeeded); + } - return bitmap; + return bitmap; + } } } } From 49d8491518e7110512060044886c25dc442f1569 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2018 22:43:17 +0100 Subject: [PATCH 06/12] Refactor the code to use a wrapper for SHDefExtractIcon() Avoid duplicating the same code in MSWGetBitmapForPath() and CreateBitmap(). This also incidentally fixes SHDefExtractIcon() return value check, which was inverted, in MSWGetBitmapForPath(). --- src/msw/artmsw.cpp | 56 +++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index afc90823a9..4d5c03b6ce 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -85,6 +85,23 @@ MSW_SHGetStockIconInfo(SHSTOCKICONID siid, #endif // #ifdef wxHAS_SHGetStockIconInfo +// Wrapper for SHDefExtractIcon(). +wxBitmap +MSWGetBitmapFromIconLocation(const TCHAR* path, int index, const wxSize& size) +{ + HICON hIcon = NULL; + if ( SHDefExtractIcon(path, index, 0, &hIcon, NULL, size.x) != S_OK ) + return wxNullBitmap; + + wxIcon icon; + icon.CreateFromHICON((WXHICON)hIcon); + + wxBitmap bitmap(icon); + ::DestroyIcon(hIcon); + + return bitmap; +} + wxBitmap MSWGetBitmapForPath(const wxString& path, const wxSize& size, DWORD uFlags = 0) { @@ -97,18 +114,7 @@ MSWGetBitmapForPath(const wxString& path, const wxSize& size, DWORD uFlags = 0) &fi, sizeof(SHFILEINFO), uFlags) ) return wxNullBitmap; - HICON hIcon = NULL; - if ( !SHDefExtractIcon(fi.szDisplayName, fi.iIcon, 0, - &hIcon, NULL, size.x) ) - return wxNullBitmap; - - wxIcon icon; - icon.CreateFromHICON((WXHICON)hIcon); - - wxBitmap bitmap(icon); - ::DestroyIcon(hIcon); - - return bitmap; + return MSWGetBitmapFromIconLocation(fi.szDisplayName, fi.iIcon, size); } #if wxUSE_FSVOLUME @@ -190,27 +196,17 @@ wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id, ? size : wxArtProvider::GetNativeSizeHint(client); - HICON hIcon = NULL; - res = SHDefExtractIcon(sii.szPath, sii.iIcon, 0, - &hIcon, NULL, sizeNeeded.x); - if ( res == S_OK ) + bitmap = MSWGetBitmapFromIconLocation(sii.szPath, sii.iIcon, + sizeNeeded); + if ( bitmap.IsOk() ) { - wxIcon icon; - icon.CreateFromHICON((WXHICON)hIcon); - - bitmap = wxBitmap(icon); - ::DestroyIcon(hIcon); - - if ( bitmap.IsOk() ) + if ( sizeNeeded.IsFullySpecified() && + bitmap.GetSize() != sizeNeeded ) { - if ( sizeNeeded.IsFullySpecified() && - bitmap.GetSize() != sizeNeeded ) - { - wxArtProvider::RescaleBitmap(bitmap, sizeNeeded); - } - - return bitmap; + wxArtProvider::RescaleBitmap(bitmap, sizeNeeded); } + + return bitmap; } } } From 262124ca1b13bc4f0c3caa58bc2948804696838c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2018 22:47:29 +0100 Subject: [PATCH 07/12] Remove unnecessary bitmap size check in wxWindowsArtProvider This "sizeNeeded" is always fully specified as we explicitly use a fallback size if the input size wasn't, so there is no need for checking this. --- src/msw/artmsw.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 4d5c03b6ce..730b5127cd 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -200,8 +200,7 @@ wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id, sizeNeeded); if ( bitmap.IsOk() ) { - if ( sizeNeeded.IsFullySpecified() && - bitmap.GetSize() != sizeNeeded ) + if ( bitmap.GetSize() != sizeNeeded ) { wxArtProvider::RescaleBitmap(bitmap, sizeNeeded); } From 8e740c69cdfe7717a7435cea8a365d839f106fb9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2018 23:09:01 +0100 Subject: [PATCH 08/12] Initialize icon using InitFromHICON() instead of CreateFromHICON() The former avoids an unnecessary call to ::GetIconInfo() done by the latter to retrieve the icon size, as we already have the size here. --- src/msw/artmsw.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 730b5127cd..2fea3339e9 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -93,8 +93,13 @@ MSWGetBitmapFromIconLocation(const TCHAR* path, int index, const wxSize& size) if ( SHDefExtractIcon(path, index, 0, &hIcon, NULL, size.x) != S_OK ) return wxNullBitmap; + // Note that using "size.x" twice here is not a typo: normally size.y is + // the same anyhow, of course, but if it isn't, the actual icon size would + // be size.x in both directions as we only pass "x" to SHDefExtractIcon() + // above. wxIcon icon; - icon.CreateFromHICON((WXHICON)hIcon); + if ( !icon.InitFromHICON((WXHICON)hIcon, size.x, size.x) ) + return wxNullBitmap; wxBitmap bitmap(icon); ::DestroyIcon(hIcon); From 3169524864cab5178cf1106222e64170c866f16d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2018 23:10:07 +0100 Subject: [PATCH 09/12] Don't destroy the HICON returned by SHDefExtractIcon() twice Surprisingly, this doesn't seem to result in any ill effects, but passing HICON to wxIcon already ensures that this HICON will be destroyed in wxIcon dtor, so we shouldn't call ::DestroyIcon() on it manually. --- src/msw/artmsw.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 2fea3339e9..0d49683846 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -101,10 +101,7 @@ MSWGetBitmapFromIconLocation(const TCHAR* path, int index, const wxSize& size) if ( !icon.InitFromHICON((WXHICON)hIcon, size.x, size.x) ) return wxNullBitmap; - wxBitmap bitmap(icon); - ::DestroyIcon(hIcon); - - return bitmap; + return wxBitmap(icon); } wxBitmap From 99247910b940e4f47728c3c73984c393d1dd48d5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 19 Nov 2018 16:12:14 +0100 Subject: [PATCH 10/12] Declare SHDefExtractIcon() if it's missing from (MinGW) headers At least the MinGW 5.3 used for AppVeyor builds doesn't declare this function, so provide its declaration ourselves to fix MinGW build after the recent changes. --- src/msw/artmsw.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 0d49683846..514912d86e 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -31,6 +31,27 @@ #define wxHAS_SHGetStockIconInfo #endif +// MinGW headers don't always define this symbol (up to at least 5.3 version), +// so do it ourselves. +// +// Note that at least there is no need for run-time loading here, as it's +// available since XP. +#ifndef SHDefExtractIcon + +#ifdef UNICODE +extern "C" HRESULT wxSTDCALL +SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, + HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); +#define SHDefExtractIcon SHDefExtractIconW +#else // !UNICODE +extern "C" HRESULT wxSTDCALL +SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags, + HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); +#define SHDefExtractIcon SHDefExtractIconA +#endif // UNICODE/!UNICODE + +#endif // !defined(SHDefExtractIcon) + namespace { From 0308596e924970a384116b838fc21d44e287968c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 19 Nov 2018 16:17:05 +0100 Subject: [PATCH 11/12] Use real email address for Markus Juergens See #18248. --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index f91ded8157..122cdf3c75 100644 --- a/.mailmap +++ b/.mailmap @@ -31,6 +31,7 @@ Lauri Nurmi Lynn C. Rees Maarten Bent Manuel Martin +Markus Juergens Martin Ettl Martin Ettl Martin Ettl From ea28f00cb817cf1fc557f80bae5270be18118d6c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 20 Nov 2018 15:29:43 +0100 Subject: [PATCH 12/12] Do load SHDefExtractIcon() during run-time for old MinGW The problem with MinGW 5.3 is not just due to the missing function declaration in the header, but also due to the function missing from libshell32.a import library, so we do need to load it during run-time, contrary to what the comment in the previous commit said. This should finally fix MinGW build. --- src/msw/artmsw.cpp | 56 ++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/msw/artmsw.cpp b/src/msw/artmsw.cpp index 514912d86e..1d836fd56e 100644 --- a/src/msw/artmsw.cpp +++ b/src/msw/artmsw.cpp @@ -31,30 +31,42 @@ #define wxHAS_SHGetStockIconInfo #endif -// MinGW headers don't always define this symbol (up to at least 5.3 version), -// so do it ourselves. -// -// Note that at least there is no need for run-time loading here, as it's -// available since XP. -#ifndef SHDefExtractIcon - -#ifdef UNICODE -extern "C" HRESULT wxSTDCALL -SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, - HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); -#define SHDefExtractIcon SHDefExtractIconW -#else // !UNICODE -extern "C" HRESULT wxSTDCALL -SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags, - HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); -#define SHDefExtractIcon SHDefExtractIconA -#endif // UNICODE/!UNICODE - -#endif // !defined(SHDefExtractIcon) - namespace { +#ifdef SHDefExtractIcon + #define MSW_SHDefExtractIcon SHDefExtractIcon +#else // !defined(SHDefExtractIcon) + +// MinGW doesn't provide SHDefExtractIcon() up to at least the 5.3 version, so +// define it ourselves. +HRESULT +MSW_SHDefExtractIcon(LPCTSTR pszIconFile, int iIndex, UINT uFlags, + HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) +{ + typedef HRESULT + (WINAPI *SHDefExtractIcon_t)(LPCTSTR, int, UINT, HICON*, HICON*, UINT); + + static SHDefExtractIcon_t s_SHDefExtractIcon = NULL; + if ( !s_SHDefExtractIcon ) + { + wxDynamicLibrary shell32(wxT("shell32.dll")); + wxDL_INIT_FUNC_AW(s_, SHDefExtractIcon, shell32); + + if ( !s_SHDefExtractIcon ) + return E_FAIL; + + // Prevent the DLL from being unloaded while we use its function. + // Normally it's not a problem as shell32.dll is always loaded anyhow. + shell32.Detach(); + } + + return (*s_SHDefExtractIcon)(pszIconFile, iIndex, uFlags, + phiconLarge, phiconSmall, nIconSize); +} + +#endif // !defined(SHDefExtractIcon) + #ifdef wxHAS_SHGetStockIconInfo SHSTOCKICONID MSWGetStockIconIdForArtProviderId(const wxArtID& art_id) @@ -111,7 +123,7 @@ wxBitmap MSWGetBitmapFromIconLocation(const TCHAR* path, int index, const wxSize& size) { HICON hIcon = NULL; - if ( SHDefExtractIcon(path, index, 0, &hIcon, NULL, size.x) != S_OK ) + if ( MSW_SHDefExtractIcon(path, index, 0, &hIcon, NULL, size.x) != S_OK ) return wxNullBitmap; // Note that using "size.x" twice here is not a typo: normally size.y is