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