From fe3fbf34e9b9aaca6b99356712e1b5e256b87c2f Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Mon, 12 Oct 2020 15:10:51 +0800 Subject: [PATCH] Add the QMainWindow example. And re-arrange the examples. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/QMainWindow/MainWindow.ui | 106 ++++++++ examples/QMainWindow/QMainWindow.pro | 6 + examples/QMainWindow/TitleBar.ui | 257 ++++++++++++++++++ examples/QMainWindow/main.cpp | 126 +++++++++ .../CMakeLists.txt | 0 .../QQPlayer.exe.manifest | 0 .../{QQPlayer-demo => QQPlayer}/QQPlayer.ico | Bin .../{QQPlayer-demo => QQPlayer}/QQPlayer.rc | 0 .../{QQPlayer-demo => QQPlayer}/README.txt | 0 .../{QQPlayer-demo => QQPlayer}/build.bat | 0 .../{QQPlayer-demo => QQPlayer}/images.qrc | 0 examples/{QQPlayer-demo => QQPlayer}/main.cpp | 0 examples/{QQPlayer-demo => QQPlayer}/qml.qrc | 0 .../resources/images/background.png | Bin .../resources/images/logo.png | Bin .../resources/images/main_menu_blue.png | Bin .../resources/images/main_menu_white.png | Bin .../resources/images/next_blue.png | Bin .../resources/images/next_blue_light.png | Bin .../resources/images/open_file_blue.png | Bin .../resources/images/open_file_white.png | Bin .../resources/images/play_blue.png | Bin .../resources/images/play_blue_light.png | Bin .../resources/images/previous_blue.png | Bin .../resources/images/previous_blue_light.png | Bin .../resources/images/stop_blue.png | Bin .../resources/images/stop_blue_light.png | Bin .../resources/images/volume_blue.png | Bin .../resources/images/volume_blue_light.png | Bin .../resources/qml/CloseButton.qml | 0 .../resources/qml/MainMenuButton.qml | 0 .../resources/qml/MaximizeButton.qml | 0 .../resources/qml/MinimizeButton.qml | 0 .../resources/qml/NextButton.qml | 0 .../resources/qml/OpenFileButton.qml | 0 .../resources/qml/PlayButton.qml | 0 .../resources/qml/PreviousButton.qml | 0 .../resources/qml/ProgressSlider.qml | 0 .../resources/qml/StopButton.qml | 0 .../resources/qml/VolumeButton.qml | 0 .../resources/qml/main.qml | 0 examples/QWidget/QWidget.pro | 5 + main_windows.cpp => examples/QWidget/main.cpp | 83 +++--- examples/Quick/Quick.pro | 6 + examples/Quick/main.cpp | 94 +++++++ examples/common.pri | 24 ++ examples/examples.pro | 4 + .../windows.ico | Bin .../windows.manifest | 0 examples/windows.qrc | 18 ++ .../windows.rc | 14 +- framelesshelper_unix.pro | 18 -- framelesshelper_windows.pro | 27 -- framelesshelper_windows.qrc | 18 -- main_unix.cpp | 96 ------- 55 files changed, 687 insertions(+), 215 deletions(-) create mode 100644 examples/QMainWindow/MainWindow.ui create mode 100644 examples/QMainWindow/QMainWindow.pro create mode 100644 examples/QMainWindow/TitleBar.ui create mode 100644 examples/QMainWindow/main.cpp rename examples/{QQPlayer-demo => QQPlayer}/CMakeLists.txt (100%) rename examples/{QQPlayer-demo => QQPlayer}/QQPlayer.exe.manifest (100%) rename examples/{QQPlayer-demo => QQPlayer}/QQPlayer.ico (100%) rename examples/{QQPlayer-demo => QQPlayer}/QQPlayer.rc (100%) rename examples/{QQPlayer-demo => QQPlayer}/README.txt (100%) rename examples/{QQPlayer-demo => QQPlayer}/build.bat (100%) rename examples/{QQPlayer-demo => QQPlayer}/images.qrc (100%) rename examples/{QQPlayer-demo => QQPlayer}/main.cpp (100%) rename examples/{QQPlayer-demo => QQPlayer}/qml.qrc (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/background.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/logo.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/main_menu_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/main_menu_white.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/next_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/next_blue_light.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/open_file_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/open_file_white.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/play_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/play_blue_light.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/previous_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/previous_blue_light.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/stop_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/stop_blue_light.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/volume_blue.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/images/volume_blue_light.png (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/CloseButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/MainMenuButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/MaximizeButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/MinimizeButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/NextButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/OpenFileButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/PlayButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/PreviousButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/ProgressSlider.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/StopButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/VolumeButton.qml (100%) rename examples/{QQPlayer-demo => QQPlayer}/resources/qml/main.qml (100%) create mode 100644 examples/QWidget/QWidget.pro rename main_windows.cpp => examples/QWidget/main.cpp (77%) create mode 100644 examples/Quick/Quick.pro create mode 100644 examples/Quick/main.cpp create mode 100644 examples/common.pri create mode 100644 examples/examples.pro rename framelesshelper_windows.ico => examples/windows.ico (100%) rename framelesshelper_windows.manifest => examples/windows.manifest (100%) create mode 100644 examples/windows.qrc rename framelesshelper_windows.rc => examples/windows.rc (81%) delete mode 100644 framelesshelper_unix.pro delete mode 100644 framelesshelper_windows.pro delete mode 100644 framelesshelper_windows.qrc delete mode 100644 main_unix.cpp diff --git a/examples/QMainWindow/MainWindow.ui b/examples/QMainWindow/MainWindow.ui new file mode 100644 index 0000000..6719af0 --- /dev/null +++ b/examples/QMainWindow/MainWindow.ui @@ -0,0 +1,106 @@ + + + MainWindow + + + + 0 + 0 + 497 + 348 + + + + MainWindow + + + + ../windows.ico../windows.ico + + + + + + 0 + 0 + 497 + 21 + + + + + Menu 1 + + + + + + + Menu 2 + + + + + Menu 3 + + + + + + + + + + Dock 1 + + + 1 + + + + + + Dock 2 + + + 1 + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + Action 1 + + + + + Action 2 + + + + + Item 1 + + + + + Item 2 + + + + + + diff --git a/examples/QMainWindow/QMainWindow.pro b/examples/QMainWindow/QMainWindow.pro new file mode 100644 index 0000000..777e72d --- /dev/null +++ b/examples/QMainWindow/QMainWindow.pro @@ -0,0 +1,6 @@ +TARGET = QMainWindow +TEMPLATE = app +QT += widgets +SOURCES += main.cpp +FORMS += TitleBar.ui MainWindow.ui +include($$PWD/../common.pri) diff --git a/examples/QMainWindow/TitleBar.ui b/examples/QMainWindow/TitleBar.ui new file mode 100644 index 0000000..56aa5ab --- /dev/null +++ b/examples/QMainWindow/TitleBar.ui @@ -0,0 +1,257 @@ + + + TitleBar + + + + 0 + 0 + 423 + 26 + + + + #TitleBar { + border-top: 1px solid 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; +} + + + + 0 + + + 0 + + + 1 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 26 + 26 + + + + + 26 + 26 + + + + Qt::NoFocus + + + + 24 + 24 + + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + + + + + + + Qt::Horizontal + + + + 262 + 20 + + + + + + + + + 0 + 0 + + + + + 45 + 26 + + + + + 45 + 26 + + + + Qt::NoFocus + + + Qt::NoContextMenu + + + Minimize + + + + :/images/button_minimize_black.svg:/images/button_minimize_black.svg + + + + 45 + 30 + + + + + + + + + 0 + 0 + + + + + 45 + 26 + + + + + 45 + 26 + + + + Qt::NoFocus + + + Qt::NoContextMenu + + + Maximize + + + + :/images/button_maximize_black.svg + :/images/button_restore_black.svg:/images/button_maximize_black.svg + + + + 45 + 30 + + + + true + + + + + + + + 0 + 0 + + + + + 45 + 26 + + + + + 45 + 26 + + + + Qt::NoFocus + + + Qt::NoContextMenu + + + Close + + + + :/images/button_close_black.svg:/images/button_close_black.svg + + + + 45 + 30 + + + + + + + + + + + + diff --git a/examples/QMainWindow/main.cpp b/examples/QMainWindow/main.cpp new file mode 100644 index 0000000..145adbb --- /dev/null +++ b/examples/QMainWindow/main.cpp @@ -0,0 +1,126 @@ +/* + * 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 "ui_MainWindow.h" +#include "ui_TitleBar.h" +#include +#include +#ifdef Q_OS_WINDOWS +#include "../../winnativeeventfilter.h" +#else +#include "../../framelesshelper.h" +#endif + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QGuiApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif +#endif + + QApplication application(argc, argv); + +#ifndef Q_OS_WINDOWS + FramelessHelper helper; +#endif + + QMainWindow *mainWindow = new QMainWindow; + Ui::MainWindow appMainWindow; + appMainWindow.setupUi(mainWindow); + + QWidget *widget = new QWidget; + Ui::TitleBar titleBarWidget; + titleBarWidget.setupUi(widget); + + QMenuBar *menuBar = mainWindow->menuBar(); + titleBarWidget.horizontalLayout->insertWidget(1, menuBar); + menuBar->setMaximumHeight(20); + + titleBarWidget.iconButton->setIcon(mainWindow->windowIcon()); + titleBarWidget.titleLabel->setText(mainWindow->windowTitle()); + + mainWindow->setMenuWidget(widget); + + QObject::connect(mainWindow, + &QMainWindow::windowIconChanged, + titleBarWidget.iconButton, + &QPushButton::setIcon); + QObject::connect(mainWindow, + &QMainWindow::windowTitleChanged, + titleBarWidget.titleLabel, + &QLabel::setText); + QObject::connect(titleBarWidget.closeButton, + &QPushButton::clicked, + mainWindow, + &QMainWindow::close); + QObject::connect(titleBarWidget.minimizeButton, + &QPushButton::clicked, + mainWindow, + &QMainWindow::showMinimized); + QObject::connect(titleBarWidget.maximizeButton, + &QPushButton::clicked, + [mainWindow, titleBarWidget]() { + if (mainWindow->isMaximized()) { + mainWindow->showNormal(); + titleBarWidget.maximizeButton->setToolTip(QObject::tr("Maximize")); + } else { + mainWindow->showMaximized(); + titleBarWidget.maximizeButton->setToolTip(QObject::tr("Restore")); + } + }); + +#ifdef Q_OS_WINDOWS + WinNativeEventFilter::addFramelessWindow(mainWindow); + const auto data = WinNativeEventFilter::windowData(mainWindow); + if (data) { + data->ignoreObjects << titleBarWidget.iconButton << titleBarWidget.minimizeButton + << titleBarWidget.maximizeButton << titleBarWidget.closeButton + << appMainWindow.menubar; + } +#else + helper.setIgnoreObjects(mainWindow, + {titleBarWidget.iconButton, + titleBarWidget.minimizeButton, + titleBarWidget.maximizeButton, + titleBarWidget.closeButton, + appMainWindow.menubar}); + helper.removeWindowFrame(mainWindow); +#endif + + mainWindow->resize(800, 600); +#ifdef Q_OS_WINDOWS + WinNativeEventFilter::moveWindowToDesktopCenter(mainWindow); +#else + FramelessHelper::moveWindowToDesktopCenter(mainWindow); +#endif + + mainWindow->show(); + + return QApplication::exec(); +} diff --git a/examples/QQPlayer-demo/CMakeLists.txt b/examples/QQPlayer/CMakeLists.txt similarity index 100% rename from examples/QQPlayer-demo/CMakeLists.txt rename to examples/QQPlayer/CMakeLists.txt diff --git a/examples/QQPlayer-demo/QQPlayer.exe.manifest b/examples/QQPlayer/QQPlayer.exe.manifest similarity index 100% rename from examples/QQPlayer-demo/QQPlayer.exe.manifest rename to examples/QQPlayer/QQPlayer.exe.manifest diff --git a/examples/QQPlayer-demo/QQPlayer.ico b/examples/QQPlayer/QQPlayer.ico similarity index 100% rename from examples/QQPlayer-demo/QQPlayer.ico rename to examples/QQPlayer/QQPlayer.ico diff --git a/examples/QQPlayer-demo/QQPlayer.rc b/examples/QQPlayer/QQPlayer.rc similarity index 100% rename from examples/QQPlayer-demo/QQPlayer.rc rename to examples/QQPlayer/QQPlayer.rc diff --git a/examples/QQPlayer-demo/README.txt b/examples/QQPlayer/README.txt similarity index 100% rename from examples/QQPlayer-demo/README.txt rename to examples/QQPlayer/README.txt diff --git a/examples/QQPlayer-demo/build.bat b/examples/QQPlayer/build.bat similarity index 100% rename from examples/QQPlayer-demo/build.bat rename to examples/QQPlayer/build.bat diff --git a/examples/QQPlayer-demo/images.qrc b/examples/QQPlayer/images.qrc similarity index 100% rename from examples/QQPlayer-demo/images.qrc rename to examples/QQPlayer/images.qrc diff --git a/examples/QQPlayer-demo/main.cpp b/examples/QQPlayer/main.cpp similarity index 100% rename from examples/QQPlayer-demo/main.cpp rename to examples/QQPlayer/main.cpp diff --git a/examples/QQPlayer-demo/qml.qrc b/examples/QQPlayer/qml.qrc similarity index 100% rename from examples/QQPlayer-demo/qml.qrc rename to examples/QQPlayer/qml.qrc diff --git a/examples/QQPlayer-demo/resources/images/background.png b/examples/QQPlayer/resources/images/background.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/background.png rename to examples/QQPlayer/resources/images/background.png diff --git a/examples/QQPlayer-demo/resources/images/logo.png b/examples/QQPlayer/resources/images/logo.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/logo.png rename to examples/QQPlayer/resources/images/logo.png diff --git a/examples/QQPlayer-demo/resources/images/main_menu_blue.png b/examples/QQPlayer/resources/images/main_menu_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/main_menu_blue.png rename to examples/QQPlayer/resources/images/main_menu_blue.png diff --git a/examples/QQPlayer-demo/resources/images/main_menu_white.png b/examples/QQPlayer/resources/images/main_menu_white.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/main_menu_white.png rename to examples/QQPlayer/resources/images/main_menu_white.png diff --git a/examples/QQPlayer-demo/resources/images/next_blue.png b/examples/QQPlayer/resources/images/next_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/next_blue.png rename to examples/QQPlayer/resources/images/next_blue.png diff --git a/examples/QQPlayer-demo/resources/images/next_blue_light.png b/examples/QQPlayer/resources/images/next_blue_light.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/next_blue_light.png rename to examples/QQPlayer/resources/images/next_blue_light.png diff --git a/examples/QQPlayer-demo/resources/images/open_file_blue.png b/examples/QQPlayer/resources/images/open_file_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/open_file_blue.png rename to examples/QQPlayer/resources/images/open_file_blue.png diff --git a/examples/QQPlayer-demo/resources/images/open_file_white.png b/examples/QQPlayer/resources/images/open_file_white.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/open_file_white.png rename to examples/QQPlayer/resources/images/open_file_white.png diff --git a/examples/QQPlayer-demo/resources/images/play_blue.png b/examples/QQPlayer/resources/images/play_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/play_blue.png rename to examples/QQPlayer/resources/images/play_blue.png diff --git a/examples/QQPlayer-demo/resources/images/play_blue_light.png b/examples/QQPlayer/resources/images/play_blue_light.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/play_blue_light.png rename to examples/QQPlayer/resources/images/play_blue_light.png diff --git a/examples/QQPlayer-demo/resources/images/previous_blue.png b/examples/QQPlayer/resources/images/previous_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/previous_blue.png rename to examples/QQPlayer/resources/images/previous_blue.png diff --git a/examples/QQPlayer-demo/resources/images/previous_blue_light.png b/examples/QQPlayer/resources/images/previous_blue_light.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/previous_blue_light.png rename to examples/QQPlayer/resources/images/previous_blue_light.png diff --git a/examples/QQPlayer-demo/resources/images/stop_blue.png b/examples/QQPlayer/resources/images/stop_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/stop_blue.png rename to examples/QQPlayer/resources/images/stop_blue.png diff --git a/examples/QQPlayer-demo/resources/images/stop_blue_light.png b/examples/QQPlayer/resources/images/stop_blue_light.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/stop_blue_light.png rename to examples/QQPlayer/resources/images/stop_blue_light.png diff --git a/examples/QQPlayer-demo/resources/images/volume_blue.png b/examples/QQPlayer/resources/images/volume_blue.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/volume_blue.png rename to examples/QQPlayer/resources/images/volume_blue.png diff --git a/examples/QQPlayer-demo/resources/images/volume_blue_light.png b/examples/QQPlayer/resources/images/volume_blue_light.png similarity index 100% rename from examples/QQPlayer-demo/resources/images/volume_blue_light.png rename to examples/QQPlayer/resources/images/volume_blue_light.png diff --git a/examples/QQPlayer-demo/resources/qml/CloseButton.qml b/examples/QQPlayer/resources/qml/CloseButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/CloseButton.qml rename to examples/QQPlayer/resources/qml/CloseButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/MainMenuButton.qml b/examples/QQPlayer/resources/qml/MainMenuButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/MainMenuButton.qml rename to examples/QQPlayer/resources/qml/MainMenuButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/MaximizeButton.qml b/examples/QQPlayer/resources/qml/MaximizeButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/MaximizeButton.qml rename to examples/QQPlayer/resources/qml/MaximizeButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/MinimizeButton.qml b/examples/QQPlayer/resources/qml/MinimizeButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/MinimizeButton.qml rename to examples/QQPlayer/resources/qml/MinimizeButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/NextButton.qml b/examples/QQPlayer/resources/qml/NextButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/NextButton.qml rename to examples/QQPlayer/resources/qml/NextButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/OpenFileButton.qml b/examples/QQPlayer/resources/qml/OpenFileButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/OpenFileButton.qml rename to examples/QQPlayer/resources/qml/OpenFileButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/PlayButton.qml b/examples/QQPlayer/resources/qml/PlayButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/PlayButton.qml rename to examples/QQPlayer/resources/qml/PlayButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/PreviousButton.qml b/examples/QQPlayer/resources/qml/PreviousButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/PreviousButton.qml rename to examples/QQPlayer/resources/qml/PreviousButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/ProgressSlider.qml b/examples/QQPlayer/resources/qml/ProgressSlider.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/ProgressSlider.qml rename to examples/QQPlayer/resources/qml/ProgressSlider.qml diff --git a/examples/QQPlayer-demo/resources/qml/StopButton.qml b/examples/QQPlayer/resources/qml/StopButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/StopButton.qml rename to examples/QQPlayer/resources/qml/StopButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/VolumeButton.qml b/examples/QQPlayer/resources/qml/VolumeButton.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/VolumeButton.qml rename to examples/QQPlayer/resources/qml/VolumeButton.qml diff --git a/examples/QQPlayer-demo/resources/qml/main.qml b/examples/QQPlayer/resources/qml/main.qml similarity index 100% rename from examples/QQPlayer-demo/resources/qml/main.qml rename to examples/QQPlayer/resources/qml/main.qml diff --git a/examples/QWidget/QWidget.pro b/examples/QWidget/QWidget.pro new file mode 100644 index 0000000..3850c77 --- /dev/null +++ b/examples/QWidget/QWidget.pro @@ -0,0 +1,5 @@ +TARGET = QWidget +TEMPLATE = app +QT += widgets +SOURCES += main.cpp +include($$PWD/../common.pri) diff --git a/main_windows.cpp b/examples/QWidget/main.cpp similarity index 77% rename from main_windows.cpp rename to examples/QWidget/main.cpp index fa5e1d6..110869b 100644 --- a/main_windows.cpp +++ b/examples/QWidget/main.cpp @@ -22,37 +22,40 @@ * SOFTWARE. */ -#include "winnativeeventfilter.h" #include #include #include -#include -#include #include #include #include -#ifdef QT_QUICK_LIB -#include "framelessquickhelper.h" -#include -#include +#ifdef Q_OS_WINDOWS +#include "../../winnativeeventfilter.h" +#include +#include +#else +#include "../../framelesshelper.h" #endif static inline bool shouldHaveWindowFrame() { +#ifdef Q_OS_WINDOWS return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10; +#else + return false; +#endif } -class FramelessWidget : public QWidget +class Widget : public QWidget { Q_OBJECT - Q_DISABLE_COPY_MOVE(FramelessWidget) + Q_DISABLE_COPY_MOVE(Widget) public: - explicit FramelessWidget(QWidget *parent = nullptr) : QWidget(parent) + explicit Widget(QWidget *parent = nullptr) : QWidget(parent) { isWin10OrGreater = shouldHaveWindowFrame(); } - ~FramelessWidget() override = default; + ~Widget() override = default; bool isNormaled() const { return !isMinimized() && !isMaximized() && !isFullScreen(); } @@ -60,6 +63,7 @@ protected: void paintEvent(QPaintEvent *event) override { QWidget::paintEvent(event); +#ifdef Q_OS_WINDOWS if (isWin10OrGreater && isNormaled()) { QPainter painter(this); painter.save(); @@ -70,6 +74,7 @@ protected: // painter.drawLine(width(), 0, width(), height()); painter.restore(); } +#endif } private: @@ -104,8 +109,11 @@ int main(int argc, char *argv[]) QApplication application(argc, argv); - // Qt Widgets example: - FramelessWidget widget; +#ifndef Q_OS_WINDOWS + FramelessHelper helper; +#endif + + Widget widget; widget.setContentsMargins(2, 2, 2, 2); QLabel *label = new QLabel; QObject::connect(&widget, &QWidget::windowTitleChanged, label, &QLabel::setText); @@ -142,44 +150,25 @@ int main(int argc, char *argv[]) mainLayout->addStretch(); widget.setLayout(mainLayout); widget.setWindowTitle(QObject::tr("Hello, World!")); +#ifdef Q_OS_WINDOWS WinNativeEventFilter::addFramelessWindow(&widget); - const auto data_widget = WinNativeEventFilter::windowData(&widget); - if (data_widget) { - data_widget->ignoreObjects << minimizeButton << maximizeButton << closeButton; + const auto data = WinNativeEventFilter::windowData(&widget); + if (data) { + data->ignoreObjects << minimizeButton << maximizeButton << closeButton; } - widget.resize(800, 600); - WinNativeEventFilter::moveWindowToDesktopCenter(&widget); - widget.show(); - -#ifdef QT_QUICK_LIB - // Qt Quick example: - QQmlApplicationEngine engine; - qmlRegisterType("wangwenx190.Utils", 1, 0, "FramelessHelper"); - const QUrl mainQmlUrl(QString::fromUtf8("qrc:///qml/main.qml")); - const QMetaObject::Connection connection = QObject::connect( - &engine, - &QQmlApplicationEngine::objectCreated, - &application, - [&mainQmlUrl, &connection](QObject *object, const QUrl &url) { - if (url != mainQmlUrl) { - return; - } - if (!object) { - QGuiApplication::exit(-1); - } else { - QObject::disconnect(connection); - } - }, - Qt::QueuedConnection); - engine.load(mainQmlUrl); - QList rootObjs = engine.rootObjects(); - Q_ASSERT(!rootObjs.isEmpty()); - QObject *rootObj = rootObjs.at(0); - Q_ASSERT(rootObj); - QQmlProperty::write(rootObj, QString::fromUtf8("isWin10OrGreater"), shouldHaveWindowFrame()); +#else + helper.setIgnoreObjects(&widget, {minimizeButton, maximizeButton, closeButton}); + helper.removeWindowFrame(&widget); #endif + widget.resize(800, 600); +#ifdef Q_OS_WINDOWS + WinNativeEventFilter::moveWindowToDesktopCenter(&widget); +#else + FramelessHelper::moveWindowToDesktopCenter(&widget); +#endif + widget.show(); return QApplication::exec(); } -#include "main_windows.moc" +#include "main.moc" diff --git a/examples/Quick/Quick.pro b/examples/Quick/Quick.pro new file mode 100644 index 0000000..4371988 --- /dev/null +++ b/examples/Quick/Quick.pro @@ -0,0 +1,6 @@ +TARGET = Quick +TEMPLATE = app +QT += quick +HEADERS += $$PWD/../../framelessquickhelper.h +SOURCES += $$PWD/../../framelessquickhelper.cpp main.cpp +include($$PWD/../common.pri) diff --git a/examples/Quick/main.cpp b/examples/Quick/main.cpp new file mode 100644 index 0000000..33fcf0b --- /dev/null +++ b/examples/Quick/main.cpp @@ -0,0 +1,94 @@ +/* + * 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 "../../framelessquickhelper.h" +#include +#include +#include +#ifdef Q_OS_WINDOWS +#include +#endif + +static inline bool shouldHaveWindowFrame() +{ +#ifdef Q_OS_WINDOWS + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10; +#else + return false; +#endif +} + +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 + + QGuiApplication application(argc, argv); + + QQmlApplicationEngine engine; + qmlRegisterType("wangwenx190.Utils", 1, 0, "FramelessHelper"); + const QUrl mainQmlUrl(QString::fromUtf8("qrc:///qml/main.qml")); + const QMetaObject::Connection connection = QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreated, + &application, + [&mainQmlUrl, &connection](QObject *object, const QUrl &url) { + if (url != mainQmlUrl) { + return; + } + if (!object) { + QGuiApplication::exit(-1); + } else { + QObject::disconnect(connection); + } + }, + Qt::QueuedConnection); + engine.load(mainQmlUrl); + QList rootObjs = engine.rootObjects(); + Q_ASSERT(!rootObjs.isEmpty()); + QObject *rootObj = rootObjs.at(0); + Q_ASSERT(rootObj); + QQmlProperty::write(rootObj, QString::fromUtf8("isWin10OrGreater"), shouldHaveWindowFrame()); + + return QGuiApplication::exec(); +} diff --git a/examples/common.pri b/examples/common.pri new file mode 100644 index 0000000..046de70 --- /dev/null +++ b/examples/common.pri @@ -0,0 +1,24 @@ +QT += gui-private +CONFIG += c++17 strict_c++ utf8_source warn_on +DEFINES += \ + QT_NO_CAST_FROM_ASCII \ + QT_NO_CAST_TO_ASCII \ + FRAMELESSHELPER_STATIC +HEADERS += \ + $$PWD/../framelesshelper_global.h \ + $$PWD/../framelesshelper.h +SOURCES += $$PWD/../framelesshelper.cpp +win32 { + DEFINES += WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS + CONFIG += windeployqt + CONFIG -= embed_manifest_exe + HEADERS += $$PWD/../winnativeeventfilter.h + SOURCES += $$PWD/../winnativeeventfilter.cpp + LINK_TO_SYSTEM_DLL { + DEFINES += WNEF_LINK_SYSLIB + LIBS += -luser32 -lgdi32 -ldwmapi -lshcore -ld2d1 + } + RESOURCES += $$PWD/windows.qrc + RC_FILE = $$PWD/windows.rc + OTHER_FILES += $$PWD/windows.manifest +} diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100644 index 0000000..c458979 --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG -= ordered +qtHaveModule(widgets): SUBDIRS += QWidget QMainWindow +qtHaveModule(quick): SUBDIRS += Quick diff --git a/framelesshelper_windows.ico b/examples/windows.ico similarity index 100% rename from framelesshelper_windows.ico rename to examples/windows.ico diff --git a/framelesshelper_windows.manifest b/examples/windows.manifest similarity index 100% rename from framelesshelper_windows.manifest rename to examples/windows.manifest diff --git a/examples/windows.qrc b/examples/windows.qrc new file mode 100644 index 0000000..c13ddf8 --- /dev/null +++ b/examples/windows.qrc @@ -0,0 +1,18 @@ + + + ../resources/qml/main.qml + ../resources/qml/MinimizeButton.qml + ../resources/qml/MaximizeButton.qml + ../resources/qml/CloseButton.qml + + + ../resources/images/button_minimize_black.svg + ../resources/images/button_minimize_white.svg + ../resources/images/button_maximize_black.svg + ../resources/images/button_maximize_white.svg + ../resources/images/button_restore_black.svg + ../resources/images/button_restore_white.svg + ../resources/images/button_close_black.svg + ../resources/images/button_close_white.svg + + diff --git a/framelesshelper_windows.rc b/examples/windows.rc similarity index 81% rename from framelesshelper_windows.rc rename to examples/windows.rc index 3654aa6..ef5cc0e 100644 --- a/framelesshelper_windows.rc +++ b/examples/windows.rc @@ -24,9 +24,9 @@ #include -IDI_ICON1 ICON "framelesshelper_windows.ico" +IDI_ICON1 ICON "windows.ico" -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "framelesshelper_windows.manifest" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "windows.manifest" VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,0 @@ -47,15 +47,11 @@ BEGIN BEGIN VALUE "Comments", "Built by the Qt Toolkit." VALUE "CompanyName", "wangwenx190" - VALUE "FileDescription", "A framelesshelper based Qt application." + VALUE "FileDescription", "A FramelessHelper based Qt application." VALUE "FileVersion", "1.0.0.0" - VALUE "InternalName", "flh-test-app" + VALUE "InternalName", "" VALUE "LegalCopyright", "MIT License" - #ifdef _DEBUG - VALUE "OriginalFilename", "framelessapplicationd.exe" - #else - VALUE "OriginalFilename", "framelessapplication.exe" - #endif + VALUE "OriginalFilename", "" VALUE "ProductName", "Test Application" VALUE "ProductVersion", "1.0.0.0" END diff --git a/framelesshelper_unix.pro b/framelesshelper_unix.pro deleted file mode 100644 index e990d1a..0000000 --- a/framelesshelper_unix.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = framelessapplication -CONFIG(debug, debug|release): TARGET = $$join(TARGET,,,_debug) -TEMPLATE = app -QT += gui-private -qtHaveModule(widgets): QT += widgets -qtHaveModule(quick) { - QT += quick - HEADERS += framelessquickhelper.h - SOURCES += framelessquickhelper.cpp -} -CONFIG += c++17 strict_c++ warn_on utf8_source -DEFINES += \ - QT_NO_CAST_FROM_ASCII \ - QT_NO_CAST_TO_ASCII \ - FRAMELESSHELPER_STATIC -VERSION = 1.0.0 -HEADERS += framelesshelper_global.h framelesshelper.h -SOURCES += framelesshelper.cpp main_unix.cpp diff --git a/framelesshelper_windows.pro b/framelesshelper_windows.pro deleted file mode 100644 index 8557871..0000000 --- a/framelesshelper_windows.pro +++ /dev/null @@ -1,27 +0,0 @@ -TARGET = framelessapplication -CONFIG(debug, debug|release): TARGET = $$join(TARGET,,,d) -TEMPLATE = app -QT += gui-private -qtHaveModule(widgets): QT += widgets -qtHaveModule(quick) { - QT += quick - HEADERS += framelessquickhelper.h - SOURCES += framelessquickhelper.cpp -} -CONFIG += c++17 strict_c++ utf8_source warn_on windeployqt -DEFINES += \ - WIN32_LEAN_AND_MEAN \ - _CRT_SECURE_NO_WARNINGS \ - QT_NO_CAST_FROM_ASCII \ - QT_NO_CAST_TO_ASCII \ - FRAMELESSHELPER_STATIC -LINK_TO_SYSTEM_DLL { - DEFINES += WNEF_LINK_SYSLIB - LIBS += -luser32 -lgdi32 -ldwmapi -lshcore -ld2d1 -} -CONFIG -= embed_manifest_exe -RC_FILE = framelesshelper_windows.rc -HEADERS += framelesshelper_global.h winnativeeventfilter.h -SOURCES += winnativeeventfilter.cpp main_windows.cpp -RESOURCES += framelesshelper_windows.qrc -OTHER_FILES += framelesshelper_windows.manifest diff --git a/framelesshelper_windows.qrc b/framelesshelper_windows.qrc deleted file mode 100644 index c8da852..0000000 --- a/framelesshelper_windows.qrc +++ /dev/null @@ -1,18 +0,0 @@ - - - resources/qml/main.qml - resources/qml/MinimizeButton.qml - resources/qml/MaximizeButton.qml - resources/qml/CloseButton.qml - - - resources/images/button_minimize_black.svg - resources/images/button_minimize_white.svg - resources/images/button_maximize_black.svg - resources/images/button_maximize_white.svg - resources/images/button_restore_black.svg - resources/images/button_restore_white.svg - resources/images/button_close_black.svg - resources/images/button_close_white.svg - - diff --git a/main_unix.cpp b/main_unix.cpp deleted file mode 100644 index fde5d91..0000000 --- a/main_unix.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 "framelesshelper.h" -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - // High DPI scaling is enabled by default from Qt 6 -#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - 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); - - FramelessHelper helper; - - QWidget widget; - widget.setContentsMargins(0, 0, 0, 0); - QLabel *label = new QLabel; - QObject::connect(&widget, &QWidget::windowTitleChanged, label, &QLabel::setText); - QPushButton *minimizeButton = new QPushButton; - minimizeButton->setText(QObject::tr("Minimize")); - QObject::connect(minimizeButton, &QPushButton::clicked, &widget, &QWidget::showMinimized); - QPushButton *maximizeButton = new QPushButton; - maximizeButton->setText(QObject::tr("Maximize")); - QObject::connect(maximizeButton, &QPushButton::clicked, [&widget, &maximizeButton]() { - if (widget.isMaximized()) { - widget.showNormal(); - maximizeButton->setText(QObject::tr("Maximize")); - } else { - widget.showMaximized(); - maximizeButton->setText(QObject::tr("Restore")); - } - }); - QPushButton *closeButton = new QPushButton; - closeButton->setText(QObject::tr("Close")); - QObject::connect(closeButton, &QPushButton::clicked, &widget, &QWidget::close); - QHBoxLayout *tbLayout = new QHBoxLayout; - tbLayout->setContentsMargins(0, 0, 0, 0); - tbLayout->setSpacing(0); - tbLayout->addSpacing(15); - tbLayout->addWidget(label); - tbLayout->addStretch(); - tbLayout->addWidget(minimizeButton); - tbLayout->addWidget(maximizeButton); - tbLayout->addWidget(closeButton); - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->setSpacing(0); - mainLayout->addLayout(tbLayout); - mainLayout->addStretch(); - widget.setLayout(mainLayout); - widget.setWindowTitle(QObject::tr("Hello, World!")); - helper.setIgnoreObjects(&widget, {minimizeButton, maximizeButton, closeButton}); - helper.removeWindowFrame(&widget); - widget.resize(800, 600); - FramelessHelper::moveWindowToDesktopCenter(&widget); - widget.show(); - - return QApplication::exec(); -}