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" 
  49 #include "wx/listimpl.cpp" 
  50 WX_DEFINE_LIST(wxGDIImageHandlerList
) 
  52 // ---------------------------------------------------------------------------- 
  54 // ---------------------------------------------------------------------------- 
  56 #ifndef __WXMICROWIN__ 
  58 // all image handlers are declared/defined in this file because the outside 
  59 // world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids) 
  61 class WXDLLEXPORT wxBMPFileHandler 
: public wxBitmapHandler
 
  64     wxBMPFileHandler() : wxBitmapHandler(_T("Windows bitmap file"), _T("bmp"), 
  69     virtual bool LoadFile(wxBitmap 
*bitmap
, 
  70                           const wxString
& name
, wxBitmapType flags
, 
  71                           int desiredWidth
, int desiredHeight
); 
  72     virtual bool SaveFile(const wxBitmap 
*bitmap
, 
  73                           const wxString
& name
, wxBitmapType type
, 
  74                           const wxPalette 
*palette 
= NULL
) const; 
  77     DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
) 
  80 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
 
  83     wxBMPResourceHandler() : wxBitmapHandler(_T("Windows bitmap resource"), 
  85                                              wxBITMAP_TYPE_BMP_RESOURCE
) 
  89     virtual bool LoadFile(wxBitmap 
*bitmap
, 
  90                           const wxString
& name
, wxBitmapType flags
, 
  91                           int desiredWidth
, int desiredHeight
); 
  94     DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
) 
  97 class WXDLLEXPORT wxIconHandler 
: public wxGDIImageHandler
 
 100     wxIconHandler(const wxString
& name
, const wxString
& ext
, wxBitmapType type
) 
 101         : wxGDIImageHandler(name
, ext
, type
) 
 105     // creating and saving icons is not supported 
 106     virtual bool Create(wxGDIImage 
*WXUNUSED(image
), 
 107                         const void* WXUNUSED(data
), 
 108                         wxBitmapType 
WXUNUSED(flags
), 
 110                         int WXUNUSED(height
), 
 111                         int WXUNUSED(depth
) = 1) 
 116     virtual bool Save(const wxGDIImage 
*WXUNUSED(image
), 
 117                       const wxString
& WXUNUSED(name
), 
 118                       wxBitmapType 
WXUNUSED(type
)) const 
 123     virtual bool Load(wxGDIImage 
*image
, 
 124                       const wxString
& name
, 
 126                       int desiredWidth
, int desiredHeight
) 
 128         wxIcon 
*icon 
= wxDynamicCast(image
, wxIcon
); 
 129         wxCHECK_MSG( icon
, false, _T("wxIconHandler only works with icons") ); 
 131         return LoadIcon(icon
, name
, flags
, desiredWidth
, desiredHeight
); 
 135     virtual bool LoadIcon(wxIcon 
*icon
, 
 136                           const wxString
& name
, wxBitmapType flags
, 
 137                           int desiredWidth 
= -1, int desiredHeight 
= -1) = 0; 
 140 class WXDLLEXPORT wxICOFileHandler 
: public wxIconHandler
 
 143     wxICOFileHandler() : wxIconHandler(_T("ICO icon file"), 
 150     virtual bool LoadIcon(wxIcon 
*icon
, 
 151                           const wxString
& name
, wxBitmapType flags
, 
 152                           int desiredWidth 
= -1, int desiredHeight 
= -1); 
 155     DECLARE_DYNAMIC_CLASS(wxICOFileHandler
) 
 158 class WXDLLEXPORT wxICOResourceHandler
: public wxIconHandler
 
 161     wxICOResourceHandler() : wxIconHandler(_T("ICO resource"), 
 163                                            wxBITMAP_TYPE_ICO_RESOURCE
) 
 168     virtual bool LoadIcon(wxIcon 
*icon
, 
 169                           const wxString
& name
, wxBitmapType flags
, 
 170                           int desiredWidth 
= -1, int desiredHeight 
= -1); 
 173     DECLARE_DYNAMIC_CLASS(wxICOResourceHandler
) 
 176 // ---------------------------------------------------------------------------- 
 178 // ---------------------------------------------------------------------------- 
 180 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
) 
 181 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
) 
 182 IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler
