#include "wx/artprov.h"
#include "wx/image.h"
+#include "wx/dynlib.h"
+#include "wx/volume.h"
+#include "wx/msw/private.h"
#include "wx/msw/wrapwin.h"
+#ifdef SHGSI_ICON
+ #define wxHAS_SHGetStockIconInfo
+#endif
+
+namespace
+{
+
+#ifdef wxHAS_SHGetStockIconInfo
+
+SHSTOCKICONID MSWGetStockIconIdForArtProviderId(const wxArtID& art_id)
+{
+ // try to find an equivalent MSW stock icon id for wxArtID
+ if ( art_id == wxART_ERROR) return SIID_ERROR;
+ else if ( art_id == wxART_QUESTION ) return SIID_HELP;
+ else if ( art_id == wxART_WARNING ) return SIID_WARNING;
+ else if ( art_id == wxART_INFORMATION ) return SIID_INFO;
+ else if ( art_id == wxART_HELP ) return SIID_HELP;
+ else if ( art_id == wxART_FOLDER ) return SIID_FOLDER;
+ else if ( art_id == wxART_FOLDER_OPEN ) return SIID_FOLDEROPEN;
+ else if ( art_id == wxART_DELETE ) return SIID_DELETE;
+ else if ( art_id == wxART_FIND ) return SIID_FIND;
+ else if ( art_id == wxART_HARDDISK ) return SIID_DRIVEFIXED;
+ 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;
+
+ return SIID_INVALID;
+};
+
+
+// try to load SHGetStockIconInfo dynamically, so this code runs
+// even on pre-Vista Windows versions
+HRESULT
+MSW_SHGetStockIconInfo(SHSTOCKICONID siid,
+ UINT uFlags,
+ SHSTOCKICONINFO *psii)
+{
+ typedef HRESULT (WINAPI *PSHGETSTOCKICONINFO)(SHSTOCKICONID, UINT, SHSTOCKICONINFO *);
+ static PSHGETSTOCKICONINFO pSHGetStockIconInfo = (PSHGETSTOCKICONINFO)-1;
+
+ if ( pSHGetStockIconInfo == (PSHGETSTOCKICONINFO)-1 )
+ {
+ wxDynamicLibrary shell32(wxT("shell32.dll"));
+
+ pSHGetStockIconInfo = (PSHGETSTOCKICONINFO)shell32.RawGetSymbol( wxT("SHGetStockIconInfo") );
+ }
+
+ if ( !pSHGetStockIconInfo )
+ return E_FAIL;
+
+ return pSHGetStockIconInfo(siid, uFlags, psii);
+}
+
+#endif // #ifdef wxHAS_SHGetStockIconInfo
+
+wxBitmap
+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;
+ }
+
+ if ( !SHGetFileInfo(path.t_str(), FILE_ATTRIBUTE_DIRECTORY,
+ &fi, sizeof(SHFILEINFO), uFlags) )
+ return wxNullBitmap;
+
+ wxIcon icon;
+ icon.CreateFromHICON((WXHICON)fi.hIcon);
+
+ wxBitmap bitmap(icon);
+ ::DestroyIcon(fi.hIcon);
+
+ return bitmap;
+}
+
+#if wxUSE_FSVOLUME
+
+wxBitmap
+GetDriveBitmapForVolumeType(const wxFSVolumeKind& volKind, const wxSize& size)
+{
+ // get all volumes and try to find one with a matching type
+ wxArrayString volumes = wxFSVolume::GetVolumes();
+ for ( size_t i = 0; i < volumes.Count(); i++ )
+ {
+ wxFSVolume vol( volumes[i] );
+ if ( vol.GetKind() == volKind )
+ {
+ return MSWGetBitmapForPath(volumes[i], size);
+ }
+ }
+
+ return wxNullBitmap;
+}
+
+#endif // wxUSE_FSVOLUME
+
+} // anonymous namespace
// ----------------------------------------------------------------------------
// wxWindowsArtProvider
wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id,
const wxArtClient& client,
- const wxSize& WXUNUSED(size))
+ const wxSize& size)
{
- // handle message box icons specially (wxIcon ctor treat these names
- // as special cases via wxICOResourceHandler::LoadIcon):
- const char *name = NULL;
- if ( id == wxART_ERROR )
- name = "wxICON_ERROR";
- else if ( id == wxART_INFORMATION )
- name = "wxICON_INFORMATION";
- else if ( id == wxART_WARNING )
- name = "wxICON_WARNING";
- else if ( id == wxART_QUESTION )
- name = "wxICON_QUESTION";
-
- if ( name )
- return CreateFromStdIcon(name, client);
+ wxBitmap bitmap;
+
+#ifdef wxHAS_SHGetStockIconInfo
+ // first try to use SHGetStockIconInfo, available only on Vista and higher
+ SHSTOCKICONID stockIconId = MSWGetStockIconIdForArtProviderId( id );
+ if ( stockIconId != SIID_INVALID )
+ {
+ WinStruct<SHSTOCKICONINFO> sii;
+
+ UINT uFlags = SHGSI_ICON;
+ if ( size != wxDefaultSize )
+ {
+ if ( size.x <= 16 )
+ uFlags |= SHGSI_SMALLICON;
+ else if ( size.x >= 64 )
+ uFlags |= SHGSI_LARGEICON;
+ }
+
+ HRESULT res = MSW_SHGetStockIconInfo(stockIconId, uFlags, &sii);
+ if ( res == S_OK )
+ {
+ wxIcon icon;
+ icon.CreateFromHICON( (WXHICON)sii.hIcon );
+
+ wxBitmap bitmap( icon );
+ ::DestroyIcon(sii.hIcon);
+
+ if ( bitmap.IsOk() )
+ return bitmap;
+ }
+ }
+#endif // wxHAS_SHGetStockIconInfo
+
+
+#if wxUSE_FSVOLUME
+ // now try SHGetFileInfo
+ wxFSVolumeKind volKind = wxFS_VOL_OTHER;
+ if ( id == wxART_HARDDISK )
+ volKind = wxFS_VOL_DISK;
+ else if ( id == wxART_FLOPPY )
+ volKind = wxFS_VOL_FLOPPY;
+ else if ( id == wxART_CDROM )
+ volKind = wxFS_VOL_CDROM;
+
+ if ( volKind != wxFS_VOL_OTHER )
+ {
+ bitmap = GetDriveBitmapForVolumeType(volKind, size);
+ if ( bitmap.IsOk() )
+ return bitmap;
+ }
+#endif // wxUSE_FSVOLUME
+
+ // notice that the directory used here doesn't need to exist
+ if ( id == wxART_FOLDER )
+ bitmap = MSWGetBitmapForPath("C:\\wxdummydir\\", size );
+ else if ( id == wxART_FOLDER_OPEN )
+ bitmap = MSWGetBitmapForPath("C:\\wxdummydir\\", size, SHGFI_OPENICON );
+
+ if ( !bitmap.IsOk() )
+ {
+ // handle message box icons specially (wxIcon ctor treat these names
+ // as special cases via wxICOResourceHandler::LoadIcon):
+ const char *name = NULL;
+ if ( id == wxART_ERROR )
+ name = "wxICON_ERROR";
+ else if ( id == wxART_INFORMATION )
+ name = "wxICON_INFORMATION";
+ else if ( id == wxART_WARNING )
+ name = "wxICON_WARNING";
+ else if ( id == wxART_QUESTION )
+ name = "wxICON_QUESTION";
+
+ if ( name )
+ return CreateFromStdIcon(name, client);
+ }
// for anything else, fall back to generic provider:
- return wxNullBitmap;
+ return bitmap;
}
// ----------------------------------------------------------------------------