]>
Commit | Line | Data |
---|---|---|
0d0512bd VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: msw/gdiimage.cpp | |
3 | // Purpose: wxGDIImage implementation | |
4 | // Author: Vadim Zeitlin | |
5 | // Modified by: | |
6 | // Created: 20.11.99 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> | |
9 | // Licence: wxWindows license | |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
20 | #ifdef __GNUG__ | |
21 | #pragma implementation "gdiimage.h" | |
22 | #endif | |
23 | ||
24 | // For compilers that support precompilation, includes "wx.h". | |
25 | #include "wx/wxprec.h" | |
26 | ||
27 | #ifdef __BORLANDC__ | |
28 | #pragma hdrstop | |
29 | #endif | |
30 | ||
31 | #ifndef WX_PRECOMP | |
32 | #include "wx/string.h" | |
33 | #endif // WX_PRECOMP | |
34 | ||
e42a6c18 VZ |
35 | #include "wx/msw/private.h" |
36 | ||
0d0512bd VZ |
37 | #include "wx/app.h" |
38 | ||
39 | #include "wx/msw/dib.h" | |
c25a510b | 40 | #include "wx/msw/bitmap.h" |
0d0512bd VZ |
41 | #include "wx/msw/gdiimage.h" |
42 | ||
8f177c8e VZ |
43 | #ifdef __WIN16__ |
44 | #include "wx/msw/curico.h" | |
45 | #endif // __WIN16__ | |
46 | ||
0d0512bd VZ |
47 | // ---------------------------------------------------------------------------- |
48 | // private classes | |
49 | // ---------------------------------------------------------------------------- | |
50 | ||
51 | // all image handlers are declared/defined in this file because the outside | |
52 | // world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids) | |
53 | ||
54 | class WXDLLEXPORT wxBMPFileHandler : public wxBitmapHandler | |
55 | { | |
56 | public: | |
57 | wxBMPFileHandler() : wxBitmapHandler(_T("Windows bitmap file"), _T("bmp"), | |
58 | wxBITMAP_TYPE_BMP) | |
59 | { | |
60 | } | |
61 | ||
62 | virtual bool LoadFile(wxBitmap *bitmap, | |
63 | const wxString& name, long flags, | |
64 | int desiredWidth, int desiredHeight); | |
65 | virtual bool SaveFile(wxBitmap *bitmap, | |
66 | const wxString& name, int type, | |
67 | const wxPalette *palette = NULL); | |
68 | ||
69 | private: | |
70 | DECLARE_DYNAMIC_CLASS(wxBMPFileHandler) | |
71 | }; | |
72 | ||
73 | class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler | |
74 | { | |
75 | public: | |
76 | wxBMPResourceHandler() : wxBitmapHandler(_T("Windows bitmap resource"), | |
77 | wxEmptyString, | |
78 | wxBITMAP_TYPE_BMP_RESOURCE) | |
79 | { | |
80 | } | |
81 | ||
82 | virtual bool LoadFile(wxBitmap *bitmap, | |
83 | const wxString& name, long flags, | |
84 | int desiredWidth, int desiredHeight); | |
85 | ||
86 | private: | |
87 | DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler) | |
88 | }; | |
89 | ||
90 | class WXDLLEXPORT wxIconHandler : public wxGDIImageHandler | |
91 | { | |
92 | public: | |
93 | wxIconHandler(const wxString& name, const wxString& ext, long type) | |
94 | : wxGDIImageHandler(name, ext, type) | |
95 | { | |
96 | } | |
97 | ||
98 | // creating and saving icons is not supported | |
99 | virtual bool Create(wxGDIImage *WXUNUSED(image), | |
100 | void *WXUNUSED(data), | |
101 | long WXUNUSED(flags), | |
102 | int WXUNUSED(width), | |
103 | int WXUNUSED(height), | |
104 | int WXUNUSED(depth) = 1) | |
105 | { | |
106 | return FALSE; | |
107 | } | |
108 | ||
109 | virtual bool Save(wxGDIImage *WXUNUSED(image), | |
110 | const wxString& WXUNUSED(name), | |
111 | int WXUNUSED(type)) | |
112 | { | |
113 | return FALSE; | |
114 | } | |
115 | ||
116 | virtual bool Load(wxGDIImage *image, | |
117 | const wxString& name, | |
118 | long flags, | |
119 | int desiredWidth, int desiredHeight) | |
120 | { | |
121 | wxIcon *icon = wxDynamicCast(image, wxIcon); | |
122 | wxCHECK_MSG( icon, FALSE, _T("wxIconHandler only works with icons") ); | |
123 | ||
124 | return LoadIcon(icon, name, flags, desiredWidth, desiredHeight); | |
125 | } | |
126 | ||
127 | protected: | |
128 | virtual bool LoadIcon(wxIcon *icon, | |
129 | const wxString& name, long flags, | |
130 | int desiredWidth = -1, int desiredHeight = -1) = 0; | |
131 | }; | |
132 | ||
133 | class WXDLLEXPORT wxICOFileHandler : public wxIconHandler | |
134 | { | |
135 | public: | |
136 | wxICOFileHandler() : wxIconHandler(_T("ICO icon file"), | |
137 | _T("ico"), | |
138 | wxBITMAP_TYPE_ICO) | |
139 | { | |
140 | } | |
141 | ||
142 | virtual bool LoadIcon(wxIcon *icon, | |
143 | const wxString& name, long flags, | |
144 | int desiredWidth = -1, int desiredHeight = -1); | |
145 | ||
146 | private: | |
147 | DECLARE_DYNAMIC_CLASS(wxICOFileHandler) | |
148 | }; | |
149 | ||
150 | class WXDLLEXPORT wxICOResourceHandler: public wxIconHandler | |
151 | { | |
152 | public: | |
153 | wxICOResourceHandler() : wxIconHandler(_T("ICO resource"), | |
154 | _T("ico"), | |
155 | wxBITMAP_TYPE_ICO_RESOURCE) | |
156 | { | |
157 | } | |
158 | ||
159 | virtual bool LoadIcon(wxIcon *icon, | |
160 | const wxString& name, long flags, | |
161 | int desiredWidth = -1, int desiredHeight = -1); | |
162 | ||
163 | private: | |
164 | DECLARE_DYNAMIC_CLASS(wxICOResourceHandler) | |
165 | }; | |
166 | ||
167 | // ---------------------------------------------------------------------------- | |
168 | // wxWin macros | |
169 | // ---------------------------------------------------------------------------- | |
170 | ||
0d0512bd VZ |
171 | IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler) |
172 | IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler) | |
173 | IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxGDIImageHandler) | |
174 | IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxGDIImageHandler) | |
0d0512bd VZ |
175 | |
176 | // ---------------------------------------------------------------------------- | |
177 | // private functions | |
178 | // ---------------------------------------------------------------------------- | |
179 | ||
180 | static wxSize GetHiconSize(HICON hicon); | |
181 | ||
182 | // ============================================================================ | |
183 | // implementation | |
184 | // ============================================================================ | |
185 | ||
186 | wxList wxGDIImage::ms_handlers; | |
187 | ||
188 | // ---------------------------------------------------------------------------- | |
189 | // wxGDIImage functions forwarded to wxGDIImageRefData | |
190 | // ---------------------------------------------------------------------------- | |
191 | ||
192 | bool wxGDIImage::FreeResource(bool WXUNUSED(force)) | |
193 | { | |
194 | if ( !IsNull() ) | |
195 | { | |
196 | GetGDIImageData()->Free(); | |
197 | GetGDIImageData()->m_handle = 0; | |
198 | } | |
199 | ||
200 | return TRUE; | |
201 | } | |
202 | ||
203 | WXHANDLE wxGDIImage::GetResourceHandle() | |
204 | { | |
205 | return GetHandle(); | |
206 | } | |
207 | ||
208 | // ---------------------------------------------------------------------------- | |
209 | // wxGDIImage handler stuff | |
210 | // ---------------------------------------------------------------------------- | |
211 | ||
212 | void wxGDIImage::AddHandler(wxGDIImageHandler *handler) | |
213 | { | |
214 | ms_handlers.Append(handler); | |
215 | } | |
216 | ||
217 | void wxGDIImage::InsertHandler(wxGDIImageHandler *handler) | |
218 | { | |
219 | ms_handlers.Insert(handler); | |
220 | } | |
221 | ||
222 | bool wxGDIImage::RemoveHandler(const wxString& name) | |
223 | { | |
224 | wxGDIImageHandler *handler = FindHandler(name); | |
225 | if ( handler ) | |
226 | { | |
227 | ms_handlers.DeleteObject(handler); | |
228 | return TRUE; | |
229 | } | |
230 | else | |
231 | return FALSE; | |
232 | } | |
233 | ||
234 | wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name) | |
235 | { | |
236 | wxNode *node = ms_handlers.First(); | |
237 | while ( node ) | |
238 | { | |
239 | wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data(); | |
240 | if ( handler->GetName() == name ) | |
241 | return handler; | |
242 | node = node->Next(); | |
243 | } | |
244 | ||
245 | return NULL; | |
246 | } | |
247 | ||
248 | wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension, | |
249 | long type) | |
250 | { | |
251 | wxNode *node = ms_handlers.First(); | |
252 | while ( node ) | |
253 | { | |
254 | wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data(); | |
255 | if ( (handler->GetExtension() = extension) && | |
256 | (type == -1 || handler->GetType() == type) ) | |
257 | { | |
258 | return handler; | |
259 | } | |
260 | ||
261 | node = node->Next(); | |
262 | } | |
263 | return NULL; | |
264 | } | |
265 | ||
266 | wxGDIImageHandler *wxGDIImage::FindHandler(long type) | |
267 | { | |
268 | wxNode *node = ms_handlers.First(); | |
269 | while ( node ) | |
270 | { | |
271 | wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data(); | |
272 | if ( handler->GetType() == type ) | |
273 | return handler; | |
274 | ||
275 | node = node->Next(); | |
276 | } | |
277 | ||
278 | return NULL; | |
279 | } | |
280 | ||
281 | void wxGDIImage::CleanUpHandlers() | |
282 | { | |
283 | wxNode *node = ms_handlers.First(); | |
284 | while ( node ) | |
285 | { | |
286 | wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data(); | |
287 | wxNode *next = node->Next(); | |
288 | delete handler; | |
289 | delete node; | |
290 | node = next; | |
291 | } | |
292 | } | |
293 | ||
294 | void wxGDIImage::InitStandardHandlers() | |
295 | { | |
296 | AddHandler(new wxBMPResourceHandler); | |
297 | AddHandler(new wxBMPFileHandler); | |
298 | ||
299 | // Not added by default: include xpmhand.h in your app | |
300 | // and call these in your wxApp::OnInit. | |
301 | // AddHandler(new wxXPMFileHandler); | |
302 | // AddHandler(new wxXPMDataHandler); | |
303 | ||
304 | AddHandler(new wxICOResourceHandler); | |
305 | AddHandler(new wxICOFileHandler); | |
306 | } | |
307 | ||
308 | // ---------------------------------------------------------------------------- | |
309 | // wxBitmap handlers | |
310 | // ---------------------------------------------------------------------------- | |
311 | ||
312 | bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, | |
313 | const wxString& name, long WXUNUSED(flags), | |
314 | int WXUNUSED(desiredWidth), | |
315 | int WXUNUSED(desiredHeight)) | |
316 | { | |
317 | // TODO: load colourmap. | |
318 | bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name)); | |
319 | ||
320 | wxBitmapRefData *data = bitmap->GetBitmapData(); | |
321 | if ( bitmap->Ok() ) | |
322 | { | |
323 | BITMAP bm; | |
324 | if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) ) | |
325 | { | |
326 | wxLogLastError("GetObject(HBITMAP)"); | |
327 | } | |
328 | ||
329 | data->m_width = bm.bmWidth; | |
330 | data->m_height = bm.bmHeight; | |
331 | data->m_depth = bm.bmBitsPixel; | |
332 | } | |
333 | else | |
334 | { | |
335 | // it's probably not found | |
336 | wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."), | |
337 | name.c_str()); | |
338 | } | |
339 | ||
340 | return bitmap->Ok(); | |
341 | } | |
342 | ||
343 | bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, | |
344 | const wxString& name, long WXUNUSED(flags), | |
345 | int WXUNUSED(desiredWidth), | |
346 | int WXUNUSED(desiredHeight)) | |
347 | { | |
348 | #if wxUSE_IMAGE_LOADING_IN_MSW | |
349 | wxPalette *palette = NULL; | |
350 | bool success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0; | |
351 | if ( success && palette ) | |
352 | { | |
353 | bitmap->SetPalette(*palette); | |
354 | } | |
355 | ||
356 | // it was copied by the bitmap if it was loaded successfully | |
357 | delete palette; | |
358 | ||
359 | return success; | |
360 | #else | |
361 | return FALSE; | |
362 | #endif | |
363 | } | |
364 | ||
365 | bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, | |
366 | const wxString& name, | |
367 | int WXUNUSED(type), | |
368 | const wxPalette *pal) | |
369 | { | |
370 | #if wxUSE_IMAGE_LOADING_IN_MSW | |
371 | wxPalette *actualPalette = (wxPalette *)pal; | |
372 | if ( !actualPalette ) | |
373 | actualPalette = bitmap->GetPalette(); | |
374 | return wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0; | |
375 | #else | |
376 | return FALSE; | |
377 | #endif | |
378 | } | |
379 | ||
380 | // ---------------------------------------------------------------------------- | |
381 | // wxIcon handlers | |
382 | // ---------------------------------------------------------------------------- | |
383 | ||
384 | bool wxICOFileHandler::LoadIcon(wxIcon *icon, | |
385 | const wxString& name, | |
386 | long flags, | |
387 | int desiredWidth, int desiredHeight) | |
388 | { | |
389 | #if wxUSE_RESOURCE_LOADING_IN_MSW | |
390 | icon->UnRef(); | |
391 | ||
392 | // actual size | |
393 | wxSize size; | |
394 | ||
395 | #ifdef __WIN32__ | |
396 | HICON hicon = ::ExtractIcon(wxGetInstance(), name, 0 /* first */); | |
397 | if ( !hicon ) | |
398 | { | |
399 | wxLogSysError(_T("Failed to load icon from the file '%s'"), | |
400 | name.c_str()); | |
401 | ||
402 | return FALSE; | |
403 | } | |
404 | ||
405 | size = GetHiconSize(hicon); | |
406 | #else // Win16 | |
407 | HICON hicon = ReadIconFile((wxChar *)name.c_str(), | |
408 | wxGetInstance(), | |
409 | &size.x, &size.y); | |
410 | #endif // Win32/Win16 | |
411 | ||
412 | if ( (desiredWidth != -1 && desiredWidth != size.x) || | |
413 | (desiredHeight != -1 && desiredHeight != size.y) ) | |
414 | { | |
415 | wxLogDebug(_T("Returning FALSE from wxICOFileHandler::Load because " | |
416 | "of the size mismatch: actual (%d, %d), " | |
417 | "requested (%d, %d)"), | |
418 | size.x, size.y, | |
419 | desiredWidth, desiredHeight); | |
420 | ||
421 | ::DestroyIcon(hicon); | |
422 | ||
423 | return FALSE; | |
424 | } | |
425 | ||
426 | icon->SetHICON((WXHICON)hicon); | |
427 | icon->SetSize(size.x, size.y); | |
428 | ||
429 | return icon->Ok(); | |
430 | #else | |
431 | return FALSE; | |
432 | #endif | |
433 | } | |
434 | ||
435 | bool wxICOResourceHandler::LoadIcon(wxIcon *icon, | |
436 | const wxString& name, | |
437 | long flags, | |
438 | int desiredWidth, int desiredHeight) | |
439 | { | |
440 | HICON hicon; | |
441 | ||
442 | #if defined(__WIN32__) && !defined(__SC__) | |
443 | if ( desiredWidth != -1 && desiredHeight != -1 ) | |
444 | { | |
445 | hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON, | |
446 | desiredWidth, desiredHeight, | |
447 | LR_DEFAULTCOLOR); | |
448 | } | |
449 | else | |
450 | #endif // Win32 | |
451 | { | |
452 | hicon = ::LoadIcon(wxGetInstance(), name); | |
453 | } | |
454 | ||
455 | wxSize size = GetHiconSize(hicon); | |
456 | icon->SetSize(size.x, size.y); | |
457 | ||
458 | // Override the found values with desired values | |
459 | if ( desiredWidth > -1 && desiredHeight > -1 ) | |
460 | { | |
461 | icon->SetSize(desiredWidth, desiredHeight); | |
462 | } | |
463 | ||
464 | icon->SetHICON((WXHICON)hicon); | |
465 | ||
466 | return icon->Ok(); | |
467 | } | |
468 | ||
469 | // ---------------------------------------------------------------------------- | |
470 | // private functions | |
471 | // ---------------------------------------------------------------------------- | |
472 | ||
473 | static wxSize GetHiconSize(HICON hicon) | |
474 | { | |
475 | wxSize size(32, 32); // default | |
476 | ||
477 | #ifdef __WIN32__ | |
478 | // Win32s doesn't have GetIconInfo function... | |
479 | if ( hicon && wxGetOsVersion() != wxWIN32S ) | |
480 | { | |
481 | ICONINFO info; | |
482 | if ( !::GetIconInfo(hicon, &info) ) | |
483 | { | |
484 | wxLogLastError("GetIconInfo"); | |
485 | } | |
486 | else | |
487 | { | |
488 | HBITMAP hbmp = info.hbmMask; | |
489 | if ( hbmp ) | |
490 | { | |
491 | BITMAP bm; | |
492 | if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) ) | |
493 | { | |
494 | size = wxSize(bm.bmWidth, bm.bmHeight); | |
495 | } | |
496 | ||
497 | ::DeleteObject(info.hbmMask); | |
498 | } | |
499 | if ( info.hbmColor ) | |
500 | ::DeleteObject(info.hbmColor); | |
501 | } | |
502 | } | |
503 | #endif | |
504 | ||
505 | return size; | |
506 | } |