1 //////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/bitmap.cpp 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #include "wx/bitmap.h" 
  35     #include "wx/palette.h" 
  36     #include "wx/dcmemory.h" 
  42 #include "wx/scopedptr.h" 
  43 #include "wx/msw/private.h" 
  44 #include "wx/msw/dc.h" 
  47     #include "wx/msw/dib.h" 
  50 #ifdef wxHAS_RAW_BITMAP 
  51     #include "wx/rawbmp.h" 
  54 // missing from mingw32 header 
  56     #define CLR_INVALID ((COLORREF)-1) 
  57 #endif // no CLR_INVALID 
  59 // ---------------------------------------------------------------------------- 
  61 // ---------------------------------------------------------------------------- 
  63 class WXDLLEXPORT wxBitmapRefData 
: public wxGDIImageRefData
 
  66     wxBitmapRefData() { Init(); } 
  67     wxBitmapRefData(const wxBitmapRefData
& data
); 
  68     virtual ~wxBitmapRefData() { Free(); } 
  72     void CopyFromDIB(const wxDIB
& dib
); 
  74     // set the mask object to use as the mask, we take ownership of it 
  75     void SetMask(wxMask 
*mask
) 
  81     // set the HBITMAP to use as the mask 
  82     void SetMask(HBITMAP hbmpMask
) 
  84         SetMask(new wxMask((WXHBITMAP
)hbmpMask
)); 
  88     wxMask 
*GetMask() const { return m_bitmapMask
; } 
  92     wxPalette     m_bitmapPalette
; 
  93 #endif // wxUSE_PALETTE 
  99     // this field is solely for error checking: we detect selecting a bitmap 
 100     // into more than one DC at once or deleting a bitmap still selected into a 
 101     // DC (both are serious programming errors under Windows) 
 102     wxDC         
*m_selectedInto
; 
 103 #endif // wxDEBUG_LEVEL 
 106     // when GetRawData() is called for a DDB we need to convert it to a DIB 
 107     // first to be able to provide direct access to it and we cache that DIB 
 108     // here and convert it back to DDB when UngetRawData() is called 
 112     // true if we have alpha transparency info and can be drawn using 
 116     // true if our HBITMAP is a DIB section, false if it is a DDB 
 122     // optional mask for transparent drawing 
 123     wxMask       
*m_bitmapMask
; 
 127     wxBitmapRefData
& operator=(const wxBitmapRefData
&); 
 130 // ---------------------------------------------------------------------------- 
 132 // ---------------------------------------------------------------------------- 
 134 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
) 
 135 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
) 
 137 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
) 
 139 // ============================================================================ 
 141 // ============================================================================ 
 143 // ---------------------------------------------------------------------------- 
 145 // ---------------------------------------------------------------------------- 
 147 // decide whether we should create a DIB or a DDB for the given parameters 
 149 // NB: we always use DIBs under Windows CE as this is much simpler (even if 
 150 //     also less efficient...) and we obviously can't use them if there is no 
 151 //     DIB support compiled in at all 
 153     static inline bool wxShouldCreateDIB(int, int, int, WXHDC
) { return true; } 
 155     #define ALWAYS_USE_DIB 
 157     // no sense in defining wxShouldCreateDIB() as we can't compile code 
 158     // executed if it is true, so we have to use #if's anyhow 
 159     #define NEVER_USE_DIB 
 160 #else // wxUSE_WXDIB && !__WXWINCE__ 
 161     static inline bool wxShouldCreateDIB(int w
, int h
, int d
, WXHDC hdc
) 
 163         // here is the logic: 
 165         //  (a) if hdc is specified, the caller explicitly wants DDB 
 166         //  (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp 
 167         //      or less DIBs anyhow) 
 168         //  (c) finally, create DIBs under Win9x even if the depth hasn't been 
 169         //      explicitly specified but the current display depth is 24 or 
 170         //      more and the image is "big", i.e. > 16Mb which is the 
 171         //      theoretical limit for DDBs under Win9x 
 173         // consequences (all of which seem to make sense): 
 175         //  (i)     by default, DDBs are created (depth == -1 usually) 
 176         //  (ii)    DIBs can be created by explicitly specifying the depth 
 177         //  (iii)   using a DC always forces creating a DDB 
 181                         wxDIB::GetLineSize(w
, wxDisplayDepth())*h 
> 16*1024*1024)); 
 184     #define SOMETIMES_USE_DIB 
 185 #endif // different DIB usage scenarious 
 187 // ---------------------------------------------------------------------------- 
 189 // ---------------------------------------------------------------------------- 
 191 void wxBitmapRefData::Init() 
 194     m_selectedInto 
= NULL
; 
 198     m_hBitmap 
= (WXHBITMAP
) NULL
; 
 207 wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData
& data
) 
 208                : wxGDIImageRefData(data
) 
 212     // (deep) copy the mask if present 
 213     if (data
.m_bitmapMask
) 
 214         m_bitmapMask 
= new wxMask(*data
.m_bitmapMask
); 
 216     wxASSERT_MSG( !data
.m_dib
, 
 217                     wxT("can't copy bitmap locked for raw access!") ); 
 219     m_hasAlpha 
= data
.m_hasAlpha
; 
 222     // copy the other bitmap 
 223     if ( data
.m_hBitmap 
) 
 225         wxDIB 
dib((HBITMAP
)(data
.m_hBitmap
)); 
 228 #endif // wxUSE_WXDIB 
 231 void wxBitmapRefData::Free() 
 233     wxASSERT_MSG( !m_selectedInto
, 
 234                   wxT("deleting bitmap still selected into wxMemoryDC") ); 
 237     wxASSERT_MSG( !m_dib
, wxT("forgot to call wxBitmap::UngetRawData()!") ); 
 242         if ( !::DeleteObject((HBITMAP
)m_hBitmap
) ) 
 244             wxLogLastError(wxT("DeleteObject(hbitmap)")); 
 248     wxDELETE(m_bitmapMask
); 
 251 void wxBitmapRefData::CopyFromDIB(const wxDIB
& dib
) 
 253     wxCHECK_RET( !IsOk(), "bitmap already initialized" ); 
 254     wxCHECK_RET( dib
.IsOk(), wxT("invalid DIB in CopyFromDIB") ); 
 256 #ifdef SOMETIMES_USE_DIB 
 257     HBITMAP hbitmap 