, wxObject
) 
 183 IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler
, wxObject
) 
 185 // ---------------------------------------------------------------------------- 
 187 // ---------------------------------------------------------------------------- 
 192 // ============================================================================ 
 194 // ============================================================================ 
 196 wxGDIImageHandlerList 
wxGDIImage::ms_handlers
; 
 198 // ---------------------------------------------------------------------------- 
 199 // wxGDIImage functions forwarded to wxGDIImageRefData 
 200 // ---------------------------------------------------------------------------- 
 202 bool wxGDIImage::FreeResource(bool WXUNUSED(force
)) 
 206         GetGDIImageData()->Free(); 
 207         GetGDIImageData()->m_handle 
= 0; 
 213 WXHANDLE 
wxGDIImage::GetResourceHandle() const 
 218 // ---------------------------------------------------------------------------- 
 219 // wxGDIImage handler stuff 
 220 // ---------------------------------------------------------------------------- 
 222 void wxGDIImage::AddHandler(wxGDIImageHandler 
*handler
) 
 224     ms_handlers
.Append(handler
); 
 227 void wxGDIImage::InsertHandler(wxGDIImageHandler 
*handler
) 
 229     ms_handlers
.Insert(handler
); 
 232 bool wxGDIImage::RemoveHandler(const wxString
& name
) 
 234     wxGDIImageHandler 
*handler 
= FindHandler(name
); 
 237         ms_handlers
.DeleteObject(handler
); 
 244 wxGDIImageHandler 
*wxGDIImage::FindHandler(const wxString
& name
) 
 246     wxGDIImageHandlerList::compatibility_iterator node 
= ms_handlers
.GetFirst(); 
 249         wxGDIImageHandler 
*handler 
= node
->GetData(); 
 250         if ( handler
->GetName() == name 
) 
 252         node 
= node
->GetNext(); 
 258 wxGDIImageHandler 
