Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / src / msw / artmsw.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/artmsw.cpp
3 // Purpose: stock wxArtProvider instance with native MSW stock icons
4 // Author: Vaclav Slavik
5 // Modified by:
6 // Created: 2008-10-15
7 // Copyright: (c) Vaclav Slavik, 2008
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ---------------------------------------------------------------------------
12 // headers
13 // ---------------------------------------------------------------------------
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #if defined(__BORLANDC__)
19 #pragma hdrstop
20 #endif
21
22 #include "wx/artprov.h"
23 #include "wx/image.h"
24 #include "wx/dynlib.h"
25 #include "wx/volume.h"
26 #include "wx/msw/private.h"
27 #include "wx/msw/wrapwin.h"
28
29 #ifdef SHGSI_ICON
30 #define wxHAS_SHGetStockIconInfo
31 #endif
32
33 namespace
34 {
35
36 #ifdef wxHAS_SHGetStockIconInfo
37
38 SHSTOCKICONID MSWGetStockIconIdForArtProviderId(const wxArtID& art_id)
39 {
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;
54
55 return SIID_INVALID;
56 };
57
58
59 // try to load SHGetStockIconInfo dynamically, so this code runs
60 // even on pre-Vista Windows versions
61 HRESULT
62 MSW_SHGetStockIconInfo(SHSTOCKICONID siid,
63 UINT uFlags,
64 SHSTOCKICONINFO *psii)
65 {
66 typedef HRESULT (WINAPI *PSHGETSTOCKICONINFO)(SHSTOCKICONID, UINT, SHSTOCKICONINFO *);
67 static PSHGETSTOCKICONINFO pSHGetStockIconInfo = (PSHGETSTOCKICONINFO)-1;
68
69 if ( pSHGetStockIconInfo == (PSHGETSTOCKICONINFO)-1 )
70 {
71 wxDynamicLibrary shell32(wxT("shell32.dll"));
72
73 pSHGetStockIconInfo = (PSHGETSTOCKICONINFO)shell32.RawGetSymbol( wxT("SHGetStockIconInfo") );
74 }
75
76 if ( !pSHGetStockIconInfo )
77 return E_FAIL;
78
79 return pSHGetStockIconInfo(siid, uFlags, psii);
80 }
81
82 #endif // #ifdef wxHAS_SHGetStockIconInfo
83
84 wxBitmap
85 MSWGetBitmapForPath(const wxString& path, const wxSize& size, DWORD uFlags = 0)
86 {
87 SHFILEINFO fi;
88 wxZeroMemory(fi);
89
90 uFlags |= SHGFI_USEFILEATTRIBUTES | SHGFI_ICON;
91 if ( size != wxDefaultSize )
92 {
93 if ( size.x <= 16 )
94 uFlags |= SHGFI_SMALLICON;
95 else if ( size.x >= 64 )
96 uFlags |= SHGFI_LARGEICON;
97 }
98
99 if ( !SHGetFileInfo(path.t_str(), FILE_ATTRIBUTE_DIRECTORY,
100 &fi, sizeof(SHFILEINFO), uFlags) )
101 return wxNullBitmap;
102
103 wxIcon icon;
104 icon.CreateFromHICON((WXHICON)fi.hIcon);
105
106 wxBitmap bitmap(icon);
107 ::DestroyIcon(fi.hIcon);
108
109 return bitmap;
110 }
111
112 #if wxUSE_FSVOLUME
113
114 wxBitmap
115 GetDriveBitmapForVolumeType(const wxFSVolumeKind& volKind, const wxSize& size)
116 {
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++ )
120 {
121 wxFSVolume vol( volumes[i] );
122 if ( vol.GetKind() == volKind )
123 {
124 return MSWGetBitmapForPath(volumes[i], size);
125 }
126 }
127
128 return wxNullBitmap;
129 }
130
131 #endif // wxUSE_FSVOLUME
132
133 } // anonymous namespace
134
135 // ----------------------------------------------------------------------------
136 // wxWindowsArtProvider
137 // ----------------------------------------------------------------------------
138
139 class wxWindowsArtProvider : public wxArtProvider
140 {
141 protected:
142 virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client,
143 const wxSize& size);
144 };
145
146 static wxBitmap CreateFromStdIcon(const char *iconName,
147 const wxArtClient& client)
148 {
149 wxIcon icon(iconName);
150 wxBitmap bmp;
151 bmp.CopyFromIcon(icon);
152
153 #if wxUSE_IMAGE
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 )
158 {
159 const wxSize size = wxArtProvider::GetNativeSizeHint(client);
160 if ( size != wxDefaultSize )
161 {
162 wxImage img = bmp.ConvertToImage();
163 img.Rescale(size.x, size.y);
164 bmp = wxBitmap(img);
165 }
166 }
167 #endif // wxUSE_IMAGE
168
169 return bmp;
170 }
171
172 wxBitmap wxWindowsArtProvider::CreateBitmap(const wxArtID& id,
173 const wxArtClient& client,
174 const wxSize& size)
175 {
176 wxBitmap bitmap;
177
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 )
182 {
183 WinStruct<SHSTOCKICONINFO> sii;
184
185 UINT uFlags = SHGSI_ICON;
186 if ( size != wxDefaultSize )
187 {
188 if ( size.x <= 16 )
189 uFlags |= SHGSI_SMALLICON;
190 else if ( size.x >= 64 )
191 uFlags |= SHGSI_LARGEICON;
192 }
193
194 HRESULT res = MSW_SHGetStockIconInfo(stockIconId, uFlags, &sii);
195 if ( res == S_OK )
196 {
197 wxIcon icon;
198 icon.CreateFromHICON( (WXHICON)sii.hIcon );
199
200 wxBitmap bitmap( icon );
201 ::DestroyIcon(sii.hIcon);
202
203 if ( bitmap.IsOk() )
204 return bitmap;
205 }
206 }
207 #endif // wxHAS_SHGetStockIconInfo
208
209
210 #if wxUSE_FSVOLUME
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;
219
220 if ( volKind != wxFS_VOL_OTHER )
221 {
222 bitmap = GetDriveBitmapForVolumeType(volKind, size);
223 if ( bitmap.IsOk() )
224 return bitmap;
225 }
226 #endif // wxUSE_FSVOLUME
227
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 );
233
234 if ( !bitmap.IsOk() )
235 {
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";
247
248 if ( name )
249 return CreateFromStdIcon(name, client);
250 }
251
252 // for anything else, fall back to generic provider:
253 return bitmap;
254 }
255
256 // ----------------------------------------------------------------------------
257 // wxArtProvider::InitNativeProvider()
258 // ----------------------------------------------------------------------------
259
260 /*static*/ void wxArtProvider::InitNativeProvider()
261 {
262 PushBack(new wxWindowsArtProvider);
263 }
264
265 // ----------------------------------------------------------------------------
266 // wxArtProvider::GetNativeSizeHint()
267 // ----------------------------------------------------------------------------
268
269 /*static*/
270 wxSize wxArtProvider::GetNativeSizeHint(const wxArtClient& client)
271 {
272 if ( client == wxART_TOOLBAR )
273 {
274 return wxSize(24, 24);
275 }
276 else if ( client == wxART_MENU )
277 {
278 return wxSize(16, 16);
279 }
280 else if ( client == wxART_FRAME_ICON )
281 {
282 return wxSize(::GetSystemMetrics(SM_CXSMICON),
283 ::GetSystemMetrics(SM_CYSMICON));
284 }
285 else if ( client == wxART_CMN_DIALOG ||
286 client == wxART_MESSAGE_BOX )
287 {
288 return wxSize(::GetSystemMetrics(SM_CXICON),
289 ::GetSystemMetrics(SM_CYICON));
290 }
291 else if (client == wxART_BUTTON)
292 {
293 return wxSize(16, 16);
294 }
295 else if (client == wxART_LIST)
296 {
297 return wxSize(16, 16);
298 }
299
300 return wxDefaultSize;
301 }