= dib
.CreateDDB(); 
 261 #else // ALWAYS_USE_DIB 
 262     HBITMAP hbitmap 
= const_cast<wxDIB 
&>(dib
).Detach(); 
 264 #endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB 
 266     m_width 
= dib
.GetWidth(); 
 267     m_height 
= dib
.GetHeight(); 
 268     m_depth 
= dib
.GetDepth(); 
 270     m_hBitmap 
= (WXHBITMAP
)hbitmap
; 
 273     wxPalette 
*palette 
= dib
.CreatePalette(); 
 275         m_bitmapPalette 
= *palette
; 
 277 #endif // wxUSE_PALETTE 
 280 // ---------------------------------------------------------------------------- 
 282 // ---------------------------------------------------------------------------- 
 284 wxGDIImageRefData 
*wxBitmap::CreateData() const 
 286     return new wxBitmapRefData
; 
 289 wxGDIRefData 
*wxBitmap::CloneGDIRefData(const wxGDIRefData 
*data
) const 
 291     return new wxBitmapRefData(*static_cast<const wxBitmapRefData 
*>(data
)); 
 294 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
, 
 295                                     wxBitmapTransparency transp
) 
 297 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 298     // it may be either HICON or HCURSOR 
 299     HICON hicon 
= (HICON
)icon
.GetHandle(); 
 302     if ( !::GetIconInfo(hicon
, &iconInfo
) ) 
 304         wxLogLastError(wxT("GetIconInfo")); 
 309     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 312     int w 
= icon
.GetWidth(), 
 313         h 
= icon
.GetHeight(); 
 315     refData
->m_width 
= w
; 
 316     refData
->m_height 
= h
; 
 317     refData
->m_depth 
= wxDisplayDepth(); 
 319     refData
->m_hBitmap 
= (WXHBITMAP
)iconInfo
.hbmColor
; 
 324             wxFAIL_MSG( wxT("unknown wxBitmapTransparency value") ); 
 326         case wxBitmapTransparency_None
: 
 327             // nothing to do, refData->m_hasAlpha is false by default 
 330         case wxBitmapTransparency_Auto
: 
 332             // If the icon is 32 bits per pixel then it may have alpha channel 
 333             // data, although there are some icons that are 32 bpp but have no 
 334             // alpha... So convert to a DIB and manually check the 4th byte for 
 338                 if ( ::GetObject(iconInfo
.hbmColor
, sizeof(bm
), &bm
) && 
 339                         (bm
.bmBitsPixel 
== 32) ) 
 341                     wxDIB 
dib(iconInfo
.hbmColor
); 
 344                         unsigned char* const pixels 
= dib
.GetData(); 
 346                         for ( idx 
= 0; idx 
< w
*h
*4; idx 
+= 4 ) 
 348                             if (pixels
[idx
+3] != 0) 
 350                                 // If there is an alpha byte that is non-zero 
 351                                 // then set the alpha flag and stop checking 
 352                                 refData
->m_hasAlpha 
= true; 
 357                         if ( refData
->m_hasAlpha 
) 
 359                             // If we do have alpha, ensure we use premultiplied 
 360                             // data for our pixels as this is what the bitmaps 
 361                             // created in other ways do and this is necessary 
 362                             // for e.g. AlphaBlend() to work with this bitmap. 
 363                             for ( idx 
= 0; idx 
< w
*h
*4; idx 
+= 4 ) 
 365                                 const unsigned char a 
= pixels
[idx
+3]; 
 367                                 pixels
[idx
]   = ((pixels
[idx
]  *a
) + 127)/255; 
 368                                 pixels
[idx
+1] = ((pixels
[idx
+1]*a
) + 127)/255; 
 369                                 pixels
[idx
+2] = ((pixels
[idx
+2]*a
) + 127)/255; 
 372                             ::DeleteObject(refData
->m_hBitmap
); 
 373                             refData
->m_hBitmap 
= dib
.Detach(); 
 379 #endif // wxUSE_WXDIB 
 381         case wxBitmapTransparency_Always
: 
 382             refData
->m_hasAlpha 
= true; 
 386     if ( !refData
->m_hasAlpha 
) 
 388         // the mask returned by GetIconInfo() is inverted compared to the usual 
 390         refData
->SetMask(wxInvertMask(iconInfo
.hbmMask
, w
, h
)); 
 393     // delete the old one now as we don't need it any more 
 394     ::DeleteObject(iconInfo
.hbmMask
); 
 397 #else // __WXMICROWIN__ || __WXWINCE__ 
 402 #endif // !__WXWINCE__/__WXWINCE__ 
 405 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
, wxBitmapTransparency transp
) 
 409     if ( !cursor
.IsOk() ) 
 412     return CopyFromIconOrCursor(cursor
, transp
); 
 415 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
, wxBitmapTransparency transp
) 
 422     return CopyFromIconOrCursor(icon
, transp
); 
 425 #ifndef NEVER_USE_DIB 
 427 bool wxBitmap::CopyFromDIB(const wxDIB
& dib
) 
 429     wxScopedPtr
<wxBitmapRefData
> newData(new wxBitmapRefData
); 
 430     newData
->CopyFromDIB(dib
); 
 431     if ( !newData
->IsOk() ) 
 435     m_refData 
= newData
.release(); 
 439 #endif // NEVER_USE_DIB 
 441 wxBitmap::~wxBitmap() 
 445 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
) 
 447 #ifndef __WXMICROWIN__ 
 448     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 451     refData
->m_width 
= width
; 
 452     refData
->m_height 
= height
; 
 453     refData
->m_depth 
= depth
; 
 458         // we assume that it is in XBM format which is not quite the same as 
 459         // the format CreateBitmap() wants because the order of bytes in the 
 461         const size_t bytesPerLine 
= (width 
+ 7) / 8; 
 462         const size_t padding 