*wxGDIImage::FindHandler(const wxString
& extension
, 
 261     wxGDIImageHandlerList::compatibility_iterator node 
= ms_handlers
.GetFirst(); 
 264         wxGDIImageHandler 
*handler 
= node
->GetData(); 
 265         if ( (handler
->GetExtension() == extension
) && 
 266              (type 
== -1 || handler
->GetType() == type
) ) 
 271         node 
= node
->GetNext(); 
 276 wxGDIImageHandler 
*wxGDIImage::FindHandler(long type
) 
 278     wxGDIImageHandlerList::compatibility_iterator node 
= ms_handlers
.GetFirst(); 
 281         wxGDIImageHandler 
*handler 
= node
->GetData(); 
 282         if ( handler
->GetType() == type 
) 
 285         node 
= node
->GetNext(); 
 291 void wxGDIImage::CleanUpHandlers() 
 293     wxGDIImageHandlerList::compatibility_iterator node 
= ms_handlers
.GetFirst(); 
 296         wxGDIImageHandler 
*handler 
= node
->GetData(); 
 297         wxGDIImageHandlerList::compatibility_iterator next 
= node
->GetNext(); 
 299         ms_handlers
.Erase( node 
); 
 304 void wxGDIImage::InitStandardHandlers() 
 306 #ifndef __WXMICROWIN__ 
 307     AddHandler(new wxBMPResourceHandler
); 
 308     AddHandler(new wxBMPFileHandler
); 
 309     AddHandler(new wxICOResourceHandler
); 
 310     AddHandler(new wxICOFileHandler
); 
 314 #ifndef __WXMICROWIN__ 
 316 // ---------------------------------------------------------------------------- 
 318 // ---------------------------------------------------------------------------- 
 320 bool wxBMPResourceHandler::LoadFile(wxBitmap 
*bitmap
, 
 321                                     const wxString
& name
, wxBitmapType 
WXUNUSED(flags
), 
 322                                     int WXUNUSED(desiredWidth
), 
 323                                     int WXUNUSED(desiredHeight
)) 
 325     // TODO: load colourmap. 
 326     bitmap
->SetHBITMAP((WXHBITMAP
)::LoadBitmap(wxGetInstance(), name
.wx_str())); 
 330         // it's probably not found 
 331         wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."), 
 338     if ( !::GetObject(GetHbitmapOf(*bitmap
), sizeof(BITMAP
), (LPSTR
) &bm
) ) 
 340         wxLogLastError(wxT("GetObject(HBITMAP)")); 
 343     bitmap
->SetWidth(bm
.bmWidth
); 
 344     bitmap
->SetHeight(bm
.bmHeight
); 
 345     bitmap
->SetDepth(bm
.bmBitsPixel
); 
 347     // use 0xc0c0c0 as transparent colour by default 
 348     bitmap
->SetMask(new wxMask(*bitmap
, *wxLIGHT_GREY
)); 
 353 bool wxBMPFileHandler::LoadFile(wxBitmap 
*bitmap
, 
 354                                 const wxString
& name
, wxBitmapType 
WXUNUSED(flags
), 
 355                                 int WXUNUSED(desiredWidth
), 
 356                                 int WXUNUSED(desiredHeight
)) 
 359     wxCHECK_MSG( bitmap
, false, _T("NULL bitmap in LoadFile") ); 
 363     return dib
.IsOk() && bitmap
->CopyFromDIB(dib
); 
 369 bool wxBMPFileHandler::SaveFile(const wxBitmap 
*bitmap
, 
 370                                 const wxString
& name
, 
 371                                 wxBitmapType 
WXUNUSED(type
), 
 372                                 const wxPalette 
* WXUNUSED(pal
)) const 
 375     wxCHECK_MSG( bitmap
, false, _T("NULL bitmap in SaveFile") ); 
 379     return dib
.Save(name
); 
 385 // ---------------------------------------------------------------------------- 
 387 // ---------------------------------------------------------------------------- 
 389 bool wxICOFileHandler::LoadIcon(wxIcon 
*icon
, 
 390                                 const wxString
& name
, 
 391                                 wxBitmapType 
WXUNUSED(flags
), 
 392                                 int desiredWidth
, int desiredHeight
) 
 401     // Parse the filename: it may be of the form "filename;n" in order to 
 402     // specify the nth icon in the file. 
 404     // For the moment, ignore the issue of possible semicolons in the 
 407     wxString 
nameReal(name
); 
 408     wxString strIconIndex 
= name
.AfterLast(wxT(';')); 
 409     if (strIconIndex 
!= name
) 
 411         iconIndex 
= wxAtoi(strIconIndex
); 
 412         nameReal 
= name
.BeforeLast(wxT(';')); 
 416     // If we don't know what size icon we're looking for, 
 417     // try to find out what's there. 
 418     // Unfortunately this doesn't work, because ExtractIconEx 
 419     // will scale the icon to the 'desired' size, even if that 
 420     // size of icon isn't explicitly stored. So we would have 
 421     // to parse the icon file outselves. 
 422     if ( desiredWidth 
== -1 && 
 425         // Try loading a large icon first 
 426         if ( ::ExtractIconEx(nameReal
, iconIndex
, &hicon
, NULL
, 1) == 1) 
 429         // Then try loading a small icon 
 430         else if ( ::ExtractIconEx(nameReal
, iconIndex
, NULL
, &hicon
, 1) == 1) 
 436         // were we asked for a large icon? 
 437     if ( desiredWidth 
== ::GetSystemMetrics(SM_CXICON
) && 
 438          desiredHeight 
== ::GetSystemMetrics(SM_CYICON
) ) 
 440         // get the specified large icon from file 
 441         if ( !::ExtractIconEx(nameReal
.wx_str(), iconIndex
, &hicon
, NULL
, 1) ) 
 443             // it is not an error, but it might still be useful to be informed 
 444             // about it optionally 
 445             wxLogTrace(_T("iconload"), 
 446                        _T("No large icons found in the file '%s'."), 
 450     else if ( desiredWidth 
== ::GetSystemMetrics(SM_CXSMICON
) && 
 451               desiredHeight 
== ::GetSystemMetrics(SM_CYSMICON
) ) 
 453         // get the specified small icon from file 
 454         if ( !::ExtractIconEx(nameReal
.wx_str(), iconIndex
, NULL
, &hicon
, 1) ) 
 456             wxLogTrace(_T("iconload"), 
 457                        _T("No small icons found in the file '%s'."), 
 461     //else: not standard size, load below 
 466         // take any size icon from the file by index 
 467         hicon 
= ::ExtractIcon(wxGetInstance(), nameReal
.wx_str(), iconIndex
); 
 473         wxLogSysError(_T("Failed to load icon from the file '%s'"), 
 479     size 
= wxGetHiconSize(hicon
); 
 481     if ( (desiredWidth 
!= -1 && desiredWidth 
!= size
.x
) || 
 482          (desiredHeight 
!= -1 && desiredHeight 
!= size
.y
) ) 
 484         wxLogTrace(_T("iconload"), 
 485                    _T("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"), 
 487                    desiredWidth
, desiredHeight
); 
 489         ::DestroyIcon(hicon
); 
 494     icon
->SetHICON((WXHICON
)hicon
); 
 495     icon
->SetSize(size
.x
, size
.y
); 
 500 bool wxICOResourceHandler::LoadIcon(wxIcon 
*icon
, 
 501                                     const wxString
& name
, 
 502                                     wxBitmapType 
WXUNUSED(flags
), 
 503                                     int desiredWidth
, int desiredHeight
) 
 507     // do we need the icon of the specific size or would any icon do? 
 508     bool hasSize 
= desiredWidth 
!= -1 || desiredHeight 
!= -1; 
 510     wxASSERT_MSG( !hasSize 
|| (desiredWidth 
!= -1 && desiredHeight 
!= -1), 
 511                   _T("width and height should be either both -1 or not") ); 
 513     // try to load the icon from this program first to allow overriding the 
 514     // standard icons (although why one would want to do it considering that 
 515     // we already have wxApp::GetStdIcon() is unclear) 
 517     // note that we can't just always call LoadImage() because it seems to do 
 518     // some icon rescaling internally which results in very ugly 16x16 icons 
 521         hicon 
= (HICON
)::LoadImage(wxGetInstance(), name
.wx_str(), IMAGE_ICON
, 
 522                                     desiredWidth
, desiredHeight
, 
 527         hicon 
= ::LoadIcon(wxGetInstance(), name
.wx_str()); 
 530     // next check if it's not a standard icon 
 532     if ( !hicon 
&& !hasSize 
) 
 540             { wxT("wxICON_QUESTION"),   IDI_QUESTION    
}, 
 541             { wxT("wxICON_WARNING"),    IDI_EXCLAMATION 
}, 
 542             { wxT("wxICON_ERROR"),      IDI_HAND        
}, 
 543             { wxT("wxICON_INFORMATION"),       IDI_ASTERISK    
}, 
 546         for ( size_t nIcon 
= 0; !hicon 
&& nIcon 
< WXSIZEOF(stdIcons
); nIcon
++ ) 
 548             if ( name 
== stdIcons
[nIcon
].name 
) 
 550                 hicon 
= ::LoadIcon((HINSTANCE
)NULL
, stdIcons
[nIcon
].id
); 
 557     wxSize size 
= wxGetHiconSize(hicon
); 
 558     icon
->SetSize(size
.x
, size
.y
); 
 560     icon
->SetHICON((WXHICON
)hicon
); 
 565 // ---------------------------------------------------------------------------- 
 567 // ---------------------------------------------------------------------------- 
 569 wxSize 
wxGetHiconSize(HICON 
WXUNUSED_IN_WINCE(hicon
)) 
 577         if ( !::GetIconInfo(hicon
, &info
) ) 
 579             wxLogLastError(wxT("GetIconInfo")); 
 583             HBITMAP hbmp 
= info
.hbmMask
; 
 587                 if ( ::GetObject(hbmp
, sizeof(BITMAP
), (LPSTR
) &bm
) ) 
 589                     size 
= wxSize(bm
.bmWidth
, bm
.bmHeight
); 
 592                 ::DeleteObject(info
.hbmMask
); 
 595                 ::DeleteObject(info
.hbmColor
); 
 600 #endif // !__WXWINCE__ 
 602         // use default icon size on this hardware 
 603         size
.x 
= ::GetSystemMetrics(SM_CXICON
); 
 604         size
.y 
= ::GetSystemMetrics(SM_CYICON
); 
 610 #endif // __WXMICROWIN__