miscellaneous LnF improvements, including support for Vista-style (patch 1588794)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44735 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-03-10 18:06:11 +00:00
parent 33e61c47c0
commit c905c0d60f
5 changed files with 392 additions and 168 deletions

View File

@@ -75,6 +75,12 @@ enum
wxCC_POPUP_ON_MOUSE_UP = 0x0002, wxCC_POPUP_ON_MOUSE_UP = 0x0002,
// All text is not automatically selected on click // All text is not automatically selected on click
wxCC_NO_TEXT_AUTO_SELECT = 0x0004, wxCC_NO_TEXT_AUTO_SELECT = 0x0004,
// Drop-button stays down as long as popup is displayed.
wxCC_BUTTON_STAYS_DOWN = 0x0008,
// Drop-button covers the entire control.
wxCC_FULL_BUTTON = 0x0010,
// Drop-button goes over the custom-border (used under WinVista).
wxCC_BUTTON_COVERS_BORDER = 0x0020,
// Internal use: signals creation is complete // Internal use: signals creation is complete
wxCC_IFLAG_CREATED = 0x0100, wxCC_IFLAG_CREATED = 0x0100,
@@ -87,7 +93,10 @@ enum
// Internal use: Secondary popup window type should be used (if available). // Internal use: Secondary popup window type should be used (if available).
wxCC_IFLAG_USE_ALT_POPUP = 0x1000, wxCC_IFLAG_USE_ALT_POPUP = 0x1000,
// Internal use: Skip popup animation. // Internal use: Skip popup animation.
wxCC_IFLAG_DISABLE_POPUP_ANIM = 0x2000 wxCC_IFLAG_DISABLE_POPUP_ANIM = 0x2000,
// Internal use: Drop-button is a bitmap button or has non-default size
// (but can still be on either side of the control).
wxCC_IFLAG_HAS_NONSTANDARD_BUTTON = 0x4000
}; };
@@ -365,8 +374,8 @@ public:
bool ShouldDrawFocus() const bool ShouldDrawFocus() const
{ {
const wxWindow* curFocus = FindFocus(); const wxWindow* curFocus = FindFocus();
return ( !IsPopupShown() && return ( IsPopupWindowState(Hidden) &&
(curFocus == this || (m_btn && curFocus == m_btn)) && (curFocus == m_mainCtrlWnd || (m_btn && curFocus == m_btn)) &&
(m_windowStyle & wxCB_READONLY) ); (m_windowStyle & wxCB_READONLY) );
} }
@@ -401,6 +410,10 @@ public:
// Set value returned by GetMainWindowOfCompositeControl // Set value returned by GetMainWindowOfCompositeControl
void SetCtrlMainWnd( wxWindow* wnd ) { m_mainCtrlWnd = wnd; } void SetCtrlMainWnd( wxWindow* wnd ) { m_mainCtrlWnd = wnd; }
// This is public so we can access it from wxComboCtrlTextCtrl
virtual wxWindow *GetMainWindowOfCompositeControl()
{ return m_mainCtrlWnd; }
protected: protected:
// //
@@ -423,14 +436,16 @@ protected:
// Installs standard input handler to combo (and optionally to the textctrl) // Installs standard input handler to combo (and optionally to the textctrl)
void InstallInputHandlers(); void InstallInputHandlers();
// flags for DrawButton() // Flags for DrawButton
enum enum
{ {
Draw_PaintBg = 1 Button_PaintBackground = 0x0001, // Paints control background below the button
Button_BitmapOnly = 0x0002 // Only paints the bitmap
}; };
// Draws dropbutton. Using wxRenderer or bitmaps, as appropriate. // Draws dropbutton. Using wxRenderer or bitmaps, as appropriate.
void DrawButton( wxDC& dc, const wxRect& rect, int flags = Draw_PaintBg ); // Flags are defined above.
void DrawButton( wxDC& dc, const wxRect& rect, int flags = Button_PaintBackground );
// Call if cursor is on button area or mouse is captured for the button. // Call if cursor is on button area or mouse is captured for the button.
//bool HandleButtonMouseEvent( wxMouseEvent& event, bool isInside ); //bool HandleButtonMouseEvent( wxMouseEvent& event, bool isInside );
@@ -506,9 +521,6 @@ protected:
virtual void DoSetToolTip( wxToolTip *tip ); virtual void DoSetToolTip( wxToolTip *tip );
#endif #endif
virtual wxWindow *GetMainWindowOfCompositeControl()
{ return m_mainCtrlWnd; }
// This is used when m_text is hidden (readonly). // This is used when m_text is hidden (readonly).
wxString m_valueString; wxString m_valueString;

View File