= bytesPerLine 
% 2; 
 463         const size_t len 
= height 
* ( padding 
+ bytesPerLine 
); 
 464         data 
= (char *)malloc(len
); 
 465         const char *src 
= bits
; 
 468         for ( int rows 
= 0; rows 
< height
; rows
++ ) 
 470             for ( size_t cols 
= 0; cols 
< bytesPerLine
; cols
++ ) 
 472                 unsigned char val 
= *src
++; 
 473                 unsigned char reversed 
= 0; 
 475                 for ( int bits 
= 0; bits 
< 8; bits
++) 
 478                     reversed 
|= (unsigned char)(val 
& 0x01); 
 490         // bits should already be in Windows standard format 
 491         data 
= const_cast<char *>(bits
); 
 494     HBITMAP hbmp 
= ::CreateBitmap(width
, height
, 1, depth
, data
); 
 497         wxLogLastError(wxT("CreateBitmap")); 
 505     SetHBITMAP((WXHBITMAP
)hbmp
); 
 509 wxBitmap::wxBitmap(int w
, int h
, const wxDC
& dc
) 
 511     (void)Create(w
, h
, dc
); 
 514 wxBitmap::wxBitmap(const void* data
, wxBitmapType type
, int width
, int height
, int depth
) 
 516     (void)Create(data
, type
, width
, height
, depth
); 
 519 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
) 
 521     LoadFile(filename
, type
); 
 524 bool wxBitmap::Create(int width
, int height
, int depth
) 
 526     return DoCreate(width
, height
, depth
, 0); 
 529 bool wxBitmap::Create(int width
, int height
, const wxDC
& dc
) 
 531     wxCHECK_MSG( dc
.IsOk(), false, wxT("invalid HDC in wxBitmap::Create()") ); 
 533     const wxMSWDCImpl 
*impl 
= wxDynamicCast( dc
.GetImpl(), wxMSWDCImpl 
); 
 536         return DoCreate(width
, height
, -1, impl
->GetHDC()); 
 541 bool wxBitmap::DoCreate(int w
, int h
, int d
, WXHDC hdc
) 
 545     m_refData 
= new wxBitmapRefData
; 
 547     GetBitmapData()->m_width 
= w
; 
 548     GetBitmapData()->m_height 
= h
; 
 550     HBITMAP hbmp    
wxDUMMY_INITIALIZE(0); 
 552 #ifndef NEVER_USE_DIB 
 553     if ( wxShouldCreateDIB(w
, h
, d
, hdc
) ) 
 557             // create DIBs without alpha channel by default 
 565         // don't delete the DIB section in dib object dtor 
 568         GetBitmapData()->m_isDIB 
= true; 
 569         GetBitmapData()->m_depth 
= d
; 
 572 #endif // NEVER_USE_DIB 
 574 #ifndef ALWAYS_USE_DIB 
 575 #ifndef __WXMICROWIN__ 
 578             hbmp 
= ::CreateBitmap(w
, h
, 1, d
, NULL
); 
 581                 wxLogLastError(wxT("CreateBitmap")); 
 584             GetBitmapData()->m_depth 
= d
; 
 586         else // d == 0, create bitmap compatible with the screen 
 587 #endif // !__WXMICROWIN__ 
 590             hbmp 
= ::CreateCompatibleBitmap(dc
, w
, h
); 
 593                 wxLogLastError(wxT("CreateCompatibleBitmap")); 
 596             GetBitmapData()->m_depth 
= wxDisplayDepth(); 
 598 #endif // !ALWAYS_USE_DIB 
 601     SetHBITMAP((WXHBITMAP
)hbmp
); 
 608 // ---------------------------------------------------------------------------- 
 609 // wxImage to/from conversions for Microwin 
 610 // ---------------------------------------------------------------------------- 
 612 // Microwin versions are so different from normal ones that it really doesn't 
 613 // make sense to use #ifdefs inside the function bodies 
 614 #ifdef __WXMICROWIN__ 
 616 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, const wxDC
& dc
) 
 618     // Set this to 1 to experiment with mask code, 
 619     // which currently doesn't work 
 622     m_refData 
= new wxBitmapRefData(); 
 624     // Initial attempt at a simple-minded implementation. 
 625     // The bitmap will always be created at the screen depth, 
 626     // so the 'depth' argument is ignored. 
 628     HDC hScreenDC 
= ::GetDC(NULL
); 
 629     int screenDepth 
= ::GetDeviceCaps(hScreenDC
, BITSPIXEL
); 
 631     HBITMAP hBitmap 
= ::CreateCompatibleBitmap(hScreenDC
, image
.GetWidth(), image
.GetHeight()); 
 632     HBITMAP hMaskBitmap 
= NULL
; 
 633     HBITMAP hOldMaskBitmap 
= NULL
; 
 635     unsigned char maskR 
= 0; 
 636     unsigned char maskG 
= 0; 
 637     unsigned char maskB 
= 0; 
 639     //    printf("Created bitmap %d\n", (int) hBitmap); 
 642         ::ReleaseDC(NULL
, hScreenDC
); 
 645     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 647     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 648     ::ReleaseDC(NULL
, hScreenDC
); 
 650     // created an mono-bitmap for the possible mask 
 651     bool hasMask 
= image
.HasMask(); 
 656         // FIXME: we should be able to pass bpp = 1, but 
 657         // GdBlit can't handle a different depth 
 659         hMaskBitmap 
