diff --git a/include/wx/msw/statbmp.h b/include/wx/msw/statbmp.h index 1e88548995..39b0cbbd4b 100644 --- a/include/wx/msw/statbmp.h +++ b/include/wx/msw/statbmp.h @@ -25,7 +25,20 @@ public: wxStaticBitmap(wxWindow *parent, wxWindowID id, - const wxGDIImage& label, + const wxBitmap& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxASCII_STR(wxStaticBitmapNameStr)) + { + Init(); + + Create(parent, id, label, pos, size, style, name); + } + + wxStaticBitmap(wxWindow *parent, + wxWindowID id, + const wxIcon& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, @@ -38,16 +51,34 @@ public: bool Create(wxWindow *parent, wxWindowID id, - const wxGDIImage& label, + const wxBitmap& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxASCII_STR(wxStaticBitmapNameStr)); + const wxString& name = wxASCII_STR(wxStaticBitmapNameStr)) + { + m_bitmap = label; + + return DoCreate(parent, id, pos, size, style, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxIcon& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxASCII_STR(wxStaticBitmapNameStr)) + { + m_icon = label; + + return DoCreate(parent, id, pos, size, style, name); + } virtual ~wxStaticBitmap() { Free(); } - virtual void SetIcon(const wxIcon& icon) wxOVERRIDE { SetImage(&icon); } - virtual void SetBitmap(const wxBitmap& bitmap) wxOVERRIDE { SetImage(&bitmap); } + virtual void SetIcon(const wxIcon& icon) wxOVERRIDE; + virtual void SetBitmap(const wxBitmap& bitmap) wxOVERRIDE; virtual wxBitmap GetBitmap() const wxOVERRIDE; virtual wxIcon GetIcon() const wxOVERRIDE; @@ -59,15 +90,23 @@ public: protected: virtual wxSize DoGetBestClientSize() const wxOVERRIDE; +private: // ctor/dtor helpers void Init(); void Free(); - // true if icon/bitmap is valid - bool ImageIsOk() const; + // common part of both Create() overloads + bool DoCreate(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name); - void SetImage(const wxGDIImage* image); - void SetImageNoCopy( wxGDIImage* image ); + // update the image to correspond to the current m_icon or m_bitmap value, + // resize the control if the new size is different from the old one and + // update its style if the new "is icon" value differs from the old one + void DoUpdateImage(const wxSize& sizeOld, bool wasIcon); // draw the bitmap ourselves here if the OS can't do it correctly (if it // can we leave it to it) @@ -75,14 +114,19 @@ protected: void WXHandleSize(wxSizeEvent& event); - // we can have either an icon or a bitmap - bool m_isIcon; - wxGDIImage *m_image; + // return the either m_icon or m_bitmap (may still be invalid of both of + // them are) + const wxGDIImage& GetImage() const; + + + // we can have either an icon or a bitmap: if m_icon is valid, it is used, + // otherwise m_bitmap is used if it is valid + wxIcon m_icon; + wxBitmap m_bitmap; // handle used in last call to STM_SETIMAGE WXHANDLE m_currentHandle; -private: // Flag indicating whether we own m_currentHandle, i.e. should delete it. bool m_ownsCurrentHandle; diff --git a/src/msw/statbmp.cpp b/src/msw/statbmp.cpp index 4c6d7cc2a1..7c157ab9e7 100644 --- a/src/msw/statbmp.cpp +++ b/src/msw/statbmp.cpp @@ -55,41 +55,8 @@ wxEND_EVENT_TABLE() // wxStaticBitmap // --------------------------------------------------------------------------- -// we may have either bitmap or icon: if a bitmap with mask is passed, we -// will transform it to an icon ourselves because otherwise the mask will -// be ignored by Windows -// note that this function will create a new object every time -// it is called even if the image needs no conversion - -static wxGDIImage* ConvertImage( const wxGDIImage& bitmap ) -{ - bool isIcon = bitmap.IsKindOf( wxCLASSINFO(wxIcon) ); - - if( !isIcon ) - { - wxASSERT_MSG( wxDynamicCast(&bitmap, wxBitmap), - wxT("not an icon and not a bitmap?") ); - - const wxBitmap& bmp = (const wxBitmap&)bitmap; - wxMask *mask = bmp.GetMask(); - if ( mask && mask->GetMaskBitmap() ) - { - wxIcon* icon = new wxIcon; - icon->CopyFromBitmap(bmp); - - return icon; - } - - return new wxBitmap( bmp ); - } - - // copying a bitmap is a cheap operation - return new wxIcon( (const wxIcon&)bitmap ); -} - -bool wxStaticBitmap::Create(wxWindow *parent, +bool wxStaticBitmap::DoCreate(wxWindow *parent, wxWindowID id, - const wxGDIImage& bitmap, const wxPoint& pos, const wxSize& size, long style, @@ -98,17 +65,6 @@ bool wxStaticBitmap::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) return false; - // we may have either bitmap or icon: if a bitmap with mask is passed, we - // will transform it to an icon ourselves because otherwise the mask will - // be ignored by Windows - wxGDIImage *image = ConvertImage( bitmap ); - - // Note that m_isIcon must be set before calling MSWCreateControl() so that - // it creates the control with the correct style, as returned by - // MSWGetStyle(), which uses m_isIcon to determine whether to use SS_ICON - // or SS_BITMAP. - m_isIcon = image->IsKindOf( wxCLASSINFO(wxIcon) ); - // create the native control if ( !MSWCreateControl(wxT("STATIC"), wxEmptyString, pos, size) ) { @@ -116,8 +72,7 @@ bool wxStaticBitmap::Create(wxWindow *parent, return false; } - // no need to delete the new image - SetImageNoCopy(image); + DoUpdateImage(wxSize(), m_icon.IsOk()); // GetBestSize will work properly now, so set the best size if needed SetInitialSize(size); @@ -139,7 +94,7 @@ WXDWORD wxStaticBitmap::MSWGetStyle(long style, WXDWORD *exstyle) const WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle); // what kind of control are we? - msStyle |= m_isIcon ? SS_ICON : SS_BITMAP; + msStyle |= m_icon.IsOk() ? SS_ICON : SS_BITMAP; // we use SS_CENTERIMAGE to prevent the control from resizing the bitmap to // fit to its size -- this is unexpected and doesn't happen in other ports @@ -150,43 +105,58 @@ WXDWORD wxStaticBitmap::MSWGetStyle(long style, WXDWORD *exstyle) const return msStyle; } -bool wxStaticBitmap::ImageIsOk() const +const wxGDIImage& wxStaticBitmap::GetImage() const { - return m_image && m_image->IsOk(); + // Note: do not use ternary operator here to avoid unwanted conversions + // from wxIcon to wxBitmap. + if ( m_icon.IsOk() ) + return m_icon; + + return m_bitmap; +} + +void wxStaticBitmap::SetIcon(const wxIcon& icon) +{ + const wxSize sizeOld = GetImage().GetSize(); + const bool wasIcon = m_icon.IsOk(); + + m_icon = icon; + m_bitmap = wxBitmap(); + + DoUpdateImage(sizeOld, wasIcon); +} + +void wxStaticBitmap::SetBitmap(const wxBitmap& bitmap) +{ + const wxSize sizeOld = GetImage().GetSize(); + const bool wasIcon = m_icon.IsOk(); + + m_icon = wxIcon(); + m_bitmap = bitmap; + + DoUpdateImage(sizeOld, wasIcon); } wxIcon wxStaticBitmap::GetIcon() const { - wxCHECK_MSG( m_image, wxIcon(), wxT("no image in wxStaticBitmap") ); + wxIcon icon = m_icon; + if ( !icon.IsOk() && m_bitmap.IsOk() ) + icon.CopyFromBitmap(m_bitmap); - // we can't ask for an icon if all we have is a bitmap - wxCHECK_MSG( m_isIcon, wxIcon(), wxT("no icon in this wxStaticBitmap") ); - - return *(wxIcon *)m_image; + return icon; } wxBitmap wxStaticBitmap::GetBitmap() const { - if ( m_isIcon ) - { - // don't fail because we might have replaced the bitmap with icon - // ourselves internally in ConvertImage() to keep the transparency but - // the user code doesn't know about it so it still can use GetBitmap() - // to retrieve the bitmap - return wxBitmap(GetIcon()); - } - else // we have a bitmap - { - wxCHECK_MSG( m_image, wxBitmap(), wxT("no image in wxStaticBitmap") ); + wxBitmap bitmap = m_bitmap; + if ( !bitmap.IsOk() && m_icon.IsOk() ) + bitmap.CopyFromIcon(m_icon); - return *(wxBitmap *)m_image; - } + return bitmap; } void wxStaticBitmap::Init() { - m_isIcon = true; - m_image = NULL; m_currentHandle = 0; m_ownsCurrentHandle = false; } @@ -200,16 +170,15 @@ void wxStaticBitmap::Free() ::DeleteObject(m_currentHandle); m_ownsCurrentHandle = false; } - - wxDELETE(m_image); } wxSize wxStaticBitmap::DoGetBestClientSize() const { wxSize size; - if ( ImageIsOk() ) + const wxGDIImage& image = GetImage(); + if ( image.IsOk() ) { - size = m_image->GetSize(); + size = image.GetSize(); } else // No image yet { @@ -252,16 +221,10 @@ void wxStaticBitmap::DoPaintManually(wxPaintEvent& WXUNUSED(event)) true /* use mask */); } -void wxStaticBitmap::SetImage( const wxGDIImage* image ) -{ - wxGDIImage* convertedImage = ConvertImage( *image ); - SetImageNoCopy( convertedImage ); -} - void wxStaticBitmap::MSWReplaceImageHandle(WXLPARAM handle) { HGDIOBJ oldHandle = (HGDIOBJ)::SendMessage(GetHwnd(), STM_SETIMAGE, - m_isIcon ? IMAGE_ICON : IMAGE_BITMAP, (LPARAM)handle); + m_icon.IsOk() ? IMAGE_ICON : IMAGE_BITMAP, (LPARAM)handle); // detect if this is still the handle we passed before or // if the static-control made a copy of the bitmap! if (oldHandle != 0 && oldHandle != (HGDIOBJ) m_currentHandle) @@ -271,53 +234,41 @@ void wxStaticBitmap::MSWReplaceImageHandle(WXLPARAM handle) } } -void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image) +void wxStaticBitmap::DoUpdateImage(const wxSize& sizeOld, bool wasIcon) { - wxSize sizeOld; - if ( m_image ) - sizeOld = m_image->GetSize(); - - wxSize sizeNew; - if ( image ) - sizeNew = image->GetSize(); - - const bool wasIcon = m_isIcon; + const wxSize sizeNew = GetImage().GetSize(); + const bool isIcon = m_icon.IsOk(); Free(); - m_isIcon = image->IsKindOf( wxCLASSINFO(wxIcon) ); - // the image has already been copied - m_image = image; - // Normally we just use the handle of provided image but in some cases we // create our own temporary bitmap, so the actual handle may end up being // different from the original one. - const HANDLE handleOrig = (HANDLE)m_image->GetHandle(); + const HANDLE handleOrig = (HANDLE)GetImage().GetHandle(); HANDLE handle = handleOrig; #if wxUSE_WXDIB - if ( !m_isIcon ) + if ( !isIcon ) { // wxBitmap normally stores alpha in pre-multiplied format but // apparently STM_SETIMAGE message handler does pre-multiplication // internally so we need to undo the pre-multiplication here for a // while (this is similar to what we do in ImageList::Add()). - const wxBitmap& bmp = static_cast(*image); - if ( bmp.HasAlpha() ) + if ( m_bitmap.HasAlpha() ) { // For bitmap with alpha channel create temporary DIB with // not-premultiplied alpha values. - handle = wxDIB(bmp.ConvertToImage(), + handle = wxDIB(m_bitmap.ConvertToImage(), wxDIB::PixelFormat_NotPreMultiplied).Detach(); } } #endif // wxUSE_WXDIB - if ( m_isIcon != wasIcon ) + if ( isIcon != wasIcon ) { wxMSWWinStyleUpdater(GetHwnd()) .TurnOff(SS_BITMAP | SS_ICON) - .TurnOn(m_isIcon ? SS_ICON : SS_BITMAP); + .TurnOn(isIcon ? SS_ICON : SS_BITMAP); } MSWReplaceImageHandle((WXLPARAM)handle);