Merge branch 'sys-theme-fixes'

Fix disabling system theme for wxMSW wxListCtrl.

See https://github.com/wxWidgets/wxWidgets/pull/1332
This commit is contained in:
Vadim Zeitlin 2019-05-28 17:17:49 +02:00
commit 8caa379490
6 changed files with 80 additions and 8 deletions

View File

@ -21,7 +21,21 @@ class WXDLLIMPEXP_FWD_CORE wxWindow;
class WXDLLIMPEXP_CORE wxSystemThemedControlBase
{
public:
wxSystemThemedControlBase() { }
wxSystemThemedControlBase()
{
#ifdef wxHAS_SYSTEM_THEMED_CONTROL
m_systemThemeDisabled = false;
#endif // wxHAS_SYSTEM_THEMED_CONTROL
}
bool IsSystemThemeDisabled() const
{
#ifdef wxHAS_SYSTEM_THEMED_CONTROL
return m_systemThemeDisabled;
#else // !wxHAS_SYSTEM_THEMED_CONTROL
return false;
#endif // wxHAS_SYSTEM_THEMED_CONTROL/!wxHAS_SYSTEM_THEMED_CONTROL
}
virtual ~wxSystemThemedControlBase() { }
@ -36,6 +50,11 @@ protected:
(bool WXUNUSED(enable), wxWindow* WXUNUSED(window)) { }
#endif // wxHAS_SYSTEM_THEMED_CONTROL
private:
#ifdef wxHAS_SYSTEM_THEMED_CONTROL
bool m_systemThemeDisabled;
#endif // wxHAS_SYSTEM_THEMED_CONTROL
wxDECLARE_NO_COPY_CLASS(wxSystemThemedControlBase);
};
@ -54,6 +73,14 @@ public:
}
protected:
void EnableSystemThemeByDefault()
{
// Check if the system theme hadn't been explicitly disabled before
// enabling it by default.
if ( !this->IsSystemThemeDisabled() )
DoEnableSystemTheme(true, this);
}
wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxSystemThemedControl, C);
};

View File

@ -45,6 +45,27 @@
};
@endcode
Please also note that if you want to disable the system theme use in the
control that use it by default, it's best to do it before actually creating
the control as enabling the system theme can't always be completely undone
later. I.e. instead of
@code
// THIS CODE IS WRONG, DO NOT DO IT LIKE THIS
wxTreeCtrl* tree = new wxTreeCtrl(parent, wxID_ANY);
tree->EnableSystemTheme(false);
@endcode
prefer the following version:
@code
// Use default ctor to create the object, avoiding creating the window.
wxTreeCtrl* tree = new wxTreeCtrl();
// Then disable the system theme used by default.
tree->EnableSystemTheme(false);
// And only then actually create the window.
tree->Create(parent, wxID_ANY);
@endcode
On non-MSW platforms this class currently does nothing but is still
available, so that it can be used in portable code without any conditional
compilation directives.

View File

@ -5177,7 +5177,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent,
sizer->Add( m_clientArea, 1, wxGROW );
SetSizer( sizer );
EnableSystemTheme();
EnableSystemThemeByDefault();
#if wxUSE_ACCESSIBILITY
wxAccessible::NotifyEvent(wxACC_EVENT_OBJECT_CREATE, this, wxOBJID_CLIENT, wxACC_SELF);

View File

@ -302,7 +302,7 @@ bool wxListCtrl::Create(wxWindow *parent,
if ( !MSWCreateControl(WC_LISTVIEW, wxEmptyString, pos, size) )
return false;
EnableSystemTheme();
EnableSystemThemeByDefault();
// explicitly say that we want to use Unicode because otherwise we get ANSI
// versions of _some_ messages (notably LVN_GETDISPINFOA)
@ -2835,8 +2835,9 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
const int col = pLVCD->iSubItem;
const DWORD item = nmcd.dwItemSpec;
// the font must be valid, otherwise we wouldn't be painting the item at all
SelectInHDC selFont(hdc, hfont);
SelectInHDC selFont;
if ( hfont )
selFont.Init(hdc, hfont);
// get the rectangle to paint
RECT rc;
@ -3053,6 +3054,22 @@ static WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
return CDRF_NEWFONT;
}
// For some unknown reason, native control incorrectly uses the active
// selection colour for the background of the items using COLOR_BTNFACE as
// their custom background even when the control doesn't have focus (see
// #17988). To work around this, draw the item ourselves in this case.
//
// Note that the problem doesn't arise when using system theme, which is
// lucky as HandleItemPaint() doesn't result in the same appearance as with
// the system theme, so we should avoid using it in this case to ensure
// that all items appear consistently.
if ( listctrl->IsSystemThemeDisabled() &&
pLVCD->clrTextBk == ::GetSysColor(COLOR_BTNFACE) )
{
HandleItemPaint(pLVCD, NULL);
return CDRF_SKIPDEFAULT;
}
return CDRF_DODEFAULT;
}

View File

@ -24,8 +24,15 @@ void wxSystemThemedControlBase::DoEnableSystemTheme(bool enable, wxWindow* windo
{
if ( wxGetWinVersion() >= wxWinVersion_Vista && wxUxThemeIsActive() )
{
const wchar_t* const sysThemeId = enable ? L"EXPLORER" : NULL;
::SetWindowTheme(GetHwndOf(window), sysThemeId, NULL);
// It's possible to call EnableSystemTheme(false) before creating the
// window, just don't do anything in this case.
if ( window->GetHandle() )
{
const wchar_t* const sysThemeId = enable ? L"EXPLORER" : NULL;
::SetWindowTheme(GetHwndOf(window), sysThemeId, NULL);
}
m_systemThemeDisabled = !enable;
}
}

View File

@ -790,7 +790,7 @@ bool wxTreeCtrl::Create(wxWindow *parent,
{
// The Vista+ system theme uses rotating ("twist") buttons, so we map
// this style to it.
EnableSystemTheme();
EnableSystemThemeByDefault();
}
return true;