Factor out common owner drawn code from wx{Check,Radio}Box.
Create wxMSWOwnerDrawnButton class which contains all of this code. Currently the methods of this class are (still) implemented in src/msw/control.cpp. See #10137. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76459 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -11,8 +11,10 @@
|
|||||||
#ifndef _WX_CHECKBOX_H_
|
#ifndef _WX_CHECKBOX_H_
|
||||||
#define _WX_CHECKBOX_H_
|
#define _WX_CHECKBOX_H_
|
||||||
|
|
||||||
|
#include "wx/msw/ownerdrawnbutton.h"
|
||||||
|
|
||||||
// Checkbox item (single checkbox)
|
// Checkbox item (single checkbox)
|
||||||
class WXDLLIMPEXP_CORE wxCheckBox : public wxCheckBoxBase
|
class WXDLLIMPEXP_CORE wxCheckBox : public wxMSWOwnerDrawnButton<wxCheckBoxBase>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxCheckBox() { }
|
wxCheckBox() { }
|
||||||
@@ -45,15 +47,10 @@ public:
|
|||||||
|
|
||||||
virtual bool MSWCommand(WXUINT param, WXWORD id);
|
virtual bool MSWCommand(WXUINT param, WXWORD id);
|
||||||
virtual void Command(wxCommandEvent& event);
|
virtual void Command(wxCommandEvent& event);
|
||||||
virtual bool SetForegroundColour(const wxColour& colour);
|
|
||||||
virtual bool MSWOnDraw(WXDRAWITEMSTRUCT *item);
|
|
||||||
|
|
||||||
// returns true if the platform should explicitly apply a theme border
|
// returns true if the platform should explicitly apply a theme border
|
||||||
virtual bool CanApplyThemeBorder() const { return false; }
|
virtual bool CanApplyThemeBorder() const { return false; }
|
||||||
|
|
||||||
// make the checkbox owner drawn or reset it to normal style
|
|
||||||
void MSWMakeOwnerDrawn(bool ownerDrawn);
|
|
||||||
|
|
||||||
// implementation only from now on
|
// implementation only from now on
|
||||||
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle = NULL) const;
|
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle = NULL) const;
|
||||||
|
|
||||||
@@ -62,32 +59,21 @@ protected:
|
|||||||
|
|
||||||
virtual void DoSet3StateValue(wxCheckBoxState value);
|
virtual void DoSet3StateValue(wxCheckBoxState value);
|
||||||
virtual wxCheckBoxState DoGet3StateValue() const;
|
virtual wxCheckBoxState DoGet3StateValue() const;
|
||||||
virtual void MSWDrawButtonBitmap(wxWindow *win, wxDC& dc,
|
|
||||||
const wxRect& rect, int flags);
|
|
||||||
|
|
||||||
// return true if this checkbox is owner drawn
|
// Implement wxMSWOwnerDrawnButtonBase methods.
|
||||||
bool IsOwnerDrawn() const;
|
virtual int MSWGetButtonStyle() const wxOVERRIDE;
|
||||||
|
virtual void MSWOnButtonResetOwnerDrawn() wxOVERRIDE;
|
||||||
|
virtual int MSWGetButtonCheckedFlag() const wxOVERRIDE;
|
||||||
|
virtual void
|
||||||
|
MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags) wxOVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
// event handlers used by owner-drawn checkbox
|
|
||||||
void OnMouseEnterOrLeave(wxMouseEvent& event);
|
|
||||||
void OnMouseLeft(wxMouseEvent& event);
|
|
||||||
void OnFocus(wxFocusEvent& event);
|
|
||||||
|
|
||||||
|
|
||||||
// current state of the checkbox
|
// current state of the checkbox
|
||||||
wxCheckBoxState m_state;
|
wxCheckBoxState m_state;
|
||||||
|
|
||||||
// true if the checkbox is currently pressed
|
|
||||||
bool m_isPressed;
|
|
||||||
|
|
||||||
// true if mouse is currently over the control
|
|
||||||
bool m_isHot;
|
|
||||||
|
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckBox)
|
DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckBox)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -124,10 +124,6 @@ protected:
|
|||||||
// Look in our GetSubcontrols() for the windows with the given ID.
|
// Look in our GetSubcontrols() for the windows with the given ID.
|
||||||
virtual wxWindow *MSWFindItem(long id, WXHWND hWnd) const;
|
virtual wxWindow *MSWFindItem(long id, WXHWND hWnd) const;
|
||||||
|
|
||||||
// For ownerdraw buttons
|
|
||||||
virtual bool MSWOwnerDrawnButton(const DRAWITEMSTRUCT *dis, int flags, bool isFocused);
|
|
||||||
virtual void MSWDrawButtonBitmap(wxWindow *WXUNUSED(win), wxDC& WXUNUSED(dc),
|
|
||||||
const wxRect& WXUNUSED(rect), int WXUNUSED(flags)) {}
|
|
||||||
|
|
||||||
// for controls like radiobuttons which are really composite this array
|
// for controls like radiobuttons which are really composite this array
|
||||||
// holds the ids (not HWNDs!) of the sub controls
|
// holds the ids (not HWNDs!) of the sub controls
|
||||||
|
122
include/wx/msw/ownerdrawnbutton.h
Normal file
122
include/wx/msw/ownerdrawnbutton.h
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: wx/msw/ownerdrawnbutton.h
|
||||||
|
// Purpose: Common base class for wxCheckBox and wxRadioButton
|
||||||
|
// Author: Vadim Zeitlin
|
||||||
|
// Created: 2014-05-04
|
||||||
|
// Copyright: (c) 2014 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_MSW_OWNERDRAWNBUTTON_H_
|
||||||
|
#define _WX_MSW_OWNERDRAWNBUTTON_H_
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxMSWOwnerDrawnButton: base class for any kind of Windows buttons
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class contains the type-independent part of wxMSWOwnerDrawnButton and
|
||||||
|
// is implemented in src/msw/control.cpp.
|
||||||
|
//
|
||||||
|
// Notice that it is intentionally not exported, it is internal implementation
|
||||||
|
// detail only.
|
||||||
|
class wxMSWOwnerDrawnButtonBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Ctor takes the back pointer to the real window, must be non-NULL.
|
||||||
|
wxMSWOwnerDrawnButtonBase(wxWindow* win) :
|
||||||
|
m_win(win)
|
||||||
|
{
|
||||||
|
m_isPressed =
|
||||||
|
m_isHot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the control owner drawn if necessary to implement support for the
|
||||||
|
// given foreground colour.
|
||||||
|
void MSWMakeOwnerDrawnIfNecessary(const wxColour& colFg);
|
||||||
|
|
||||||
|
// Return true if the control is currently owner drawn.
|
||||||
|
bool MSWIsOwnerDrawn() const;
|
||||||
|
|
||||||
|
// Draw the button if the message information about which is provided in
|
||||||
|
// the given DRAWITEMSTRUCT asks us to do it, otherwise just return false.
|
||||||
|
bool MSWDrawButton(WXDRAWITEMSTRUCT *item);
|
||||||
|
|
||||||
|
|
||||||
|
// Methods which must be overridden in the derived concrete class.
|
||||||
|
|
||||||
|
// Return the style to use for the non-owner-drawn button.
|
||||||
|
virtual int MSWGetButtonStyle() const = 0;
|
||||||
|
|
||||||
|
// Called after reverting button to non-owner drawn state, provides a hook
|
||||||
|
// for wxCheckBox-specific hack.
|
||||||
|
virtual void MSWOnButtonResetOwnerDrawn() { }
|
||||||
|
|
||||||
|
// Return the flags (such as wxCONTROL_CHECKED) to use for the control when
|
||||||
|
// drawing it. Notice that this class already takes care of the common
|
||||||
|
// logic and sets the other wxCONTROL_XXX flags on its own, this method
|
||||||
|
// really only needs to return the flags depending on the checked state.
|
||||||
|
virtual int MSWGetButtonCheckedFlag() const = 0;
|
||||||
|
|
||||||
|
// Actually draw the check or radio bitmap, typically just by using the
|
||||||
|
// appropriate wxRendererNative method.
|
||||||
|
virtual void
|
||||||
|
MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Make the control owner drawn or reset it to normal style.
|
||||||
|
void MSWMakeOwnerDrawn(bool ownerDrawn);
|
||||||
|
|
||||||
|
// Event handlers used to update the appearance of owner drawn button.
|
||||||
|
void OnMouseEnterOrLeave(wxMouseEvent& event);
|
||||||
|
void OnMouseLeft(wxMouseEvent& event);
|
||||||
|
void OnFocus(wxFocusEvent& event);
|
||||||
|
|
||||||
|
|
||||||
|
// The real window.
|
||||||
|
wxWindow* const m_win;
|
||||||
|
|
||||||
|
// true if the checkbox is currently pressed
|
||||||
|
bool m_isPressed;
|
||||||
|
|
||||||
|
// true if mouse is currently over the control
|
||||||
|
bool m_isHot;
|
||||||
|
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxMSWOwnerDrawnButtonBase);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class uses a weak version of CRTP, i.e. it's a template class taking
|
||||||
|
// the base class that the class deriving from it would normally derive from.
|
||||||
|
template <class T>
|
||||||
|
class wxMSWOwnerDrawnButton : public T,
|
||||||
|
private wxMSWOwnerDrawnButtonBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef T Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
wxMSWOwnerDrawnButton() : wxMSWOwnerDrawnButtonBase(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool SetForegroundColour(const wxColour& colour) wxOVERRIDE
|
||||||
|
{
|
||||||
|
if ( !Base::SetForegroundColour(colour) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MSWMakeOwnerDrawnIfNecessary(colour);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool MSWOnDraw(WXDRAWITEMSTRUCT *item) wxOVERRIDE
|
||||||
|
{
|
||||||
|
return MSWDrawButton(item) || Base::MSWOnDraw(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool IsOwnerDrawn() const { return MSWIsOwnerDrawn(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _WX_MSW_OWNERDRAWNBUTTON_H_
|
@@ -11,7 +11,9 @@
|
|||||||
#ifndef _WX_RADIOBUT_H_
|
#ifndef _WX_RADIOBUT_H_
|
||||||
#define _WX_RADIOBUT_H_
|
#define _WX_RADIOBUT_H_
|
||||||
|
|
||||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxControl
|
#include "wx/msw/ownerdrawnbutton.h"
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_CORE wxRadioButton : public wxMSWOwnerDrawnButton<wxControl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// ctors and creation functions
|
// ctors and creation functions
|
||||||
@@ -47,36 +49,26 @@ public:
|
|||||||
// implementation only from now on
|
// implementation only from now on
|
||||||
virtual bool MSWCommand(WXUINT param, WXWORD id);
|
virtual bool MSWCommand(WXUINT param, WXWORD id);
|
||||||
virtual void Command(wxCommandEvent& event);
|
virtual void Command(wxCommandEvent& event);
|
||||||
virtual bool SetForegroundColour(const wxColour& colour);
|
|
||||||
virtual bool MSWOnDraw(WXDRAWITEMSTRUCT *item);
|
|
||||||
|
|
||||||
virtual bool HasTransparentBackground() { return true; }
|
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;
|
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
|
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
|
||||||
virtual wxSize DoGetBestSize() const;
|
virtual wxSize DoGetBestSize() const;
|
||||||
virtual void MSWDrawButtonBitmap(wxWindow *win, wxDC& dc,
|
|
||||||
const wxRect& rect, int flags);
|
|
||||||
|
|
||||||
// return true if this checkbox is owner drawn
|
// Implement wxMSWOwnerDrawnButtonBase methods.
|
||||||
bool IsOwnerDrawn() const;
|
virtual int MSWGetButtonStyle() const wxOVERRIDE;
|
||||||
|
virtual int MSWGetButtonCheckedFlag() const wxOVERRIDE;
|
||||||
|
virtual void
|
||||||
|
MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags) wxOVERRIDE;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
void Init();
|
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()
|
// we need to store the state internally as the result of GetValue()
|
||||||
// sometimes gets out of sync in WM_COMMAND handler
|
// sometimes gets out of sync in WM_COMMAND handler
|
||||||
|
@@ -84,8 +84,6 @@ enum
|
|||||||
void wxCheckBox::Init()
|
void wxCheckBox::Init()
|
||||||
{
|
{
|
||||||
m_state = wxCHK_UNCHECKED;
|
m_state = wxCHK_UNCHECKED;
|
||||||
m_isPressed =
|
|
||||||
m_isHot = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxCheckBox::Create(wxWindow *parent,
|
bool wxCheckBox::Create(wxWindow *parent,
|
||||||
@@ -269,145 +267,43 @@ bool wxCheckBox::MSWCommand(WXUINT cmd, WXWORD WXUNUSED(id))
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// owner drawn checkboxes stuff
|
// owner drawn checkboxes support
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxCheckBox::SetForegroundColour(const wxColour& colour)
|
int wxCheckBox::MSWGetButtonStyle() const
|
||||||
{
|
{
|
||||||
if ( !wxCheckBoxBase::SetForegroundColour(colour) )
|
return HasFlag(wxCHK_3STATE) ? BS_3STATE : BS_CHECKBOX;
|
||||||
return false;
|
|
||||||
|
|
||||||
// the only way to change the checkbox foreground colour under Windows XP
|
|
||||||
// is to owner draw it
|
|
||||||
if ( wxUxThemeEngine::GetIfActive() )
|
|
||||||
MSWMakeOwnerDrawn(colour.IsOk());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxCheckBox::IsOwnerDrawn() const
|
void wxCheckBox::MSWOnButtonResetOwnerDrawn()
|
||||||
{
|
|
||||||
return
|
|
||||||
(::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_OWNERDRAW) == BS_OWNERDRAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxCheckBox::MSWMakeOwnerDrawn(bool ownerDrawn)
|
|
||||||
{
|
|
||||||
long style = ::GetWindowLong(GetHwnd(), GWL_STYLE);
|
|
||||||
|
|
||||||
// note that BS_CHECKBOX & BS_OWNERDRAW != 0 so we can't operate on
|
|
||||||
// them as on independent style bits
|
|
||||||
if ( ownerDrawn )
|
|
||||||
{
|
|
||||||
style &= ~(BS_CHECKBOX | BS_3STATE);
|
|
||||||
style |= BS_OWNERDRAW;
|
|
||||||
|
|
||||||
Connect(wxEVT_ENTER_WINDOW,
|
|
||||||
wxMouseEventHandler(wxCheckBox::OnMouseEnterOrLeave));
|
|
||||||
Connect(wxEVT_LEAVE_WINDOW,
|
|
||||||
wxMouseEventHandler(wxCheckBox::OnMouseEnterOrLeave));
|
|
||||||
Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxCheckBox::OnMouseLeft));
|
|
||||||
Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxCheckBox::OnMouseLeft));
|
|
||||||
Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxCheckBox::OnFocus));
|
|
||||||
Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(wxCheckBox::OnFocus));
|
|
||||||
}
|
|
||||||
else // reset to default colour
|
|
||||||
{
|
|
||||||
style &= ~BS_OWNERDRAW;
|
|
||||||
style |= HasFlag(wxCHK_3STATE) ? BS_3STATE : BS_CHECKBOX;
|
|
||||||
|
|
||||||
Disconnect(wxEVT_ENTER_WINDOW,
|
|
||||||
wxMouseEventHandler(wxCheckBox::OnMouseEnterOrLeave));
|
|
||||||
Disconnect(wxEVT_LEAVE_WINDOW,
|
|
||||||
wxMouseEventHandler(wxCheckBox::OnMouseEnterOrLeave));
|
|
||||||
Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxCheckBox::OnMouseLeft));
|
|
||||||
Disconnect(wxEVT_LEFT_UP, wxMouseEventHandler(wxCheckBox::OnMouseLeft));
|
|
||||||
Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxCheckBox::OnFocus));
|
|
||||||
Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(wxCheckBox::OnFocus));
|
|
||||||
}
|
|
||||||
|
|
||||||
::SetWindowLong(GetHwnd(), GWL_STYLE, style);
|
|
||||||
|
|
||||||
if ( !ownerDrawn )
|
|
||||||
{
|
{
|
||||||
// ensure that controls state is consistent with internal state
|
// ensure that controls state is consistent with internal state
|
||||||
DoSet3StateValue(m_state);
|
DoSet3StateValue(m_state);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void wxCheckBox::OnMouseEnterOrLeave(wxMouseEvent& event)
|
int wxCheckBox::MSWGetButtonCheckedFlag() const
|
||||||
{
|
{
|
||||||
m_isHot = event.GetEventType() == wxEVT_ENTER_WINDOW;
|
|
||||||
if ( !m_isHot )
|
|
||||||
m_isPressed = false;
|
|
||||||
|
|
||||||
Refresh();
|
|
||||||
|
|
||||||
event.Skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxCheckBox::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 wxCheckBox::OnFocus(wxFocusEvent& event)
|
|
||||||
{
|
|
||||||
Refresh();
|
|
||||||
|
|
||||||
event.Skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxCheckBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
|
|
||||||
{
|
|
||||||
DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)item;
|
|
||||||
|
|
||||||
if ( !IsOwnerDrawn() || dis->CtlType != ODT_BUTTON )
|
|
||||||
return wxCheckBoxBase::MSWOnDraw(item);
|
|
||||||
|
|
||||||
// shall we draw a focus rect?
|
|
||||||
const bool isFocused = m_isPressed || FindFocus() == this;
|
|
||||||
|
|
||||||
int flags = 0;
|
|
||||||
if ( !IsEnabled() )
|
|
||||||
flags |= wxCONTROL_DISABLED;
|
|
||||||
switch ( Get3StateValue() )
|
switch ( Get3StateValue() )
|
||||||
{
|
{
|
||||||
case wxCHK_CHECKED:
|
case wxCHK_CHECKED:
|
||||||
flags |= wxCONTROL_CHECKED;
|
return wxCONTROL_CHECKED;
|
||||||
break;
|
|
||||||
|
|
||||||
case wxCHK_UNDETERMINED:
|
case wxCHK_UNDETERMINED:
|
||||||
flags |= wxCONTROL_PRESSED;
|
return wxCONTROL_PRESSED;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
wxFAIL_MSG( wxT("unexpected Get3StateValue() return value") );
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
case wxCHK_UNCHECKED:
|
case wxCHK_UNCHECKED:
|
||||||
// no extra styles needed
|
// no extra styles needed
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_isPressed )
|
wxFAIL_MSG( wxT("unexpected Get3StateValue() return value") );
|
||||||
flags |= wxCONTROL_PRESSED;
|
|
||||||
|
|
||||||
if ( wxFindWindowAtPoint(wxGetMousePosition()) == this )
|
return 0;
|
||||||
flags |= wxCONTROL_CURRENT;
|
|
||||||
|
|
||||||
return MSWOwnerDrawnButton(dis, flags, isFocused);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCheckBox::MSWDrawButtonBitmap(wxWindow *win, wxDC& dc, const wxRect& rect, int flags)
|
void wxCheckBox::MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags)
|
||||||
{
|
{
|
||||||
wxRendererNative::Get().DrawCheckBox(win, dc, rect, flags);
|
wxRendererNative::Get().DrawCheckBox(this, dc, rect, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_CHECKBOX
|
#endif // wxUSE_CHECKBOX
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include "wx/treectrl.h"
|
#include "wx/treectrl.h"
|
||||||
#endif // wxUSE_TREECTRL
|
#endif // wxUSE_TREECTRL
|
||||||
|
|
||||||
|
#include "wx/renderer.h"
|
||||||
#include "wx/msw/private.h"
|
#include "wx/msw/private.h"
|
||||||
#include "wx/msw/uxtheme.h"
|
#include "wx/msw/uxtheme.h"
|
||||||
#include "wx/msw/dc.h" // for wxDCTemp
|
#include "wx/msw/dc.h" // for wxDCTemp
|
||||||
@@ -452,17 +453,139 @@ wxWindow* wxControl::MSWFindItem(long id, WXHWND hWnd) const
|
|||||||
return wxControlBase::MSWFindItem(id, hWnd);
|
return wxControlBase::MSWFindItem(id, hWnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxControl::MSWOwnerDrawnButton(const DRAWITEMSTRUCT *dis, int flags, bool isFocused)
|
// ----------------------------------------------------------------------------
|
||||||
|
// Owner drawn buttons support.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
wxMSWOwnerDrawnButtonBase::MSWMakeOwnerDrawnIfNecessary(const wxColour& colFg)
|
||||||
{
|
{
|
||||||
|
// The only way to change the checkbox foreground colour when using
|
||||||
|
// themes is to owner draw it.
|
||||||
|
if ( wxUxThemeEngine::GetIfActive() )
|
||||||
|
MSWMakeOwnerDrawn(colFg.IsOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxMSWOwnerDrawnButtonBase::MSWIsOwnerDrawn() const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(::GetWindowLong(GetHwndOf(m_win), GWL_STYLE) & BS_OWNERDRAW) == BS_OWNERDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMSWOwnerDrawnButtonBase::MSWMakeOwnerDrawn(bool ownerDrawn)
|
||||||
|
{
|
||||||
|
long style = ::GetWindowLong(GetHwndOf(m_win), GWL_STYLE);
|
||||||
|
|
||||||
|
// note that BS_CHECKBOX & BS_OWNERDRAW != 0 so we can't operate on
|
||||||
|
// them as on independent style bits
|
||||||
|
if ( ownerDrawn )
|
||||||
|
{
|
||||||
|
style &= ~BS_TYPEMASK;
|
||||||
|
style |= BS_OWNERDRAW;
|
||||||
|
|
||||||
|
m_win->Bind(wxEVT_ENTER_WINDOW,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this);
|
||||||
|
m_win->Bind(wxEVT_LEAVE_WINDOW,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this);
|
||||||
|
|
||||||
|
m_win->Bind(wxEVT_LEFT_DOWN,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseLeft, this);
|
||||||
|
m_win->Bind(wxEVT_LEFT_UP,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseLeft, this);
|
||||||
|
|
||||||
|
m_win->Bind(wxEVT_SET_FOCUS,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnFocus, this);
|
||||||
|
|
||||||
|
m_win->Bind(wxEVT_KILL_FOCUS,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnFocus, this);
|
||||||
|
}
|
||||||
|
else // reset to default colour
|
||||||
|
{
|
||||||
|
style &= ~BS_OWNERDRAW;
|
||||||
|
style |= MSWGetButtonStyle();
|
||||||
|
|
||||||
|
m_win->Unbind(wxEVT_ENTER_WINDOW,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this);
|
||||||
|
m_win->Unbind(wxEVT_LEAVE_WINDOW,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this);
|
||||||
|
|
||||||
|
m_win->Unbind(wxEVT_LEFT_DOWN,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseLeft, this);
|
||||||
|
m_win->Unbind(wxEVT_LEFT_UP,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnMouseLeft, this);
|
||||||
|
|
||||||
|
m_win->Unbind(wxEVT_SET_FOCUS,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnFocus, this);
|
||||||
|
m_win->Unbind(wxEVT_KILL_FOCUS,
|
||||||
|
&wxMSWOwnerDrawnButtonBase::OnFocus, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
::SetWindowLong(GetHwndOf(m_win), GWL_STYLE, style);
|
||||||
|
|
||||||
|
if ( !ownerDrawn )
|
||||||
|
MSWOnButtonResetOwnerDrawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave(wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
if ( event.GetEventType() == wxEVT_LEAVE_WINDOW )
|
||||||
|
m_isPressed = false;
|
||||||
|
|
||||||
|
m_win->Refresh();
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMSWOwnerDrawnButtonBase::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;
|
||||||
|
m_win->Refresh();
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMSWOwnerDrawnButtonBase::OnFocus(wxFocusEvent& event)
|
||||||
|
{
|
||||||
|
m_win->Refresh();
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxMSWOwnerDrawnButtonBase::MSWDrawButton(WXDRAWITEMSTRUCT *item)
|
||||||
|
{
|
||||||
|
DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)item;
|
||||||
|
|
||||||
|
if ( !MSWIsOwnerDrawn() || dis->CtlType != ODT_BUTTON )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// shall we draw a focus rect?
|
||||||
|
const bool isFocused = m_isPressed || m_win->HasFocus();
|
||||||
|
|
||||||
|
int flags = MSWGetButtonCheckedFlag();
|
||||||
|
|
||||||
|
if ( !m_win->IsEnabled() )
|
||||||
|
flags |= wxCONTROL_DISABLED;
|
||||||
|
|
||||||
|
if ( m_isPressed )
|
||||||
|
flags |= wxCONTROL_PRESSED;
|
||||||
|
|
||||||
|
if ( wxFindWindowAtPoint(wxGetMousePosition()) == m_win )
|
||||||
|
flags |= wxCONTROL_CURRENT;
|
||||||
|
|
||||||
|
|
||||||
// calculate the rectangles for the button itself and the label
|
// calculate the rectangles for the button itself and the label
|
||||||
HDC hdc = dis->hDC;
|
HDC hdc = dis->hDC;
|
||||||
const RECT& rect = dis->rcItem;
|
const RECT& rect = dis->rcItem;
|
||||||
|
|
||||||
// calculate the rectangles for the button itself and the label
|
// calculate the rectangles for the button itself and the label
|
||||||
|
const wxSize bestSize = m_win->GetBestSize();
|
||||||
RECT rectButton,
|
RECT rectButton,
|
||||||
rectLabel;
|
rectLabel;
|
||||||
rectLabel.top = rect.top + (rect.bottom - rect.top - GetBestSize().y) / 2;
|
rectLabel.top = rect.top + (rect.bottom - rect.top - bestSize.y) / 2;
|
||||||
rectLabel.bottom = rectLabel.top + GetBestSize().y;
|
rectLabel.bottom = rectLabel.top + bestSize.y;
|
||||||
|
|
||||||
// choose the values consistent with those used for native, non
|
// choose the values consistent with those used for native, non
|
||||||
// owner-drawn, buttons
|
// owner-drawn, buttons
|
||||||
@@ -475,11 +598,11 @@ bool wxControl::MSWOwnerDrawnButton(const DRAWITEMSTRUCT *dis, int flags, bool i
|
|||||||
|
|
||||||
// The space between the button and the label
|
// The space between the button and the label
|
||||||
// is included in the button bitmap.
|
// is included in the button bitmap.
|
||||||
const int buttonSize = wxMin(CXMENUCHECK - MARGIN, GetSize().y);
|
const int buttonSize = wxMin(CXMENUCHECK - MARGIN, m_win->GetSize().y);
|
||||||
rectButton.top = rect.top + (rect.bottom - rect.top - buttonSize) / 2;
|
rectButton.top = rect.top + (rect.bottom - rect.top - buttonSize) / 2;
|
||||||
rectButton.bottom = rectButton.top + buttonSize;
|
rectButton.bottom = rectButton.top + buttonSize;
|
||||||
|
|
||||||
const bool isRightAligned = HasFlag(wxALIGN_RIGHT);
|
const bool isRightAligned = m_win->HasFlag(wxALIGN_RIGHT);
|
||||||
if ( isRightAligned )
|
if ( isRightAligned )
|
||||||
{
|
{
|
||||||
rectLabel.right = rect.right - CXMENUCHECK;
|
rectLabel.right = rect.right - CXMENUCHECK;
|
||||||
@@ -500,10 +623,10 @@ bool wxControl::MSWOwnerDrawnButton(const DRAWITEMSTRUCT *dis, int flags, bool i
|
|||||||
// draw the button itself
|
// draw the button itself
|
||||||
wxDCTemp dc(hdc);
|
wxDCTemp dc(hdc);
|
||||||
|
|
||||||
MSWDrawButtonBitmap(this, dc, wxRectFromRECT(rectButton), flags);
|
MSWDrawButtonBitmap(dc, wxRectFromRECT(rectButton), flags);
|
||||||
|
|
||||||
// draw the text
|
// draw the text
|
||||||
const wxString& label = GetLabel();
|
const wxString& label = m_win->GetLabel();
|
||||||
|
|
||||||
// first we need to measure it
|
// first we need to measure it
|
||||||
UINT fmt = DT_NOCLIP;
|
UINT fmt = DT_NOCLIP;
|
||||||
@@ -537,7 +660,7 @@ bool wxControl::MSWOwnerDrawnButton(const DRAWITEMSTRUCT *dis, int flags, bool i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !IsEnabled() )
|
if ( flags & wxCONTROL_DISABLED )
|
||||||
{
|
{
|
||||||
::SetTextColor(hdc, ::GetSysColor(COLOR_GRAYTEXT));
|
::SetTextColor(hdc, ::GetSysColor(COLOR_GRAYTEXT));
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,6 @@
|
|||||||
void wxRadioButton::Init()
|
void wxRadioButton::Init()
|
||||||
{
|
{
|
||||||
m_isChecked = false;
|
m_isChecked = false;
|
||||||
m_isPressed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRadioButton::Create(wxWindow *parent,
|
bool wxRadioButton::Create(wxWindow *parent,
|
||||||
@@ -306,122 +305,19 @@ WXDWORD wxRadioButton::MSWGetStyle(long style, WXDWORD *exstyle) const
|
|||||||
// owner drawn radio button stuff
|
// owner drawn radio button stuff
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxRadioButton::SetForegroundColour(const wxColour& colour)
|
int wxRadioButton::MSWGetButtonStyle() const
|
||||||
{
|
{
|
||||||
if ( !wxControl::SetForegroundColour(colour) )
|
return BS_RADIOBUTTON;
|
||||||
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
|
int wxRadioButton::MSWGetButtonCheckedFlag() const
|
||||||
{
|
{
|
||||||
return
|
return m_isChecked ? wxCONTROL_CHECKED : 0;
|
||||||
(::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_OWNERDRAW) == BS_OWNERDRAW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxRadioButton::MSWMakeOwnerDrawn(bool ownerDrawn)
|
void wxRadioButton::MSWDrawButtonBitmap(wxDC& dc, const wxRect& rect, int flags)
|
||||||
{
|
{
|
||||||
long style = ::GetWindowLong(GetHwnd(), GWL_STYLE);
|
wxRendererNative::Get().DrawRadioBitmap(this, dc, rect, flags);
|
||||||
|
|
||||||
// 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
|
#endif // wxUSE_RADIOBTN
|
||||||
|
Reference in New Issue
Block a user