Windows 11: draw checked menu items with an explicit background

On Windows 11, the UXTheme API draws both MBI_PUSHED and MBI_HOT in the
exact same color as the icon grove. For menu items with icon, but with
no explicit "On" icon, that makes it impossible to see whether the item
is checked.

Work around this problem by drawing the background in a light version of
the highlight color, which simulates the style on Windows 10.

Note: In modern Windows 11 menus, checkable items with icons render both
the checkmark, and the icon next to each other.

Pick-to: 6.4 6.2
Fixes: QTBUG-98354
Change-Id: I830eca5cdb3317f69dd5c863586e0b0eaa8774d2
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2022-10-23 11:01:02 +02:00
parent 91e7925dde
commit b3ce494bac

View File

@ -67,6 +67,14 @@ HTHEME QWindowsVistaStylePrivate::m_themes[NThemes];
bool QWindowsVistaStylePrivate::useVistaTheme = false;
Q_CONSTINIT QBasicAtomicInt QWindowsVistaStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
namespace QOSWorkaround {
// Due to a mingw bug being confused by static constexpr variables in an exported class,
// we cannot use QOperatingSystemVersion::Windows11 in libraries outside of QtCore.
// ### TODO Remove this when that problem is fixed.
static constexpr QOperatingSystemVersionBase Windows11 { QOperatingSystemVersionBase::Windows,
10, 0, 22000 };
}
static void qt_add_rect(HRGN &winRegion, QRect r)
{
HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
@ -2932,6 +2940,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
else
theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
d->drawBackground(theme);
} else if (QOperatingSystemVersion::current() >= QOSWorkaround::Windows11
&& !act) {
painter->fillRect(checkRect, menuitem->palette.highlight().color().lighter(200));
}
}