1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/gdiimage.cpp
3 // Purpose: wxGDIImage implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
27 #include "wx/string.h"
30 #include "wx/bitmap.h"
33 #include "wx/msw/private.h"
35 #include "wx/msw/gdiimage.h"
38 #include "wx/msw/dib.h"
41 // By default, use PNG resource handler if we can, i.e. have support for
42 // loading PNG images in the library. This symbol could be predefined as 0 to
43 // avoid doing this if anybody ever needs to do it for some reason.
44 #if !defined(wxUSE_PNG_RESOURCE_HANDLER) && wxUSE_LIBPNG && wxUSE_IMAGE
45 #define wxUSE_PNG_RESOURCE_HANDLER 1
48 #if wxUSE_PNG_RESOURCE_HANDLER
50 #include "wx/utils.h" // For wxLoadUserResource()
60 #include "wx/listimpl.cpp"
61 WX_DEFINE_LIST(wxGDIImageHandlerList
)
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #ifndef __WXMICROWIN__
69 // all image handlers are declared/defined in this file because the outside
70 // world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
72 class WXDLLEXPORT wxBMPFileHandler
: public wxBitmapHandler
75 wxBMPFileHandler() : wxBitmapHandler(wxT("Windows bitmap file"), wxT("bmp"),
80 virtual bool LoadFile(wxBitmap
*bitmap
,
81 const wxString
& name
, wxBitmapType flags
,
82 int desiredWidth
, int desiredHeight
);
83 virtual bool SaveFile(const wxBitmap
*bitmap
,
84 const wxString
& name
, wxBitmapType type
,
85 const wxPalette
*palette
= NULL
) const;
88 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
)
91 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
94 wxBMPResourceHandler() : wxBitmapHandler(wxT("Windows bitmap resource"),
96 wxBITMAP_TYPE_BMP_RESOURCE
)
100 virtual bool LoadFile(wxBitmap
*bitmap
,
101 const wxString
& name
, wxBitmapType flags
,
102 int desiredWidth
, int desiredHeight
);
105 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
)
108 class WXDLLEXPORT wxIconHandler
: public wxGDIImageHandler
111 wxIconHandler(const wxString
& name
, const wxString
& ext
, wxBitmapType type
)
112 : wxGDIImageHandler(name
, ext
, type
)
116 // creating and saving icons is not supported
117 virtual bool Create(wxGDIImage
*WXUNUSED(image
),
118 const void* WXUNUSED(data
),
119 wxBitmapType
WXUNUSED(flags
),
121 int WXUNUSED(height
),
122 int WXUNUSED(depth
) = 1)
127 virtual bool Save(const wxGDIImage
*WXUNUSED(image
),
128 const wxString
& WXUNUSED(name
),
129 wxBitmapType
WXUNUSED(type
)) const
134 virtual bool Load(wxGDIImage
*image
,
135 const wxString
& name
,
137 int desiredWidth
, int desiredHeight
)
139 wxIcon
*icon
= wxDynamicCast(image
, wxIcon
);
140 wxCHECK_MSG( icon
, false, wxT("wxIconHandler only works with icons") );
142 return LoadIcon(icon
, name
, flags
, desiredWidth
, desiredHeight
);
146 virtual bool LoadIcon(wxIcon
*icon
,
147 const wxString
& name
, wxBitmapType flags
,
148 int desiredWidth
= -1, int desiredHeight
= -1) = 0;
151 class WXDLLEXPORT wxICOFileHandler
: public wxIconHandler
154 wxICOFileHandler() : wxIconHandler(wxT("ICO icon file"),
161 virtual bool LoadIcon(wxIcon
*icon
,
162 const wxString
& name
, wxBitmapType flags
,
163 int desiredWidth
= -1, int desiredHeight
= -1);
166 DECLARE_DYNAMIC_CLASS(wxICOFileHandler
)
169 class WXDLLEXPORT wxICOResourceHandler
: public wxIconHandler
172 wxICOResourceHandler() : wxIconHandler(wxT("ICO resource"),
174 wxBITMAP_TYPE_ICO_RESOURCE
)
179 virtual bool LoadIcon(wxIcon
*icon
,
180 const wxString
& name
, wxBitmapType flags
,
181 int desiredWidth
= -1, int desiredHeight
= -1);
184 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler
)
187 #if wxUSE_PNG_RESOURCE_HANDLER
189 class WXDLLEXPORT wxPNGResourceHandler
: public wxBitmapHandler
192 wxPNGResourceHandler() : wxBitmapHandler(wxS("Windows PNG resource"),
194 wxBITMAP_TYPE_PNG_RESOURCE
)
198 virtual bool LoadFile(wxBitmap
*bitmap
,
199 const wxString
& name
, wxBitmapType flags
,
200 int desiredWidth
, int desiredHeight
);
203 wxDECLARE_DYNAMIC_CLASS(wxPNGResourceHandler
);
206 #endif // wxUSE_PNG_RESOURCE_HANDLER
208 // ----------------------------------------------------------------------------
210 // ----------------------------------------------------------------------------
212 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
)
213 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
)
214 IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler
, wxObject
)
215 IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler
, wxObject
)
216 #if wxUSE_PNG_RESOURCE_HANDLER
217 IMPLEMENT_DYNAMIC_CLASS(wxPNGResourceHandler
, wxBitmapHandler
)
218 #endif // wxUSE_PNG_RESOURCE_HANDLER
220 // ----------------------------------------------------------------------------
222 // ----------------------------------------------------------------------------
227 // ============================================================================
229 // ============================================================================
231 wxGDIImageHandlerList
wxGDIImage::ms_handlers
;
233 // ----------------------------------------------------------------------------
234 // wxGDIImage functions forwarded to wxGDIImageRefData
235 // ----------------------------------------------------------------------------
237 bool wxGDIImage::FreeResource(bool WXUNUSED(force
))
241 GetGDIImageData()->Free();
242 GetGDIImageData()->m_handle
= 0;
248 WXHANDLE
wxGDIImage::GetResourceHandle() const
253 // ----------------------------------------------------------------------------
254 // wxGDIImage handler stuff
255 // ----------------------------------------------------------------------------
257 void wxGDIImage::AddHandler(wxGDIImageHandler
*handler
)
259 ms_handlers
.Append(handler
);
262 void wxGDIImage::InsertHandler(wxGDIImageHandler
*handler
)
264 ms_handlers
.Insert(handler
);
267 bool wxGDIImage::RemoveHandler(const wxString
& name
)
269 wxGDIImageHandler
*handler
= FindHandler(name
);
272 ms_handlers
.DeleteObject(handler
);
279 wxGDIImageHandler
*wxGDIImage::FindHandler(const wxString
& name
)
281 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
284 wxGDIImageHandler
*handler
= node
->GetData();
285 if ( handler
->GetName() == name
)
287 node
= node
->GetNext();
293 wxGDIImageHandler
*wxGDIImage::FindHandler(const wxString
& extension
,
296 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
299 wxGDIImageHandler
*handler
= node
->GetData();
300 if ( (handler
->GetExtension() == extension
) &&
301 (type
== -1 || handler
->GetType() == type
) )
306 node
= node
->GetNext();
311 wxGDIImageHandler
*wxGDIImage::FindHandler(long type
)
313 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
316 wxGDIImageHandler
*handler
= node
->GetData();
317 if ( handler
->GetType() == type
)
320 node
= node
->GetNext();
326 void wxGDIImage::CleanUpHandlers()
328 wxGDIImageHandlerList::compatibility_iterator node
= ms_handlers
.GetFirst();
331 wxGDIImageHandler
*handler
= node
->GetData();
332 wxGDIImageHandlerList::compatibility_iterator next
= node
->GetNext();
334 ms_handlers
.Erase( node
);
339 void wxGDIImage::InitStandardHandlers()
341 #ifndef __WXMICROWIN__
342 AddHandler(new wxBMPResourceHandler
);
343 AddHandler(new wxBMPFileHandler
);
344 AddHandler(new wxICOFileHandler
);
345 AddHandler(new wxICOResourceHandler
);
346 #if wxUSE_PNG_RESOURCE_HANDLER
347 AddHandler(new wxPNGResourceHandler
);
348 #endif // wxUSE_PNG_RESOURCE_HANDLER
352 #ifndef __WXMICROWIN__
354 // ----------------------------------------------------------------------------
356 // ----------------------------------------------------------------------------
358 bool wxBMPResourceHandler::LoadFile(wxBitmap
*bitmap
,
359 const wxString
& name
, wxBitmapType
WXUNUSED(flags
),
360 int WXUNUSED(desiredWidth
),
361 int WXUNUSED(desiredHeight
))
363 // TODO: load colourmap.
364 bitmap
->SetHBITMAP((WXHBITMAP
)::LoadBitmap(wxGetInstance(), name
.t_str()));
366 if ( !bitmap
->IsOk() )
368 // it's probably not found
369 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
376 if ( !::GetObject(GetHbitmapOf(*bitmap
), sizeof(BITMAP
), (LPSTR
) &bm
) )
378 wxLogLastError(wxT("GetObject(HBITMAP)"));
381 bitmap
->SetWidth(bm
.bmWidth
);
382 bitmap
->SetHeight(bm
.bmHeight
);
383 bitmap
->SetDepth(bm
.bmBitsPixel
);
385 // use 0xc0c0c0 as transparent colour by default
386 bitmap
->SetMask(new wxMask(*bitmap
, *wxLIGHT_GREY
));
391 bool wxBMPFileHandler::LoadFile(wxBitmap
*bitmap
,
392 const wxString
& name
, wxBitmapType
WXUNUSED(flags
),
393 int WXUNUSED(desiredWidth
),
394 int WXUNUSED(desiredHeight
))
397 wxCHECK_MSG( bitmap
, false, wxT("NULL bitmap in LoadFile") );
401 return dib
.IsOk() && bitmap
->CopyFromDIB(dib
);
407 bool wxBMPFileHandler::SaveFile(const wxBitmap
*bitmap
,
408 const wxString
& name
,
409 wxBitmapType
WXUNUSED(type
),
410 const wxPalette
* WXUNUSED(pal
)) const
413 wxCHECK_MSG( bitmap
, false, wxT("NULL bitmap in SaveFile") );
417 return dib
.Save(name
);
423 // ----------------------------------------------------------------------------
425 // ----------------------------------------------------------------------------
427 bool wxICOFileHandler::LoadIcon(wxIcon
*icon
,
428 const wxString
& name
,
429 wxBitmapType
WXUNUSED(flags
),
430 int desiredWidth
, int desiredHeight
)
436 // Parse the filename: it may be of the form "filename;n" in order to
437 // specify the nth icon in the file.
439 // For the moment, ignore the issue of possible semicolons in the
442 wxString
nameReal(name
);
443 wxString strIconIndex
= name
.AfterLast(wxT(';'));
444 if (strIconIndex
!= name
)
446 iconIndex
= wxAtoi(strIconIndex
);
447 nameReal
= name
.BeforeLast(wxT(';'));
451 // If we don't know what size icon we're looking for,
452 // try to find out what's there.
453 // Unfortunately this doesn't work, because ExtractIconEx
454 // will scale the icon to the 'desired' size, even if that
455 // size of icon isn't explicitly stored. So we would have
456 // to parse the icon file outselves.
457 if ( desiredWidth
== -1 &&
460 // Try loading a large icon first
461 if ( ::ExtractIconEx(nameReal
, iconIndex
, &hicon
, NULL
, 1) == 1)
464 // Then try loading a small icon
465 else if ( ::ExtractIconEx(nameReal
, iconIndex
, NULL
, &hicon
, 1) == 1)
471 // were we asked for a large icon?
472 if ( desiredWidth
== ::GetSystemMetrics(SM_CXICON
) &&
473 desiredHeight
== ::GetSystemMetrics(SM_CYICON
) )
475 // get the specified large icon from file
476 if ( !::ExtractIconEx(nameReal
.t_str(), iconIndex
, &hicon
, NULL
, 1) )
478 // it is not an error, but it might still be useful to be informed
479 // about it optionally
480 wxLogTrace(wxT("iconload"),
481 wxT("No large icons found in the file '%s'."),
485 else if ( desiredWidth
== ::GetSystemMetrics(SM_CXSMICON
) &&
486 desiredHeight
== ::GetSystemMetrics(SM_CYSMICON
) )
488 // get the specified small icon from file
489 if ( !::ExtractIconEx(nameReal
.t_str(), iconIndex
, NULL
, &hicon
, 1) )
491 wxLogTrace(wxT("iconload"),
492 wxT("No small icons found in the file '%s'."),
496 //else: not standard size, load below
501 // take any size icon from the file by index
502 hicon
= ::ExtractIcon(wxGetInstance(), nameReal
.t_str(), iconIndex
);
508 wxLogSysError(wxT("Failed to load icon from the file '%s'"),
514 if ( !icon
->CreateFromHICON(hicon
) )
517 if ( (desiredWidth
!= -1 && desiredWidth
!= icon
->GetWidth()) ||
518 (desiredHeight
!= -1 && desiredHeight
!= icon
->GetHeight()) )
520 wxLogTrace(wxT("iconload"),
521 wxT("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
522 icon
->GetWidth(), icon
->GetHeight(),
523 desiredWidth
, desiredHeight
);
533 bool wxICOResourceHandler::LoadIcon(wxIcon
*icon
,
534 const wxString
& name
,
535 wxBitmapType
WXUNUSED(flags
),
536 int desiredWidth
, int desiredHeight
)
540 // do we need the icon of the specific size or would any icon do?
541 bool hasSize
= desiredWidth
!= -1 || desiredHeight
!= -1;
543 wxASSERT_MSG( !hasSize
|| (desiredWidth
!= -1 && desiredHeight
!= -1),
544 wxT("width and height should be either both -1 or not") );
546 // try to load the icon from this program first to allow overriding the
547 // standard icons (although why one would want to do it considering that
548 // we already have wxApp::GetStdIcon() is unclear)
550 // note that we can't just always call LoadImage() because it seems to do
551 // some icon rescaling internally which results in very ugly 16x16 icons
554 hicon
= (HICON
)::LoadImage(wxGetInstance(), name
.t_str(), IMAGE_ICON
,
555 desiredWidth
, desiredHeight
,
560 hicon
= ::LoadIcon(wxGetInstance(), name
.t_str());
563 // next check if it's not a standard icon
565 if ( !hicon
&& !hasSize
)
573 { wxT("wxICON_QUESTION"), IDI_QUESTION
},
574 { wxT("wxICON_WARNING"), IDI_EXCLAMATION
},
575 { wxT("wxICON_ERROR"), IDI_HAND
},
576 { wxT("wxICON_INFORMATION"), IDI_ASTERISK
},
579 for ( size_t nIcon
= 0; !hicon
&& nIcon
< WXSIZEOF(stdIcons
); nIcon
++ )
581 if ( name
== stdIcons
[nIcon
].name
)
583 hicon
= ::LoadIcon((HINSTANCE
)NULL
, stdIcons
[nIcon
].id
);
590 return icon
->CreateFromHICON((WXHICON
)hicon
);
593 #if wxUSE_PNG_RESOURCE_HANDLER
595 // ----------------------------------------------------------------------------
597 // ----------------------------------------------------------------------------
599 bool wxPNGResourceHandler::LoadFile(wxBitmap
*bitmap
,
600 const wxString
& name
,
601 wxBitmapType
WXUNUSED(flags
),
602 int WXUNUSED(desiredWidth
),
603 int WXUNUSED(desiredHeight
))
605 const void* pngData
= NULL
;
608 // Currently we hardcode RCDATA resource type as this is what is usually
609 // used for the embedded images. We could allow specifying the type as part
610 // of the name in the future (e.g. "type:name" or something like this) if
612 if ( !wxLoadUserResource(&pngData
, &pngSize
,
617 // Notice that this message is not translated because only the
618 // programmer (and not the end user) can make any use of it.
619 wxLogError(wxS("Bitmap in PNG format \"%s\" not found, check ")
620 wxS("that the resource file contains \"RCDATA\" ")
621 wxS("resource with this name."),
627 *bitmap
= wxBitmap::NewFromPNGData(pngData
, pngSize
);
628 if ( !bitmap
->IsOk() )
630 wxLogError(wxS("Couldn't load resource bitmap \"%s\" as a PNG. "),
631 wxS("Have you registered PNG image handler?"),
640 #endif // wxUSE_PNG_RESOURCE_HANDLER
642 // ----------------------------------------------------------------------------
644 // ----------------------------------------------------------------------------
646 wxSize
wxGetHiconSize(HICON
WXUNUSED_IN_WINCE(hicon
))
654 if ( !::GetIconInfo(hicon
, &info
) )
656 wxLogLastError(wxT("GetIconInfo"));
660 HBITMAP hbmp
= info
.hbmMask
;
664 if ( ::GetObject(hbmp
, sizeof(BITMAP
), (LPSTR
) &bm
) )
666 size
= wxSize(bm
.bmWidth
, bm
.bmHeight
);
669 ::DeleteObject(info
.hbmMask
);
672 ::DeleteObject(info
.hbmColor
);
677 #endif // !__WXWINCE__
679 // use default icon size on this hardware
680 size
.x
= ::GetSystemMetrics(SM_CXICON
);
681 size
.y
= ::GetSystemMetrics(SM_CYICON
);
687 #endif // __WXMICROWIN__