= ::CreateBitmap( (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight(), 1, 1, NULL 
); 
 661         hMaskBitmap 
= ::CreateCompatibleBitmap( hMemDC
, (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight()); 
 663         maskR 
= image
.GetMaskRed(); 
 664         maskG 
= image
.GetMaskGreen(); 
 665         maskB 
= image
.GetMaskBlue(); 
 673             hScreenDC 
= ::GetDC(NULL
); 
 674             hMaskDC 
= ::CreateCompatibleDC(hScreenDC
); 
 675            ::ReleaseDC(NULL
, hScreenDC
); 
 677             hOldMaskBitmap 
= ::SelectObject( hMaskDC
, hMaskBitmap
); 
 685     for (i 
= 0; i 
< image
.GetWidth(); i
++) 
 687         for (j 
= 0; j 
< image
.GetHeight(); j
++) 
 689             unsigned char red 
= image
.GetRed(i
, j
); 
 690             unsigned char green 
= image
.GetGreen(i
, j
); 
 691             unsigned char blue 
= image
.GetBlue(i
, j
); 
 693             ::SetPixel(hMemDC
, i
, j
, PALETTERGB(red
, green
, blue
)); 
 697                 // scan the bitmap for the transparent colour and set the corresponding 
 698                 // pixels in the mask to BLACK and the rest to WHITE 
 699                 if (maskR 
== red 
&& maskG 
== green 
&& maskB 
== blue
) 
 700                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(0, 0, 0)); 
 702                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(255, 255, 255)); 
 707     ::SelectObject(hMemDC
, hOldBitmap
); 
 711         ::SelectObject(hMaskDC
, hOldMaskBitmap
); 
 714         ((wxBitmapRefData
*)m_refData
)->SetMask(hMaskBitmap
); 
 717     SetWidth(image
.GetWidth()); 
 718     SetHeight(image
.GetHeight()); 
 719     SetDepth(screenDepth
); 
 720     SetHBITMAP( (WXHBITMAP
) hBitmap 
); 
 723     // Copy the palette from the source image 
 724     SetPalette(image
.GetPalette()); 
 725 #endif // wxUSE_PALETTE 
 730 wxImage 
wxBitmap::ConvertToImage() const 
 732     // Initial attempt at a simple-minded implementation. 
 733     // The bitmap will always be created at the screen depth, 
 734     // so the 'depth' argument is ignored. 
 735     // TODO: transparency (create a mask image) 
 739         wxFAIL_MSG( wxT("bitmap is invalid") ); 
 745     wxCHECK_MSG( IsOk(), wxNullImage
, wxT("invalid bitmap") ); 
 747     // create an wxImage object 
 748     int width 
= GetWidth(); 
 749     int height 
= GetHeight(); 
 750     image
.Create( width
, height 
); 
 751     unsigned char *data 
= image
.GetData(); 
 754         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 758     HDC hScreenDC 
= ::GetDC(NULL
); 
 760     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 761     ::ReleaseDC(NULL
, hScreenDC
); 
 763     HBITMAP hBitmap 
= (HBITMAP
) GetHBITMAP(); 
 765     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 768     for (i 
= 0; i 
< GetWidth(); i
++) 
 770         for (j 
= 0; j 
< GetHeight(); j
++) 
 772             COLORREF color 
= ::GetPixel(hMemDC
, i
, j
); 
 773             unsigned char red 
= GetRValue(color
); 
 774             unsigned char green 
= GetGValue(color
); 
 775             unsigned char blue 
= GetBValue(color
); 
 777             image
.SetRGB(i
, j
, red
, green
, blue
); 
 781     ::SelectObject(hMemDC
, hOldBitmap
); 
 785     // Copy the palette from the source image 
 787         image
.SetPalette(* GetPalette()); 
 788 #endif // wxUSE_PALETTE 
 793 #endif // __WXMICROWIN__ 
 795 // ---------------------------------------------------------------------------- 
 796 // wxImage to/from conversions 
 797 // ---------------------------------------------------------------------------- 
 799 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
) 
 801     return CreateFromImage(image
, depth
, 0); 
 804 bool wxBitmap::CreateFromImage(const wxImage
& image
, const wxDC
& dc
) 
 806     wxCHECK_MSG( dc
.IsOk(), false, 
 807                     wxT("invalid HDC in wxBitmap::CreateFromImage()") ); 
 809     const wxMSWDCImpl 
*impl 
= wxDynamicCast( dc
.GetImpl(), wxMSWDCImpl 
); 
 812         return CreateFromImage(image
, -1, impl
->GetHDC()); 
 819 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, WXHDC hdc
) 
 821     wxCHECK_MSG( image
.IsOk(), false, wxT("invalid image") ); 
 825     // first convert the image to DIB 
 826     const int h 
= image
.GetHeight(); 
 827     const int w 
= image
.GetWidth(); 
 833     const bool hasAlpha 
= image
.HasAlpha(); 
 836       depth 
= dib
.GetDepth(); 
 838     // store the bitmap parameters 
 839     wxBitmapRefData 
* const refData 
= new wxBitmapRefData
; 
 840     refData
->m_width 
= w
; 
 841     refData
->m_height 
= h
; 
 842     refData
->m_hasAlpha 
= hasAlpha
; 
 843     refData
->m_depth 
= depth
; 
 848     // next either store DIB as is or create a DDB from it 
 849     HBITMAP hbitmap     
wxDUMMY_INITIALIZE(0); 
 851     // are we going to use DIB? 
 853     // NB: DDBs don't support alpha so if we have alpha channel we must use DIB 
 854     if ( hasAlpha 
|| wxShouldCreateDIB(w
, h
, depth
, hdc
) ) 
 856         // don't delete the DIB section in dib object dtor 
 857         hbitmap 
= dib
.Detach(); 
 859         refData
->m_isDIB 
= true; 
 861 #ifndef ALWAYS_USE_DIB 
 862     else // we need to convert DIB to DDB 
 864         hbitmap 
= dib
.CreateDDB((HDC
)hdc
); 
 866 #endif // !ALWAYS_USE_DIB 
 868     // validate this object 
 869     SetHBITMAP((WXHBITMAP
)hbitmap
); 
 871     // finally also set the mask if we have one 
 872     if ( image
.HasMask() ) 
 874         const size_t len  
= 2*((w
+15)/16); 
 875         BYTE 
*src  
= image
.GetData(); 
 876         BYTE 
*data 
= new BYTE
[h
*len
]; 
 877         memset(data
, 0, h
*len
); 
 878         BYTE r 
= image
.GetMaskRed(), 
 879              g 
= image
.GetMaskGreen(), 
 880              b 
