1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/artmsw.cpp
3 // Purpose: stock wxArtProvider instance with native MSW stock icons
4 // Author: Vaclav Slavik
8 // Copyright: (c) Vaclav Slavik, 2008
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ---------------------------------------------------------------------------
14 // ---------------------------------------------------------------------------
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
19 #if defined(__BORLANDC__)
23 #include "wx/artprov.h"
25 #include "wx/dynlib.h"
26 #include "wx/volume.h"
27 #include "wx/msw/private.h"
28 #include "wx/msw/wrapwin.h"
31 #define wxHAS_SHGetStockIconInfo
37 #ifdef wxHAS_SHGetStockIconInfo
39 SHSTOCKICONID
MSWGetStockIconIdForArtProviderId(const wxArtID
& art_id
)
41 // try to find an equivalent MSW stock icon id for wxArtID
42 if ( art_id
== wxART_ERROR
) return SIID_ERROR
;
43 else if ( art_id
== wxART_QUESTION
) return SIID_HELP
;
44 else if ( art_id
== wxART_WARNING
) return SIID_WARNING
;
45 else if ( art_id
== wxART_INFORMATION
) return SIID_INFO
;
46 else if ( art_id
== wxART_HELP
) return SIID_HELP
;
47 else if ( art_id
== wxART_FOLDER
) return SIID_FOLDER
;
48 else if ( art_id
== wxART_FOLDER_OPEN
) return SIID_FOLDEROPEN
;
49 else if ( art_id
== wxART_DELETE
) return SIID_DELETE
;
50 else if ( art_id
== wxART_FIND
) return SIID_FIND
;
51 else if ( art_id
== wxART_HARDDISK
) return SIID_DRIVEFIXED
;
52 else if ( art_id
== wxART_FLOPPY
) return SIID_DRIVE35
;
53 else if ( art_id
== wxART_CDROM
) return SIID_DRIVECD
;
54 else if ( art_id
== wxART_REMOVABLE
) return SIID_DRIVEREMOVE
;
60 // try to load SHGetStockIconInfo dynamically, so this code runs
61 // even on pre-Vista Windows versions
63 MSW_SHGetStockIconInfo(SHSTOCKICONID siid
,
65 SHSTOCKICONINFO
*psii
)
67 typedef HRESULT (WINAPI
*PSHGETSTOCKICONINFO
)(SHSTOCKICONID
, UINT
, SHSTOCKICONINFO
*);
68 static PSHGETSTOCKICONINFO pSHGetStockIconInfo
= (PSHGETSTOCKICONINFO
)-1;
70 if ( pSHGetStockIconInfo
== (PSHGETSTOCKICONINFO
)-1 )
72 wxDynamicLibrary
shell32(wxT("shell32.dll"));
74 pSHGetStockIconInfo
= (PSHGETSTOCKICONINFO
)shell32
.RawGetSymbol( wxT("SHGetStockIconInfo") );
77 if ( !pSHGetStockIconInfo
)
80 return pSHGetStockIconInfo(siid
, uFlags
, psii
);
83 #endif // #ifdef wxHAS_SHGetStockIconInfo
86 MSWGetBitmapForPath(const wxString
& path
, const wxSize
& size
, DWORD uFlags
= 0)
91 uFlags
|= SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
;
92 if ( size
!= wxDefaultSize
)
95 uFlags
|= SHGFI_SMALLICON
;
96 else if ( size
.x
>= 64 )
97 uFlags
|= SHGFI_LARGEICON
;
100 if ( !SHGetFileInfo(path
.t_str(), FILE_ATTRIBUTE_DIRECTORY
,
101 &fi
, sizeof(SHFILEINFO
), uFlags
) )
105 icon
.CreateFromHICON((WXHICON
)fi
.hIcon
);
107 wxBitmap
bitmap(icon
);
108 ::DestroyIcon(fi
.hIcon
);
116 GetDriveBitmapForVolumeType(const wxFSVolumeKind
& volKind
, const wxSize
& size
)
118 // get all volumes and try to find one with a matching type
119 wxArrayString volumes
= wxFSVolume::GetVolumes();
120 for ( size_t i
= 0; i
< volumes
.Count(); i
++ )
122 wxFSVolume
vol( volumes
[i
] );
123 if ( vol
.GetKind() == volKind
)
125 return MSWGetBitmapForPath(volumes
[i
], size
);
132 #endif // wxUSE_FSVOLUME
134 } // anonymous namespace
136 // ----------------------------------------------------------------------------
137 // wxWindowsArtProvider
138 // ----------------------------------------------------------------------------
140 class wxWindowsArtProvider
: public wxArtProvider
143 virtual wxBitmap
CreateBitmap(const wxArtID
& id
, const wxArtClient
& client
,
147 static wxBitmap
CreateFromStdIcon(const char *iconName
,
148 const wxArtClient
& client
)
150 wxIcon
icon(iconName
);
152 bmp
.CopyFromIcon(icon
);
155 // The standard native message box icons are in message box size (32x32).
156 // If they are requested in any size other than the default or message
157 // box size, they must be rescaled first.
158 if ( client
!= wxART_MESSAGE_BOX
&& client
!= wxART_OTHER
)
160 const wxSize size
= wxArtProvider::GetNativeSizeHint(client
);
161 if ( size
!= wxDefaultSize
)
163 wxImage img
= bmp
.ConvertToImage();
164 img
.Rescale(size
.x
, size
.y
);
168 #endif // wxUSE_IMAGE
173 wxBitmap
wxWindowsArtProvider::CreateBitmap(const wxArtID
& id
,
174 const wxArtClient
& client
,
179 #ifdef wxHAS_SHGetStockIconInfo
180 // first try to use SHGetStockIconInfo, available only on Vista and higher
181 SHSTOCKICONID stockIconId
= MSWGetStockIconIdForArtProviderId( id
);
182 if ( stockIconId
!= SIID_INVALID
)
184 WinStruct
<SHSTOCKICONINFO
> sii
;
186 UINT uFlags
= SHGSI_ICON
;
187 if ( size
!= wxDefaultSize
)
190 uFlags
|= SHGSI_SMALLICON
;
191 else if ( size
.x
>= 64 )
192 uFlags
|= SHGSI_LARGEICON
;
195 HRESULT res
= MSW_SHGetStockIconInfo(stockIconId
, uFlags
, &sii
);
199 icon
.CreateFromHICON( (WXHICON
)sii
.hIcon
);
201 wxBitmap
bitmap( icon
);
202 ::DestroyIcon(sii
.hIcon
);
208 #endif // wxHAS_SHGetStockIconInfo
212 // now try SHGetFileInfo
213 wxFSVolumeKind volKind
= wxFS_VOL_OTHER
;
214 if ( id
== wxART_HARDDISK
)
215 volKind
= wxFS_VOL_DISK
;
216 else if ( id
== wxART_FLOPPY
)
217 volKind
= wxFS_VOL_FLOPPY
;
218 else if ( id
== wxART_CDROM
)
219 volKind
= wxFS_VOL_CDROM
;
221 if ( volKind
!= wxFS_VOL_OTHER
)
223 bitmap
= GetDriveBitmapForVolumeType(volKind
, size
);
227 #endif // wxUSE_FSVOLUME
229 // notice that the directory used here doesn't need to exist
230 if ( id
== wxART_FOLDER
)
231 bitmap
= MSWGetBitmapForPath("C:\\wxdummydir\\", size
);
232 else if ( id
== wxART_FOLDER_OPEN
)
233 bitmap
= MSWGetBitmapForPath("C:\\wxdummydir\\", size
, SHGFI_OPENICON
);
235 if ( !bitmap
.IsOk() )
237 // handle message box icons specially (wxIcon ctor treat these names
238 // as special cases via wxICOResourceHandler::LoadIcon):
239 const char *name
= NULL
;
240 if ( id
== wxART_ERROR
)
241 name
= "wxICON_ERROR";
242 else if ( id
== wxART_INFORMATION
)
243 name
= "wxICON_INFORMATION";
244 else if ( id
== wxART_WARNING
)
245 name
= "wxICON_WARNING";
246 else if ( id
== wxART_QUESTION
)
247 name
= "wxICON_QUESTION";
250 return CreateFromStdIcon(name
, client
);
253 // for anything else, fall back to generic provider:
257 // ----------------------------------------------------------------------------
258 // wxArtProvider::InitNativeProvider()
259 // ----------------------------------------------------------------------------
261 /*static*/ void wxArtProvider::InitNativeProvider()
263 PushBack(new wxWindowsArtProvider
);
266 // ----------------------------------------------------------------------------
267 // wxArtProvider::GetNativeSizeHint()
268 // ----------------------------------------------------------------------------
271 wxSize
wxArtProvider::GetNativeSizeHint(const wxArtClient
& client
)
273 if ( client
== wxART_TOOLBAR
)
275 return wxSize(24, 24);
277 else if ( client
== wxART_MENU
)
279 return wxSize(16, 16);
281 else if ( client
== wxART_FRAME_ICON
)
283 return wxSize(::GetSystemMetrics(SM_CXSMICON
),
284 ::GetSystemMetrics(SM_CYSMICON
));
286 else if ( client
== wxART_CMN_DIALOG
||
287 client
== wxART_MESSAGE_BOX
)
289 return wxSize(::GetSystemMetrics(SM_CXICON
),
290 ::GetSystemMetrics(SM_CYICON
));
292 else if (client
== wxART_BUTTON
)
294 return wxSize(16, 16);
296 else if (client
== wxART_LIST
)
298 return wxSize(16, 16);
301 return wxDefaultSize
;