#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.
#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
// 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
m_widthCustomBorder = 1;
}
else
+#endif
border = wxBORDER_SUNKEN;
style = (style & ~(wxBORDER_MASK)) | border;
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);
{
}
-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
// 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);
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;
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 )
{
focusSpacingY = sz.y > (GetCharHeight()+2) && isEnabled ? 2 : 1;
}
else
+#endif
{
// Classic Theme
if ( isEnabled )
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;
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 )
{
// 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;
if ( hTheme )
theme = wxUxThemeEngine::GetIfActive();
+#endif // wxUSE_UXTHEME
wxRect borderRect(0,0,sz.x,sz.y);
int drawButFlags = 0;
+#if wxUSE_UXTHEME
if ( hTheme )
{
const bool useVistaComboBox = ::wxGetWinVersion() >= wxWinVersion_Vista;
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 )
{
}
}
else
+#endif
{
// Windows 2000 and earlier
drawButFlags = Button_PaintBackground;
else
wxComboPopup::DefaultPaintComboControl(this,dc,rectTextField);
}
+
+ delete dcPtr;
}
void wxComboCtrl::OnMouseEvent( wxMouseEvent& event )
#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?
{
wxLongLong t = ::wxGetLocalTimeMillis();
const wxRect& rect = m_animRect;
- wxWindow* win = GetPopupWindow();
int pos = (int) (t-m_animStart).GetLo();
if ( pos < COMBOBOX_ANIMATION_DURATION )
}
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
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
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;
}
wxCoord wxComboCtrl::GetNativeTextIndent() const
{
+#if wxUSE_UXTHEME
if ( wxUxThemeEngine::GetIfActive() )
return NATIVE_TEXT_INDENT_XP;
+#endif
return NATIVE_TEXT_INDENT_CLASSIC;
}
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;
}