1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/gdiimage.cpp
3 // Purpose: wxGDIImage implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
31 #include "wx/bitmap.h"
34 #include "wx/msw/private.h"
36 #include "wx/msw/gdiimage.h"
39 #include "wx/msw/dib.h"
42 // By default, use PNG resource handler if we can, i.e. have support for
43 // loading PNG images in the library. This symbol could be predefined as 0 to
44 // avoid doing this if anybody ever needs to do it for some reason.
45 #if !defined(wxUSE_PNG_RESOURCE_HANDLER) && wxUSE_LIBPNG && wxUSE_IMAGE
46 #define wxUSE_PNG_RESOURCE_HANDLER 1
49 #if wxUSE_PNG_RESOURCE_HANDLER
51 #include "wx/utils.h" // For wxLoadUserResource()
61 #include "wx/listimpl.cpp"
62 WX_DEFINE_LIST(wxGDIImageHandlerList
)
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 #ifndef __WXMICROWIN__
70 // all image handlers are declared/defined in this file because the outside
71 // world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
73 class WXDLLEXPORT wxBMPFileHandler
: public wxBitmapHandler
76 wxBMPFileHandler() : wxBitmapHandler(wxT("Windows bitmap file"), wxT("bmp"),
81 virtual bool LoadFile(wxBitmap
*bitmap
,
82 const wxString
& name
, wxBitmapType flags
,
83 int desiredWidth
, int desiredHeight
);
84 virtual bool SaveFile(const wxBitmap
*bitmap
,
85 const wxString
& name
, wxBitmapType type
,
86 const wxPalette
*palette
= NULL
) const;
89 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
)
92 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
95 wxBMPResourceHandler() : wxBitmapHandler(wxT("Windows bitmap resource"),
97 wxBITMAP_TYPE_BMP_RESOURCE
)
101 virtual bool LoadFile(wxBitmap
*bitmap
,
102 const wxString
& name
, wxBitmapType flags
,
103 int desiredWidth
, int desiredHeight
);
106 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
)
109 class WXDLLEXPORT wxIconHandler
: public wxGDIImageHandler
112 wxIconHandler(const wxString
& name
, const wxString
& ext
, wxBitmapType type
)
113 : wxGDIImageHandler(name
, ext
, type
)
117 // creating and saving icons is not supported
118 virtual bool Create(wxGDIImage
*WXUNUSED(image
),
119 const void* WXUNUSED(data
),
120 wxBitmapType
WXUNUSED(flags
),
122 int WXUNUSED(height
),
123 int WXUNUSED(depth
) = 1)
128 virtual bool Save(const wxGDIImage
*WXUNUSED(image
),
129 const wxString
& WXUNUSED(name
),
130 wxBitmapType
WXUNUSED(type
)) const
135 virtual bool Load(wxGDIImage
*image
,
136 const wxString
& name
,
138 int desiredWidth
, int desiredHeight
)
140 wxIcon
*icon
= wxDynamicCast(image
, wxIcon
);
141 wxCHECK_MSG( icon
, false, wxT("wxIconHandler only works with icons") );
143 return LoadIcon(icon
, name
, flags
, desiredWidth
, desiredHeight
);
147 virtual bool LoadIcon(wxIcon
*icon
,
148 const wxString
& name
, wxBitmapType flags
,
149 int desiredWidth
= -1, int desiredHeight
= -1) = 0;
152 class WXDLLEXPORT wxICOFileHandler
: public wxIconHandler
155 wxICOFileHandler() : wxIconHandler(wxT("ICO icon file"),
162 virtual bool LoadIcon(wxIcon
*icon
,
163 const wxString
& name
, wxBitmapType flags
,
164 int desiredWidth
= -1, int desiredHeight
= -1);
167 DECLARE_DYNAMIC_CLASS(wxICOFileHandler
)
170 class WXDLLEXPORT wxICOResourceHandler
: public wxIconHandler
173 wxICOResourceHandler() : wxIconHandler(wxT("ICO resource"),
175 wxBITMAP_TYPE_ICO_RESOURCE
)
180 virtual bool LoadIcon(wxIcon
*icon
,
181 const wxString
& name
, wxBitmapType flags
,
182 int desiredWidth
= -1, int desiredHeight
= -1);
185 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler
)
188 #if wxUSE_PNG_RESOURCE_HANDLER
190 class WXDLLEXPORT wxPNGResourceHandler
: public wxBitmapHandler
193 wxPNGResourceHandler() : wxBitmapHandler(wxS("Windows PNG resource"),
195 wxBITMAP_TYPE_PNG_RESOURCE
)
199 virtual bool LoadFile(wxBitmap
*bitmap
,
200 const wxString
& name
, wxBitmapType flags
,
201 int desiredWidth
, int desiredHeight
);
204 wxDECLARE_DYNAMIC_CLASS(wxPNGResourceHandler
);
207 #endif // wxUSE_PNG_RESOURCE_HANDLER
209 // ----------------------------------------------------------------------------
211 // ----------------------------------------------------------------------------
213 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
)
214 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
)
215 IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler
, wxObject
)
216 IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler
, wxObject
)
217 #if wxUSE_PNG_RESOURCE_HANDLER
218 IMPLEMENT_DYNAMIC_CLASS(wxPNGResourceHandler
, wxBitmapHandler
)
219 #endif // wxUSE_PNG_RESOURCE_HANDLER
221 // ----------------------------------------------------------------------------
223 // ----------------------------------------------------------------------------
228 // ============================================================================
230 // ============================================================================
232 wxGDIImageHandlerList
wxGDIImage::ms_handlers
;
234 // ----------------------------------------------------------------------------
235 // wxGDIImage functions forwarded to wxGDIImageRefData
236 // ----------------------------------------------------------------------------
238 bool wxGDIImage::FreeResource(bool WXUNUSED(force
))
242 GetGDIImageData()->Free();
243 GetGDIImageData()->m_handle
= 0;
249 WXHANDLE
wxGDIImage::GetResourceHandle() const
254 // ----------------------------------------------------------------------------
255 // wxGDIImage handler stuff
256 // ----------------------------------------------------------------------------
258 void wxGDIImage::AddHandler(wxGDIImageHandler
*handler
)
260 ms_handlers
.Append(handler
);
263 void wxGDIImage::InsertHandler(wxGDIImageHandler
*handler
)
265 ms_handlers
.Insert(handler
);
268 bool wxGDIImage::RemoveHandler(const wxString
& name
)
270 wxGDIImageHandler
*handler
= FindHandler(name
);
273 ms_handlers
.DeleteObject(handler
);
280 wxGDIImageHandler
*wxGDIImage::FindHandler(const wxString
& name
)
282 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
285 wxGDIImageHandler
*handler
= node
->GetData();
286 if ( handler
->GetName() == name
)
288 node
= node
->GetNext();
294 wxGDIImageHandler
*wxGDIImage::FindHandler(const wxString
& extension
,
297 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
300 wxGDIImageHandler
*handler
= node
->GetData();
301 if ( (handler
->GetExtension() == extension
) &&
302 (type
== -1 || handler
->GetType() == type
) )
307 node
= node
->GetNext();
312 wxGDIImageHandler
*wxGDIImage::FindHandler(long type
)
314 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
317 wxGDIImageHandler
*handler
= node
->GetData();
318 if ( handler
->GetType() == type
)
321 node
= node
->GetNext();
327 void wxGDIImage::CleanUpHandlers()
329 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
332 wxGDIImageHandler
*handler
= node
->GetData();
333 wxGDIImageHandlerList::compatibility_iterator next
= node
->GetNext();
335 ms_handlers
.Erase( node
);
340 void wxGDIImage::InitStandardHandlers()
342 #ifndef __WXMICROWIN__
343 AddHandler(new wxBMPResourceHandler
);
344 AddHandler(new wxBMPFileHandler
);
345 AddHandler(new wxICOFileHandler
);
346 AddHandler(new wxICOResourceHandler
);
347 #if wxUSE_PNG_RESOURCE_HANDLER
348 AddHandler(new wxPNGResourceHandler
);
349 #endif // wxUSE_PNG_RESOURCE_HANDLER
353 #ifndef __WXMICROWIN__
355 // ----------------------------------------------------------------------------
357 // ----------------------------------------------------------------------------
359 bool wxBMPResourceHandler::LoadFile(wxBitmap
*bitmap
,
360 const wxString
& name
, wxBitmapType
WXUNUSED(flags
),
361 int WXUNUSED(desiredWidth
),
362 int WXUNUSED(desiredHeight
))
364 // TODO: load colourmap.
365 bitmap
->SetHBITMAP((WXHBITMAP
)::LoadBitmap(wxGetInstance(), name
.t_str()));
367 if ( !bitmap
->IsOk() )
369 // it's probably not found
370 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
377 if ( !::GetObject(GetHbitmapOf(*bitmap
), sizeof(BITMAP
), (LPSTR
) &bm
) )
379 wxLogLastError(wxT("GetObject(HBITMAP)"));
382 bitmap
->SetWidth(bm
.bmWidth
);
383 bitmap
->SetHeight(bm
.bmHeight
);
384 bitmap
->SetDepth(bm
.bmBitsPixel
);
386 // use 0xc0c0c0 as transparent colour by default
387 bitmap
->SetMask(new wxMask(*bitmap
, *wxLIGHT_GREY
));
392 bool wxBMPFileHandler::LoadFile(wxBitmap
*bitmap
,
393 const wxString
& name
, wxBitmapType
WXUNUSED(flags
),
394 int WXUNUSED(desiredWidth
),
395 int WXUNUSED(desiredHeight
))
398 wxCHECK_MSG( bitmap
, false, wxT("NULL bitmap in LoadFile") );
402 return dib
.IsOk() && bitmap
->CopyFromDIB(dib
);
408 bool wxBMPFileHandler::SaveFile(const wxBitmap
*bitmap
,
409 const wxString
& name
,
410 wxBitmapType
WXUNUSED(type
),
411 const wxPalette
* WXUNUSED(pal
)) const
414 wxCHECK_MSG( bitmap
, false, wxT("NULL bitmap in SaveFile") );
418 return dib
.Save(name
);
424 // ----------------------------------------------------------------------------
426 // ----------------------------------------------------------------------------
428 bool wxICOFileHandler::LoadIcon(wxIcon
*icon
,
429 const wxString
& name
,
430 wxBitmapType
WXUNUSED(flags
),
431 int desiredWidth
, int desiredHeight
)
440 // Parse the filename: it may be of the form "filename;n" in order to
441 // specify the nth icon in the file.
443 // For the moment, ignore the issue of possible semicolons in the
446 wxString
nameReal(name
);
447 wxString strIconIndex
= name
.AfterLast(wxT(';'));
448 if (strIconIndex
!= name
)
450 iconIndex
= wxAtoi(strIconIndex
);
451 nameReal
= name
.BeforeLast(wxT(';'));
455 // If we don't know what size icon we're looking for,
456 // try to find out what's there.
457 // Unfortunately this doesn't work, because ExtractIconEx
458 // will scale the icon to the 'desired' size, even if that
459 // size of icon isn't explicitly stored. So we would have
460 // to parse the icon file outselves.
461 if ( desiredWidth
== -1 &&
464 // Try loading a large icon first
465 if ( ::ExtractIconEx(nameReal
, iconIndex
, &hicon
, NULL
, 1) == 1)
468 // Then try loading a small icon
469 else if ( ::ExtractIconEx(nameReal
, iconIndex
, NULL
, &hicon
, 1) == 1)
475 // were we asked for a large icon?
476 if ( desiredWidth
== ::GetSystemMetrics(SM_CXICON
) &&
477 desiredHeight
== ::GetSystemMetrics(SM_CYICON
) )
479 // get the specified large icon from file
480 if ( !::ExtractIconEx(nameReal
.t_str(), iconIndex
, &hicon
, NULL
, 1) )
482 // it is not an error, but it might still be useful to be informed
483 // about it optionally
484 wxLogTrace(wxT("iconload"),
485 wxT("No large icons found in the file '%s'."),
489 else if ( desiredWidth
== ::GetSystemMetrics(SM_CXSMICON
) &&
490 desiredHeight
== ::GetSystemMetrics(SM_CYSMICON
) )
492 // get the specified small icon from file
493 if ( !::ExtractIconEx(nameReal
.t_str(), iconIndex
, NULL
, &hicon
, 1) )
495 wxLogTrace(wxT("iconload"),
496 wxT("No small icons found in the file '%s'."),
500 //else: not standard size, load below
505 // take any size icon from the file by index
506 hicon
= ::ExtractIcon(wxGetInstance(), nameReal
.t_str(), iconIndex
);
512 wxLogSysError(wxT("Failed to load icon from the file '%s'"),
518 size
= wxGetHiconSize(hicon
);
520 if ( (desiredWidth
!= -1 && desiredWidth
!= size
.x
) ||
521 (desiredHeight
!= -1 && desiredHeight
!= size
.y
) )
523 wxLogTrace(wxT("iconload"),
524 wxT("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
526 desiredWidth
, desiredHeight
);
528 ::DestroyIcon(hicon
);
533 icon
->SetHICON((WXHICON
)hicon
);
534 icon
->SetSize(size
.x
, size
.y
);
539 bool wxICOResourceHandler::LoadIcon(wxIcon
*icon
,
540 const wxString
& name
,
541 wxBitmapType
WXUNUSED(flags
),
542 int desiredWidth
, int desiredHeight
)
546 // do we need the icon of the specific size or would any icon do?
547 bool hasSize
= desiredWidth
!= -1 || desiredHeight
!= -1;
549 wxASSERT_MSG( !hasSize
|| (desiredWidth
!= -1 && desiredHeight
!= -1),
550 wxT("width and height should be either both -1 or not") );
552 // try to load the icon from this program first to allow overriding the
553 // standard icons (although why one would want to do it considering that
554 // we already have wxApp::GetStdIcon() is unclear)
556 // note that we can't just always call LoadImage() because it seems to do
557 // some icon rescaling internally which results in very ugly 16x16 icons
560 hicon
= (HICON
)::LoadImage(wxGetInstance(), name
.t_str(), IMAGE_ICON
,
561 desiredWidth
, desiredHeight
,
566 hicon
= ::LoadIcon(wxGetInstance(), name
.t_str());
569 // next check if it's not a standard icon
571 if ( !hicon
&& !hasSize
)
579 { wxT("wxICON_QUESTION"), IDI_QUESTION
},
580 { wxT("wxICON_WARNING"), IDI_EXCLAMATION
},
581 { wxT("wxICON_ERROR"), IDI_HAND
},
582 { wxT("wxICON_INFORMATION"), IDI_ASTERISK
},
585 for ( size_t nIcon
= 0; !hicon
&& nIcon
< WXSIZEOF(stdIcons
); nIcon
++ )
587 if ( name
== stdIcons
[nIcon
].name
)
589 hicon
= ::LoadIcon((HINSTANCE
)NULL
, stdIcons
[nIcon
].id
);
596 wxSize size
= wxGetHiconSize(hicon
);
597 icon
->SetSize(size
.x
, size
.y
);
599 icon
->SetHICON((WXHICON
)hicon
);
604 #if wxUSE_PNG_RESOURCE_HANDLER
606 // ----------------------------------------------------------------------------
608 // ----------------------------------------------------------------------------
610 bool wxPNGResourceHandler::LoadFile(wxBitmap
*bitmap
,
611 const wxString
& name
,
612 wxBitmapType
WXUNUSED(flags
),
613 int WXUNUSED(desiredWidth
),
614 int WXUNUSED(desiredHeight
))
616 const void* pngData
= NULL
;
619 // Currently we hardcode RCDATA resource type as this is what is usually
620 // used for the embedded images. We could allow specifying the type as part
621 // of the name in the future (e.g. "type:name" or something like this) if
623 if ( !wxLoadUserResource(&pngData
, &pngSize
,
628 // Notice that this message is not translated because only the
629 // programmer (and not the end user) can make any use of it.
630 wxLogError(wxS("Bitmap in PNG format \"%s\" not found, check ")
631 wxS("that the resource file contains \"RCDATA\" ")
632 wxS("resource with this name."),
638 *bitmap
= wxBitmap::NewFromPNGData(pngData
, pngSize
);
639 if ( !bitmap
->IsOk() )
641 wxLogError(wxS("Couldn't load resource bitmap \"%s\" as a PNG. "),
642 wxS("Have you registered PNG image handler?"),
651 #endif // wxUSE_PNG_RESOURCE_HANDLER
653 // ----------------------------------------------------------------------------
655 // ----------------------------------------------------------------------------
657 wxSize
wxGetHiconSize(HICON
WXUNUSED_IN_WINCE(hicon
))
665 if ( !::GetIconInfo(hicon
, &info
) )
667 wxLogLastError(wxT("GetIconInfo"));
671 HBITMAP hbmp
= info
.hbmMask
;
675 if ( ::GetObject(hbmp
, sizeof(BITMAP
), (LPSTR
) &bm
) )
677 size
= wxSize(bm
.bmWidth
, bm
.bmHeight
);
680 ::DeleteObject(info
.hbmMask
);
683 ::DeleteObject(info
.hbmColor
);
688 #endif // !__WXWINCE__
690 // use default icon size on this hardware
691 size
.x
= ::GetSystemMetrics(SM_CXICON
);
692 size
.y
= ::GetSystemMetrics(SM_CYICON
);
698 #endif // __WXMICROWIN__