Mostly Mingw32/Cygwin corrections
[wxWidgets.git] / src / msw / gdiimage.cpp
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
35 #include "wx/msw/private.h"
36
37 #include "wx/app.h"
38
39 #include "wx/msw/dib.h"
40 #include "wx/msw/bitmap.h"
41 #include "wx/msw/gdiimage.h"
42
43 #ifdef __WIN16__
44 #include "wx/msw/curico.h"
45 #endif // __WIN16__
46
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
171 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
172 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
173 IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxGDIImageHandler)
174 IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxGDIImageHandler)
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 }