Minor tweaks.
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
c3d54c616d
commit
955961cf9b
|
@ -1,6 +1,7 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>qml/main.qml</file>
|
<file alias="qml/+windows/main.qml">qml/main_windows.qml</file>
|
||||||
|
<file alias="qml/+unix/main.qml">qml/main_unix.qml</file>
|
||||||
<file>qml/MinimizeButton.qml</file>
|
<file>qml/MinimizeButton.qml</file>
|
||||||
<file>qml/MaximizeButton.qml</file>
|
<file>qml/MaximizeButton.qml</file>
|
||||||
<file>qml/CloseButton.qml</file>
|
<file>qml/CloseButton.qml</file>
|
||||||
|
|
|
@ -50,9 +50,8 @@ Window {
|
||||||
Text {
|
Text {
|
||||||
id: titleBarText
|
id: titleBarText
|
||||||
text: window.title
|
text: window.title
|
||||||
font.family: "Noto Sans CJK SC"
|
|
||||||
font.pointSize: 13
|
font.pointSize: 13
|
||||||
color: "black"
|
color: window.active ? "black" : "gray"
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 15
|
anchors.leftMargin: 15
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Window 2.15
|
||||||
|
import wangwenx190.Utils 1.0
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: window
|
||||||
|
visible: true
|
||||||
|
width: 800
|
||||||
|
height: 600
|
||||||
|
title: qsTr("Hello, World!")
|
||||||
|
|
||||||
|
FramelessHelper {
|
||||||
|
id: framelessHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: titleBar
|
||||||
|
height: framelessHelper.titleBarHeight
|
||||||
|
color: (window.active && framelessHelper.colorizationEnabled) ? framelessHelper.colorizationColor : "white"
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: titleBarText
|
||||||
|
text: window.title
|
||||||
|
font.pointSize: 13
|
||||||
|
color: window.active ? (framelessHelper.colorizationEnabled ? "white" : "black") : "gray"
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
MinimizeButton {
|
||||||
|
id: minimizeButton
|
||||||
|
onClicked: window.showMinimized()
|
||||||
|
Component.onCompleted: framelessHelper.addIgnoreObject(
|
||||||
|
minimizeButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
MaximizeButton {
|
||||||
|
id: maximizeButton
|
||||||
|
maximized: window.visibility === Window.Maximized
|
||||||
|
onClicked: {
|
||||||
|
if (maximized) {
|
||||||
|
window.showNormal()
|
||||||
|
} else {
|
||||||
|
window.showMaximized()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: framelessHelper.addIgnoreObject(
|
||||||
|
maximizeButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseButton {
|
||||||
|
id: closeButton
|
||||||
|
onClicked: window.close()
|
||||||
|
Component.onCompleted: framelessHelper.addIgnoreObject(
|
||||||
|
closeButton)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: content
|
||||||
|
color: "#f0f0f0"
|
||||||
|
anchors {
|
||||||
|
top: titleBar.bottom
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: topFrame
|
||||||
|
visible: framelessHelper.canHaveWindowFrame && (window.visibility === Window.Windowed)
|
||||||
|
color: window.active ? (framelessHelper.colorizationEnabled ? framelessHelper.colorizationColor : "#707070") : "#aaaaaa"
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
framelessHelper.setWindowFrameVisible(framelessHelper.canHaveWindowFrame)
|
||||||
|
framelessHelper.removeWindowFrame(true)
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include "../../winnativeeventfilter.h"
|
#include "../../winnativeeventfilter.h"
|
||||||
#include <dwmapi.h>
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
|
@ -34,7 +33,6 @@
|
||||||
#include <QOperatingSystemVersion>
|
#include <QOperatingSystemVersion>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSettings>
|
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
|
@ -54,12 +52,7 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum : WORD { DwmwaUseImmersiveDarkMode = 20, DwmwaUseImmersiveDarkModeBefore20h1 = 19 };
|
|
||||||
|
|
||||||
const Widget::Win10Version g_vAcrylicEffectVersion = Widget::Win10Version::Win10_1803;
|
const Widget::Win10Version g_vAcrylicEffectVersion = Widget::Win10Version::Win10_1803;
|
||||||
const Widget::Win10Version g_vLightThemeVersion = Widget::Win10Version::Win10_1809;
|
|
||||||
const Widget::Win10Version g_vDarkThemeVersion = g_vLightThemeVersion; // check
|
|
||||||
const Widget::Win10Version g_vDarkFrameVersion = g_vDarkThemeVersion; // check
|
|
||||||
|
|
||||||
const QColor g_cDefaultActiveBorderColor = {"#707070"};
|
const QColor g_cDefaultActiveBorderColor = {"#707070"};
|
||||||
const QColor g_cDefaultInactiveBorderColor = {"#aaaaaa"};
|
const QColor g_cDefaultInactiveBorderColor = {"#aaaaaa"};
|
||||||
|
@ -70,10 +63,6 @@ const char g_sPreserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME";
|
||||||
const char g_sForceUseAcrylicEffect[] = "WNEF_FORCE_ACRYLIC_ON_WIN10";
|
const char g_sForceUseAcrylicEffect[] = "WNEF_FORCE_ACRYLIC_ON_WIN10";
|
||||||
const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME";
|
const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME";
|
||||||
|
|
||||||
const QLatin1String g_sDwmRegistryKey(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM)");
|
|
||||||
const QLatin1String g_sPersonalizeRegistryKey(
|
|
||||||
R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
|
|
||||||
|
|
||||||
const QLatin1String g_sSystemButtonsStyleSheet(R"(
|
const QLatin1String g_sSystemButtonsStyleSheet(R"(
|
||||||
#iconButton, #minimizeButton, #maximizeButton, #closeButton {
|
#iconButton, #minimizeButton, #maximizeButton, #closeButton {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -296,17 +285,18 @@ bool Widget::shouldDrawBorder(const bool ignoreWindowState) const
|
||||||
|
|
||||||
bool Widget::shouldDrawThemedBorder(const bool ignoreWindowState) const
|
bool Widget::shouldDrawThemedBorder(const bool ignoreWindowState) const
|
||||||
{
|
{
|
||||||
return (shouldDrawBorder(ignoreWindowState) && colorizationColorEnabled());
|
return (shouldDrawBorder(ignoreWindowState) && WinNativeEventFilter::colorizationEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::shouldDrawThemedTitleBar() const
|
bool Widget::shouldDrawThemedTitleBar() const
|
||||||
{
|
{
|
||||||
return m_bIsWin10OrGreater && colorizationColorEnabled();
|
return m_bIsWin10OrGreater && WinNativeEventFilter::colorizationEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Widget::activeBorderColor()
|
QColor Widget::activeBorderColor()
|
||||||
{
|
{
|
||||||
return colorizationColorEnabled() ? g_cColorizationColor : g_cDefaultActiveBorderColor;
|
return WinNativeEventFilter::colorizationEnabled() ? g_cColorizationColor
|
||||||
|
: g_cDefaultActiveBorderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Widget::inactiveBorderColor()
|
QColor Widget::inactiveBorderColor()
|
||||||
|
@ -330,91 +320,6 @@ bool Widget::isWin10OrGreater(const Win10Version subVer)
|
||||||
static_cast<int>(subVer))));
|
static_cast<int>(subVer))));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Widget::colorizationColor()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
DWORD color = 0;
|
|
||||||
BOOL opaqueBlend = FALSE;
|
|
||||||
return SUCCEEDED(DwmGetColorizationColor(&color, &opaqueBlend)) ? QColor::fromRgba(color)
|
|
||||||
: Qt::white;
|
|
||||||
#else
|
|
||||||
bool ok = false;
|
|
||||||
const QSettings registry(g_sDwmRegistryKey, QSettings::NativeFormat);
|
|
||||||
const quint64 color = registry.value(QLatin1String("ColorizationColor"), 0).toULongLong(&ok);
|
|
||||||
return ok ? QColor::fromRgba(color) : Qt::white;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::colorizationColorEnabled()
|
|
||||||
{
|
|
||||||
if (!isWin10OrGreater()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool ok = false;
|
|
||||||
const QSettings registry(g_sDwmRegistryKey, QSettings::NativeFormat);
|
|
||||||
const bool colorPrevalence = registry.value(QLatin1String("ColorPrevalence"), 0).toULongLong(&ok)
|
|
||||||
!= 0;
|
|
||||||
return (ok && colorPrevalence);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::lightThemeEnabled()
|
|
||||||
{
|
|
||||||
if (!isWin10OrGreater(g_vLightThemeVersion)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool ok = false;
|
|
||||||
const QSettings registry(g_sPersonalizeRegistryKey, QSettings::NativeFormat);
|
|
||||||
const bool appsUseLightTheme
|
|
||||||
= registry.value(QLatin1String("AppsUseLightTheme"), 0).toULongLong(&ok) != 0;
|
|
||||||
return (ok && appsUseLightTheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::darkThemeEnabled()
|
|
||||||
{
|
|
||||||
if (!isWin10OrGreater(g_vDarkThemeVersion)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !lightThemeEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::highContrastModeEnabled()
|
|
||||||
{
|
|
||||||
HIGHCONTRASTW hc;
|
|
||||||
SecureZeroMemory(&hc, sizeof(hc));
|
|
||||||
hc.cbSize = sizeof(hc);
|
|
||||||
return SystemParametersInfoW(SPI_GETHIGHCONTRAST, 0, &hc, 0) ? (hc.dwFlags & HCF_HIGHCONTRASTON)
|
|
||||||
: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::darkFrameEnabled(void *handle)
|
|
||||||
{
|
|
||||||
Q_ASSERT(handle);
|
|
||||||
if (!isWin10OrGreater(g_vDarkFrameVersion)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto hwnd = reinterpret_cast<HWND>(handle);
|
|
||||||
BOOL result = FALSE;
|
|
||||||
const bool ok
|
|
||||||
= SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result)))
|
|
||||||
|| SUCCEEDED(DwmGetWindowAttribute(hwnd,
|
|
||||||
DwmwaUseImmersiveDarkModeBefore20h1,
|
|
||||||
&result,
|
|
||||||
sizeof(result)));
|
|
||||||
return (ok && result);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Widget::transparencyEffectEnabled()
|
|
||||||
{
|
|
||||||
if (!isWin10OrGreater()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool ok = false;
|
|
||||||
const QSettings registry(g_sPersonalizeRegistryKey, QSettings::NativeFormat);
|
|
||||||
const bool enableTransparency
|
|
||||||
= registry.value(QLatin1String("EnableTransparency"), 0).toULongLong(&ok) != 0;
|
|
||||||
return (ok && enableTransparency);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Widget::rawHandle() const
|
void *Widget::rawHandle() const
|
||||||
{
|
{
|
||||||
return reinterpret_cast<void *>(winId());
|
return reinterpret_cast<void *>(winId());
|
||||||
|
@ -650,7 +555,7 @@ void Widget::setupConnections()
|
||||||
}
|
}
|
||||||
WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enable, color);
|
WinNativeEventFilter::setBlurEffectEnabled(rawHandle(), enable, color);
|
||||||
updateWindow();
|
updateWindow();
|
||||||
if (useAcrylicEffect && enable && transparencyEffectEnabled()) {
|
if (useAcrylicEffect && enable && WinNativeEventFilter::transparencyEffectEnabled()) {
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("BUG Warning!"),
|
tr("BUG Warning!"),
|
||||||
tr("You have enabled the transparency effect in the personalize "
|
tr("You have enabled the transparency effect in the personalize "
|
||||||
|
@ -697,7 +602,7 @@ void Widget::initializeVariables()
|
||||||
m_bIsWin10OrGreater = isWin10OrGreater();
|
m_bIsWin10OrGreater = isWin10OrGreater();
|
||||||
if (m_bIsWin10OrGreater) {
|
if (m_bIsWin10OrGreater) {
|
||||||
m_bCanAcrylicBeEnabled = isWin10OrGreater(g_vAcrylicEffectVersion);
|
m_bCanAcrylicBeEnabled = isWin10OrGreater(g_vAcrylicEffectVersion);
|
||||||
g_cColorizationColor = colorizationColor();
|
g_cColorizationColor = WinNativeEventFilter::colorizationColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,13 +80,6 @@ public:
|
||||||
QColor borderColor() const;
|
QColor borderColor() const;
|
||||||
|
|
||||||
static bool isWin10OrGreater(const Win10Version subVer = Win10Version::Windows10);
|
static bool isWin10OrGreater(const Win10Version subVer = Win10Version::Windows10);
|
||||||
static QColor colorizationColor();
|
|
||||||
static bool colorizationColorEnabled();
|
|
||||||
static bool lightThemeEnabled();
|
|
||||||
static bool darkThemeEnabled();
|
|
||||||
static bool highContrastModeEnabled();
|
|
||||||
static bool darkFrameEnabled(void *handle);
|
|
||||||
static bool transparencyEffectEnabled();
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
|
|
|
@ -26,8 +26,26 @@
|
||||||
|
|
||||||
#include "framelesswindowsmanager.h"
|
#include "framelesswindowsmanager.h"
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
#include "winnativeeventfilter.h"
|
||||||
|
#include <QOperatingSystemVersion>
|
||||||
|
#endif
|
||||||
|
|
||||||
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent) {}
|
#ifdef Q_OS_WINDOWS
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char g_sPreserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME";
|
||||||
|
const char g_sDontExtendFrame[] = "WNEF_DO_NOT_EXTEND_FRAME";
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
startTimer(500);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int FramelessQuickHelper::borderWidth() const
|
int FramelessQuickHelper::borderWidth() const
|
||||||
{
|
{
|
||||||
|
@ -84,6 +102,23 @@ void FramelessQuickHelper::setTitleBarEnabled(const bool val)
|
||||||
Q_EMIT titleBarEnabledChanged(val);
|
Q_EMIT titleBarEnabledChanged(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
bool FramelessQuickHelper::canHaveWindowFrame() const
|
||||||
|
{
|
||||||
|
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessQuickHelper::colorizationEnabled() const
|
||||||
|
{
|
||||||
|
return WinNativeEventFilter::colorizationEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor FramelessQuickHelper::colorizationColor() const
|
||||||
|
{
|
||||||
|
return WinNativeEventFilter::colorizationColor();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QSize FramelessQuickHelper::minimumSize() const
|
QSize FramelessQuickHelper::minimumSize() const
|
||||||
{
|
{
|
||||||
return FramelessWindowsManager::getMinimumSize(window());
|
return FramelessWindowsManager::getMinimumSize(window());
|
||||||
|
@ -152,3 +187,23 @@ void FramelessQuickHelper::addDraggableObject(QQuickItem *val)
|
||||||
Q_ASSERT(val);
|
Q_ASSERT(val);
|
||||||
FramelessWindowsManager::addDraggableObject(window(), val);
|
FramelessWindowsManager::addDraggableObject(window(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
void FramelessQuickHelper::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
QQuickItem::timerEvent(event);
|
||||||
|
Q_EMIT colorizationEnabledChanged(colorizationEnabled());
|
||||||
|
Q_EMIT colorizationColorChanged(colorizationColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessQuickHelper::setWindowFrameVisible(const bool value)
|
||||||
|
{
|
||||||
|
if (value) {
|
||||||
|
qputenv(g_sPreserveWindowFrame, "1");
|
||||||
|
qputenv(g_sDontExtendFrame, "1");
|
||||||
|
} else {
|
||||||
|
qunsetenv(g_sPreserveWindowFrame);
|
||||||
|
qunsetenv(g_sDontExtendFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
#include "framelesshelper_global.h"
|
#include "framelesshelper_global.h"
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
|
|
||||||
|
#if (defined(Q_OS_WIN) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)) \
|
||||||
|
&& !defined(Q_OS_WINDOWS)
|
||||||
|
#define Q_OS_WINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
|
||||||
#define Q_DISABLE_MOVE(Class) \
|
#define Q_DISABLE_MOVE(Class) \
|
||||||
Class(Class &&) = delete; \
|
Class(Class &&) = delete; \
|
||||||
|
@ -53,6 +58,11 @@ class FRAMELESSHELPER_EXPORT FramelessQuickHelper : public QQuickItem
|
||||||
Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize NOTIFY maximumSizeChanged)
|
Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize NOTIFY maximumSizeChanged)
|
||||||
Q_PROPERTY(bool titleBarEnabled READ titleBarEnabled WRITE setTitleBarEnabled NOTIFY
|
Q_PROPERTY(bool titleBarEnabled READ titleBarEnabled WRITE setTitleBarEnabled NOTIFY
|
||||||
titleBarEnabledChanged)
|
titleBarEnabledChanged)
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
Q_PROPERTY(bool canHaveWindowFrame READ canHaveWindowFrame CONSTANT)
|
||||||
|
Q_PROPERTY(bool colorizationEnabled READ colorizationEnabled NOTIFY colorizationEnabledChanged)
|
||||||
|
Q_PROPERTY(QColor colorizationColor READ colorizationColor NOTIFY colorizationColorChanged)
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
explicit FramelessQuickHelper(QQuickItem *parent = nullptr);
|
||||||
|
@ -79,6 +89,12 @@ public:
|
||||||
bool titleBarEnabled() const;
|
bool titleBarEnabled() const;
|
||||||
void setTitleBarEnabled(const bool val);
|
void setTitleBarEnabled(const bool val);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
bool canHaveWindowFrame() const;
|
||||||
|
bool colorizationEnabled() const;
|
||||||
|
QColor colorizationColor() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void removeWindowFrame(const bool center = false);
|
void removeWindowFrame(const bool center = false);
|
||||||
|
|
||||||
|
@ -94,6 +110,15 @@ public Q_SLOTS:
|
||||||
void addIgnoreObject(QQuickItem *val);
|
void addIgnoreObject(QQuickItem *val);
|
||||||
void addDraggableObject(QQuickItem *val);
|
void addDraggableObject(QQuickItem *val);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
void setWindowFrameVisible(const bool value = true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void borderWidthChanged(int);
|
void borderWidthChanged(int);
|
||||||
void borderHeightChanged(int);
|
void borderHeightChanged(int);
|
||||||
|
@ -102,4 +127,8 @@ Q_SIGNALS:
|
||||||
void minimumSizeChanged(const QSize &);
|
void minimumSizeChanged(const QSize &);
|
||||||
void maximumSizeChanged(const QSize &);
|
void maximumSizeChanged(const QSize &);
|
||||||
void titleBarEnabledChanged(bool);
|
void titleBarEnabledChanged(bool);
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
void colorizationEnabledChanged(bool);
|
||||||
|
void colorizationColorChanged(const QColor &);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <QLibrary>
|
#include <QLibrary>
|
||||||
#include <QMargins>
|
#include <QMargins>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
#include <QSettings>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
|
@ -154,6 +155,8 @@ Q_DECLARE_METATYPE(QMargins)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
enum : WORD { DwmwaUseImmersiveDarkMode = 20, DwmwaUseImmersiveDarkModeBefore20h1 = 19 };
|
||||||
|
|
||||||
using WINDOWCOMPOSITIONATTRIB = enum _WINDOWCOMPOSITIONATTRIB { WCA_ACCENT_POLICY = 19 };
|
using WINDOWCOMPOSITIONATTRIB = enum _WINDOWCOMPOSITIONATTRIB { WCA_ACCENT_POLICY = 19 };
|
||||||
|
|
||||||
using WINDOWCOMPOSITIONATTRIBDATA = struct _WINDOWCOMPOSITIONATTRIBDATA
|
using WINDOWCOMPOSITIONATTRIBDATA = struct _WINDOWCOMPOSITIONATTRIBDATA
|
||||||
|
@ -198,6 +201,15 @@ bool isWin8Point1OrGreater()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isWin10OrGreater()
|
||||||
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
|
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
||||||
|
#else
|
||||||
|
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool isWin10OrGreater(const int ver)
|
bool isWin10OrGreater(const int ver)
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
|
@ -487,6 +499,7 @@ using WNEF_CORE_DATA = struct _WNEF_CORE_DATA
|
||||||
WNEF_GENERATE_WINAPI(TrackPopupMenu, BOOL, HMENU, UINT, int, int, int, HWND, CONST RECT *)
|
WNEF_GENERATE_WINAPI(TrackPopupMenu, BOOL, HMENU, UINT, int, int, int, HWND, CONST RECT *)
|
||||||
WNEF_GENERATE_WINAPI(PostMessageW, BOOL, HWND, UINT, WPARAM, LPARAM)
|
WNEF_GENERATE_WINAPI(PostMessageW, BOOL, HWND, UINT, WPARAM, LPARAM)
|
||||||
WNEF_GENERATE_WINAPI(GetMessagePos, DWORD)
|
WNEF_GENERATE_WINAPI(GetMessagePos, DWORD)
|
||||||
|
WNEF_GENERATE_WINAPI(SystemParametersInfoW, BOOL, UINT, UINT, PVOID, UINT)
|
||||||
|
|
||||||
#endif // WNEF_LINK_SYSLIB
|
#endif // WNEF_LINK_SYSLIB
|
||||||
|
|
||||||
|
@ -566,6 +579,7 @@ using WNEF_CORE_DATA = struct _WNEF_CORE_DATA
|
||||||
}
|
}
|
||||||
resolved = true;
|
resolved = true;
|
||||||
// Available since Windows 2000.
|
// Available since Windows 2000.
|
||||||
|
WNEF_RESOLVE_WINAPI(User32, SystemParametersInfoW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetMessagePos)
|
WNEF_RESOLVE_WINAPI(User32, GetMessagePos)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetSystemMenu)
|
WNEF_RESOLVE_WINAPI(User32, GetSystemMenu)
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetMenuItemInfoW)
|
WNEF_RESOLVE_WINAPI(User32, SetMenuItemInfoW)
|
||||||
|
@ -685,11 +699,7 @@ bool shouldHaveWindowFrame()
|
||||||
if (should) {
|
if (should) {
|
||||||
// If you preserve the window frame on Win7~8.1,
|
// If you preserve the window frame on Win7~8.1,
|
||||||
// the window will have a terrible appearance.
|
// the window will have a terrible appearance.
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
return isWin10OrGreater();
|
||||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
|
||||||
#else
|
|
||||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1208,6 +1218,10 @@ const int m_defaultBorderWidth = 8, m_defaultBorderHeight = 8, m_defaultTitleBar
|
||||||
const int kAutoHideTaskbarThicknessPx = 2;
|
const int kAutoHideTaskbarThicknessPx = 2;
|
||||||
const int kAutoHideTaskbarThicknessPy = kAutoHideTaskbarThicknessPx;
|
const int kAutoHideTaskbarThicknessPy = kAutoHideTaskbarThicknessPx;
|
||||||
|
|
||||||
|
const QLatin1String g_sDwmRegistryKey(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM)");
|
||||||
|
const QLatin1String g_sPersonalizeRegistryKey(
|
||||||
|
R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WinNativeEventFilter::WinNativeEventFilter()
|
WinNativeEventFilter::WinNativeEventFilter()
|
||||||
|
@ -2489,3 +2503,97 @@ void WinNativeEventFilter::setWindowResizable(void *handle, const bool resizable
|
||||||
updateWindow(hwnd, true, false);
|
updateWindow(hwnd, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::colorizationEnabled()
|
||||||
|
{
|
||||||
|
if (!isWin10OrGreater()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ok = false;
|
||||||
|
const QSettings registry(g_sDwmRegistryKey, QSettings::NativeFormat);
|
||||||
|
const bool colorPrevalence = registry.value(QLatin1String("ColorPrevalence"), 0).toULongLong(&ok)
|
||||||
|
!= 0;
|
||||||
|
return (ok && colorPrevalence);
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor WinNativeEventFilter::colorizationColor()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
DWORD color = 0;
|
||||||
|
BOOL opaqueBlend = FALSE;
|
||||||
|
return SUCCEEDED(DwmGetColorizationColor(&color, &opaqueBlend)) ? QColor::fromRgba(color)
|
||||||
|
: Qt::white;
|
||||||
|
*/
|
||||||
|
bool ok = false;
|
||||||
|
const QSettings registry(g_sDwmRegistryKey, QSettings::NativeFormat);
|
||||||
|
const quint64 color = registry.value(QLatin1String("ColorizationColor"), 0).toULongLong(&ok);
|
||||||
|
return ok ? QColor::fromRgba(color) : Qt::white;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::lightThemeEnabled()
|
||||||
|
{
|
||||||
|
if (!isWin10OrGreater(17763)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ok = false;
|
||||||
|
const QSettings registry(g_sPersonalizeRegistryKey, QSettings::NativeFormat);
|
||||||
|
const bool appsUseLightTheme
|
||||||
|
= registry.value(QLatin1String("AppsUseLightTheme"), 0).toULongLong(&ok) != 0;
|
||||||
|
return (ok && appsUseLightTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::darkThemeEnabled()
|
||||||
|
{
|
||||||
|
if (!isWin10OrGreater(17763)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !lightThemeEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::highContrastModeEnabled()
|
||||||
|
{
|
||||||
|
HIGHCONTRASTW hc;
|
||||||
|
SecureZeroMemory(&hc, sizeof(hc));
|
||||||
|
hc.cbSize = sizeof(hc);
|
||||||
|
return WNEF_EXECUTE_WINAPI_RETURN(SystemParametersInfoW, FALSE, SPI_GETHIGHCONTRAST, 0, &hc, 0)
|
||||||
|
? (hc.dwFlags & HCF_HIGHCONTRASTON)
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::darkFrameEnabled(void *handle)
|
||||||
|
{
|
||||||
|
Q_ASSERT(handle);
|
||||||
|
if (!isWin10OrGreater(17763)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto hwnd = reinterpret_cast<HWND>(handle);
|
||||||
|
if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, hwnd)) {
|
||||||
|
BOOL result = FALSE;
|
||||||
|
const bool ok = SUCCEEDED(WNEF_EXECUTE_WINAPI_RETURN(DwmGetWindowAttribute,
|
||||||
|
E_FAIL,
|
||||||
|
hwnd,
|
||||||
|
DwmwaUseImmersiveDarkMode,
|
||||||
|
&result,
|
||||||
|
sizeof(result)))
|
||||||
|
|| SUCCEEDED(WNEF_EXECUTE_WINAPI_RETURN(DwmGetWindowAttribute,
|
||||||
|
E_FAIL,
|
||||||
|
hwnd,
|
||||||
|
DwmwaUseImmersiveDarkModeBefore20h1,
|
||||||
|
&result,
|
||||||
|
sizeof(result)));
|
||||||
|
return (ok && result);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::transparencyEffectEnabled()
|
||||||
|
{
|
||||||
|
if (!isWin10OrGreater()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ok = false;
|
||||||
|
const QSettings registry(g_sPersonalizeRegistryKey, QSettings::NativeFormat);
|
||||||
|
const bool enableTransparency
|
||||||
|
= registry.value(QLatin1String("EnableTransparency"), 0).toULongLong(&ok) != 0;
|
||||||
|
return (ok && enableTransparency);
|
||||||
|
}
|
||||||
|
|
|
@ -153,6 +153,27 @@ public:
|
||||||
// window can only be moved and minimized, it can't be resized and maximized.
|
// window can only be moved and minimized, it can't be resized and maximized.
|
||||||
static void setWindowResizable(void *handle /* HWND */, const bool resizable = true);
|
static void setWindowResizable(void *handle /* HWND */, const bool resizable = true);
|
||||||
|
|
||||||
|
// Query whether colorization is enabled or not.
|
||||||
|
static bool colorizationEnabled();
|
||||||
|
|
||||||
|
// Acquire the theme/colorization color set by the user.
|
||||||
|
static QColor colorizationColor();
|
||||||
|
|
||||||
|
// Query whether the user is using the light theme or not.
|
||||||
|
static bool lightThemeEnabled();
|
||||||
|
|
||||||
|
// Query whether the user is using the dark theme or not.
|
||||||
|
static bool darkThemeEnabled();
|
||||||
|
|
||||||
|
// Query whether the high contrast mode is enabled or not.
|
||||||
|
static bool highContrastModeEnabled();
|
||||||
|
|
||||||
|
// Query whether the given window is using dark frame or not.
|
||||||
|
static bool darkFrameEnabled(void *handle /* HWND */);
|
||||||
|
|
||||||
|
// Query whether the transparency effect is enabled or not.
|
||||||
|
static bool transparencyEffectEnabled();
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
/// CORE FUNCTION - THE SOUL OF THIS CODE
|
/// CORE FUNCTION - THE SOUL OF THIS CODE
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue