]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
SF Patch #728691, dangling pointer fix
[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>
6c9a19aa 9// Licence: wxWindows licence
0d0512bd
VZ
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
f66f0fd7 40#include "wx/bitmap.h"
474df218
VZ
41#include "wx/msw/gdiimage.h"
42#include "wx/msw/dib.h"
f66f0fd7 43
d162a7ee
VZ
44#include "wx/listimpl.cpp"
45WX_DEFINE_LIST(wxGDIImageHandlerList);
46
0d0512bd
VZ
47// ----------------------------------------------------------------------------
48// private classes
49// ----------------------------------------------------------------------------
50
04ef50df
JS
51#ifndef __WXMICROWIN__
52
0d0512bd
VZ
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 {
4f8090e0 108 return false;
0d0512bd
VZ
109 }
110
111 virtual bool Save(wxGDIImage *WXUNUSED(image),
112 const wxString& WXUNUSED(name),
113 int WXUNUSED(type))
114 {
4f8090e0 115 return false;
0d0512bd
VZ
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);
4f8090e0 124 wxCHECK_MSG( icon, false, _T("wxIconHandler only works with icons") );
0d0512bd
VZ
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
621b3e21
VZ
173IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
174IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
175IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxObject)
176IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxObject)
0d0512bd
VZ
177
178// ----------------------------------------------------------------------------
179// private functions
180// ----------------------------------------------------------------------------
181
04ef50df
JS
182#endif
183 // __MICROWIN__
0d0512bd
VZ
184
185// ============================================================================
186// implementation
187// ============================================================================
188
d162a7ee 189wxGDIImageHandlerList wxGDIImage::ms_handlers;
0d0512bd
VZ
190
191// ----------------------------------------------------------------------------
192// wxGDIImage functions forwarded to wxGDIImageRefData
193// ----------------------------------------------------------------------------
194
195bool wxGDIImage::FreeResource(bool WXUNUSED(force))
196{
197 if ( !IsNull() )
198 {
199 GetGDIImageData()->Free();
200 GetGDIImageData()->m_handle = 0;
201 }
202
4f8090e0 203 return true;
0d0512bd
VZ
204}
205
2b5f62a0 206WXHANDLE wxGDIImage::GetResourceHandle() const
0d0512bd
VZ
207{
208 return GetHandle();
209}
210
211// ----------------------------------------------------------------------------
212// wxGDIImage handler stuff
213// ----------------------------------------------------------------------------
214
215void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
216{
217 ms_handlers.Append(handler);
218}
219
220void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
221{
222 ms_handlers.Insert(handler);
223}
224
225bool wxGDIImage::RemoveHandler(const wxString& name)
226{
227 wxGDIImageHandler *handler = FindHandler(name);
228 if ( handler )
229 {
230 ms_handlers.DeleteObject(handler);
4f8090e0 231 return true;
0d0512bd
VZ
232 }
233 else
4f8090e0 234 return false;
0d0512bd
VZ
235}
236
237wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
238{
d162a7ee 239 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
240 while ( node )
241 {
d162a7ee 242 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
243 if ( handler->GetName() == name )
244 return handler;
4f8090e0 245 node = node->GetNext();
0d0512bd
VZ
246 }
247
248 return NULL;
249}
250
251wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
252 long type)
253{
d162a7ee 254 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
255 while ( node )
256 {
d162a7ee 257 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
258 if ( (handler->GetExtension() = extension) &&
259 (type == -1 || handler->GetType() == type) )
260 {
261 return handler;
262 }
263
4f8090e0 264 node = node->GetNext();
0d0512bd
VZ
265 }
266 return NULL;
267}
268
269wxGDIImageHandler *wxGDIImage::FindHandler(long type)
270{
d162a7ee 271 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
272 while ( node )
273 {
d162a7ee 274 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
275 if ( handler->GetType() == type )
276 return handler;
277
4f8090e0 278 node = node->GetNext();
0d0512bd
VZ
279 }
280
281 return NULL;
282}
283
284void wxGDIImage::CleanUpHandlers()
285{
d162a7ee 286 wxGDIImageHandlerList::Node *node = ms_handlers.GetFirst();
0d0512bd
VZ
287 while ( node )
288 {
d162a7ee
VZ
289 wxGDIImageHandler *handler = node->GetData();
290 wxGDIImageHandlerList::Node *next = node->GetNext();
0d0512bd
VZ
291 delete handler;
292 delete node;
293 node = next;
294 }
295}
296
297void wxGDIImage::InitStandardHandlers()
298{
04ef50df 299#ifndef __WXMICROWIN__
0d0512bd
VZ
300 AddHandler(new wxBMPResourceHandler);
301 AddHandler(new wxBMPFileHandler);
0d0512bd
VZ
302 AddHandler(new wxICOResourceHandler);
303 AddHandler(new wxICOFileHandler);
04ef50df 304#endif
0d0512bd
VZ
305}
306
04ef50df
JS
307#ifndef __WXMICROWIN__
308
0d0512bd
VZ
309// ----------------------------------------------------------------------------
310// wxBitmap handlers
311// ----------------------------------------------------------------------------
312
313bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
314 const wxString& name, long WXUNUSED(flags),
315 int WXUNUSED(desiredWidth),
316 int WXUNUSED(desiredHeight))
317{
318 // TODO: load colourmap.
319 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name));
320
8bbbae21 321 if ( !bitmap->Ok() )
0d0512bd
VZ
322 {
323 // it's probably not found
324 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
325 name.c_str());
8bbbae21 326
4f8090e0 327 return false;
8bbbae21
VZ
328 }
329
330 BITMAP bm;
331 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
332 {
333 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
334 }
335
8bbbae21
VZ
336 bitmap->SetWidth(bm.bmWidth);
337 bitmap->SetHeight(bm.bmHeight);
338 bitmap->SetDepth(bm.bmBitsPixel);
339
4f8090e0 340 return true;
0d0512bd
VZ
341}
342
343bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
344 const wxString& name, long WXUNUSED(flags),
345 int WXUNUSED(desiredWidth),
346 int WXUNUSED(desiredHeight))
347{
474df218 348 wxCHECK_MSG( bitmap, false, _T("NULL bitmap in LoadFile") );
d275c7eb 349
474df218 350 wxDIB dib(name);
0d0512bd 351
474df218 352 return dib.IsOk() && bitmap->CopyFromDIB(dib);
0d0512bd
VZ
353}
354
355bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap,
356 const wxString& name,
357 int WXUNUSED(type),
2b254edf 358 const wxPalette * WXUNUSED(pal))
0d0512bd 359{
2b254edf
VZ
360 wxCHECK_MSG( bitmap, false, _T("NULL bitmap in SaveFile") );
361
362 wxDIB dib(*bitmap);
363
364 return dib.Save(name);
0d0512bd
VZ
365}
366
367// ----------------------------------------------------------------------------
368// wxIcon handlers
369// ----------------------------------------------------------------------------
370
371bool wxICOFileHandler::LoadIcon(wxIcon *icon,
372 const wxString& name,
33ac7e6f 373 long WXUNUSED(flags),
0d0512bd
VZ
374 int desiredWidth, int desiredHeight)
375{
4ce1efe1
CE
376#ifdef __DIGITALMARS__
377//FIXME __DIGITALMARS__ April 2003 CE
378 // why no ExtractIcon in library
379 wxLogTrace(_T("iconload"),
380 _T("Returning false from wxICOFileHandler::Load because of DigitalMars compiler bug"));
381
382 return false;
383#else
0d0512bd
VZ
384 icon->UnRef();
385
386 // actual size
387 wxSize size;
388
a4352768
VZ
389 HICON hicon = NULL;
390
2dace059
VZ
391 // Parse the filename: it may be of the form "filename;n" in order to
392 // specify the nth icon in the file.
393 //
394 // For the moment, ignore the issue of possible semicolons in the
395 // filename.
ff9aab3c 396 int iconIndex = 0;
2dace059 397 wxString nameReal(name);
ff9aab3c 398 wxString strIconIndex = name.AfterLast(wxT(';'));
b642d457 399 if (strIconIndex != name)
ff9aab3c
JS
400 {
401 iconIndex = wxAtoi(strIconIndex);
2dace059 402 nameReal = name.BeforeLast(wxT(';'));
ff9aab3c
JS
403 }
404
2b5f62a0
VZ
405#if 0
406 // If we don't know what size icon we're looking for,
407 // try to find out what's there.
408 // Unfortunately this doesn't work, because ExtractIconEx
409 // will scale the icon to the 'desired' size, even if that
410 // size of icon isn't explicitly stored. So we would have
411 // to parse the icon file outselves.
412 if ( desiredWidth == -1 &&
413 desiredHeight == -1)
414 {
415 // Try loading a large icon first
416 if ( ::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) == 1)
417 {
418 }
419 // Then try loading a small icon
420 else if ( ::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) == 1)
421 {
422 }
423 }
424 else
425#endif
a4352768
VZ
426 // were we asked for a large icon?
427 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
428 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
429 {
ff9aab3c 430 // get the specified large icon from file
2dace059 431 if ( !::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) )
a4352768
VZ
432 {
433 // it is not an error, but it might still be useful to be informed
434 // about it optionally
435 wxLogTrace(_T("iconload"),
436 _T("No large icons found in the file '%s'."),
437 name.c_str());
438 }
439 }
440 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
441 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
442 {
ff9aab3c 443 // get the specified small icon from file
2dace059 444 if ( !::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) )
a4352768
VZ
445 {
446 wxLogTrace(_T("iconload"),
447 _T("No small icons found in the file '%s'."),
448 name.c_str());
449 }
450 }
451 //else: not standard size, load below
452
453 if ( !hicon )
454 {
d8f3f983
RD
455 // take any size icon from the file by index
456 hicon = ::ExtractIcon(wxGetInstance(), nameReal, iconIndex);
a4352768
VZ
457 }
458
0d0512bd
VZ
459 if ( !hicon )
460 {
461 wxLogSysError(_T("Failed to load icon from the file '%s'"),
462 name.c_str());
463
4f8090e0 464 return false;
0d0512bd
VZ
465 }
466
6bad4c32 467 size = wxGetHiconSize(hicon);
0d0512bd
VZ
468
469 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
470 (desiredHeight != -1 && desiredHeight != size.y) )
471 {
a4352768 472 wxLogTrace(_T("iconload"),
4f8090e0 473 _T("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
a4352768
VZ
474 size.x, size.y,
475 desiredWidth, desiredHeight);
0d0512bd
VZ
476
477 ::DestroyIcon(hicon);
478
4f8090e0 479 return false;
0d0512bd
VZ
480 }
481
482 icon->SetHICON((WXHICON)hicon);
483 icon->SetSize(size.x, size.y);
484
485 return icon->Ok();
4ce1efe1 486#endif // Digitalmars
0d0512bd
VZ
487}
488
489bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
490 const wxString& name,
33ac7e6f 491 long WXUNUSED(flags),
0d0512bd
VZ
492 int desiredWidth, int desiredHeight)
493{
494 HICON hicon;
495
9cb9fdb3
VZ
496 // do we need the icon of the specific size or would any icon do?
497 bool hasSize = desiredWidth != -1 || desiredHeight != -1;
498
499 wxASSERT_MSG( !hasSize || (desiredWidth != -1 && desiredHeight != -1),
500 _T("width and height should be either both -1 or not") );
501
2dace059
VZ
502 // try to load the icon from this program first to allow overriding the
503 // standard icons (although why one would want to do it considering that
504 // we already have wxApp::GetStdIcon() is unclear)
9990cb50
VZ
505
506 // note that we can't just always call LoadImage() because it seems to do
507 // some icon rescaling internally which results in very ugly 16x16 icons
9990cb50 508 if ( hasSize )
0d0512bd 509 {
9990cb50
VZ
510 hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON,
511 desiredWidth, desiredHeight,
512 LR_DEFAULTCOLOR);
0d0512bd 513 }
9990cb50 514 else
9990cb50
VZ
515 {
516 hicon = ::LoadIcon(wxGetInstance(), name);
517 }
fea2b62e 518
2dace059 519 // next check if it's not a standard icon
9cb9fdb3 520 if ( !hicon && !hasSize )
2dace059
VZ
521 {
522 static const struct
523 {
524 const wxChar *name;
525 LPTSTR id;
526 } stdIcons[] =
527 {
528 { wxT("wxICON_QUESTION"), IDI_QUESTION },
529 { wxT("wxICON_WARNING"), IDI_EXCLAMATION },
530 { wxT("wxICON_ERROR"), IDI_HAND },
c2edb18a 531 { wxT("wxICON_INFORMATION"), IDI_ASTERISK },
2dace059
VZ
532 };
533
534 for ( size_t nIcon = 0; !hicon && nIcon < WXSIZEOF(stdIcons); nIcon++ )
535 {
536 if ( name == stdIcons[nIcon].name )
537 {
9cb9fdb3 538 hicon = ::LoadIcon((HINSTANCE)NULL, stdIcons[nIcon].id);
2dace059
VZ
539 }
540 }
541 }
542
6bad4c32 543 wxSize size = wxGetHiconSize(hicon);
0d0512bd
VZ
544 icon->SetSize(size.x, size.y);
545
0d0512bd
VZ
546 icon->SetHICON((WXHICON)hicon);
547
548 return icon->Ok();
549}
550
551// ----------------------------------------------------------------------------
552// private functions
553// ----------------------------------------------------------------------------
554
6bad4c32 555wxSize wxGetHiconSize(HICON hicon)
0d0512bd
VZ
556{
557 wxSize size(32, 32); // default
558
0d0512bd
VZ
559 if ( hicon && wxGetOsVersion() != wxWIN32S )
560 {
561 ICONINFO info;
562 if ( !::GetIconInfo(hicon, &info) )
563 {
f6bcfd97 564 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
565 }
566 else
567 {
568 HBITMAP hbmp = info.hbmMask;
569 if ( hbmp )
570 {
571 BITMAP bm;
572 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
573 {
574 size = wxSize(bm.bmWidth, bm.bmHeight);
575 }
576
577 ::DeleteObject(info.hbmMask);
578 }
579 if ( info.hbmColor )
580 ::DeleteObject(info.hbmColor);
581 }
582 }
0d0512bd
VZ
583
584 return size;
585}
474df218
VZ
586
587#endif // __WXMICROWIN__
588