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