= image
.GetMaskBlue(); 
 882         for ( int y 
= 0; y 
< h
; y
++, dst 
+= len 
) 
 886             for ( int x 
= 0; x 
< w
; x
++, src 
+= 3 ) 
 888                 if (src
[0] != r 
|| src
[1] != g 
|| src
[2] != b
) 
 891                 if ( (mask 
>>= 1) == 0 ) 
 899         hbitmap 
= ::CreateBitmap(w
, h
, 1, 1, data
); 
 902             wxLogLastError(wxT("CreateBitmap(mask)")); 
 906             SetMask(new wxMask((WXHBITMAP
)hbitmap
)); 
 915 wxImage 
wxBitmap::ConvertToImage() const 
 917     // convert DDB to DIB 
 925     // and then DIB to our wxImage 
 926     wxImage image 
= dib
.ConvertToImage(); 
 932     // now do the same for the mask, if we have any 
 933     HBITMAP hbmpMask 
= GetMask() ? (HBITMAP
) GetMask()->GetMaskBitmap() : NULL
; 
 936         wxDIB 
dibMask(hbmpMask
); 
 937         if ( dibMask
.IsOk() ) 
 939             // TODO: use wxRawBitmap to iterate over DIB 
 941             // we hard code the mask colour for now but we could also make an 
 942             // effort (and waste time) to choose a colour not present in the 
 943             // image already to avoid having to fudge the pixels below -- 
 944             // whether it's worth to do it is unclear however 
 945             static const int MASK_RED 
= 1; 
 946             static const int MASK_GREEN 
= 2; 
 947             static const int MASK_BLUE 
= 3; 
 948             static const int MASK_BLUE_REPLACEMENT 
= 2; 
 950             const int h 
= dibMask
.GetHeight(); 
 951             const int w 
= dibMask
.GetWidth(); 
 952             const int bpp 
= dibMask
.GetDepth(); 
 953             const int maskBytesPerPixel 
= bpp 
>> 3; 
 954             const int maskBytesPerLine 
= wxDIB::GetLineSize(w
, bpp
); 
 955             unsigned char *data 
= image
.GetData(); 
 957             // remember that DIBs are stored in bottom to top order 
 959                 maskLineStart 
= dibMask
.GetData() + ((h 
- 1) * maskBytesPerLine
); 
 961             for ( int y 
= 0; y 
< h
; y
++, maskLineStart 
-= maskBytesPerLine 
) 
 963                 // traverse one mask DIB line 
 964                 unsigned char *mask 
= maskLineStart
; 
 965                 for ( int x 
= 0; x 
< w
; x
++, mask 
+= maskBytesPerPixel 
) 
 967                     // should this pixel be transparent? 
 970                         // no, check that it isn't transparent by accident 
 971                         if ( (data
[0] == MASK_RED
) && 
 972                                 (data
[1] == MASK_GREEN
) && 
 973                                     (data
[2] == MASK_BLUE
) ) 
 975                             // we have to fudge the colour a bit to prevent 
 976                             // this pixel from appearing transparent 
 977                             data
[2] = MASK_BLUE_REPLACEMENT
; 
 982                     else // yes, transparent pixel 
 985                         *data
++ = MASK_GREEN
; 
 991             image
.SetMaskColour(MASK_RED
, MASK_GREEN
, MASK_BLUE
); 
 998 #else // !wxUSE_WXDIB 
1001 wxBitmap::CreateFromImage(const wxImage
& WXUNUSED(image
), 
1002                           int WXUNUSED(depth
), 
1003                           WXHDC 
WXUNUSED(hdc
)) 
1008 wxImage 
wxBitmap::ConvertToImage() const 
1013 #endif // wxUSE_WXDIB/!wxUSE_WXDIB 
1015 #endif // wxUSE_IMAGE 
1017 // ---------------------------------------------------------------------------- 
1018 // loading and saving bitmaps 
1019 // ---------------------------------------------------------------------------- 
1021 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
) 
1025     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1029         m_refData 
= new wxBitmapRefData
; 
1031         return handler
->LoadFile(this, filename
, type
, -1, -1); 
1033 #if wxUSE_IMAGE && wxUSE_WXDIB 
1034     else // no bitmap handler found 
1037         if ( image
.LoadFile( filename
, type 
) && image
.IsOk() ) 
1039             *this = wxBitmap(image
); 
1044 #endif // wxUSE_IMAGE 
1049 bool wxBitmap::Create(const void* data
, wxBitmapType type
, int width
, int height
, int depth
) 
1053     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1057         wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), type
); 
1062     m_refData 
= new wxBitmapRefData
; 
1064     return handler
->Create(this, data
, type
, width
, height
, depth
); 
1067 bool wxBitmap::SaveFile(const wxString
& filename
, 
1069                         const wxPalette 
*palette
) const 
1071     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
1075         return handler
->SaveFile(this, filename
, type
, palette
); 
1077 #if wxUSE_IMAGE && wxUSE_WXDIB 
1078     else // no bitmap handler found 
1080         // FIXME what about palette? shouldn't we use it? 
1081         wxImage image 
= ConvertToImage(); 
1084             return image
.SaveFile(filename
, type
); 
1087 #endif // wxUSE_IMAGE 
1092 // ---------------------------------------------------------------------------- 
1093 // sub bitmap extraction 
1094 // ---------------------------------------------------------------------------- 
1095 wxBitmap 
wxBitmap::GetSubBitmap( const wxRect
& rect 
) const 
1098         SelectInHDC 
selectSrc(dcSrc
, GetHbitmap()); 
1099         return GetSubBitmapOfHDC( rect
, (WXHDC
)dcSrc 
); 
1102 wxBitmap 
wxBitmap::GetSubBitmapOfHDC( const wxRect
& rect
, WXHDC hdc 
) const 
1104     wxCHECK_MSG( IsOk() && 
1105                  (rect
.x 
>= 0) && (rect
.y 
>= 0) && 
1106                  (rect
.x
+rect
.width 
<= GetWidth()) && 
1107                  (rect
.y
+rect
.height 
<= GetHeight()), 
1108                  wxNullBitmap
, wxT("Invalid bitmap or bitmap region") ); 
1110     wxBitmap 
ret( rect
.width
, rect
.height
, GetDepth() ); 
1111     wxASSERT_MSG( ret
.IsOk(), wxT("GetSubBitmap error") ); 
1113 #ifndef __WXMICROWIN__ 
1114     // handle alpha channel, if any 
1123         SelectInHDC 
selectDst(dcDst
, GetHbitmapOf(ret
)); 
1127             wxLogLastError(wxT("SelectObject(destBitmap)")); 
1130         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
1131                        (HDC
)hdc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
1133             wxLogLastError(wxT("BitBlt")); 
1137     // copy mask if there is one 
1140         HBITMAP hbmpMask 
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0); 
1142         SelectInHDC 
selectSrc(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap()), 
1143                     selectDst(dcDst
, hbmpMask
); 
1145         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
1146                        dcSrc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
1148             wxLogLastError(wxT("BitBlt")); 
1151         wxMask 
*mask 
= new wxMask((WXHBITMAP
) hbmpMask
); 
1154 #endif // !__WXMICROWIN__ 
1159 // ---------------------------------------------------------------------------- 
1160 // wxBitmap accessors 
1161 // ---------------------------------------------------------------------------- 
1164 wxPalette
* wxBitmap::GetPalette() const 
1166     return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
 
