Add a full-featured win32 example.
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
c95e8fc806
commit
208e831fc5
|
@ -0,0 +1,7 @@
|
|||
TARGET = Win32Demo
|
||||
TEMPLATE = app
|
||||
QT += widgets
|
||||
HEADERS += widget.h
|
||||
SOURCES += widget.cpp main.cpp
|
||||
FORMS += widget.ui
|
||||
include($$PWD/../common.pri)
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "widget.h"
|
||||
#include <QApplication>
|
||||
#include <QFont>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
// High DPI scaling is enabled by default from Qt 6
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
// Windows: we are using the manifest file to get maximum compatibility
|
||||
// because some APIs are not supprted on old systems such as Windows 7
|
||||
// and Windows 8. And once we have set the DPI awareness level in the
|
||||
// manifest file, any attemptation to try to change it through API will
|
||||
// fail. In other words, Qt won't be able to enable or disable high DPI
|
||||
// scaling or change the DPI awareness level once we have set it in the
|
||||
// manifest file. So the following two lines are uesless actually (However,
|
||||
// they are still useful on other platforms).
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
// Don't round the scale factor.
|
||||
// This will break QWidget applications because they can't render correctly.
|
||||
// Qt Quick applications won't have this issue.
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(
|
||||
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
QFont font = QApplication::font();
|
||||
font.setFamily(QLatin1String("Arial"));
|
||||
font.setBold(true);
|
||||
font.setPointSize(15);
|
||||
QApplication::setFont(font);
|
||||
|
||||
Widget widget;
|
||||
widget.show();
|
||||
|
||||
return QApplication::exec();
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "widget.h"
|
||||
#include "../../winnativeeventfilter.h"
|
||||
#include "ui_widget.h"
|
||||
#include <QStyleOption>
|
||||
|
||||
namespace {
|
||||
|
||||
const char useNativeTitleBar[] = "WNEF_USE_NATIVE_TITLE_BAR";
|
||||
const char preserveWindowFrame[] = "WNEF_FORCE_PRESERVE_WINDOW_FRAME";
|
||||
|
||||
void *getRawHandle(QWidget *widget)
|
||||
{
|
||||
Q_ASSERT(widget);
|
||||
return widget->isTopLevel() ? reinterpret_cast<void *>(widget->winId()) : nullptr;
|
||||
}
|
||||
|
||||
void updateWindow(QWidget *widget)
|
||||
{
|
||||
Q_ASSERT(widget);
|
||||
if (widget->isTopLevel()) {
|
||||
WinNativeEventFilter::updateWindow(getRawHandle(widget), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->minimizeButton, &QPushButton::clicked, this, &Widget::showMinimized);
|
||||
connect(ui->maximizeButton, &QPushButton::clicked, this, [this]() {
|
||||
if (isMaximized()) {
|
||||
showNormal();
|
||||
} else {
|
||||
showMaximized();
|
||||
}
|
||||
});
|
||||
connect(ui->closeButton, &QPushButton::clicked, this, &Widget::close);
|
||||
|
||||
connect(ui->moveCenterButton, &QPushButton::clicked, this, [this]() {
|
||||
WinNativeEventFilter::moveWindowToDesktopCenter(getRawHandle(this));
|
||||
});
|
||||
|
||||
connect(this, &Widget::windowTitleChanged, ui->titleLabel, &QLabel::setText);
|
||||
connect(this, &Widget::windowIconChanged, ui->iconButton, &QPushButton::setIcon);
|
||||
|
||||
connect(ui->customizeTitleBarCB, &QCheckBox::stateChanged, this, [this](int state) {
|
||||
const bool enable = state == Qt::Checked;
|
||||
WinNativeEventFilter::updateQtFrame(windowHandle(),
|
||||
enable ? WinNativeEventFilter::getSystemMetric(
|
||||
getRawHandle(this),
|
||||
WinNativeEventFilter::SystemMetric::TitleBarHeight)
|
||||
: 0);
|
||||
ui->titleBarWidget->setVisible(enable);
|
||||
if (enable) {
|
||||
qunsetenv(useNativeTitleBar);
|
||||
} else if (state == Qt::Unchecked) {
|
||||
qputenv(useNativeTitleBar, "1");
|
||||
}
|
||||
updateWindow(this);
|
||||
});
|
||||
connect(ui->windowFrameCB, &QCheckBox::stateChanged, this, [this](int state) {
|
||||
if (state == Qt::Checked) {
|
||||
qunsetenv(preserveWindowFrame);
|
||||
} else if (state == Qt::Unchecked) {
|
||||
qputenv(preserveWindowFrame, "1");
|
||||
}
|
||||
updateWindow(this);
|
||||
});
|
||||
connect(ui->blurEffectCB, &QCheckBox::stateChanged, this, [this](int state) {
|
||||
const bool enable = state == Qt::Checked;
|
||||
QPalette palette = {};
|
||||
// Choose the gradient color you like.
|
||||
palette.setColor(QPalette::Window, QColor(255, 255, 255, 235));
|
||||
setPalette(enable ? palette : QPalette());
|
||||
WinNativeEventFilter::setBlurEffectEnabled(getRawHandle(this), enable);
|
||||
updateWindow(this);
|
||||
});
|
||||
connect(ui->resizableCB, &QCheckBox::stateChanged, this, [this](int state) {
|
||||
const auto data = WinNativeEventFilter::windowData(this);
|
||||
if (data) {
|
||||
data->fixedSize = state == Qt::Unchecked;
|
||||
updateWindow(this);
|
||||
}
|
||||
});
|
||||
|
||||
QStyleOption option;
|
||||
option.initFrom(this);
|
||||
setWindowIcon(style()->standardIcon(QStyle::SP_ComputerIcon, &option));
|
||||
setWindowTitle(tr("Hello, World!"));
|
||||
|
||||
WinNativeEventFilter::WINDOWDATA data = {};
|
||||
data.ignoreObjects << ui->minimizeButton << ui->maximizeButton << ui->closeButton;
|
||||
WinNativeEventFilter::addFramelessWindow(this, &data);
|
||||
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool Widget::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_ASSERT(object);
|
||||
Q_ASSERT(event);
|
||||
switch (event->type()) {
|
||||
case QEvent::WindowStateChange: {
|
||||
if (isMaximized()) {
|
||||
ui->maximizeButton->setIcon(QIcon(QLatin1String(":/images/button_restore_black.svg")));
|
||||
} else if (!isFullScreen() && !isMinimized()) {
|
||||
ui->maximizeButton->setIcon(QIcon(QLatin1String(":/images/button_maximize_black.svg")));
|
||||
}
|
||||
ui->moveCenterButton->setEnabled(!isMaximized() && !isFullScreen());
|
||||
} break;
|
||||
case QEvent::WinIdChange:
|
||||
WinNativeEventFilter::addFramelessWindow(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
QT_FORWARD_DECLARE_CLASS(Widget)
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class Widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(Widget)
|
||||
|
||||
public:
|
||||
explicit Widget(QWidget *parent = nullptr);
|
||||
~Widget();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
private:
|
||||
Ui::Widget *ui = nullptr;
|
||||
};
|
|
@ -0,0 +1,403 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Widget</class>
|
||||
<widget class="QWidget" name="Widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1056</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Widget</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#titleBarWidget {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#iconButton, #minimizeButton, #maximizeButton, #closeButton {
|
||||
background-color: transparent;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#minimizeButton:hover, #maximizeButton:hover {
|
||||
border-style: none;
|
||||
background-color: #80c7c7c7;
|
||||
}
|
||||
|
||||
#minimizeButton:pressed, #maximizeButton:pressed {
|
||||
border-style: none;
|
||||
background-color: #80808080;
|
||||
}
|
||||
|
||||
#closeButton:hover {
|
||||
border-style: none;
|
||||
background-color: #e81123;
|
||||
}
|
||||
|
||||
#closeButton:pressed {
|
||||
border-style: none;
|
||||
background-color: #8c0a15;
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="titleBarWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="iconButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="minimizeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../windows.qrc">
|
||||
<normaloff>:/images/button_minimize_black.svg</normaloff>:/images/button_minimize_black.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="maximizeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../windows.qrc">
|
||||
<normaloff>:/images/button_maximize_black.svg</normaloff>:/images/button_maximize_black.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../windows.qrc">
|
||||
<normaloff>:/images/button_close_black.svg</normaloff>:/images/button_close_black.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="contentsWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="controlPanelWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="customizeTitleBarCB">
|
||||
<property name="text">
|
||||
<string>Enable customized title bar</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="windowFrameCB">
|
||||
<property name="text">
|
||||
<string>Get rid of window frame</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="blurEffectCB">
|
||||
<property name="text">
|
||||
<string>Enable blur effect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="resizableCB">
|
||||
<property name="text">
|
||||
<string>Resizable</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveCenterButton">
|
||||
<property name="text">
|
||||
<string>Move to desktop center</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../windows.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -2,3 +2,4 @@ TEMPLATE = subdirs
|
|||
CONFIG -= ordered
|
||||
qtHaveModule(widgets): SUBDIRS += QWidget QMainWindow
|
||||
qtHaveModule(quick): SUBDIRS += Quick
|
||||
win32: qtHaveModule(widgets): SUBDIRS += Win32Demo
|
||||
|
|
|
@ -660,15 +660,28 @@ const qreal m_defaultDevicePixelRatio = 1.0;
|
|||
|
||||
bool shouldHaveWindowFrame()
|
||||
{
|
||||
#if 0
|
||||
const bool should = qEnvironmentVariableIsSet("WNEF_PRESERVE_WINDOW_FRAME");
|
||||
const bool force = qEnvironmentVariableIsSet("WNEF_FORCE_PRESERVE_WINDOW_FRAME");
|
||||
if (should || force) {
|
||||
if (force) {
|
||||
return true;
|
||||
}
|
||||
if (should) {
|
||||
// If you preserve the window frame on Win7~8.1,
|
||||
// the window will have a terrible appearance.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
|
||||
#else
|
||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10;
|
||||
return QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS10;
|
||||
#endif
|
||||
#else
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool shouldUseNativeTitleBar()
|
||||
{
|
||||
return qEnvironmentVariableIsSet("WNEF_USE_NATIVE_TITLE_BAR");
|
||||
}
|
||||
|
||||
BOOL IsDwmCompositionEnabled()
|
||||
|
@ -959,17 +972,23 @@ void UpdateFrameMarginsForWindow(const HWND handle)
|
|||
const auto GetTopBorderHeight = [](const HWND handle) -> int {
|
||||
Q_ASSERT(handle);
|
||||
if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) {
|
||||
if (IsMaximized(handle) || IsFullScreen(handle) || !IsDwmCompositionEnabled()) {
|
||||
return 0;
|
||||
if (IsDwmCompositionEnabled() && !IsMaximized(handle) && !IsFullScreen(handle)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
};
|
||||
if (GetTopBorderHeight(handle) != 0) {
|
||||
margins.cyTopHeight = GetFrameSizeForWindow(handle, TRUE).top;
|
||||
}
|
||||
} else {
|
||||
margins.cyTopHeight = 1;
|
||||
//margins.cyTopHeight = GetFrameSizeForWindow(handle, TRUE).top;
|
||||
}
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
// If we are going to use the native title bar,
|
||||
// we should use the original window frame as well.
|
||||
margins = {0, 0, 0, 0};
|
||||
}
|
||||
WNEF_EXECUTE_WINAPI(DwmExtendFrameIntoClientArea, handle, &margins)
|
||||
}
|
||||
|
@ -1353,7 +1372,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// Bring our frame shadow back through DWM, don't draw it manually.
|
||||
UpdateFrameMarginsForWindow(msg->hwnd);
|
||||
// Blur effect.
|
||||
setAcrylicEffectEnabled(msg->hwnd, data->enableBlurBehindWindow);
|
||||
setBlurEffectEnabled(msg->hwnd, data->enableBlurBehindWindow);
|
||||
}
|
||||
switch (msg->message) {
|
||||
case WM_NCCALCSIZE: {
|
||||
|
@ -1427,6 +1446,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// preserve the four window borders. So we just remove the whole
|
||||
// window frame, otherwise the code will become much more complex.
|
||||
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const auto mode = static_cast<BOOL>(msg->wParam);
|
||||
// If the window bounds change, we're going to relayout and repaint
|
||||
// anyway. Returning WVR_REDRAW avoids an extra paint before that of
|
||||
|
@ -1594,7 +1617,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// area.
|
||||
case WM_NCUAHDRAWCAPTION:
|
||||
case WM_NCUAHDRAWFRAME: {
|
||||
if (shouldHaveWindowFrame()) {
|
||||
if (shouldHaveWindowFrame() || shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
} else {
|
||||
*result = 0;
|
||||
|
@ -1604,7 +1627,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
case WM_NCPAINT: {
|
||||
// 边框阴影处于非客户区的范围,因此如果直接阻止非客户区的绘制,会导致边框阴影丢失
|
||||
|
||||
if (!IsDwmCompositionEnabled() && !shouldHaveWindowFrame()) {
|
||||
if (!IsDwmCompositionEnabled() && !shouldHaveWindowFrame()
|
||||
&& !shouldUseNativeTitleBar()) {
|
||||
// Only block WM_NCPAINT when DWM composition is disabled. If
|
||||
// it's blocked when DWM composition is enabled, the frame
|
||||
// shadow won't be drawn.
|
||||
|
@ -1615,7 +1639,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
}
|
||||
}
|
||||
case WM_NCACTIVATE: {
|
||||
if (shouldHaveWindowFrame()) {
|
||||
if (shouldHaveWindowFrame() || shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
} else {
|
||||
if (IsDwmCompositionEnabled()) {
|
||||
|
@ -1707,6 +1731,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// another branch, if you are interested in it, you can give it a
|
||||
// try.
|
||||
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->mouseTransparent) {
|
||||
// Mouse events will be passed to the parent window.
|
||||
*result = HTTRANSPARENT;
|
||||
|
@ -1947,6 +1975,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
}
|
||||
case WM_SETICON:
|
||||
case WM_SETTEXT: {
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Disable painting while these messages are handled to prevent them
|
||||
// from drawing a window caption over the client area.
|
||||
const auto oldStyle = WNEF_EXECUTE_WINAPI_RETURN(GetWindowLongPtrW,
|
||||
|
@ -1968,7 +2000,11 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
*result = ret;
|
||||
return true;
|
||||
}
|
||||
case WM_DWMCOMPOSITIONCHANGED:
|
||||
case WM_DWMCOMPOSITIONCHANGED: {
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// DWM won't draw the frame shadow if the window doesn't have a
|
||||
// frame. So extend the window frame a bit to make sure we still
|
||||
// have the frame shadow. But don't worry, the extended window frame
|
||||
|
@ -1976,6 +2012,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// as what we did in WM_NCCALCSIZE.
|
||||
UpdateFrameMarginsForWindow(msg->hwnd);
|
||||
break;
|
||||
}
|
||||
case WM_DPICHANGED:
|
||||
// Sent when the effective dots per inch (dpi) for a window has
|
||||
// changed. You won't get this message until Windows 8.1
|
||||
|
@ -1998,6 +2035,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/windows/qwindowscontext.cpp
|
||||
break;
|
||||
case WM_CONTEXTMENU: {
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If the context menu is brought up from the keyboard
|
||||
// (SHIFT + F10 or the context menu key), lParam will be -1.
|
||||
const LPARAM lParam = (msg->lParam == -1) ? WNEF_EXECUTE_WINAPI_RETURN(GetMessagePos, 0)
|
||||
|
@ -2011,6 +2052,10 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
}
|
||||
}
|
||||
case WM_MOVE: {
|
||||
if (shouldUseNativeTitleBar()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const QString sn = getCurrentScreenSerialNumber(msg->hwnd);
|
||||
if (data->currentScreen.toUpper() != sn) {
|
||||
data->currentScreen = sn;
|
||||
|
@ -2222,7 +2267,7 @@ void WinNativeEventFilter::moveWindowToDesktopCenter(void *handle)
|
|||
void WinNativeEventFilter::updateQtFrame(QWindow *window, const int titleBarHeight)
|
||||
{
|
||||
Q_ASSERT(window);
|
||||
if (titleBarHeight > 0) {
|
||||
if (titleBarHeight >= 0) {
|
||||
// Reduce top frame to zero since we paint it ourselves. Use
|
||||
// device pixel to avoid rounding errors.
|
||||
const QMargins margins = {0, -titleBarHeight, 0, 0};
|
||||
|
@ -2301,7 +2346,7 @@ bool WinNativeEventFilter::displaySystemMenu(void *handle,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WinNativeEventFilter::setAcrylicEffectEnabled(void *handle, const bool enabled)
|
||||
bool WinNativeEventFilter::setBlurEffectEnabled(void *handle, const bool enabled)
|
||||
{
|
||||
Q_ASSERT(handle);
|
||||
const auto hwnd = reinterpret_cast<HWND>(handle);
|
||||
|
@ -2343,3 +2388,12 @@ bool WinNativeEventFilter::setAcrylicEffectEnabled(void *handle, const bool enab
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WinNativeEventFilter::updateFrameMargins(void *handle)
|
||||
{
|
||||
Q_ASSERT(handle);
|
||||
const auto hwnd = reinterpret_cast<HWND>(handle);
|
||||
if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, hwnd)) {
|
||||
UpdateFrameMarginsForWindow(hwnd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,10 @@ public:
|
|||
|
||||
// Enable or disable the blur effect for a specific window.
|
||||
// On Win10 it's the Acrylic effect.
|
||||
static bool setAcrylicEffectEnabled(void *handle /* HWND */, const bool enabled = true);
|
||||
static bool setBlurEffectEnabled(void *handle /* HWND */, const bool enabled = true);
|
||||
|
||||
// a
|
||||
static void updateFrameMargins(void *handle /* HWND */);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
/// CORE FUNCTION - THE SOUL OF THIS CODE
|
||||
|
|
Loading…
Reference in New Issue