X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/95912bdddeb21afe1cabc0401c0f8b8475a5e5c6..e3778b4d9c7eebc39f496a9dd055638e06fb9140:/src/msw/button.cpp diff --git a/src/msw/button.cpp b/src/msw/button.cpp index de442f98e5..10bb135fb5 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -115,6 +115,10 @@ using namespace wxMSWImpl; #define BCM_SETSHIELD 0x160c #endif +#if wxUSE_UXTHEME +extern wxWindowMSW *wxWindowBeingErased; // From src/msw/window.cpp +#endif // wxUSE_UXTHEME + // ---------------------------------------------------------------------------- // button image data // ---------------------------------------------------------------------------- @@ -153,6 +157,7 @@ public: wxODButtonImageData(wxButton *btn, const wxBitmap& bitmap) { SetBitmap(bitmap, wxButton::State_Normal); + SetBitmap(bitmap.ConvertToDisabled(), wxButton::State_Disabled); m_dir = wxLEFT; @@ -221,10 +226,11 @@ public: wxButton::State_Max), m_hwndBtn(GetHwndOf(btn)) { - // initialize all bitmaps to normal state + // initialize all bitmaps except for the disabled one to normal state for ( int n = 0; n < wxButton::State_Max; n++ ) { - m_iml.Add(bitmap); + m_iml.Add(n == wxButton::State_Disabled ? bitmap.ConvertToDisabled() + : bitmap); } m_data.himl = GetHimagelistOf(&m_iml); @@ -512,7 +518,7 @@ WXDWORD wxButton::MSWGetStyle(long style, WXDWORD *exstyle) const ); // we must use WS_CLIPSIBLINGS with the buttons or they would draw over - // each other in any resizeable dialog which has more than one button in + // each other in any resizable dialog which has more than one button in // the bottom msStyle |= WS_CLIPSIBLINGS; @@ -987,6 +993,30 @@ wxBitmap wxButton::DoGetBitmap(State which) const void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which) { +#if wxUSE_UXTHEME + wxXPButtonImageData *oldData = NULL; +#endif // wxUSE_UXTHEME + + // Check if we already had bitmaps of different size. + if ( m_imageData && + bitmap.GetSize() != m_imageData->GetBitmap(State_Normal).GetSize() ) + { + wxASSERT_MSG( which == State_Normal, + "Must set normal bitmap with the new size first" ); + +#if wxUSE_UXTHEME + if ( ShowsLabel() && wxUxThemeEngine::GetIfActive() ) + { + // We can't change the size of the images stored in wxImageList + // in wxXPButtonImageData::m_iml so force recreating it below but + // keep the current data to copy its values into the new one. + oldData = static_cast(m_imageData); + m_imageData = NULL; + } +#endif // wxUSE_UXTHEME + //else: wxODButtonImageData doesn't require anything special + } + // allocate the image data when the first bitmap is set if ( !m_imageData ) { @@ -998,6 +1028,20 @@ void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which) if ( ShowsLabel() && wxUxThemeEngine::GetIfActive() ) { m_imageData = new wxXPButtonImageData(this, bitmap); + + if ( oldData ) + { + // Preserve the old values in case the user changed them. + m_imageData->SetBitmapPosition(oldData->GetBitmapPosition()); + + const wxSize oldMargins = oldData->GetBitmapMargins(); + m_imageData->SetBitmapMargins(oldMargins.x, oldMargins.y); + + // No need to preserve the bitmaps though as they were of wrong + // size anyhow. + + delete oldData; + } } else #endif // wxUSE_UXTHEME @@ -1099,16 +1143,18 @@ wxButton::State GetButtonState(wxButton *btn, UINT state) void DrawButtonText(HDC hdc, RECT *pRect, - const wxString& text, + wxButton *btn, int flags) { - // center text horizontally in any case - flags |= DT_CENTER; + const wxString text = btn->GetLabel(); if ( text.find(wxT('\n')) != wxString::npos ) { // draw multiline label + // center text horizontally in any case + flags |= DT_CENTER; + // first we need to compute its bounding rect RECT rc; ::CopyRect(&rc, pRect); @@ -1127,10 +1173,31 @@ void DrawButtonText(HDC hdc, } else // single line label { - // centre text vertically too (notice that we must have DT_SINGLELINE - // for DT_VCENTER to work) + // translate wx button flags to alignment flags for DrawText() + if ( btn->HasFlag(wxBU_RIGHT) ) + { + flags |= DT_RIGHT; + } + else if ( !btn->HasFlag(wxBU_LEFT) ) + { + flags |= DT_CENTER; + } + //else: DT_LEFT is the default anyhow (and its value is 0 too) + + if ( btn->HasFlag(wxBU_BOTTOM) ) + { + flags |= DT_BOTTOM; + } + else if ( !btn->HasFlag(wxBU_TOP) ) + { + flags |= DT_VCENTER; + } + //else: as above, DT_TOP is the default + + // notice that we must have DT_SINGLELINE for vertical alignment flags + // to work ::DrawText(hdc, text.wx_str(), text.length(), pRect, - flags | DT_SINGLELINE | DT_VCENTER); + flags | DT_SINGLELINE ); } } @@ -1254,7 +1321,20 @@ void DrawXPBackground(wxButton *button, HDC hdc, RECT& rectBtn, UINT state) iState ) ) { + // Set this button as the one whose background is being erased: this + // allows our WM_ERASEBKGND handler used by DrawThemeParentBackground() + // to correctly align the background brush with this window instead of + // the parent window to which WM_ERASEBKGND is sent. Notice that this + // doesn't work with custom user-defined EVT_ERASE_BACKGROUND handlers + // as they won't be aligned but unfortunately all the attempts to fix + // it by shifting DC origin before calling DrawThemeParentBackground() + // failed to work so we at least do this, even though this is far from + // being the perfect solution. + wxWindowBeingErased = button; + engine->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn); + + wxWindowBeingErased = NULL; } // draw background @@ -1475,7 +1555,7 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis) // notice that DT_HIDEPREFIX doesn't work on old (pre-Windows 2000) // systems but by happy coincidence ODS_NOACCEL is not used under // them neither so DT_HIDEPREFIX should never be used there - DrawButtonText(hdc, &rectBtn, GetLabel(), + DrawButtonText(hdc, &rectBtn, this, state & ODS_NOACCEL ? DT_HIDEPREFIX : 0); } }