Implement setting foreground colour for wxRadioButton in wxMSW.

Native radio buttons don't support changing their foreground colour, so use
owner drawn buttons if SetForegroundColour() was called, similarly to what was
already done for wxCheckBox.

Closes #10137.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76456 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-05-04 22:13:12 +00:00
parent 3fc6738025
commit fd65d4b4f5
3 changed files with 151 additions and 3 deletions

View File

@@ -62,6 +62,7 @@ wxMSW:
- Fix loading of bitmap with non-pre-multiplied alpha (Artur Wieczorek).
- Support multiline strings in wxDC::DrawRotatedText() (Artur Wieczorek).
- Fix stretchable spacers in vertical toolbars (Artur Wieczorek).
- Implement setting foreground colour for wxRadioButton (Artur Wieczorek).
- Add font colour support to wxFontPickerCtrl (Pana Alexandru).
- Add wxEnhMetaFile::Detach() (Luca Bacci).
- Add support for saving 256*256 32bpp ICOs in PNG format (Artur Wieczorek).

View File

@@ -47,18 +47,37 @@ public:
// implementation only from now on
virtual bool MSWCommand(WXUINT param, WXWORD id);
virtual void Command(wxCommandEvent& event);
virtual bool SetForegroundColour(const wxColour& colour);
virtual bool MSWOnDraw(WXDRAWITEMSTRUCT *item);
virtual bool HasTransparentBackground() { return true; }
// make the radiobutton owner drawn or reset it to normal style
void MSWMakeOwnerDrawn(bool ownerDrawn);
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
protected:
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
virtual wxSize DoGetBestSize() const;
virtual void MSWDrawButtonBitmap(wxWindow *win, wxDC& dc,
const wxRect& rect, int flags);
// return true if this checkbox is owner drawn
bool IsOwnerDrawn() const;
private:
// common part of all ctors
void Init();
// event handlers used by owner-drawn radiobutton
void OnMouseEnterOrLeave(wxMouseEvent& event);
void OnMouseLeft(wxMouseEvent& event);
void OnFocus(wxFocusEvent& event);
// true if the radio button is currently pressed
bool m_isPressed;
// we need to store the state internally as the result of GetValue()
// sometimes gets out of sync in WM_COMMAND handler
bool m_isChecked;

View File

@@ -34,6 +34,8 @@
#endif
#include "wx/msw/private.h"
#include "wx/renderer.h"
#include "wx/msw/uxtheme.h"
// ============================================================================
// wxRadioButton implementation
@@ -46,6 +48,7 @@
void wxRadioButton::Init()
{
m_isChecked = false;
m_isPressed = false;
}
bool wxRadioButton::Create(wxWindow *parent,
@@ -82,11 +85,14 @@ bool wxRadioButton::Create(wxWindow *parent,
void wxRadioButton::SetValue(bool value)
{
::SendMessage(GetHwnd(), BM_SETCHECK,
value ? BST_CHECKED : BST_UNCHECKED, 0);
m_isChecked = value;
if ( !IsOwnerDrawn() )
::SendMessage(GetHwnd(), BM_SETCHECK,
value ? BST_CHECKED : BST_UNCHECKED, 0);
else // owner drawn buttons don't react to this message
Refresh();
if ( !value )
return;
@@ -296,4 +302,126 @@ WXDWORD wxRadioButton::MSWGetStyle(long style, WXDWORD *exstyle) const
return msStyle;
}
// ----------------------------------------------------------------------------
// owner drawn radio button stuff
// ----------------------------------------------------------------------------
bool wxRadioButton::SetForegroundColour(const wxColour& colour)
{
if ( !wxControl::SetForegroundColour(colour) )
return false;
// the only way to change the radiobox foreground colour if themes are enablad
// is to owner draw it
if ( wxUxThemeEngine::GetIfActive() )
MSWMakeOwnerDrawn(colour.IsOk());
return true;
}
bool wxRadioButton::IsOwnerDrawn() const
{
return
(::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_OWNERDRAW) == BS_OWNERDRAW;
}
void wxRadioButton::MSWMakeOwnerDrawn(bool ownerDrawn)
{
long style = ::GetWindowLong(GetHwnd(), GWL_STYLE);
// note that BS_RADIOBUTTON & BS_OWNERDRAW != 0 so we can't operate on
// them as on independent style bits
if ( ownerDrawn )
{
style &= ~BS_RADIOBUTTON;
style |= BS_OWNERDRAW;
Connect(wxEVT_ENTER_WINDOW,
wxMouseEventHandler(wxRadioButton::OnMouseEnterOrLeave));
Connect(wxEVT_LEAVE_WINDOW,
wxMouseEventHandler(wxRadioButton::OnMouseEnterOrLeave));
Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxRadioButton::OnMouseLeft));
Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxRadioButton::OnMouseLeft));
Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxRadioButton::OnFocus));
Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(wxRadioButton::OnFocus));
}
else // reset to default colour
{
style &= ~BS_OWNERDRAW;
style |= BS_RADIOBUTTON;
Disconnect(wxEVT_ENTER_WINDOW,
wxMouseEventHandler(wxRadioButton::OnMouseEnterOrLeave));
Disconnect(wxEVT_LEAVE_WINDOW,
wxMouseEventHandler(wxRadioButton::OnMouseEnterOrLeave));
Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxRadioButton::OnMouseLeft));
Disconnect(wxEVT_LEFT_UP, wxMouseEventHandler(wxRadioButton::OnMouseLeft));
Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxRadioButton::OnFocus));
Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(wxRadioButton::OnFocus));
}
::SetWindowLong(GetHwnd(), GWL_STYLE, style);
}
void wxRadioButton::OnMouseEnterOrLeave(wxMouseEvent& event)
{
const bool isHot = event.GetEventType() == wxEVT_ENTER_WINDOW;
if ( !isHot )
m_isPressed = false;
Refresh();
event.Skip();
}
void wxRadioButton::OnMouseLeft(wxMouseEvent& event)
{
// TODO: we should capture the mouse here to be notified about left up
// event but this interferes with BN_CLICKED generation so if we
// want to do this we'd need to generate them ourselves
m_isPressed = event.GetEventType() == wxEVT_LEFT_DOWN;
Refresh();
event.Skip();
}
void wxRadioButton::OnFocus(wxFocusEvent& event)
{
Refresh();
event.Skip();
}
bool wxRadioButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
{
DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)item;
if ( !IsOwnerDrawn() || dis->CtlType != ODT_BUTTON )
return wxControl::MSWOnDraw(item);
// shall we draw a focus rect?
const bool isFocused = m_isPressed || FindFocus() == this;
int flags = 0;
if ( !IsEnabled() )
flags |= wxCONTROL_DISABLED;
if ( m_isChecked )
flags |= wxCONTROL_CHECKED;
if ( m_isPressed )
flags |= wxCONTROL_PRESSED;
if ( wxFindWindowAtPoint(wxGetMousePosition()) == this )
flags |= wxCONTROL_CURRENT;
return MSWOwnerDrawnButton(dis, flags, isFocused);
}
void wxRadioButton::MSWDrawButtonBitmap(wxWindow *win, wxDC& dc, const wxRect& rect, int flags)
{
wxRendererNative::Get().DrawRadioBitmap(win, dc, rect, flags);
}
#endif // wxUSE_RADIOBTN