1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/artmsw.cpp
3 // Purpose: stock wxArtProvider instance with native MSW stock icons
4 // Author: Vaclav Slavik
7 // Copyright: (c) Vaclav Slavik, 2008
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ---------------------------------------------------------------------------
13 // ---------------------------------------------------------------------------
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
18 #if defined(__BORLANDC__)
22 #include "wx/artprov.h"
24 #include "wx/dynlib.h"
25 #include "wx/volume.h"
26 #include "wx/msw/private.h"
27 #include "wx/msw/wrapwin.h"
30 #define wxHAS_SHGetStockIconInfo
36 #ifdef wxHAS_SHGetStockIconInfo
38 SHSTOCKICONID
MSWGetStockIconIdForArtProviderId(const wxArtID
& art_id
)
40 // try to find an equivalent MSW stock icon id for wxArtID
41 if ( art_id
== wxART_ERROR
) return SIID_ERROR
;
42 else if ( art_id
== wxART_QUESTION
) return SIID_HELP
;
43 else if ( art_id
== wxART_WARNING
) return SIID_WARNING
;
44 else if ( art_id
== wxART_INFORMATION
) return SIID_INFO
;
45 else if ( art_id
== wxART_HELP
) return SIID_HELP
;
46 else if ( art_id
== wxART_FOLDER
) return SIID_FOLDER
;
47 else if ( art_id
== wxART_FOLDER_OPEN
) return SIID_FOLDEROPEN
;
48 else if ( art_id
== wxART_DELETE
) return SIID_DELETE
;
49 else if ( art_id
== wxART_FIND
) return SIID_FIND
;
50 else if ( art_id
== wxART_HARDDISK
) return SIID_DRIVEFIXED
;
51 else if ( art_id
== wxART_FLOPPY
) return SIID_DRIVE35
;
52 else if ( art_id
== wxART_CDROM
) return SIID_DRIVECD
;
53 else if ( art_id
== wxART_REMOVABLE
) return SIID_DRIVEREMOVE
;
59 // try to load SHGetStockIconInfo dynamically, so this code runs
60 // even on pre-Vista Windows versions
62 MSW_SHGetStockIconInfo(SHSTOCKICONID siid
,
64 SHSTOCKICONINFO
*psii
)
66 typedef HRESULT (WINAPI
*PSHGETSTOCKICONINFO
)(SHSTOCKICONID
, UINT
, SHSTOCKICONINFO
*);
67 static PSHGETSTOCKICONINFO pSHGetStockIconInfo
= (PSHGETSTOCKICONINFO
)-1;
69 if ( pSHGetStockIconInfo
== (PSHGETSTOCKICONINFO
)-1 )
71 wxDynamicLibrary
shell32(wxT("shell32.dll"));
73 pSHGetStockIconInfo
= (PSHGETSTOCKICONINFO
)shell32
.RawGetSymbol( wxT("SHGetStockIconInfo") );
76 if ( !pSHGetStockIconInfo
)
79 return pSHGetStockIconInfo(siid
, uFlags
, psii
);
82 #endif // #ifdef wxHAS_SHGetStockIconInfo
85 MSWGetBitmapForPath(const wxString
& path
, const wxSize
& size
, DWORD uFlags
= 0)
90 uFlags
|= SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
;
91 if ( size
!= wxDefaultSize
)
94 uFlags
|= SHGFI_SMALLICON
;
95 else if ( size
.x
>= 64 )
96 uFlags
|= SHGFI_LARGEICON
;
99 if ( !SHGetFileInfo(path
.t_str(), FILE_ATTRIBUTE_DIRECTORY
,
100 &fi
, sizeof(SHFILEINFO
), uFlags
) )
104 icon
.CreateFromHICON((WXHICON
)fi
.hIcon
);
106 wxBitmap
bitmap(icon
);
107 ::DestroyIcon(fi
.hIcon
);
115 GetDriveBitmapForVolumeType(const wxFSVolumeKind
& volKind
, const wxSize
& size
)
117 // get all volumes and try to find one with a matching type
118 wxArrayString volumes
= wxFSVolume::GetVolumes();
119 for ( size_t i
= 0; i
< volumes
.Count(); i
++ )
121 wxFSVolume
vol( volumes
[i
] );
122 if ( vol
.GetKind() == volKind
)
124 return MSWGetBitmapForPath(volumes
[i
], size
);
131 #endif // wxUSE_FSVOLUME
133 } // anonymous namespace
135 // ----------------------------------------------------------------------------
136 // wxWindowsArtProvider
137 // ----------------------------------------------------------------------------
139 class wxWindowsArtProvider
: public wxArtProvider
142 virtual wxBitmap
CreateBitmap(const wxArtID
& id
, const wxArtClient
& client
,
146 static wxBitmap
CreateFromStdIcon(const char *iconName
,
147 const wxArtClient
& client
)
149 wxIcon
icon(iconName
);
151 bmp
.CopyFromIcon(icon
);
154 // The standard native message box icons are in message box size (32x32).
155 // If they are requested in any size other than the default or message
156 // box size, they must be rescaled first.
157 if ( client
!= wxART_MESSAGE_BOX
&& client
!= wxART_OTHER
)
159 const wxSize size
= wxArtProvider::GetNativeSizeHint(client
);
160 if ( size
!= wxDefaultSize
)
162 wxImage img
= bmp
.ConvertToImage();
163 img
.Rescale(size
.x
, size
.y
);
167 #endif // wxUSE_IMAGE
172 wxBitmap
wxWindowsArtProvider::CreateBitmap(const wxArtID
& id
,
173 const wxArtClient
& client
,
178 #ifdef wxHAS_SHGetStockIconInfo
179 // first try to use SHGetStockIconInfo, available only on Vista and higher
180 SHSTOCKICONID stockIconId
= MSWGetStockIconIdForArtProviderId( id
);
181 if ( stockIconId
!= SIID_INVALID
)
183 WinStruct
<SHSTOCKICONINFO
> sii
;
185 UINT uFlags
= SHGSI_ICON
;
186 if ( size
!= wxDefaultSize
)
189 uFlags
|= SHGSI_SMALLICON
;
190 else if ( size
.x
>= 64 )
191 uFlags
|= SHGSI_LARGEICON
;
194 HRESULT res
= MSW_SHGetStockIconInfo(stockIconId
, uFlags
, &sii
);
198 icon
.CreateFromHICON( (WXHICON
)sii
.hIcon
);
200 wxBitmap
bitmap( icon
);
201 ::DestroyIcon(sii
.hIcon
);
207 #endif // wxHAS_SHGetStockIconInfo
211 // now try SHGetFileInfo
212 wxFSVolumeKind volKind
= wxFS_VOL_OTHER
;
213 if ( id
== wxART_HARDDISK
)
214 volKind
= wxFS_VOL_DISK
;
215 else if ( id
== wxART_FLOPPY
)
216 volKind
= wxFS_VOL_FLOPPY
;
217 else if ( id
== wxART_CDROM
)
218 volKind
= wxFS_VOL_CDROM
;
220 if ( volKind
!= wxFS_VOL_OTHER
)
222 bitmap
= GetDriveBitmapForVolumeType(volKind
, size
);
226 #endif // wxUSE_FSVOLUME
228 // notice that the directory used here doesn't need to exist
229 if ( id
== wxART_FOLDER
)
230 bitmap
= MSWGetBitmapForPath("C:\\wxdummydir\\", size
);
231 else if ( id
== wxART_FOLDER_OPEN
)
232 bitmap
= MSWGetBitmapForPath("C:\\wxdummydir\\", size
, SHGFI_OPENICON
);
234 if ( !bitmap
.IsOk() )
236 // handle message box icons specially (wxIcon ctor treat these names
237 // as special cases via wxICOResourceHandler::LoadIcon):
238 const char *name
= NULL
;
239 if ( id
== wxART_ERROR
)
240 name
= "wxICON_ERROR";
241 else if ( id
== wxART_INFORMATION
)
242 name
= "wxICON_INFORMATION";
243 else if ( id
== wxART_WARNING
)
244 name
= "wxICON_WARNING";
245 else if ( id
== wxART_QUESTION
)
246 name
= "wxICON_QUESTION";
249 return CreateFromStdIcon(name
, client
);
252 // for anything else, fall back to generic provider:
256 // ----------------------------------------------------------------------------
257 // wxArtProvider::InitNativeProvider()
258 // ----------------------------------------------------------------------------
260 /*static*/ void wxArtProvider::InitNativeProvider()
262 PushBack(new wxWindowsArtProvider
);
265 // ----------------------------------------------------------------------------
266 // wxArtProvider::GetNativeSizeHint()
267 // ----------------------------------------------------------------------------
270 wxSize
wxArtProvider::GetNativeSizeHint(const wxArtClient
& client
)
272 if ( client
== wxART_TOOLBAR
)
274 return wxSize(24, 24);
276 else if ( client
== wxART_MENU
)
278 return wxSize(16, 16);
280 else if ( client
== wxART_FRAME_ICON
)
282 return wxSize(::GetSystemMetrics(SM_CXSMICON
),
283 ::GetSystemMetrics(SM_CYSMICON
));
285 else if ( client
== wxART_CMN_DIALOG
||
286 client
== wxART_MESSAGE_BOX
)
288 return wxSize(::GetSystemMetrics(SM_CXICON
),
289 ::GetSystemMetrics(SM_CYICON
));
291 else if (client
== wxART_BUTTON
)
293 return wxSize(16, 16);
295 else if (client
== wxART_LIST
)
297 return wxSize(16, 16);
300 return wxDefaultSize
;