X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/73049b0db3eeda339354d29cf674d57dca92eaf3..739c5499fcab1c165b8dd0591c9fd9e2329b3cf9:/src/msw/combo.cpp diff --git a/src/msw/combo.cpp b/src/msw/combo.cpp index 3ddde4f0af..2ef7d8925a 100644 --- a/src/msw/combo.cpp +++ b/src/msw/combo.cpp @@ -38,7 +38,10 @@ #include "wx/combo.h" #include "wx/msw/registry.h" +#if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" +#endif +#include "wx/msw/dc.h" // Change to #if 1 to include tmschema.h for easier testing of theme // parameters. @@ -114,11 +117,6 @@ #define NATIVE_TEXT_INDENT_XP 4 #define NATIVE_TEXT_INDENT_CLASSIC 2 -#define TEXTCTRLXADJUST_XP 1 -#define TEXTCTRLYADJUST_XP 3 -#define TEXTCTRLXADJUST_CLASSIC 1 -#define TEXTCTRLYADJUST_CLASSIC 3 - #define COMBOBOX_ANIMATION_RESOLUTION 10 #define COMBOBOX_ANIMATION_DURATION 200 // In milliseconds @@ -159,10 +157,13 @@ bool wxComboCtrl::Create(wxWindow *parent, // Set border long border = style & wxBORDER_MASK; +#if wxUSE_UXTHEME wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive(); +#endif if ( !border ) { +#if wxUSE_UXTHEME if ( theme ) { // For XP, have 1-width custom border, for older version use sunken @@ -170,6 +171,7 @@ bool wxComboCtrl::Create(wxWindow *parent, m_widthCustomBorder = 1; } else +#endif border = wxBORDER_SUNKEN; style = (style & ~(wxBORDER_MASK)) | border; @@ -182,28 +184,33 @@ bool wxComboCtrl::Create(wxWindow *parent, pos, size, style | wxFULL_REPAINT_ON_RESIZE, - wxDefaultValidator, + validator, name) ) return false; +#if wxUSE_UXTHEME if ( theme ) { if ( ::wxGetWinVersion() >= wxWinVersion_Vista ) m_iFlags |= wxCC_BUTTON_STAYS_DOWN |wxCC_BUTTON_COVERS_BORDER; } +#endif if ( style & wxCC_STD_BUTTON ) m_iFlags |= wxCC_POPUP_ON_MOUSE_UP; + // Prepare background for double-buffering or better background theme + // support, whichever is possible. + SetDoubleBuffered(true); + if ( !IsDoubleBuffered() ) + SetBackgroundStyle( wxBG_STYLE_PAINT ); + // Create textctrl, if necessary - CreateTextCtrl( wxNO_BORDER, validator ); + CreateTextCtrl( wxNO_BORDER ); // Add keyboard input handlers for main control and textctrl InstallInputHandlers(); - // Prepare background for double-buffering - SetBackgroundStyle( wxBG_STYLE_CUSTOM ); - // SetInitialSize should be called last SetInitialSize(size); @@ -214,66 +221,18 @@ wxComboCtrl::~wxComboCtrl() { } -void wxComboCtrl::OnThemeChange() -{ - // there doesn't seem to be any way to get the text colour using themes - // API: TMT_TEXTCOLOR doesn't work neither for EDIT nor COMBOBOX - SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - - wxUxThemeEngine * const theme = wxUxThemeEngine::GetIfActive(); - if ( theme ) - { - // NB: use EDIT, not COMBOBOX (the latter works in XP but not Vista) - wxUxThemeHandle hTheme(this, L"EDIT"); - COLORREF col; - HRESULT hr = theme->GetThemeColor - ( - hTheme, - EP_EDITTEXT, - ETS_NORMAL, - TMT_FILLCOLOR, - &col - ); - if ( SUCCEEDED(hr) ) - { - SetBackgroundColour(wxRGBToColour(col)); - - // skip the call below - return; - } - - wxLogApiError(_T("GetThemeColor(EDIT, ETS_NORMAL, TMT_FILLCOLOR)"), hr); - } - - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -} - void wxComboCtrl::OnResize() { // // Recalculates button and textctrl areas - int textCtrlXAdjust; - int textCtrlYAdjust; - - if ( wxUxThemeEngine::GetIfActive() ) - { - textCtrlXAdjust = TEXTCTRLXADJUST_XP; - textCtrlYAdjust = TEXTCTRLYADJUST_XP; - } - else - { - textCtrlXAdjust = TEXTCTRLXADJUST_CLASSIC; - textCtrlYAdjust = TEXTCTRLYADJUST_CLASSIC; - } - // Technically Classic Windows style combo has more narrow button, // but the native renderer doesn't paint it well like that. int btnWidth = 17; CalculateAreas(btnWidth); // Position textctrl using standard routine - PositionTextCtrl(textCtrlXAdjust,textCtrlYAdjust); + PositionTextCtrl(); } // Draws non-XP GUI dotted line around the focus area @@ -296,7 +255,7 @@ static void wxMSWDrawFocusRect( wxDC& dc, const wxRect& rect ) // it employs wxCAP_BUTT hack to have line of width 1. dc.SetLogicalFunction(wxINVERT); - wxPen pen(*wxBLACK,1,wxDOT); + wxPen pen(*wxBLACK, 1, wxPENSTYLE_DOT); pen.SetCap(wxCAP_BUTT); dc.SetPen(pen); dc.SetBrush(*wxTRANSPARENT_BRUSH); @@ -320,7 +279,9 @@ static void wxMSWDrawFocusRect( wxDC& dc, const wxRect& rect ) void wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const { +#if wxUSE_UXTHEME wxUxThemeHandle hTheme(this, L"COMBOBOX"); +#endif wxSize sz = GetClientSize(); bool isEnabled; @@ -333,9 +294,10 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const if ( !(flags & wxCONTROL_ISSUBMENU) ) { // Drawing control - isEnabled = IsEnabled(); + isEnabled = IsThisEnabled(); doDrawFocusRect = ShouldDrawFocus(); +#if wxUSE_UXTHEME // Windows-style: for smaller size control (and for disabled background) use less spacing if ( hTheme ) { @@ -344,6 +306,7 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const focusSpacingY = sz.y > (GetCharHeight()+2) && isEnabled ? 2 : 1; } else +#endif { // Classic Theme if ( isEnabled ) @@ -381,10 +344,11 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const selRect.x += wcp + focusSpacingX; selRect.width -= wcp + (focusSpacingX*2); - //wxUxThemeEngine* theme = (wxUxThemeEngine*) NULL; + //wxUxThemeEngine* theme = NULL; //if ( hTheme ) // theme = wxUxThemeEngine::GetIfActive(); + wxColour fgCol; wxColour bgCol; bool doDrawDottedEdge = false; bool doDrawSelRect = true; @@ -410,28 +374,31 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const if ( (m_iFlags & wxCC_FULL_BUTTON) && !(flags & wxCONTROL_ISSUBMENU) ) { // Vista style read-only combo + fgCol = GetForegroundColour(); + bgCol = GetBackgroundColour(); doDrawSelRect = false; doDrawDottedEdge = true; } else { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); + fgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); } } else { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); + fgCol = GetForegroundColour(); bgCol = GetBackgroundColour(); doDrawSelRect = false; } } else { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) ); + fgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); } + dc.SetTextForeground(fgCol); dc.SetBrush(bgCol); if ( doDrawSelRect ) { @@ -454,14 +421,25 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) // TODO: Convert drawing in this function to Windows API Code wxSize sz = GetClientSize(); - wxAutoBufferedPaintDC dc(this); + wxDC* dcPtr = wxAutoBufferedPaintDCFactory(this); + wxDC& dc = *dcPtr; const wxRect& rectButton = m_btnArea; wxRect rectTextField = m_tcArea; - const bool isEnabled = IsEnabled(); - wxColour bgCol = GetBackgroundColour(); - HDC hDc = GetHdcOf(dc); + // FIXME: Either SetBackgroundColour or GetBackgroundColour + // doesn't work under Vista, so here's a temporary + // workaround. + // In the theme-less rendering code below, this fixes incorrect + // background on read-only comboboxes (they are gray, but should be + // white). + wxColour bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + +#if wxUSE_UXTHEME + const bool isEnabled = IsThisEnabled(); + + wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); + HDC hDc = GetHdcOf(*impl); HWND hWnd = GetHwndOf(this); wxUxThemeEngine* theme = NULL; @@ -469,6 +447,7 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) if ( hTheme ) theme = wxUxThemeEngine::GetIfActive(); +#endif // wxUSE_UXTHEME wxRect borderRect(0,0,sz.x,sz.y); @@ -480,6 +459,7 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) int drawButFlags = 0; +#if wxUSE_UXTHEME if ( hTheme ) { const bool useVistaComboBox = ::wxGetWinVersion() >= wxWinVersion_Vista; @@ -529,11 +509,6 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) if ( useVistaComboBox ) { - // FIXME: Either SetBackgroundColour or GetBackgroundColour - // doesn't work under Vista, so here's a temporary - // workaround. - bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - // Draw the entire control as a single button? if ( !isNonStdButton ) { @@ -624,6 +599,7 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) } } else +#endif { // Windows 2000 and earlier drawButFlags = Button_PaintBackground; @@ -654,6 +630,8 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) else wxComboPopup::DefaultPaintComboControl(this,dc,rectTextField); } + + delete dcPtr; } void wxComboCtrl::OnMouseEvent( wxMouseEvent& event ) @@ -740,10 +718,11 @@ static wxUint32 GetUserPreferencesMask() #endif #if wxUSE_COMBOCTRL_POPUP_ANIMATION -void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) ) +void wxComboCtrl::DoTimerEvent() { bool stopTimer = false; + wxWindow* win = GetPopupWindow(); wxWindow* popup = GetPopupControl()->GetControl(); // Popup was hidden before it was fully shown? @@ -755,7 +734,6 @@ void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) ) { wxLongLong t = ::wxGetLocalTimeMillis(); const wxRect& rect = m_animRect; - wxWindow* win = GetPopupWindow(); int pos = (int) (t-m_animStart).GetLo(); if ( pos < COMBOBOX_ANIMATION_DURATION ) @@ -773,8 +751,10 @@ void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) ) } else { - popup->Move( 0, -y ); + // Note that apparently Move() should be called after + // SetSize() to reduce (or even eliminate) animation garbage win->SetSize( rect.x, rect.y, rect.width, h ); + popup->Move( 0, -y ); } } else @@ -785,9 +765,13 @@ void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) ) if ( stopTimer ) { - popup->Move( 0, 0 ); m_animTimer.Stop(); DoShowPopup( m_animRect, m_animFlags ); + popup->Move( 0, 0 ); + + // Do a one final refresh to clean up the rare cases of animation + // garbage + win->Refresh(); } } #endif @@ -808,7 +792,7 @@ bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags ) m_animTimer.SetOwner( this, wxID_ANY ); m_animTimer.Start( COMBOBOX_ANIMATION_RESOLUTION, wxTIMER_CONTINUOUS ); - OnTimerEvent(*((wxTimerEvent*)NULL)); // Event is never used, so we can give NULL + DoTimerEvent(); return false; } @@ -819,8 +803,10 @@ bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags ) wxCoord wxComboCtrl::GetNativeTextIndent() const { +#if wxUSE_UXTHEME if ( wxUxThemeEngine::GetIfActive() ) return NATIVE_TEXT_INDENT_XP; +#endif return NATIVE_TEXT_INDENT_CLASSIC; } @@ -843,16 +829,12 @@ bool wxComboCtrl::IsKeyPopupToggle(const wxKeyEvent& event) const case WXK_DOWN: case WXK_UP: - // On XP or with writable combo in Classic, arrows don't open the - // popup but Alt-arrow does - if ( event.AltDown() || - ( !isPopupShown && - HasFlag(wxCB_READONLY) && - !wxUxThemeEngine::GetIfActive() - ) ) - { + case WXK_NUMPAD_DOWN: + case WXK_NUMPAD_UP: + // Arrow keys (and mouse wheel) toggle the popup in the native + // combo boxes + if ( event.AltDown() ) return true; - } break; }