1171 wxMask 
*wxBitmap::GetMask() const 
1173     return GetBitmapData() ? GetBitmapData()->GetMask() : NULL
; 
1176 wxDC 
*wxBitmap::GetSelectedInto() const 
1179     return GetBitmapData() ? GetBitmapData()->m_selectedInto 
: NULL
; 
1185 void wxBitmap::UseAlpha() 
1187     if ( GetBitmapData() ) 
1188         GetBitmapData()->m_hasAlpha 
= true; 
1191 bool wxBitmap::HasAlpha() const 
1193     return GetBitmapData() && GetBitmapData()->m_hasAlpha
; 
1196 // ---------------------------------------------------------------------------- 
1198 // ---------------------------------------------------------------------------- 
1200 void wxBitmap::SetSelectedInto(wxDC 
*dc
) 
1203     if ( GetBitmapData() ) 
1204         GetBitmapData()->m_selectedInto 
= dc
; 
1212 void wxBitmap::SetPalette(const wxPalette
& palette
) 
1216     GetBitmapData()->m_bitmapPalette 
= palette
; 
1219 #endif // wxUSE_PALETTE 
1221 void wxBitmap::SetMask(wxMask 
*mask
) 
1225     GetBitmapData()->SetMask(mask
); 
1228 // ---------------------------------------------------------------------------- 
1229 // raw bitmap access support 
1230 // ---------------------------------------------------------------------------- 
1232 #ifdef wxHAS_RAW_BITMAP 
1234 void *wxBitmap::GetRawData(wxPixelDataBase
& data
, int bpp
) 
1239         // no bitmap, no data (raw or otherwise) 
1243     // if we're already a DIB we can access our data directly, but if not we 
1244     // need to convert this DDB to a DIB section and use it for raw access and 
1245     // then convert it back 
1247     if ( !GetBitmapData()->m_isDIB 
) 
1249         wxCHECK_MSG( !GetBitmapData()->m_dib
, NULL
, 
1250                         wxT("GetRawData() may be called only once") ); 
1252         wxDIB 
*dib 
= new wxDIB(*this); 
1260         // we'll free it in UngetRawData() 
1261         GetBitmapData()->m_dib 
= dib
; 
1263         hDIB 
= dib
->GetHandle(); 
1267         hDIB 
= GetHbitmap(); 
1271     if ( ::GetObject(hDIB
, sizeof(ds
), &ds
) != sizeof(DIBSECTION
) ) 
1273         wxFAIL_MSG( wxT("failed to get DIBSECTION from a DIB?") ); 
1278     // check that the bitmap is in correct format 
1279     if ( ds
.dsBm
.bmBitsPixel 
!= bpp 
) 
1281         wxFAIL_MSG( wxT("incorrect bitmap type in wxBitmap::GetRawData()") ); 
1286     // ok, store the relevant info in wxPixelDataBase 
1287     const LONG h 
= ds
.dsBm
.bmHeight
; 
1289     data
.m_width 
= ds
.dsBm
.bmWidth
; 
1292     // remember that DIBs are stored in top to bottom order! 
1293     // (We can't just use ds.dsBm.bmWidthBytes here, because it isn't always a 
1294     // multiple of 2, as required by the documentation.  So we use the official 
1295     // formula, which we already use elsewhere.) 
1296     const LONG bytesPerRow 
= 
1297         wxDIB::GetLineSize(ds
.dsBm
.bmWidth
, ds
.dsBm
.bmBitsPixel
); 
1298     data
.m_stride 
= -bytesPerRow
; 
1300     char *bits 
= (char *)ds
.dsBm
.bmBits
; 
1303         bits 
+= (h 
- 1)*bytesPerRow
; 
1312 void wxBitmap::UngetRawData(wxPixelDataBase
& dataBase
) 
1320         // invalid data, don't crash -- but don't assert neither as we're 
1321         // called automatically from wxPixelDataBase dtor and so there is no 
1322         // way to prevent this from happening 
1326     // if we're a DDB we need to convert DIB back to DDB now to make the 
1327     // changes made via raw bitmap access effective 
1328     if ( !GetBitmapData()->m_isDIB 
) 
1330         wxDIB 
*dib 
= GetBitmapData()->m_dib
; 
1331         GetBitmapData()->m_dib 
= NULL
; 
1337 #endif // wxUSE_WXDIB 
1339 #endif // wxHAS_RAW_BITMAP 
1341 // ---------------------------------------------------------------------------- 
1343 // ---------------------------------------------------------------------------- 
1351 wxMask::wxMask(const wxMask 
&mask
) 
1356     HDC srcDC 
= CreateCompatibleDC(0); 
1357     HDC destDC 
= CreateCompatibleDC(0); 
1359     // GetBitmapDimensionEx won't work if SetBitmapDimensionEx wasn't used 
1360     // so we'll use GetObject() API here: 
1361     if (::GetObject((HGDIOBJ
)mask
.m_maskBitmap
, sizeof(bmp
), &bmp
) == 0) 
1363         wxFAIL_MSG(wxT("Cannot retrieve the dimensions of the wxMask to copy")); 
1367     // create our HBITMAP 
1368     int w 
= bmp
.bmWidth
, h 
= bmp
.bmHeight
; 
1369     m_maskBitmap 
= (WXHBITMAP
)CreateCompatibleBitmap(srcDC
, w
, h
); 
1371     // copy the mask's HBITMAP into our HBITMAP 
1372     SelectObject(srcDC
, (HBITMAP
) mask
.m_maskBitmap
); 
1373     SelectObject(destDC
, (HBITMAP
) m_maskBitmap
); 
1375     BitBlt(destDC
, 0, 0, w
, h
, srcDC
, 0, 0, SRCCOPY
); 
1377     SelectObject(srcDC
, 0); 
1379     SelectObject(destDC
, 0); 
1383 // Construct a mask from a bitmap and a colour indicating 
1384 // the transparent area 
1385 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1388     Create(bitmap
, colour
); 
1391 // Construct a mask from a bitmap and a palette index indicating 
1392 // the transparent area 
1393 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
) 
1396     Create(bitmap
, paletteIndex
); 
1399 // Construct a mask from a mono bitmap (copies the bitmap). 
1400 wxMask::wxMask(const wxBitmap
& bitmap
) 
1409         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1412 // Create a mask from a mono bitmap (copies the bitmap). 
1413 bool wxMask::Create(const wxBitmap
& bitmap
) 
1415 #ifndef __WXMICROWIN__ 
1416     wxCHECK_MSG( bitmap
.IsOk() && bitmap
.GetDepth() == 1, false, 
1417                  wxT("can't create mask from invalid or not monochrome bitmap") ); 
1421         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1425     m_maskBitmap 
= (WXHBITMAP
) CreateBitmap( 
1430     HDC srcDC 
= CreateCompatibleDC(0); 
1431     SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP()); 
1432     HDC destDC 
= CreateCompatibleDC(0); 
1433     SelectObject(destDC
, (HBITMAP
) m_maskBitmap
); 
1434     BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
); 
1435     SelectObject(srcDC
, 0); 
1437     SelectObject(destDC
, 0); 
1441     wxUnusedVar(bitmap
); 
1446 // Create a mask from a bitmap and a palette index indicating 
1447 // the transparent area 
1448 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
) 
1452         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1457     if (bitmap
.IsOk() && bitmap
.GetPalette()->IsOk()) 
1459         unsigned char red
, green
, blue
; 
1460         if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
)) 
1462             wxColour 
transparentColour(red
, green
, blue
); 
1463             return Create(bitmap
, transparentColour
); 
1466 #endif // wxUSE_PALETTE 
1471 // Create a mask from a bitmap and a colour indicating 
1472 // the transparent area 
1473 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1475 #ifndef __WXMICROWIN__ 
1476     wxCHECK_MSG( bitmap
.IsOk(), false, wxT("invalid bitmap in wxMask::Create") ); 
1480         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1484     int width 
= bitmap
.GetWidth(), 
1485         height 
= bitmap
.GetHeight(); 
1487     // scan the bitmap for the transparent colour and set the corresponding 
1488     // pixels in the mask to BLACK and the rest to WHITE 
1489     COLORREF maskColour 
= wxColourToPalRGB(colour
); 
1490     m_maskBitmap 
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0); 
1492     HDC srcDC 
= ::CreateCompatibleDC(NULL
); 
1493     HDC destDC 
= ::CreateCompatibleDC(NULL
); 
1494     if ( !srcDC 
|| !destDC 
) 
1496         wxLogLastError(wxT("CreateCompatibleDC")); 
1501     // SelectObject() will fail 
1502     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1503                   wxT("bitmap can't be selected in another DC") ); 
1505     HGDIOBJ hbmpSrcOld 
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
)); 
1508         wxLogLastError(wxT("SelectObject")); 
1513     HGDIOBJ hbmpDstOld 
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
); 
1516         wxLogLastError(wxT("SelectObject")); 
1523         // this will create a monochrome bitmap with 0 points for the pixels 
1524         // which have the same value as the background colour and 1 for the 
1526         ::SetBkColor(srcDC
, maskColour
); 
1527         ::BitBlt(destDC
, 0, 0, width
, height
, srcDC
, 0, 0, NOTSRCCOPY
); 
1530     ::SelectObject(srcDC
, hbmpSrcOld
); 
1532     ::SelectObject(destDC
, hbmpDstOld
); 
1536 #else // __WXMICROWIN__ 
1537     wxUnusedVar(bitmap
); 
1538     wxUnusedVar(colour
); 
1540 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
1543 wxBitmap 
wxMask::GetBitmap() const 
1546     bmp
.SetHBITMAP(m_maskBitmap
); 
1550 // ---------------------------------------------------------------------------- 
1552 // ---------------------------------------------------------------------------- 
1554 bool wxBitmapHandler::Create(wxGDIImage 
*image
, 
1557                              int width
, int height
, int depth
) 
1559     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1561     return bitmap 
&& Create(bitmap
, data
, type
, width
, height
, depth
); 
1564 bool wxBitmapHandler::Load(wxGDIImage 
*image
, 
1565                            const wxString
& name
, 
1567                            int width
, int height
) 
1569     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1571     return bitmap 
&& LoadFile(bitmap
, name
, type
, width
, height
); 
1574 bool wxBitmapHandler::Save(const wxGDIImage 
*image
, 
1575                            const wxString
& name
, 
1576                            wxBitmapType type
) const 
1578     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1580     return bitmap 
&& SaveFile(bitmap
, name
, type
); 
1583 bool wxBitmapHandler::Create(wxBitmap 
*WXUNUSED(bitmap
), 
1584                              const void* WXUNUSED(data
), 
1585                              wxBitmapType 
WXUNUSED(type
), 
1586                              int WXUNUSED(width
), 
1587                              int WXUNUSED(height
), 
1588                              int WXUNUSED(depth
)) 
1593 bool wxBitmapHandler::LoadFile(wxBitmap 
*WXUNUSED(bitmap
), 
1594                                const wxString
& WXUNUSED(name
), 
1595                                wxBitmapType 
WXUNUSED(type
), 
1596                                int WXUNUSED(desiredWidth
), 
1597                                int WXUNUSED(desiredHeight
)) 
1602 bool wxBitmapHandler::SaveFile(const wxBitmap 
*WXUNUSED(bitmap
), 
1603                                const wxString
& WXUNUSED(name
), 
1604                                wxBitmapType 
WXUNUSED(type
), 
1605                                const wxPalette 
*WXUNUSED(palette
)) const 
1610 // ---------------------------------------------------------------------------- 
1611 // global helper functions implemented here 
1612 // ---------------------------------------------------------------------------- 
1614 // helper of wxBitmapToHICON/HCURSOR 
1616 HICON 
wxBitmapToIconOrCursor(const wxBitmap
& bmp
, 
1623         // we can't create an icon/cursor form nothing 
1627     if ( bmp
.HasAlpha() ) 
1631 #if wxUSE_WXDIB && wxUSE_IMAGE 
1632         // CreateIconIndirect() requires non-pre-multiplied pixel data on input 
1633         // as it does pre-multiplication internally itself so we need to create 
1634         // a special DIB in such format to pass to it. This is inefficient but 
1635         // better than creating an icon with wrong colours. 
1636         AutoHBITMAP hbmpRelease
; 
1637         hbmp 
= wxDIB(bmp
.ConvertToImage(), 
1638                      wxDIB::PixelFormat_NotPreMultiplied
).Detach(); 
1639         hbmpRelease
.Init(hbmp
); 
1640 #else // !(wxUSE_WXDIB && wxUSE_IMAGE) 
1641         hbmp 
= GetHbitmapOf(bmp
); 
1642 #endif // wxUSE_WXDIB && wxUSE_IMAGE 
1644         // Create an empty mask bitmap. 
1645         // it doesn't seem to work if we mess with the mask at all. 
1647             hMonoBitmap(CreateBitmap(bmp
.GetWidth(),bmp
.GetHeight(),1,1,NULL
)); 
1650         wxZeroMemory(iconInfo
); 
1651         iconInfo
.fIcon 
= iconWanted
;  // do we want an icon or a cursor? 
1654             iconInfo
.xHotspot 
= hotSpotX
; 
1655             iconInfo
.yHotspot 
= hotSpotY
; 
1658         iconInfo
.hbmMask 
= hMonoBitmap
; 
1659         iconInfo
.hbmColor 
= hbmp
; 
1661         return ::CreateIconIndirect(&iconInfo
); 
1664     wxMask
* mask 
= bmp
.GetMask(); 
1668         // we must have a mask for an icon, so even if it's probably incorrect, 
1669         // do create it (grey is the "standard" transparent colour) 
1670         mask 
= new wxMask(bmp
, *wxLIGHT_GREY
); 
1674     wxZeroMemory(iconInfo
); 
1675     iconInfo
.fIcon 
= iconWanted
;  // do we want an icon or a cursor? 
1678         iconInfo
.xHotspot 
= hotSpotX
; 
1679         iconInfo
.yHotspot 
= hotSpotY
; 
1682     AutoHBITMAP 
hbmpMask(wxInvertMask((HBITMAP
)mask
->GetMaskBitmap())); 
1683     iconInfo
.hbmMask 
= hbmpMask
; 
1684     iconInfo
.hbmColor 
= GetHbitmapOf(bmp
); 
1686     // black out the transparent area to preserve background colour, because 
1687     // Windows blits the original bitmap using SRCINVERT (XOR) after applying 
1688     // the mask to the dest rect. 
1690         MemoryHDC dcSrc
, dcDst
; 
1691         SelectInHDC 
selectMask(dcSrc
, (HBITMAP
)mask
->GetMaskBitmap()), 
1692                     selectBitmap(dcDst
, iconInfo
.hbmColor
); 
1694         if ( !::BitBlt(dcDst
, 0, 0, bmp
.GetWidth(), bmp
.GetHeight(), 
1695                        dcSrc
, 0, 0, SRCAND
) ) 
1697             wxLogLastError(wxT("BitBlt")); 
1701     HICON hicon 
= ::CreateIconIndirect(&iconInfo
); 
1703     if ( !bmp
.GetMask() && !bmp
.HasAlpha() ) 
1705         // we created the mask, now delete it 
1712 HICON 
wxBitmapToHICON(const wxBitmap
& bmp
) 
1714     return wxBitmapToIconOrCursor(bmp
, true, 0, 0); 
1717 HCURSOR 
wxBitmapToHCURSOR(const wxBitmap
& bmp
, int hotSpotX
, int hotSpotY
) 
1719     return (HCURSOR
)wxBitmapToIconOrCursor(bmp
, false, hotSpotX
, hotSpotY
); 
1722 HBITMAP 
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
) 
1724 #ifndef __WXMICROWIN__ 
1725     wxCHECK_MSG( hbmpMask
, 0, wxT("invalid bitmap in wxInvertMask") ); 
1727     // get width/height from the bitmap if not given 
1731         ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
); 
1736     HDC hdcSrc 
= ::CreateCompatibleDC(NULL
); 
1737     HDC hdcDst 
= ::CreateCompatibleDC(NULL
); 
1738     if ( !hdcSrc 
|| !hdcDst 
) 
1740         wxLogLastError(wxT("CreateCompatibleDC")); 
1743     HBITMAP hbmpInvMask 
= ::CreateBitmap(w
, h
, 1, 1, 0); 
1746         wxLogLastError(wxT("CreateBitmap")); 
1749     HGDIOBJ srcTmp 
= ::SelectObject(hdcSrc
, hbmpMask
); 
1750     HGDIOBJ dstTmp 
= ::SelectObject(hdcDst
, hbmpInvMask
); 
1751     if ( !::BitBlt(hdcDst
, 0, 0, w
, h
, 
1755         wxLogLastError(wxT("BitBlt")); 
1759     SelectObject(hdcSrc
,srcTmp
); 
1760     SelectObject(hdcDst
,dstTmp
);