@@ -377,12 +377,14 @@ bool wxComboPopupWindow::Show( bool show )
wxASSERT( IsKindOf(CLASSINFO(wxPopupTransientWindow)) ); wxASSERT( IsKindOf(CLASSINFO(wxPopupTransientWindow)) );
wxPopupTransientWindow* ptw = (wxPopupTransientWindow*) this; wxPopupTransientWindow* ptw = (wxPopupTransientWindow*) this;
wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent();
if ( show != ptw->IsShown() ) if ( show != ptw->IsShown() )
{ {
if ( show ) if ( show )
ptw->Popup(combo->GetPopupControl()->GetControl()); // We used to do wxPopupTransientWindow::Popup here,
// but this would hide normal Show, which we are
// also going to need.
ptw->Show();
else else
ptw->Dismiss(); ptw->Dismiss();
} }
@@ -571,6 +573,7 @@ private:
BEGIN_EVENT_TABLE(wxComboBoxExtraInputHandler, wxEvtHandler) BEGIN_EVENT_TABLE(wxComboBoxExtraInputHandler, wxEvtHandler)
EVT_KEY_DOWN(wxComboBoxExtraInputHandler::OnKey) EVT_KEY_DOWN(wxComboBoxExtraInputHandler::OnKey)
EVT_SET_FOCUS(wxComboBoxExtraInputHandler::OnFocus) EVT_SET_FOCUS(wxComboBoxExtraInputHandler::OnFocus)
EVT_KILL_FOCUS(wxComboBoxExtraInputHandler::OnFocus)
END_EVENT_TABLE() END_EVENT_TABLE()
@@ -592,7 +595,8 @@ void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event)
{ {
// FIXME: This code does run when control is clicked, // FIXME: This code does run when control is clicked,
// yet on Windows it doesn't select all the text. // yet on Windows it doesn't select all the text.
if ( !(m_combo->GetInternalFlags() & wxCC_NO_TEXT_AUTO_SELECT) ) if ( event.GetEventType() == wxEVT_SET_FOCUS &&
!(m_combo->GetInternalFlags() & wxCC_NO_TEXT_AUTO_SELECT) )
{ {
if ( m_combo->GetTextCtrl() ) if ( m_combo->GetTextCtrl() )
m_combo->GetTextCtrl()->SelectAll(); m_combo->GetTextCtrl()->SelectAll();
@@ -606,7 +610,7 @@ void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event)
// wxEVT_SET_FOCUSes (since m_text->SetFocus is called // wxEVT_SET_FOCUSes (since m_text->SetFocus is called
// from combo's focus event handler), they should be quite // from combo's focus event handler), they should be quite
// harmless. // harmless.
wxFocusEvent evt2(wxEVT_SET_FOCUS,m_combo->GetId()); wxFocusEvent evt2(event.GetEventType(),m_combo->GetId());
evt2.SetEventObject(m_combo); evt2.SetEventObject(m_combo);
m_combo->GetEventHandler()->ProcessEvent(evt2); m_combo->GetEventHandler()->ProcessEvent(evt2);
@@ -659,6 +663,9 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
wxSize sz = m_combo->GetPopupControl()->GetControl()->GetClientSize(); wxSize sz = m_combo->GetPopupControl()->GetControl()->GetClientSize();
int evtType = event.GetEventType(); int evtType = event.GetEventType();
bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y; bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y;
bool relayToButton = false;
event.Skip();
if ( evtType == wxEVT_MOTION || if ( evtType == wxEVT_MOTION ||
evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DOWN ||
@@ -668,7 +675,6 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
if ( !isInside || !m_combo->IsPopupShown() ) if ( !isInside || !m_combo->IsPopupShown() )
{ {
event.Skip(false); event.Skip(false);
return;
} }
} }
else if ( evtType == wxEVT_LEFT_UP ) else if ( evtType == wxEVT_LEFT_UP )
@@ -676,38 +682,58 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
if ( !m_combo->IsPopupShown() ) if ( !m_combo->IsPopupShown() )
{ {
event.Skip(false); event.Skip(false);
return; relayToButton = true;
} }
else if ( !m_beenInside )
if ( !m_beenInside )
{ {
if ( isInside ) if ( isInside )
{ {
m_beenInside = true; m_beenInside = true;
} }
else else
{
relayToButton = true;
}
}
}
if ( relayToButton )
{ {
// //
// Some mouse events to popup that happen outside it, before cursor // Some mouse events to popup that happen outside it, before cursor
// has been inside the popu, need to be ignored by it but relayed to // has been inside the popup, need to be ignored by it but relayed to
// the dropbutton. // the dropbutton.
// //
wxWindow* eventSink = m_combo;
wxWindow* btn = m_combo->GetButton(); wxWindow* btn = m_combo->GetButton();
if ( btn ) if ( btn )
btn->GetEventHandler()->AddPendingEvent(event); eventSink = btn;
else
m_combo->GetEventHandler()->AddPendingEvent(event);
return; eventSink->GetEventHandler()->ProcessEvent(event);
} }
event.Skip();
}
}
event.Skip();
} }
// ----------------------------------------------------------------------------
// wxComboCtrlTextCtrl
// ----------------------------------------------------------------------------
class wxComboCtrlTextCtrl : public wxTextCtrl
{
public:
wxComboCtrlTextCtrl() : wxTextCtrl() { }
virtual ~wxComboCtrlTextCtrl() { }
virtual wxWindow *GetMainWindowOfCompositeControl()
{
wxComboCtrl* combo = (wxComboCtrl*) GetParent();
// Returning this instead of just 'parent' lets FindFocus work
// correctly even when parent control is a child of a composite
// generic control (as is case with wxGenericDatePickerCtrl).
return combo->GetMainWindowOfCompositeControl();
}
};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxComboCtrlBase // wxComboCtrlBase
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -841,7 +867,8 @@ wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator)
else else
m_ignoreEvtText = 0; m_ignoreEvtText = 0;
m_text = new wxTextCtrl(this, wxID_ANY, m_valueString, m_text = new wxComboCtrlTextCtrl();
m_text->Create(this, wxID_ANY, m_valueString,
wxDefaultPosition, wxSize(10,-1), wxDefaultPosition, wxSize(10,-1),
style, validator); style, validator);
} }
@@ -898,6 +925,12 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
m_iFlags |= wxCC_IFLAG_BUTTON_OUTSIDE; m_iFlags |= wxCC_IFLAG_BUTTON_OUTSIDE;
btnBorder = 0; btnBorder = 0;
} }
else if ( (m_iFlags & wxCC_BUTTON_COVERS_BORDER) &&
m_btnSpacingX == 0 && !m_bmpNormal.Ok() )
{
m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE);
btnBorder = 0;
}
else else
{ {
m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE); m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE);
@@ -972,6 +1005,11 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
{ {
int newY = butHeight+(customBorder*2); int newY = butHeight+(customBorder*2);
SetClientSize(wxDefaultCoord,newY); SetClientSize(wxDefaultCoord,newY);
if ( m_bmpNormal.Ok() || m_btnArea.width != butWidth || m_btnArea.height != butHeight )
m_iFlags |= wxCC_IFLAG_HAS_NONSTANDARD_BUTTON;
else
m_iFlags &= ~wxCC_IFLAG_HAS_NONSTANDARD_BUTTON;
sz.y = newY; sz.y = newY;
} }
} }
@@ -1217,7 +1255,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
{ {
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
bool isEnabled; bool isEnabled;
bool isFocused; // also selected bool doDrawFocusRect; // also selected
// For smaller size control (and for disabled background) use less spacing // For smaller size control (and for disabled background) use less spacing
int focusSpacingX; int focusSpacingX;
@@ -1227,7 +1265,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
{ {
// Drawing control // Drawing control
isEnabled = IsEnabled(); isEnabled = IsEnabled();
isFocused = ShouldDrawFocus(); doDrawFocusRect = ShouldDrawFocus() & !(m_iFlags & wxCC_FULL_BUTTON);
// Windows-style: for smaller size control (and for disabled background) use less spacing // Windows-style: for smaller size control (and for disabled background) use less spacing
focusSpacingX = isEnabled ? 2 : 1; focusSpacingX = isEnabled ? 2 : 1;
@@ -1237,7 +1275,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
{ {
// Drawing a list item // Drawing a list item
isEnabled = true; // they are never disabled isEnabled = true; // they are never disabled
isFocused = flags & wxCONTROL_SELECTED ? true : false; doDrawFocusRect = flags & wxCONTROL_SELECTED ? true : false;
focusSpacingX = 0; focusSpacingX = 0;
focusSpacingY = 0; focusSpacingY = 0;
@@ -1257,12 +1295,13 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
selRect.width -= wcp + (focusSpacingX*2); selRect.width -= wcp + (focusSpacingX*2);
wxColour bgCol; wxColour bgCol;
bool doDrawSelRect = true;
if ( isEnabled ) if ( isEnabled )
{ {
// If popup is hidden and this control is focused, // If popup is hidden and this control is focused,
// then draw the focus-indicator (selbgcolor background etc.). // then draw the focus-indicator (selbgcolor background etc.).
if ( isFocused ) if ( doDrawFocusRect )
{ {
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
@@ -1271,6 +1310,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
{ {
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
#ifndef __WXMAC__ // see note in OnThemeChange #ifndef __WXMAC__ // see note in OnThemeChange
doDrawSelRect = false;
bgCol = GetBackgroundColour(); bgCol = GetBackgroundColour();
#else #else
bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
@@ -1288,8 +1328,11 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags
} }
dc.SetBrush( bgCol ); dc.SetBrush( bgCol );
if ( doDrawSelRect )
{
dc.SetPen( bgCol ); dc.SetPen( bgCol );
dc.DrawRectangle( selRect ); dc.DrawRectangle( selRect );
}
// Don't clip exactly to the selection rectangle so we can draw // Don't clip exactly to the selection rectangle so we can draw
// to the non-selected area in front of it. // to the non-selected area in front of it.
@@ -1304,14 +1347,13 @@ void wxComboCtrlBase::PrepareBackground( wxDC&, const wxRect&, int ) const
} }
#endif #endif
void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int paintBg ) void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int flags )
{ {
int drawState = m_btnState; int drawState = m_btnState;
#ifdef __WXGTK__ if ( (m_iFlags & wxCC_BUTTON_STAYS_DOWN) &&
if ( GetPopupWindowState() >= Animating ) GetPopupWindowState() >= Animating )
drawState |= wxCONTROL_PRESSED; drawState |= wxCONTROL_PRESSED;
#endif
wxRect drawRect(rect.x+m_btnSpacingX, wxRect drawRect(rect.x+m_btnSpacingX,
rect.y+((rect.height-m_btnSize.y)/2), rect.y+((rect.height-m_btnSize.y)/2),
@@ -1331,8 +1373,11 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int paintBg )
if ( !m_bmpNormal.Ok() ) if ( !m_bmpNormal.Ok() )
{ {
if ( flags & Button_BitmapOnly )
return;
// Need to clear button background even if m_btn is present // Need to clear button background even if m_btn is present
if ( paintBg ) if ( flags & Button_PaintBackground )
{ {
wxColour bgCol; wxColour bgCol;
@@ -1371,7 +1416,7 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int paintBg )
{ {
// If using blank button background, we need to clear its background // If using blank button background, we need to clear its background
// with button face colour instead of colour for rest of the control. // with button face colour instead of colour for rest of the control.
if ( paintBg ) if ( flags & Button_PaintBackground )
{ {
wxColour bgCol = GetParent()->GetBackgroundColour(); //wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); wxColour bgCol = GetParent()->GetBackgroundColour(); //wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
//wxColour bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); //wxColour bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
@@ -1380,18 +1425,20 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int paintBg )
dc.DrawRectangle(rect); dc.DrawRectangle(rect);
} }
if ( !(flags & Button_BitmapOnly) )
{
wxRendererNative::Get().DrawPushButton(this, wxRendererNative::Get().DrawPushButton(this,
dc, dc,
drawRect, drawRect,
drawState); drawState);
}
} }
else else
{ {
// Need to clear button background even if m_btn is present // Need to clear button background even if m_btn is present
// (assume non-button background was cleared just before this call so brushes are good) // (assume non-button background was cleared just before this call so brushes are good)
if ( paintBg ) if ( flags & Button_PaintBackground )
dc.DrawRectangle(rect); dc.DrawRectangle(rect);
} }
@@ -1444,7 +1491,8 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event,
if ( type == wxEVT_MOTION ) if ( type == wxEVT_MOTION )
{ {
if ( flags & wxCC_MF_ON_BUTTON ) if ( (flags & wxCC_MF_ON_BUTTON) &&
IsPopupWindowState(Hidden) )
{ {
if ( !(m_btnState & wxCONTROL_CURRENT) ) if ( !(m_btnState & wxCONTROL_CURRENT) )
{ {
@@ -1513,6 +1561,11 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event,
else else
return false; return false;
// Never have 'hot' state when popup is being shown
// (this is mostly needed because of the animation).
if ( !IsPopupWindowState(Hidden) )
m_btnState &= ~wxCONTROL_CURRENT;
return true; return true;
} }
@@ -1535,7 +1588,7 @@ bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event,
} }
#endif #endif
// Filter out clicks on button immediately after popup dismiss (Windows like behaviour) // Filter out clicks on button immediately after popup dismiss
if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick ) if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick )
{ {
event.SetEventType(0); event.SetEventType(0);
@@ -1648,7 +1701,9 @@ void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& event )
#ifdef __WXMAC__ #ifdef __WXMAC__
m_resetFocus = true; m_resetFocus = true;
#else #else
{
tc->SetFocus(); tc->SetFocus();
}
#endif #endif
} }
@@ -1700,7 +1755,7 @@ void wxComboCtrlBase::CreatePopup()
m_popupWinType = SECONDARY_POPUP_TYPE; m_popupWinType = SECONDARY_POPUP_TYPE;
} }
else else
#endif #endif // wxComboPopupWindowBase2
{ {
m_winPopup = new wxComboPopupWindow( this, wxNO_BORDER ); m_winPopup = new wxComboPopupWindow( this, wxNO_BORDER );
m_popupWinType = PRIMARY_POPUP_TYPE; m_popupWinType = PRIMARY_POPUP_TYPE;
@@ -1986,6 +2041,11 @@ void wxComboCtrlBase::DoShowPopup( const wxRect& rect, int WXUNUSED(flags) )
// (though the bug was probably fixed). // (though the bug was probably fixed).
winPopup->SetSize( rect ); winPopup->SetSize( rect );
#if USES_WXPOPUPTRANSIENTWINDOW
if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW )
((wxPopupTransientWindow*)winPopup)->Popup(m_popup);
else
#endif
winPopup->Show(); winPopup->Show();
m_popupWinState = Visible; m_popupWinState = Visible;
@@ -1998,6 +2058,8 @@ void wxComboCtrlBase::DoShowPopup( const wxRect& rect, int WXUNUSED(flags) )
m_popupWinState = Hidden; m_popupWinState = Hidden;
} }
Refresh();
} }
void wxComboCtrlBase::OnPopupDismiss() void wxComboCtrlBase::OnPopupDismiss()

View File

@@ -380,7 +380,8 @@ void wxBitmapComboBox::OnDrawBackground(wxDC& dc,
{ {
if ( GetCustomPaintWidth() == 0 || if ( GetCustomPaintWidth() == 0 ||
!(flags & wxODCB_PAINTING_SELECTED) || !(flags & wxODCB_PAINTING_SELECTED) ||
item < 0 ) item < 0 ||
( (flags & wxODCB_PAINTING_CONTROL) && (GetInternalFlags() & wxCC_FULL_BUTTON)) )
{ {
wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags); wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags);
return; return;

View File

@@ -159,7 +159,8 @@ bool wxGenericComboCtrl::Create(wxWindow *parent,
border = wxBORDER_NONE; border = wxBORDER_NONE;
Customize( wxCC_BUTTON_OUTSIDE_BORDER | Customize( wxCC_BUTTON_OUTSIDE_BORDER |
wxCC_NO_TEXT_AUTO_SELECT ); wxCC_NO_TEXT_AUTO_SELECT |
wxCC_BUTTON_STAYS_DOWN );
#endif #endif

View File

@@ -44,6 +44,7 @@
// parameters. // parameters.
#if 0 #if 0
#include <tmschema.h> #include <tmschema.h>
#include <VSStyle.h>
#else #else
//---------------------------------- //----------------------------------
#define EP_EDITTEXT 1 #define EP_EDITTEXT 1
@@ -58,7 +59,55 @@
#define TMT_TEXTCOLOR 3803 #define TMT_TEXTCOLOR 3803
#define TMT_BORDERCOLOR 3801 #define TMT_BORDERCOLOR 3801
#define TMT_EDGEFILLCOLOR 3808 #define TMT_EDGEFILLCOLOR 3808
//---------------------------------- #define TMT_BGTYPE 4001
#define BT_IMAGEFILE 0
#define BT_BORDERFILL 1
#define CP_DROPDOWNBUTTON 1
#define CP_BACKGROUND 2 // This and above are Vista and later only
#define CP_TRANSPARENTBACKGROUND 3
#define CP_BORDER 4
#define CP_READONLY 5
#define CP_DROPDOWNBUTTONRIGHT 6
#define CP_DROPDOWNBUTTONLEFT 7
#define CP_CUEBANNER 8
#define CBXS_NORMAL 1
#define CBXS_HOT 2
#define CBXS_PRESSED 3
#define CBXS_DISABLED 4
#define CBXSR_NORMAL 1
#define CBXSR_HOT 2
#define CBXSR_PRESSED 3
#define CBXSR_DISABLED 4
#define CBXSL_NORMAL 1
#define CBXSL_HOT 2
#define CBXSL_PRESSED 3
#define CBXSL_DISABLED 4
#define CBTBS_NORMAL 1
#define CBTBS_HOT 2
#define CBTBS_DISABLED 3
#define CBTBS_FOCUSED 4
#define CBB_NORMAL 1
#define CBB_HOT 2
#define CBB_FOCUSED 3
#define CBB_DISABLED 4
#define CBRO_NORMAL 1
#define CBRO_HOT 2
#define CBRO_PRESSED 3
#define CBRO_DISABLED 4
#define CBCB_NORMAL 1
#define CBCB_HOT 2
#define CBCB_PRESSED 3
#define CBCB_DISABLED 4
#endif #endif
@@ -68,7 +117,7 @@
#define TEXTCTRLXADJUST_XP 1 #define TEXTCTRLXADJUST_XP 1
#define TEXTCTRLYADJUST_XP 3 #define TEXTCTRLYADJUST_XP 3
#define TEXTCTRLXADJUST_CLASSIC 1 #define TEXTCTRLXADJUST_CLASSIC 1
#define TEXTCTRLYADJUST_CLASSIC 2 #define TEXTCTRLYADJUST_CLASSIC 3
#define COMBOBOX_ANIMATION_RESOLUTION 10 #define COMBOBOX_ANIMATION_RESOLUTION 10
@@ -114,9 +163,9 @@ bool wxComboCtrl::Create(wxWindow *parent,
if ( !border ) if ( !border )
{ {
// For XP, have 1-width custom border, for older version use sunken
if ( theme ) if ( theme )
{ {
// For XP, have 1-width custom border, for older version use sunken
border = wxBORDER_NONE; border = wxBORDER_NONE;
m_widthCustomBorder = 1; m_widthCustomBorder = 1;
} }
@@ -137,6 +186,12 @@ bool wxComboCtrl::Create(wxWindow *parent,
name) ) name) )
return false; return false;
if ( theme )
{
if ( ::wxGetWinVersion() >= wxWinVersion_Vista )
m_iFlags |= wxCC_BUTTON_STAYS_DOWN |wxCC_BUTTON_COVERS_BORDER;
}
if ( style & wxCC_STD_BUTTON ) if ( style & wxCC_STD_BUTTON )
m_iFlags |= wxCC_POPUP_ON_MOUSE_UP; m_iFlags |= wxCC_POPUP_ON_MOUSE_UP;
@@ -252,11 +307,10 @@ void
wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const
{ {
wxUxThemeHandle hTheme(this, L"COMBOBOX"); wxUxThemeHandle hTheme(this, L"COMBOBOX");
//COLORREF cref;
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
bool isEnabled; bool isEnabled;
bool isFocused; // also selected bool doDrawFocusRect; // also selected
// For smaller size control (and for disabled background) use less spacing // For smaller size control (and for disabled background) use less spacing
int focusSpacingX; int focusSpacingX;
@@ -266,7 +320,7 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const
{ {
// Drawing control // Drawing control
isEnabled = IsEnabled(); isEnabled = IsEnabled();
isFocused = ShouldDrawFocus(); doDrawFocusRect = ShouldDrawFocus();
// Windows-style: for smaller size control (and for disabled background) use less spacing // Windows-style: for smaller size control (and for disabled background) use less spacing
if ( hTheme ) if ( hTheme )
@@ -294,7 +348,7 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const
{ {
// Drawing a list item // Drawing a list item
isEnabled = true; // they are never disabled isEnabled = true; // they are never disabled
isFocused = flags & wxCONTROL_SELECTED ? true : false; doDrawFocusRect = flags & wxCONTROL_SELECTED ? true : false;
focusSpacingX = 0; focusSpacingX = 0;
focusSpacingY = 0; focusSpacingY = 0;
@@ -318,70 +372,61 @@ wxComboCtrl::PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const
// theme = wxUxThemeEngine::GetIfActive(); // theme = wxUxThemeEngine::GetIfActive();
wxColour bgCol; wxColour bgCol;
bool drawDottedEdge = false; bool doDrawDottedEdge = false;
bool doDrawSelRect = true;
// TODO: doDrawDottedEdge = true when focus has arrived to control via tab.
// (and other cases which are not that apparent).
if ( isEnabled ) if ( isEnabled )
{ {
// If popup is hidden and this control is focused, // If popup is hidden and this control is focused,
// then draw the focus-indicator (selbgcolor background etc.). // then draw the focus-indicator (selbgcolor background etc.).
if ( isFocused ) if ( doDrawFocusRect )
{ {
#if 0 // NB: We can't really use XP visual styles to get TMT_TEXTCOLOR since
// TODO: Proper theme color getting (JMS: I don't know which parts/colors to use, // it is not properly defined for combo boxes. Instead, they expect
// those below don't work) // you to use DrawThemeText.
if ( hTheme ) //
// Here is, however, sample code how to get theme colours:
//
// COLORREF cref;
// theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_TEXTCOLOR,&cref);
// dc.SetTextForeground( wxRGBToColour(cref) );
if ( (m_iFlags & wxCC_FULL_BUTTON) && !(flags & wxCONTROL_ISSUBMENU) )
{ {
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_TEXTCOLOR,&cref); // Vista style read-only combo
dc.SetTextForeground( wxRGBToColour(cref) ); doDrawSelRect = false;
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_FILLCOLOR,&cref); doDrawDottedEdge = true;
bgCol = wxRGBToColour(cref);
} }
else else
#endif
{ {
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
if ( m_windowStyle & wxCB_READONLY )
drawDottedEdge = true;
} }
} }
else else
{ {
/*if ( hTheme )
{
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_TEXTCOLOR,&cref);
dc.SetTextForeground( wxRGBToColour(cref) );
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_FILLCOLOR,&cref);
bgCol = wxRGBToColour(cref);
}
else
{*/
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
bgCol = GetBackgroundColour(); bgCol = GetBackgroundColour();
//} doDrawSelRect = false;
} }
} }
else else
{ {
/*if ( hTheme )
{
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_DISABLED,TMT_TEXTCOLOR,&cref);
dc.SetTextForeground( wxRGBToColour(cref) );
theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_DISABLED,TMT_EDGEFILLCOLOR,&cref);
bgCol = wxRGBToColour(cref);
}
else
{*/
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) ); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) );
bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
//}
} }
dc.SetBrush(bgCol); dc.SetBrush(bgCol);
if ( doDrawSelRect )
{
dc.SetPen(bgCol); dc.SetPen(bgCol);
dc.DrawRectangle(selRect); dc.DrawRectangle(selRect);
if ( drawDottedEdge ) }
wxMSWDrawFocusRect(dc,selRect);
if ( doDrawDottedEdge )
wxMSWDrawFocusRect(dc, selRect);
// Don't clip exactly to the selection rectangle so we can draw // Don't clip exactly to the selection rectangle so we can draw
// to the non-selected area in front of it. // to the non-selected area in front of it.
@@ -397,84 +442,187 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
wxAutoBufferedPaintDC dc(this); wxAutoBufferedPaintDC dc(this);
const wxRect& rectb = m_btnArea; const wxRect& rectButton = m_btnArea;
wxRect rect = m_tcArea; wxRect rectTextField = m_tcArea;
bool isEnabled = IsEnabled(); const bool isEnabled = IsEnabled();
wxColour bgCol = GetBackgroundColour(); wxColour bgCol = GetBackgroundColour();
wxColour fgCol;
HDC hDc = GetHdcOf(dc);
HWND hWnd = GetHwndOf(this);
wxUxThemeEngine* theme = NULL; wxUxThemeEngine* theme = NULL;
wxUxThemeHandle hTheme(this, L"COMBOBOX"); wxUxThemeHandle hTheme(this, L"COMBOBOX");
int etsState;
// area around both controls if ( hTheme )
wxRect rect2(0,0,sz.x,sz.y); theme = wxUxThemeEngine::GetIfActive();
wxRect borderRect(0,0,sz.x,sz.y);
if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
{ {
rect2 = m_tcArea; borderRect = m_tcArea;
rect2.Inflate(1); borderRect.Inflate(1);
} }
// Use theme to draw border on XP int drawButFlags = 0;
if ( hTheme ) if ( hTheme )
{ {
theme = wxUxThemeEngine::GetIfActive(); const bool useVistaComboBox = ::wxGetWinVersion() >= wxWinVersion_Vista;
COLORREF cref;
RECT rFull;
wxCopyRectToRECT(borderRect, rFull);
RECT rButton;
wxCopyRectToRECT(rectButton, rButton);
RECT rBorder;
wxCopyRectToRECT(borderRect, rBorder);
bool isNonStdButton = (m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE) ||
(m_iFlags & wxCC_IFLAG_HAS_NONSTANDARD_BUTTON);
//
// Get some states for themed drawing
int butState;
// Select correct border colour
if ( !isEnabled ) if ( !isEnabled )
etsState = ETS_DISABLED;
else
etsState = ETS_NORMAL;
if ( m_widthCustomBorder )
{ {
theme->GetThemeColor(hTheme,EP_EDITTEXT,etsState,TMT_BORDERCOLOR,&cref); butState = CBXS_DISABLED;
// Set border colour
dc.SetPen( wxRGBToColour(cref) );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle(rect2);
} }
// Vista will display the drop-button as depressed always
theme->GetThemeColor(hTheme,EP_EDITTEXT,etsState,TMT_TEXTCOLOR,&cref); // when the popup window is visilbe
fgCol = wxRGBToColour(cref); else if ( (m_btnState & wxCONTROL_PRESSED) ||
(useVistaComboBox && !IsPopupWindowState(Hidden)) )
{
butState = CBXS_PRESSED;
}
else if ( m_btnState & wxCONTROL_CURRENT )
{
butState = CBXS_HOT;
} }
else else
{ {
// draw regular background butState = CBXS_NORMAL;
fgCol = GetForegroundColour();
} }
rect2.Deflate(m_widthCustomBorder); int comboBoxPart = 0; // For XP, use the 'default' part
RECT* rUseForBg = &rBorder;
bool drawFullButton = false;
int bgState = butState;
const bool isFocused = (FindFocus() == GetMainWindowOfCompositeControl()) ? true : false;
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 )
{
if ( HasFlag(wxCB_READONLY) )
drawFullButton = true;
}
if ( drawFullButton )
{
comboBoxPart = CP_READONLY;
rUseForBg = &rFull;
// It should be safe enough to update this flag here.
m_iFlags |= wxCC_FULL_BUTTON;
}
else
{
comboBoxPart = CP_BORDER;
m_iFlags &= ~wxCC_FULL_BUTTON;
if ( isFocused )
bgState = CBB_FOCUSED;
else
bgState = CBB_NORMAL;
}
}
//
// Draw parent's background, if necessary
RECT* rUseForTb = NULL;
if ( theme->IsThemeBackgroundPartiallyTransparent( hTheme, comboBoxPart, bgState ) )
rUseForTb = &rFull;
else if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
rUseForTb = &rButton;
if ( rUseForTb )
theme->DrawThemeParentBackground( hWnd, hDc, rUseForTb );
//
// Draw the control background (including the border)
if ( m_widthCustomBorder > 0 )
{
theme->DrawThemeBackground( hTheme, hDc, comboBoxPart, bgState, rUseForBg, NULL );
}
else
{
// No border. We can't use theme, since it cannot be relied on
// to deliver borderless drawing, even with DrawThemeBackgroundEx.
dc.SetBrush(bgCol);
dc.SetPen(bgCol);
dc.DrawRectangle(borderRect);
}
//
// Draw the drop-button
if ( !isNonStdButton )
{
drawButFlags = Button_BitmapOnly;
int butPart = CP_DROPDOWNBUTTON;
if ( useVistaComboBox )
{
if ( drawFullButton )
{
// We need to alter the button style slightly before
// drawing the actual button (but it was good above
// when background etc was done).
if ( butState == CBXS_HOT || butState == CBXS_PRESSED )
butState = CBXS_NORMAL;
}
if ( m_btnSide == wxRIGHT )
butPart = CP_DROPDOWNBUTTONRIGHT;
else
butPart = CP_DROPDOWNBUTTONLEFT;
}
theme->DrawThemeBackground( hTheme, hDc, butPart, butState, &rButton, NULL );
}
else if ( useVistaComboBox &&
(m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE) )
{
// We'll do this, because DrawThemeParentBackground
// doesn't seem to be reliable on Vista.
drawButFlags |= Button_PaintBackground;
}
}
else
{
// Windows 2000 and earlier
drawButFlags = Button_PaintBackground;
dc.SetBrush(bgCol); dc.SetBrush(bgCol);
dc.SetPen(bgCol); dc.SetPen(bgCol);
dc.DrawRectangle(borderRect);
// clear main background
dc.DrawRectangle(rect);
// Button background with theme?
int drawButFlags = Draw_PaintBg;
if ( hTheme && m_blankButtonBg )
{
RECT r;
wxCopyRectToRECT(rectb, r);
// Draw parent background if needed (since button looks like its out of
// the combo, this is preferred).
theme->DrawThemeParentBackground(GetHwndOf(this),
GetHdcOf(dc),
&r);
drawButFlags = 0;
} }
// Standard button rendering // Button rendering (may only do the bitmap on button, depending on the flags)
DrawButton(dc,rectb,drawButFlags); DrawButton( dc, rectButton, drawButFlags );
// paint required portion on the control // Paint required portion of the custom image on the control
if ( (!m_text || m_widthCustomPaint) ) if ( (!m_text || m_widthCustomPaint) )
{ {
wxASSERT( m_widthCustomPaint >= 0 ); wxASSERT( m_widthCustomPaint >= 0 );
@@ -482,15 +630,15 @@ void wxComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
// this is intentionally here to allow drawed rectangle's // this is intentionally here to allow drawed rectangle's
// right edge to be hidden // right edge to be hidden
if ( m_text ) if ( m_text )
rect.width = m_widthCustomPaint; rectTextField.width = m_widthCustomPaint;
dc.SetFont( GetFont() ); dc.SetFont( GetFont() );
dc.SetClippingRegion(rect); dc.SetClippingRegion(rectTextField);
if ( m_popupInterface ) if ( m_popupInterface )
m_popupInterface->PaintComboControl(dc,rect); m_popupInterface->PaintComboControl(dc,rectTextField);
else else
wxComboPopup::DefaultPaintComboControl(this,dc,rect); wxComboPopup::DefaultPaintComboControl(this,dc,rectTextField);
} }
} }