mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-01-23 04:14:35 +08:00
update
This commit is contained in:
parent
f616a2da6a
commit
41cbeef3fd
@ -535,104 +535,104 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="315"/>
|
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||||
<source>Dark Mode</source>
|
<source>Dark Mode</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="qml/window/MainWindow.qml" line="83"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="91"/>
|
<location filename="qml/window/MainWindow.qml" line="91"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="99"/>
|
|
||||||
<source>Quit</source>
|
<source>Quit</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
<location filename="qml/window/MainWindow.qml" line="84"/>
|
||||||
<source>Are you sure you want to exit the program?</source>
|
<source>Are you sure you want to exit the program?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="93"/>
|
<location filename="qml/window/MainWindow.qml" line="85"/>
|
||||||
<source>Minimize</source>
|
<source>Minimize</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||||
<source>Friendly Reminder</source>
|
<source>Friendly Reminder</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||||
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="100"/>
|
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="344"/>
|
<location filename="qml/window/MainWindow.qml" line="336"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="111"/>
|
<location filename="qml/window/MainWindow.qml" line="103"/>
|
||||||
<source>Open in Separate Window</source>
|
<source>Open in Separate Window</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="208"/>
|
<location filename="qml/window/MainWindow.qml" line="200"/>
|
||||||
<source>Click Time</source>
|
<source>Click Time</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="218"/>
|
<location filename="qml/window/MainWindow.qml" line="210"/>
|
||||||
<source>Search</source>
|
<source>Search</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
<location filename="qml/window/MainWindow.qml" line="301"/>
|
||||||
<source>Finish</source>
|
<source>Finish</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="310"/>
|
<location filename="qml/window/MainWindow.qml" line="302"/>
|
||||||
<source>Next</source>
|
<source>Next</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
<location filename="qml/window/MainWindow.qml" line="303"/>
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="315"/>
|
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||||
<source>Here you can switch to night mode.</source>
|
<source>Here you can switch to night mode.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="317"/>
|
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||||
<source>Hide Easter eggs</source>
|
<source>Hide Easter eggs</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="317"/>
|
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||||
<source>Try a few more clicks!!</source>
|
<source>Try a few more clicks!!</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="341"/>
|
<location filename="qml/window/MainWindow.qml" line="333"/>
|
||||||
<source>Upgrade Tips</source>
|
<source>Upgrade Tips</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source>FluentUI is currently up to date </source>
|
<source>FluentUI is currently up to date </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source> -- The current app version</source>
|
<source> -- The current app version</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source>
|
<source>
|
||||||
Now go and download the new version?
|
Now go and download the new version?
|
||||||
|
|
||||||
@ -641,17 +641,17 @@ Updated content:
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="345"/>
|
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||||
<source>OK</source>
|
<source>OK</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="372"/>
|
<location filename="qml/window/MainWindow.qml" line="364"/>
|
||||||
<source>The current version is already the latest</source>
|
<source>The current version is already the latest</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="379"/>
|
<location filename="qml/window/MainWindow.qml" line="371"/>
|
||||||
<source>The network is abnormal</source>
|
<source>The network is abnormal</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -535,104 +535,104 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="315"/>
|
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||||
<source>Dark Mode</source>
|
<source>Dark Mode</source>
|
||||||
<translation type="unfinished">夜间模式</translation>
|
<translation type="unfinished">夜间模式</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="qml/window/MainWindow.qml" line="83"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="91"/>
|
<location filename="qml/window/MainWindow.qml" line="91"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="99"/>
|
|
||||||
<source>Quit</source>
|
<source>Quit</source>
|
||||||
<translation type="unfinished">退出</translation>
|
<translation type="unfinished">退出</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="92"/>
|
<location filename="qml/window/MainWindow.qml" line="84"/>
|
||||||
<source>Are you sure you want to exit the program?</source>
|
<source>Are you sure you want to exit the program?</source>
|
||||||
<translation type="unfinished">您确定要退出程序吗</translation>
|
<translation type="unfinished">您确定要退出程序吗</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="93"/>
|
<location filename="qml/window/MainWindow.qml" line="85"/>
|
||||||
<source>Minimize</source>
|
<source>Minimize</source>
|
||||||
<translation type="unfinished">最小化</translation>
|
<translation type="unfinished">最小化</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||||
<source>Friendly Reminder</source>
|
<source>Friendly Reminder</source>
|
||||||
<translation type="unfinished">友情提示</translation>
|
<translation type="unfinished">友情提示</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="96"/>
|
<location filename="qml/window/MainWindow.qml" line="88"/>
|
||||||
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
<source>FluentUI is hidden from the tray, click on the tray to activate the window again</source>
|
||||||
<translation type="unfinished">FluentUI 在托盘中处于隐藏状态,单击托盘以再次激活窗口</translation>
|
<translation type="unfinished">FluentUI 在托盘中处于隐藏状态,单击托盘以再次激活窗口</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="100"/>
|
<location filename="qml/window/MainWindow.qml" line="92"/>
|
||||||
<location filename="qml/window/MainWindow.qml" line="344"/>
|
<location filename="qml/window/MainWindow.qml" line="336"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="unfinished">取消</translation>
|
<translation type="unfinished">取消</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="111"/>
|
<location filename="qml/window/MainWindow.qml" line="103"/>
|
||||||
<source>Open in Separate Window</source>
|
<source>Open in Separate Window</source>
|
||||||
<translation type="unfinished">在独立窗口中打开</translation>
|
<translation type="unfinished">在独立窗口中打开</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="208"/>
|
<location filename="qml/window/MainWindow.qml" line="200"/>
|
||||||
<source>Click Time</source>
|
<source>Click Time</source>
|
||||||
<translation type="unfinished">点击次数</translation>
|
<translation type="unfinished">点击次数</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="218"/>
|
<location filename="qml/window/MainWindow.qml" line="210"/>
|
||||||
<source>Search</source>
|
<source>Search</source>
|
||||||
<translation type="unfinished">搜索</translation>
|
<translation type="unfinished">搜索</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="309"/>
|
<location filename="qml/window/MainWindow.qml" line="301"/>
|
||||||
<source>Finish</source>
|
<source>Finish</source>
|
||||||
<translation type="unfinished">完成</translation>
|
<translation type="unfinished">完成</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="310"/>
|
<location filename="qml/window/MainWindow.qml" line="302"/>
|
||||||
<source>Next</source>
|
<source>Next</source>
|
||||||
<translation type="unfinished">下一步</translation>
|
<translation type="unfinished">下一步</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="311"/>
|
<location filename="qml/window/MainWindow.qml" line="303"/>
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<translation type="unfinished">上一步</translation>
|
<translation type="unfinished">上一步</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="315"/>
|
<location filename="qml/window/MainWindow.qml" line="307"/>
|
||||||
<source>Here you can switch to night mode.</source>
|
<source>Here you can switch to night mode.</source>
|
||||||
<translation type="unfinished">在这里,您可以切换到夜间模式。</translation>
|
<translation type="unfinished">在这里,您可以切换到夜间模式。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="317"/>
|
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||||
<source>Hide Easter eggs</source>
|
<source>Hide Easter eggs</source>
|
||||||
<translation type="unfinished">隐藏彩蛋</translation>
|
<translation type="unfinished">隐藏彩蛋</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="317"/>
|
<location filename="qml/window/MainWindow.qml" line="309"/>
|
||||||
<source>Try a few more clicks!!</source>
|
<source>Try a few more clicks!!</source>
|
||||||
<translation type="unfinished">再试几下!!</translation>
|
<translation type="unfinished">再试几下!!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="341"/>
|
<location filename="qml/window/MainWindow.qml" line="333"/>
|
||||||
<source>Upgrade Tips</source>
|
<source>Upgrade Tips</source>
|
||||||
<translation type="unfinished">升级提示</translation>
|
<translation type="unfinished">升级提示</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source>FluentUI is currently up to date </source>
|
<source>FluentUI is currently up to date </source>
|
||||||
<translation type="unfinished">FluentUI 目前最新版本 </translation>
|
<translation type="unfinished">FluentUI 目前最新版本 </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source> -- The current app version</source>
|
<source> -- The current app version</source>
|
||||||
<translation type="unfinished"> -- 当前应用版本</translation>
|
<translation type="unfinished"> -- 当前应用版本</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="342"/>
|
<location filename="qml/window/MainWindow.qml" line="334"/>
|
||||||
<source>
|
<source>
|
||||||
Now go and download the new version?
|
Now go and download the new version?
|
||||||
|
|
||||||
@ -645,17 +645,17 @@ Updated content:
|
|||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="345"/>
|
<location filename="qml/window/MainWindow.qml" line="337"/>
|
||||||
<source>OK</source>
|
<source>OK</source>
|
||||||
<translation type="unfinished">确定</translation>
|
<translation type="unfinished">确定</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="372"/>
|
<location filename="qml/window/MainWindow.qml" line="364"/>
|
||||||
<source>The current version is already the latest</source>
|
<source>The current version is already the latest</source>
|
||||||
<translation type="unfinished">当前版本已经是最新版本</translation>
|
<translation type="unfinished">当前版本已经是最新版本</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="qml/window/MainWindow.qml" line="379"/>
|
<location filename="qml/window/MainWindow.qml" line="371"/>
|
||||||
<source>The network is abnormal</source>
|
<source>The network is abnormal</source>
|
||||||
<translation type="unfinished">网络异常</translation>
|
<translation type="unfinished">网络异常</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -35,16 +35,8 @@ FluWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstVisible: {
|
onLazyLoad: {
|
||||||
timer_tour_delay.restart()
|
tour.open()
|
||||||
}
|
|
||||||
|
|
||||||
Timer{
|
|
||||||
id:timer_tour_delay
|
|
||||||
interval: 200
|
|
||||||
onTriggered: {
|
|
||||||
tour.open()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@ -168,7 +160,7 @@ FluWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
appBar.setHitTestVisible(layout_back_buttons)
|
window.setHitTestVisible(layout_back_buttons)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluRemoteLoader{
|
FluRemoteLoader{
|
||||||
@ -226,9 +218,9 @@ FluWindow {
|
|||||||
ItemsOriginal.paneItemMenu = nav_item_right_menu
|
ItemsOriginal.paneItemMenu = nav_item_right_menu
|
||||||
ItemsFooter.navigationView = nav_view
|
ItemsFooter.navigationView = nav_view
|
||||||
ItemsFooter.paneItemMenu = nav_item_right_menu
|
ItemsFooter.paneItemMenu = nav_item_right_menu
|
||||||
appBar.setHitTestVisible(nav_view.buttonMenu)
|
window.setHitTestVisible(nav_view.buttonMenu)
|
||||||
appBar.setHitTestVisible(nav_view.buttonBack)
|
window.setHitTestVisible(nav_view.buttonBack)
|
||||||
appBar.setHitTestVisible(nav_view.imageLogo)
|
window.setHitTestVisible(nav_view.imageLogo)
|
||||||
setCurrentIndex(0)
|
setCurrentIndex(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
459
src/FluFrameless.cpp
Normal file
459
src/FluFrameless.cpp
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
#include "FluFrameless.h"
|
||||||
|
|
||||||
|
#include <QQuickWindow>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#pragma comment (lib,"user32.lib")
|
||||||
|
#pragma comment (lib,"dwmapi.lib")
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <dwmapi.h>
|
||||||
|
static inline QByteArray qtNativeEventType()
|
||||||
|
{
|
||||||
|
static const auto result = "windows_generic_MSG";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static inline bool isCompositionEnabled(){
|
||||||
|
typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
|
||||||
|
HMODULE module = ::LoadLibraryW(L"dwmapi.dll");
|
||||||
|
if (module)
|
||||||
|
{
|
||||||
|
BOOL composition_enabled = false;
|
||||||
|
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
|
||||||
|
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
|
||||||
|
if (dwm_is_composition_enabled)
|
||||||
|
{
|
||||||
|
dwm_is_composition_enabled(&composition_enabled);
|
||||||
|
}
|
||||||
|
return composition_enabled;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FluFrameless::FluFrameless(QQuickItem *parent)
|
||||||
|
: QQuickItem{parent}
|
||||||
|
{
|
||||||
|
appbar(nullptr);
|
||||||
|
maximizeButton(nullptr);
|
||||||
|
minimizedButton(nullptr);
|
||||||
|
closeButton(nullptr);
|
||||||
|
topmost(false);
|
||||||
|
disabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FluFrameless::~FluFrameless(){
|
||||||
|
qApp->removeNativeEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::componentComplete(){
|
||||||
|
if(_disabled){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_current = window()->winId();
|
||||||
|
window()->setFlags(( window()->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
|
||||||
|
if(!_fixSize){
|
||||||
|
window()->setFlag(Qt::WindowMaximizeButtonHint);
|
||||||
|
}
|
||||||
|
window()->installEventFilter(this);
|
||||||
|
qApp->installNativeEventFilter(this);
|
||||||
|
if(_appbar){
|
||||||
|
_appbar->installEventFilter(this);
|
||||||
|
}
|
||||||
|
if(_maximizeButton){
|
||||||
|
setHitTestVisible(_maximizeButton);
|
||||||
|
}
|
||||||
|
if(_minimizedButton){
|
||||||
|
setHitTestVisible(_minimizedButton);
|
||||||
|
}
|
||||||
|
if(_closeButton){
|
||||||
|
setHitTestVisible(_closeButton);
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||||
|
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
||||||
|
if(_fixSize){
|
||||||
|
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
|
||||||
|
for (int i = 0; i < qApp->screens().count(); ++i) {
|
||||||
|
connect( qApp->screens().at(i),&QScreen::logicalDotsPerInchChanged,this,[=]{
|
||||||
|
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
|
||||||
|
}
|
||||||
|
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||||
|
connect(window(),&QQuickWindow::screenChanged,this,[hwnd]{
|
||||||
|
::SetWindowPos(hwnd,0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||||
|
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
connect(this,&FluFrameless::topmostChanged,this,[this]{
|
||||||
|
_setWindowTopmost(topmost());
|
||||||
|
});
|
||||||
|
_setWindowTopmost(topmost());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if ((eventType != qtNativeEventType()) || !message) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto msg = static_cast<const MSG *>(message);
|
||||||
|
const HWND hwnd = msg->hwnd;
|
||||||
|
if (!hwnd || !msg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const qint64 wid = reinterpret_cast<qint64>(hwnd);
|
||||||
|
if(wid != _current){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const UINT uMsg = msg->message;
|
||||||
|
const WPARAM wParam = msg->wParam;
|
||||||
|
const LPARAM lParam = msg->lParam;
|
||||||
|
static QPoint offsetXY;
|
||||||
|
if(uMsg == WM_WINDOWPOSCHANGING){
|
||||||
|
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
|
||||||
|
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
|
||||||
|
{
|
||||||
|
wp->flags |= SWP_NOCOPYBITS;
|
||||||
|
*result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}else if(uMsg == WM_NCCALCSIZE){
|
||||||
|
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||||
|
const LONG originalTop = clientRect->top;
|
||||||
|
const LONG originalLeft = clientRect->left;
|
||||||
|
const LONG originalRight = clientRect->right;
|
||||||
|
const LONG originalBottom = clientRect->bottom;
|
||||||
|
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
||||||
|
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
|
||||||
|
*result = hitTestResult;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int offsetSize = 0;
|
||||||
|
bool isMaximum = ::IsZoomed(hwnd);
|
||||||
|
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
|
||||||
|
if(isMaximum || _isFullScreen()){
|
||||||
|
offsetSize = 0;
|
||||||
|
}else{
|
||||||
|
offsetSize = 1;
|
||||||
|
}
|
||||||
|
if(!isCompositionEnabled()){
|
||||||
|
offsetSize = 0;
|
||||||
|
}
|
||||||
|
if (!isMaximum || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) {
|
||||||
|
clientRect->top = originalTop + offsetSize;
|
||||||
|
clientRect->bottom = originalBottom - offsetSize;
|
||||||
|
clientRect->left = originalLeft + offsetSize;
|
||||||
|
clientRect->right = originalRight - offsetSize;
|
||||||
|
}
|
||||||
|
*result = WVR_REDRAW;
|
||||||
|
return true;
|
||||||
|
}else if(uMsg == WM_NCHITTEST){
|
||||||
|
if(_hitMaximizeButton()){
|
||||||
|
if (*result == HTNOWHERE) {
|
||||||
|
*result = HTZOOM;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*result = 0;
|
||||||
|
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
||||||
|
POINT nativeLocalPos = nativeGlobalPos;
|
||||||
|
::ScreenToClient(hwnd, &nativeLocalPos);
|
||||||
|
RECT clientRect{0, 0, 0, 0};
|
||||||
|
::GetClientRect(hwnd, &clientRect);
|
||||||
|
auto clientWidth = clientRect.right-clientRect.left;
|
||||||
|
auto clientHeight = clientRect.bottom-clientRect.top;
|
||||||
|
bool left = nativeLocalPos.x < _margins;
|
||||||
|
bool right = nativeLocalPos.x > clientWidth - _margins;
|
||||||
|
bool top = nativeLocalPos.y < _margins;
|
||||||
|
bool bottom = nativeLocalPos.y > clientHeight - _margins;
|
||||||
|
*result = 0;
|
||||||
|
if (!_fixSize && !_isFullScreen() && !_isMaximized()) {
|
||||||
|
if (left && top) {
|
||||||
|
*result = HTTOPLEFT;
|
||||||
|
} else if (left && bottom) {
|
||||||
|
*result = HTBOTTOMLEFT;
|
||||||
|
} else if (right && top) {
|
||||||
|
*result = HTTOPRIGHT;
|
||||||
|
} else if (right && bottom) {
|
||||||
|
*result = HTBOTTOMRIGHT;
|
||||||
|
} else if (left) {
|
||||||
|
*result = HTLEFT;
|
||||||
|
} else if (right) {
|
||||||
|
*result = HTRIGHT;
|
||||||
|
} else if (top) {
|
||||||
|
*result = HTTOP;
|
||||||
|
} else if (bottom) {
|
||||||
|
*result = HTBOTTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 != *result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto aa = _hitAppBar();
|
||||||
|
if(aa){
|
||||||
|
*result = HTCAPTION;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*result = HTCLIENT;
|
||||||
|
return true;
|
||||||
|
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
|
||||||
|
if(_hitMaximizeButton()){
|
||||||
|
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||||
|
QGuiApplication::sendEvent(_maximizeButton,&event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
|
||||||
|
if(_hitMaximizeButton()){
|
||||||
|
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||||
|
QGuiApplication::sendEvent(_maximizeButton,&event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}else if(uMsg == WM_NCPAINT){
|
||||||
|
*result = FALSE;
|
||||||
|
return true;
|
||||||
|
}else if(uMsg == WM_NCACTIVATE){
|
||||||
|
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
|
||||||
|
return true;
|
||||||
|
}else if(uMsg == WM_GETMINMAXINFO){
|
||||||
|
MINMAXINFO* minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||||
|
minmaxInfo->ptMaxPosition.x = 0;
|
||||||
|
minmaxInfo->ptMaxPosition.y = 0;
|
||||||
|
minmaxInfo->ptMaxSize.x = 0;
|
||||||
|
minmaxInfo->ptMaxSize.y = 0;
|
||||||
|
#else
|
||||||
|
auto pixelRatio = window()->devicePixelRatio();
|
||||||
|
auto geometry = window()->screen()->availableGeometry();
|
||||||
|
RECT rect;
|
||||||
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
||||||
|
minmaxInfo->ptMaxPosition.x = rect.left - offsetXY.x();
|
||||||
|
minmaxInfo->ptMaxPosition.y = rect.top - offsetXY.x();
|
||||||
|
minmaxInfo->ptMaxSize.x = geometry.width()*pixelRatio + offsetXY.x() * 2;
|
||||||
|
minmaxInfo->ptMaxSize.y = geometry.height()*pixelRatio + offsetXY.y() * 2;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}else if(uMsg == WM_NCRBUTTONDOWN){
|
||||||
|
if (wParam == HTCAPTION) {
|
||||||
|
_showSystemMenu(QCursor::pos());
|
||||||
|
}
|
||||||
|
}else if(uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN){
|
||||||
|
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
|
||||||
|
const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
|
||||||
|
if (altPressed && spacePressed) {
|
||||||
|
auto pos = window()->position();
|
||||||
|
_showSystemMenu(QPoint(pos.x(),pos.y()+_appbar->height()));
|
||||||
|
}
|
||||||
|
}else if(uMsg == WM_SYSCOMMAND){
|
||||||
|
if(wParam == SC_MINIMIZE){
|
||||||
|
if(window()->transientParent()){
|
||||||
|
window()->transientParent()->showMinimized();
|
||||||
|
}else{
|
||||||
|
window()->showMinimized();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::_isMaximized(){
|
||||||
|
return window()->visibility() == QWindow::Maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::_isFullScreen(){
|
||||||
|
return window()->visibility() == QWindow::FullScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::_showSystemMenu(QPoint point){
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||||
|
DWORD style = ::GetWindowLongPtr(hwnd,GWL_STYLE);
|
||||||
|
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
|
||||||
|
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
|
||||||
|
if(_isMaximized() || _isFullScreen()){
|
||||||
|
::EnableMenuItem(hMenu,SC_MOVE,MFS_DISABLED);
|
||||||
|
::EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
|
||||||
|
}else{
|
||||||
|
::EnableMenuItem(hMenu,SC_MOVE,MFS_ENABLED);
|
||||||
|
::EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
|
||||||
|
}
|
||||||
|
if(!_fixSize && !_isMaximized() && !_isFullScreen()){
|
||||||
|
::EnableMenuItem(hMenu,SC_SIZE,MFS_ENABLED);
|
||||||
|
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
|
||||||
|
}else{
|
||||||
|
::EnableMenuItem(hMenu,SC_SIZE,MFS_DISABLED);
|
||||||
|
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_DISABLED);
|
||||||
|
}
|
||||||
|
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), point.x()*window()->devicePixelRatio(), point.y()*window()->devicePixelRatio(), 0, hwnd, nullptr);
|
||||||
|
if (result != FALSE) {
|
||||||
|
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
|
||||||
|
}
|
||||||
|
::SetWindowLongPtr(hwnd, GWL_STYLE, style &~ WS_SYSMENU);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::_containsCursorToItem(QQuickItem* item){
|
||||||
|
if(!item || !item->isVisible()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto point = QCursor::pos();
|
||||||
|
auto rect = QRectF(item->mapToGlobal(QPoint(0,0)),item->size());
|
||||||
|
if(point.x()>rect.x() && point.x()<(rect.x()+rect.width()) && point.y()>rect.y() && point.y()<(rect.y()+rect.height())){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::_hitAppBar(){
|
||||||
|
foreach (auto item, _hitTestList) {
|
||||||
|
if(_containsCursorToItem(item)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_containsCursorToItem(_appbar)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::_hitMaximizeButton(){
|
||||||
|
if(_containsCursorToItem(_maximizeButton)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::_updateCursor(int edges){
|
||||||
|
switch (edges) {
|
||||||
|
case 0:
|
||||||
|
window()->setCursor(Qt::ArrowCursor);
|
||||||
|
break;
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
case Qt::RightEdge:
|
||||||
|
window()->setCursor(Qt::SizeHorCursor);
|
||||||
|
break;
|
||||||
|
case Qt::TopEdge:
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
window()->setCursor(Qt::SizeVerCursor);
|
||||||
|
break;
|
||||||
|
case Qt::LeftEdge | Qt::TopEdge:
|
||||||
|
case Qt::RightEdge | Qt::BottomEdge:
|
||||||
|
window()->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
break;
|
||||||
|
case Qt::RightEdge | Qt::TopEdge:
|
||||||
|
case Qt::LeftEdge | Qt::BottomEdge:
|
||||||
|
window()->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::showFullScreen(){
|
||||||
|
window()->showFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::showMaximized(){
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||||
|
::ShowWindow(hwnd,3);
|
||||||
|
#else
|
||||||
|
window()->showMaximized();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::showMinimized(){
|
||||||
|
window()->showMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::showNormal(){
|
||||||
|
window()->showNormal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluFrameless::setHitTestVisible(QQuickItem* val){
|
||||||
|
_hitTestList.append(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FluFrameless::_setWindowTopmost(bool topmost){
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(window()->winId());
|
||||||
|
if(topmost){
|
||||||
|
::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}else{
|
||||||
|
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
window()->setFlag(Qt::WindowStaysOnTopHint,topmost);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev){
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
switch (ev->type()) {
|
||||||
|
case QEvent::MouseButtonPress:
|
||||||
|
if(_edges!=0){
|
||||||
|
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
||||||
|
if(event->button() == Qt::LeftButton){
|
||||||
|
_updateCursor(_edges);
|
||||||
|
window()->startSystemResize(Qt::Edges(_edges));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(_hitAppBar()){
|
||||||
|
window()->startSystemMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QEvent::MouseButtonRelease:
|
||||||
|
_edges = 0;
|
||||||
|
break;
|
||||||
|
case QEvent::MouseMove: {
|
||||||
|
if(_isMaximized() || _isFullScreen()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(_fixSize){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
||||||
|
QPoint p =
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
||||||
|
event->pos();
|
||||||
|
#else
|
||||||
|
event->position().toPoint();
|
||||||
|
#endif
|
||||||
|
if(p.x() >= _margins && p.x() <= (window()->width() - _margins) && p.y() >= _margins && p.y() <= (window()->height() - _margins)){
|
||||||
|
if(_edges != 0){
|
||||||
|
_edges = 0;
|
||||||
|
_updateCursor(_edges);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_edges = 0;
|
||||||
|
if ( p.x() < _margins ) {
|
||||||
|
_edges |= Qt::LeftEdge;
|
||||||
|
}
|
||||||
|
if ( p.x() > (window()->width() - _margins) ) {
|
||||||
|
_edges |= Qt::RightEdge;
|
||||||
|
}
|
||||||
|
if ( p.y() < _margins ) {
|
||||||
|
_edges |= Qt::TopEdge;
|
||||||
|
}
|
||||||
|
if ( p.y() > (window()->height() - _margins) ) {
|
||||||
|
_edges |= Qt::BottomEdge;
|
||||||
|
}
|
||||||
|
_updateCursor(_edges);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return QObject::eventFilter(obj, ev);
|
||||||
|
}
|
58
src/FluFrameless.h
Normal file
58
src/FluFrameless.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef FLUFRAMELESS_H
|
||||||
|
#define FLUFRAMELESS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
|
||||||
|
using QT_ENTER_EVENT_TYPE = QEnterEvent;
|
||||||
|
#else
|
||||||
|
using QT_NATIVE_EVENT_RESULT_TYPE = long;
|
||||||
|
using QT_ENTER_EVENT_TYPE = QEvent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class FluFrameless : public QQuickItem,QAbstractNativeEventFilter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY_AUTO(QQuickItem*,appbar)
|
||||||
|
Q_PROPERTY_AUTO(bool,topmost)
|
||||||
|
Q_PROPERTY_AUTO(QQuickItem*,maximizeButton)
|
||||||
|
Q_PROPERTY_AUTO(QQuickItem*,minimizedButton)
|
||||||
|
Q_PROPERTY_AUTO(QQuickItem*,closeButton)
|
||||||
|
Q_PROPERTY_AUTO(bool,disabled)
|
||||||
|
Q_PROPERTY_AUTO(bool,fixSize)
|
||||||
|
QML_NAMED_ELEMENT(FluFrameless)
|
||||||
|
public:
|
||||||
|
explicit FluFrameless(QQuickItem* parent = nullptr);
|
||||||
|
~FluFrameless();
|
||||||
|
void componentComplete() override;
|
||||||
|
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||||
|
Q_INVOKABLE void showFullScreen();
|
||||||
|
Q_INVOKABLE void showMaximized();
|
||||||
|
Q_INVOKABLE void showMinimized();
|
||||||
|
Q_INVOKABLE void showNormal();
|
||||||
|
Q_INVOKABLE void setHitTestVisible(QQuickItem*);
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
private:
|
||||||
|
bool _isFullScreen();
|
||||||
|
bool _isMaximized();
|
||||||
|
void _updateCursor(int edges);
|
||||||
|
void _setWindowTopmost(bool topmost);
|
||||||
|
void _showSystemMenu(QPoint point);
|
||||||
|
bool _containsCursorToItem(QQuickItem* item);
|
||||||
|
bool _hitAppBar();
|
||||||
|
bool _hitMaximizeButton();
|
||||||
|
qint64 _current;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _edges = 0;
|
||||||
|
int _margins = 8;
|
||||||
|
QList<QPointer<QQuickItem>> _hitTestList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FLUFRAMELESS_H
|
@ -1,493 +0,0 @@
|
|||||||
#include "FluFramelessHelper.h"
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QScreen>
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include "FluTools.h"
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#pragma comment (lib,"user32.lib")
|
|
||||||
#pragma comment (lib,"dwmapi.lib")
|
|
||||||
#include <windows.h>
|
|
||||||
#include <windowsx.h>
|
|
||||||
#include <dwmapi.h>
|
|
||||||
|
|
||||||
static inline QByteArray qtNativeEventType()
|
|
||||||
{
|
|
||||||
static const auto result = "windows_generic_MSG";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool isCompositionEnabled(){
|
|
||||||
typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
|
|
||||||
HMODULE module = ::LoadLibraryW(L"dwmapi.dll");
|
|
||||||
if (module)
|
|
||||||
{
|
|
||||||
BOOL composition_enabled = false;
|
|
||||||
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
|
|
||||||
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(::GetProcAddress(module, "DwmIsCompositionEnabled"));
|
|
||||||
if (dwm_is_composition_enabled)
|
|
||||||
{
|
|
||||||
dwm_is_composition_enabled(&composition_enabled);
|
|
||||||
}
|
|
||||||
return composition_enabled;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FramelessEventFilter::FramelessEventFilter(FluFramelessHelper* helper){
|
|
||||||
_helper = helper;
|
|
||||||
_current = _helper->window_->winId();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if ((eventType != qtNativeEventType()) || !message || _helper.isNull() || _helper->window_.isNull()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto msg = static_cast<const MSG *>(message);
|
|
||||||
const HWND hwnd = msg->hwnd;
|
|
||||||
if (!hwnd || !msg) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const qint64 wid = reinterpret_cast<qint64>(hwnd);
|
|
||||||
if(wid != _current){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const UINT uMsg = msg->message;
|
|
||||||
const WPARAM wParam = msg->wParam;
|
|
||||||
const LPARAM lParam = msg->lParam;
|
|
||||||
static QPoint offsetXY;
|
|
||||||
if(uMsg == WM_WINDOWPOSCHANGING){
|
|
||||||
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
|
|
||||||
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
|
|
||||||
{
|
|
||||||
wp->flags |= SWP_NOCOPYBITS;
|
|
||||||
*result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}else if(uMsg == WM_NCCALCSIZE){
|
|
||||||
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
|
||||||
const LONG originalTop = clientRect->top;
|
|
||||||
const LONG originalLeft = clientRect->left;
|
|
||||||
const LONG originalRight = clientRect->right;
|
|
||||||
const LONG originalBottom = clientRect->bottom;
|
|
||||||
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
|
||||||
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
|
|
||||||
*result = hitTestResult;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int offsetSize = 0;
|
|
||||||
bool isMaximum = ::IsZoomed(hwnd);
|
|
||||||
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
|
|
||||||
if(isMaximum || _helper->fullScreen()){
|
|
||||||
offsetSize = 0;
|
|
||||||
}else{
|
|
||||||
offsetSize = 1;
|
|
||||||
}
|
|
||||||
if(!isCompositionEnabled()){
|
|
||||||
offsetSize = 0;
|
|
||||||
}
|
|
||||||
if (!isMaximum || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) {
|
|
||||||
clientRect->top = originalTop + offsetSize;
|
|
||||||
clientRect->bottom = originalBottom - offsetSize;
|
|
||||||
clientRect->left = originalLeft + offsetSize;
|
|
||||||
clientRect->right = originalRight - offsetSize;
|
|
||||||
}
|
|
||||||
*result = WVR_REDRAW;
|
|
||||||
return true;
|
|
||||||
}if(uMsg == WM_NCHITTEST){
|
|
||||||
if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){
|
|
||||||
if (*result == HTNOWHERE) {
|
|
||||||
*result = HTZOOM;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*result = 0;
|
|
||||||
POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
|
||||||
POINT nativeLocalPos = nativeGlobalPos;
|
|
||||||
::ScreenToClient(hwnd, &nativeLocalPos);
|
|
||||||
RECT clientRect{0, 0, 0, 0};
|
|
||||||
::GetClientRect(hwnd, &clientRect);
|
|
||||||
auto clientWidth = clientRect.right-clientRect.left;
|
|
||||||
auto clientHeight = clientRect.bottom-clientRect.top;
|
|
||||||
int margins = _helper->getMargins();
|
|
||||||
bool left = nativeLocalPos.x < margins;
|
|
||||||
bool right = nativeLocalPos.x > clientWidth - margins;
|
|
||||||
bool top = nativeLocalPos.y < margins;
|
|
||||||
bool bottom = nativeLocalPos.y > clientHeight - margins;
|
|
||||||
*result = 0;
|
|
||||||
if (_helper->resizeable() && !_helper->fullScreen() && !_helper->maximized()) {
|
|
||||||
if (left && top) {
|
|
||||||
*result = HTTOPLEFT;
|
|
||||||
} else if (left && bottom) {
|
|
||||||
*result = HTBOTTOMLEFT;
|
|
||||||
} else if (right && top) {
|
|
||||||
*result = HTTOPRIGHT;
|
|
||||||
} else if (right && bottom) {
|
|
||||||
*result = HTBOTTOMRIGHT;
|
|
||||||
} else if (left) {
|
|
||||||
*result = HTLEFT;
|
|
||||||
} else if (right) {
|
|
||||||
*result = HTRIGHT;
|
|
||||||
} else if (top) {
|
|
||||||
*result = HTTOP;
|
|
||||||
} else if (bottom) {
|
|
||||||
*result = HTBOTTOM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (0 != *result) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
QVariant appBar = _helper->getAppBar();
|
|
||||||
if(!appBar.isNull()&& _helper->hoverAppBar()){
|
|
||||||
*result = HTCAPTION;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*result = HTCLIENT;
|
|
||||||
return true;
|
|
||||||
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
|
|
||||||
if(_helper->hoverMaxBtn()){
|
|
||||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
|
||||||
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
|
|
||||||
if(_helper->hoverMaxBtn()){
|
|
||||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
|
||||||
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
|
|
||||||
}
|
|
||||||
}else if(uMsg == WM_NCPAINT){
|
|
||||||
*result = FALSE;
|
|
||||||
return true;
|
|
||||||
}else if(uMsg == WM_NCACTIVATE){
|
|
||||||
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
|
|
||||||
return true;
|
|
||||||
}else if(uMsg == WM_GETMINMAXINFO){
|
|
||||||
MINMAXINFO* minmaxInfo = reinterpret_cast<MINMAXINFO *>(lParam);
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
|
||||||
minmaxInfo->ptMaxPosition.x = 0;
|
|
||||||
minmaxInfo->ptMaxPosition.y = 0;
|
|
||||||
minmaxInfo->ptMaxSize.x = 0;
|
|
||||||
minmaxInfo->ptMaxSize.y = 0;
|
|
||||||
#else
|
|
||||||
auto pixelRatio = _helper->window_->devicePixelRatio();
|
|
||||||
auto geometry = _helper->window_->screen()->availableGeometry();
|
|
||||||
RECT rect;
|
|
||||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
|
||||||
minmaxInfo->ptMaxPosition.x = rect.left - offsetXY.x();
|
|
||||||
minmaxInfo->ptMaxPosition.y = rect.top - offsetXY.x();
|
|
||||||
minmaxInfo->ptMaxSize.x = geometry.width()*pixelRatio + offsetXY.x() * 2;
|
|
||||||
minmaxInfo->ptMaxSize.y = geometry.height()*pixelRatio + offsetXY.y() * 2;
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}else if(uMsg == WM_NCRBUTTONDOWN){
|
|
||||||
if (wParam == HTCAPTION) {
|
|
||||||
_helper->showSystemMenu(QCursor::pos());
|
|
||||||
}
|
|
||||||
}else if(uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN){
|
|
||||||
const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
|
|
||||||
const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
|
|
||||||
if (altPressed && spacePressed) {
|
|
||||||
auto pos = _helper->window_->position();
|
|
||||||
_helper->showSystemMenu(QPoint(pos.x(),pos.y()+_helper->getAppBarHeight()));
|
|
||||||
}
|
|
||||||
}else if(uMsg == WM_SYSCOMMAND){
|
|
||||||
if(wParam == SC_MINIMIZE){
|
|
||||||
if(_helper->window_->transientParent()){
|
|
||||||
_helper->window_->transientParent()->showMinimized();
|
|
||||||
}else{
|
|
||||||
_helper->window_->showMinimized();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FluFramelessHelper::FluFramelessHelper(QQuickItem *parent)
|
|
||||||
: QQuickItem{parent}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::classBegin(){
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::_updateCursor(int edges){
|
|
||||||
switch (edges) {
|
|
||||||
case 0:
|
|
||||||
window_->setCursor(Qt::ArrowCursor);
|
|
||||||
break;
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
case Qt::RightEdge:
|
|
||||||
window_->setCursor(Qt::SizeHorCursor);
|
|
||||||
break;
|
|
||||||
case Qt::TopEdge:
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
window_->setCursor(Qt::SizeVerCursor);
|
|
||||||
break;
|
|
||||||
case Qt::LeftEdge | Qt::TopEdge:
|
|
||||||
case Qt::RightEdge | Qt::BottomEdge:
|
|
||||||
window_->setCursor(Qt::SizeFDiagCursor);
|
|
||||||
break;
|
|
||||||
case Qt::RightEdge | Qt::TopEdge:
|
|
||||||
case Qt::LeftEdge | Qt::BottomEdge:
|
|
||||||
window_->setCursor(Qt::SizeBDiagCursor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
|
|
||||||
if (!window_.isNull() && window_->flags()) {
|
|
||||||
switch (ev->type()) {
|
|
||||||
case QEvent::MouseButtonPress:
|
|
||||||
if(_edges!=0){
|
|
||||||
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
|
||||||
if(event->button() == Qt::LeftButton){
|
|
||||||
_updateCursor(_edges);
|
|
||||||
window_->startSystemResize(Qt::Edges(_edges));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QEvent::MouseButtonRelease:
|
|
||||||
_edges = 0;
|
|
||||||
break;
|
|
||||||
case QEvent::MouseMove: {
|
|
||||||
if(maximized() || fullScreen()){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!resizeable()){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
|
||||||
QPoint p =
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
|
||||||
event->pos();
|
|
||||||
#else
|
|
||||||
event->position().toPoint();
|
|
||||||
#endif
|
|
||||||
if(p.x() >= _margins && p.x() <= (window_->width() - _margins) && p.y() >= _margins && p.y() <= (window_->height() - _margins)){
|
|
||||||
if(_edges != 0){
|
|
||||||
_edges = 0;
|
|
||||||
_updateCursor(_edges);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_edges = 0;
|
|
||||||
if ( p.x() < _margins ) {
|
|
||||||
_edges |= Qt::LeftEdge;
|
|
||||||
}
|
|
||||||
if ( p.x() > (window_->width() - _margins) ) {
|
|
||||||
_edges |= Qt::RightEdge;
|
|
||||||
}
|
|
||||||
if ( p.y() < _margins ) {
|
|
||||||
_edges |= Qt::TopEdge;
|
|
||||||
}
|
|
||||||
if ( p.y() > (window_->height() - _margins) ) {
|
|
||||||
_edges |= Qt::BottomEdge;
|
|
||||||
}
|
|
||||||
_updateCursor(_edges);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QObject::eventFilter(obj, ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::componentComplete(){
|
|
||||||
this->window_ = window();
|
|
||||||
if(!window_.isNull()){
|
|
||||||
_stayTop = QQmlProperty(window_,"stayTop");
|
|
||||||
_screen = QQmlProperty(window_,"screen");
|
|
||||||
_fixSize = QQmlProperty(window_,"fixSize");
|
|
||||||
_realHeight = QQmlProperty(window_,"_realHeight");
|
|
||||||
_realWidth = QQmlProperty(window_,"_realWidth");
|
|
||||||
_appBarHeight = QQmlProperty(window_,"_appBarHeight");
|
|
||||||
_appBar = window_->property("appBar");
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if(!_appBar.isNull()){
|
|
||||||
_appBar.value<QObject*>()->setProperty("systemMoveEnable",false);
|
|
||||||
}
|
|
||||||
window_->setFlags((window_->flags()) | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::FramelessWindowHint);
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
|
||||||
if(FluTools::getInstance()->isSoftware()){
|
|
||||||
window_->setFlag(Qt::FramelessWindowHint,false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(resizeable()){
|
|
||||||
window_->setFlag(Qt::WindowMaximizeButtonHint);
|
|
||||||
}
|
|
||||||
_nativeEvent =new FramelessEventFilter(this);
|
|
||||||
qApp->installNativeEventFilter(_nativeEvent);
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(window_->winId());
|
|
||||||
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
|
|
||||||
if(resizeable()){
|
|
||||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
|
|
||||||
}else{
|
|
||||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME);
|
|
||||||
for (int i = 0; i < qApp->screens().count(); ++i) {
|
|
||||||
connect( qApp->screens().at(i),&QScreen::logicalDotsPerInchChanged,this,[=]{
|
|
||||||
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
|
||||||
#else
|
|
||||||
window_->setFlags((window_->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window);
|
|
||||||
window_->installEventFilter(this);
|
|
||||||
#endif
|
|
||||||
int w = _realWidth.read().toInt();
|
|
||||||
int h = _realHeight.read().toInt()+_appBarHeight.read().toInt();
|
|
||||||
if(!resizeable()){
|
|
||||||
window_->setMaximumSize(QSize(w,h));
|
|
||||||
window_->setMinimumSize(QSize(w,h));
|
|
||||||
}
|
|
||||||
window_->resize(QSize(w,h));
|
|
||||||
_onStayTopChange();
|
|
||||||
_stayTop.connectNotifySignal(this,SLOT(_onStayTopChange()));
|
|
||||||
_screen.connectNotifySignal(this,SLOT(_onScreenChanged()));
|
|
||||||
Q_EMIT loadCompleted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::_onScreenChanged(){
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(window_->winId());
|
|
||||||
::SetWindowPos(hwnd,0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
|
||||||
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::showSystemMenu(QPoint point){
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(window_->winId());
|
|
||||||
DWORD style = ::GetWindowLongPtr(hwnd,GWL_STYLE);
|
|
||||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
|
|
||||||
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
|
|
||||||
if(maximized() || fullScreen()){
|
|
||||||
::EnableMenuItem(hMenu,SC_MOVE,MFS_DISABLED);
|
|
||||||
::EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
|
|
||||||
}else{
|
|
||||||
::EnableMenuItem(hMenu,SC_MOVE,MFS_ENABLED);
|
|
||||||
::EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
|
|
||||||
}
|
|
||||||
if(resizeable() && !maximized() && !fullScreen()){
|
|
||||||
::EnableMenuItem(hMenu,SC_SIZE,MFS_ENABLED);
|
|
||||||
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
|
|
||||||
}else{
|
|
||||||
::EnableMenuItem(hMenu,SC_SIZE,MFS_DISABLED);
|
|
||||||
::EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_DISABLED);
|
|
||||||
}
|
|
||||||
const int result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), point.x()*window_->devicePixelRatio(), point.y()*window_->devicePixelRatio(), 0, hwnd, nullptr);
|
|
||||||
if (result != FALSE) {
|
|
||||||
::PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
|
|
||||||
}
|
|
||||||
::SetWindowLongPtr(hwnd, GWL_STYLE, style &~ WS_SYSMENU);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::showMaximized(){
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(window_->winId());
|
|
||||||
::ShowWindow(hwnd,3);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FluFramelessHelper::_onStayTopChange(){
|
|
||||||
bool isStayTop = _stayTop.read().toBool();
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
HWND hwnd = reinterpret_cast<HWND>(window_->winId());
|
|
||||||
if(isStayTop){
|
|
||||||
::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}else{
|
|
||||||
::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
window_->setFlag(Qt::WindowStaysOnTopHint,isStayTop);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
FluFramelessHelper::~FluFramelessHelper(){
|
|
||||||
if (!window_.isNull()) {
|
|
||||||
window_->setFlags(Qt::Window);
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
qApp->removeNativeEventFilter(_nativeEvent);
|
|
||||||
delete _nativeEvent;
|
|
||||||
#endif
|
|
||||||
window_->removeEventFilter(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::hoverMaxBtn(){
|
|
||||||
if(_appBar.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QVariant var;
|
|
||||||
QMetaObject::invokeMethod(_appBar.value<QObject*>(), "_maximizeButtonHover",Q_RETURN_ARG(QVariant, var));
|
|
||||||
if(var.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return var.toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::hoverAppBar(){
|
|
||||||
if(_appBar.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QVariant var;
|
|
||||||
QMetaObject::invokeMethod(_appBar.value<QObject*>(), "_appBarHover",Q_RETURN_ARG(QVariant, var));
|
|
||||||
if(var.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return var.toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant FluFramelessHelper::getAppBar(){
|
|
||||||
return _appBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FluFramelessHelper::getAppBarHeight(){
|
|
||||||
if(_appBar.isNull()){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
QVariant var = _appBar.value<QObject*>()->property("height");
|
|
||||||
if(var.isNull()){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return var.toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject* FluFramelessHelper::maximizeButton(){
|
|
||||||
if(_appBar.isNull()){
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
QVariant var = _appBar.value<QObject*>()->property("buttonMaximize");
|
|
||||||
if(var.isNull()){
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return var.value<QObject*>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::resizeable(){
|
|
||||||
return !_fixSize.read().toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::maximized(){
|
|
||||||
return window_->visibility() == QWindow::Maximized;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FluFramelessHelper::fullScreen(){
|
|
||||||
return window_->visibility() == QWindow::FullScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FluFramelessHelper::getMargins(){
|
|
||||||
return _margins;
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
#ifndef FLUFRAMELESSHELPER_H
|
|
||||||
#define FLUFRAMELESSHELPER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QQuickWindow>
|
|
||||||
#include <QtQml/qqml.h>
|
|
||||||
#include <QAbstractNativeEventFilter>
|
|
||||||
#include <QQmlProperty>
|
|
||||||
#include <QQuickItem>
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
||||||
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
|
|
||||||
using QT_ENTER_EVENT_TYPE = QEnterEvent;
|
|
||||||
#else
|
|
||||||
using QT_NATIVE_EVENT_RESULT_TYPE = long;
|
|
||||||
using QT_ENTER_EVENT_TYPE = QEvent;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class FluFramelessHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The FramelessEventFilter class
|
|
||||||
*/
|
|
||||||
class FramelessEventFilter : public QAbstractNativeEventFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FramelessEventFilter(FluFramelessHelper* helper);
|
|
||||||
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
|
||||||
public:
|
|
||||||
QPointer<FluFramelessHelper> _helper = nullptr;
|
|
||||||
qint64 _current = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The FluFramelessHelper class
|
|
||||||
*/
|
|
||||||
class FluFramelessHelper : public QQuickItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
QML_NAMED_ELEMENT(FluFramelessHelper)
|
|
||||||
public:
|
|
||||||
explicit FluFramelessHelper(QQuickItem *parent = nullptr);
|
|
||||||
~FluFramelessHelper();
|
|
||||||
void classBegin() override;
|
|
||||||
void componentComplete() override;
|
|
||||||
bool hoverMaxBtn();
|
|
||||||
bool hoverAppBar();
|
|
||||||
bool resizeable();
|
|
||||||
int getMargins();
|
|
||||||
bool maximized();
|
|
||||||
bool fullScreen();
|
|
||||||
int getAppBarHeight();
|
|
||||||
QVariant getAppBar();
|
|
||||||
QObject* maximizeButton();
|
|
||||||
Q_INVOKABLE void showSystemMenu(QPoint point);
|
|
||||||
Q_INVOKABLE void showMaximized();
|
|
||||||
Q_SIGNAL void loadCompleted();
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
|
||||||
private:
|
|
||||||
void _updateCursor(int edges);
|
|
||||||
Q_SLOT void _onStayTopChange();
|
|
||||||
Q_SLOT void _onScreenChanged();
|
|
||||||
public:
|
|
||||||
QPointer<QQuickWindow> window_ = nullptr;
|
|
||||||
private:
|
|
||||||
FramelessEventFilter* _nativeEvent = nullptr;
|
|
||||||
QQmlProperty _stayTop;
|
|
||||||
QQmlProperty _screen;
|
|
||||||
QQmlProperty _fixSize;
|
|
||||||
QQmlProperty _realHeight;
|
|
||||||
QQmlProperty _realWidth;
|
|
||||||
QQmlProperty _appBarHeight;
|
|
||||||
QVariant _appBar;
|
|
||||||
int _edges = 0;
|
|
||||||
int _margins = 8;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FLUFRAMELESSHELPER_H
|
|
@ -11,9 +11,9 @@
|
|||||||
#include "FluCaptcha.h"
|
#include "FluCaptcha.h"
|
||||||
#include "FluTreeModel.h"
|
#include "FluTreeModel.h"
|
||||||
#include "FluRectangle.h"
|
#include "FluRectangle.h"
|
||||||
#include "FluFramelessHelper.h"
|
|
||||||
#include "FluQrCodeItem.h"
|
#include "FluQrCodeItem.h"
|
||||||
#include "FluTableSortProxyModel.h"
|
#include "FluTableSortProxyModel.h"
|
||||||
|
#include "FluFrameless.h"
|
||||||
|
|
||||||
void FluentUI::registerTypes(QQmlEngine *engine){
|
void FluentUI::registerTypes(QQmlEngine *engine){
|
||||||
initializeEngine(engine,uri);
|
initializeEngine(engine,uri);
|
||||||
@ -31,7 +31,7 @@ void FluentUI::registerTypes(const char *uri){
|
|||||||
qmlRegisterType<FluAccentColor>(uri,major,minor,"FluAccentColor");
|
qmlRegisterType<FluAccentColor>(uri,major,minor,"FluAccentColor");
|
||||||
qmlRegisterType<FluTreeModel>(uri,major,minor,"FluTreeModel");
|
qmlRegisterType<FluTreeModel>(uri,major,minor,"FluTreeModel");
|
||||||
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
|
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
|
||||||
qmlRegisterType<FluFramelessHelper>(uri,major,minor,"FluFramelessHelper");
|
qmlRegisterType<FluFrameless>(uri,major,minor,"FluFrameless");
|
||||||
qmlRegisterType<FluTableSortProxyModel>(uri,major,minor,"FluTableSortProxyModel");
|
qmlRegisterType<FluTableSortProxyModel>(uri,major,minor,"FluTableSortProxyModel");
|
||||||
|
|
||||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"),uri,major,minor,"FluAcrylic");
|
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"),uri,major,minor,"FluAcrylic");
|
||||||
|
@ -34,7 +34,13 @@ Rectangle{
|
|||||||
property int iconSize: 20
|
property int iconSize: 20
|
||||||
property bool isMac: FluTools.isMacos()
|
property bool isMac: FluTools.isMacos()
|
||||||
property color borerlessColor : FluTheme.primaryColor
|
property color borerlessColor : FluTheme.primaryColor
|
||||||
property bool systemMoveEnable: true
|
property alias buttonStayTop: btn_stay_top
|
||||||
|
property alias buttonMinimize: btn_minimize
|
||||||
|
property alias buttonMaximize: btn_maximize
|
||||||
|
property alias buttonClose: btn_close
|
||||||
|
property alias buttonDark: btn_dark
|
||||||
|
property alias layoutMacosButtons: layout_macos_buttons
|
||||||
|
property alias layoutStandardbuttons: layout_standard_buttons
|
||||||
property var maxClickListener : function(){
|
property var maxClickListener : function(){
|
||||||
if(FluTools.isMacos()){
|
if(FluTools.isMacos()){
|
||||||
if (d.win.visibility === Window.FullScreen)
|
if (d.win.visibility === Window.FullScreen)
|
||||||
@ -71,16 +77,6 @@ Rectangle{
|
|||||||
FluTheme.darkMode = FluThemeType.Dark
|
FluTheme.darkMode = FluThemeType.Dark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property var systemMenuListener: function(){
|
|
||||||
if(d.win instanceof FluWindow){
|
|
||||||
d.win.showSystemMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property alias buttonStayTop: btn_stay_top
|
|
||||||
property alias buttonMinimize: btn_minimize
|
|
||||||
property alias buttonMaximize: btn_maximize
|
|
||||||
property alias buttonClose: btn_close
|
|
||||||
property alias buttonDark: btn_dark
|
|
||||||
id:control
|
id:control
|
||||||
color: Qt.rgba(0,0,0,0)
|
color: Qt.rgba(0,0,0,0)
|
||||||
height: visible ? 30 : 0
|
height: visible ? 30 : 0
|
||||||
@ -108,29 +104,6 @@ Rectangle{
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseArea{
|
|
||||||
id:mouse_app_bar
|
|
||||||
anchors.fill: parent
|
|
||||||
onPositionChanged:
|
|
||||||
(mouse)=>{
|
|
||||||
if(systemMoveEnable){
|
|
||||||
d.win.startSystemMove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDoubleClicked:
|
|
||||||
(mouse)=>{
|
|
||||||
if(systemMoveEnable && d.resizable && Qt.LeftButton){
|
|
||||||
btn_maximize.clicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acceptedButtons: Qt.LeftButton|Qt.RightButton
|
|
||||||
onClicked:
|
|
||||||
(mouse)=>{
|
|
||||||
if (systemMoveEnable && mouse.button === Qt.RightButton){
|
|
||||||
control.systemMenuListener()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row{
|
Row{
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
@ -153,9 +126,8 @@ Rectangle{
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component{
|
Component{
|
||||||
id:com_mac_buttons
|
id:com_macos_buttons
|
||||||
RowLayout{
|
RowLayout{
|
||||||
FluImageButton{
|
FluImageButton{
|
||||||
Layout.preferredHeight: 12
|
Layout.preferredHeight: 12
|
||||||
@ -186,24 +158,11 @@ Rectangle{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluLoader{
|
|
||||||
anchors{
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 10
|
|
||||||
}
|
|
||||||
sourceComponent: isMac ? com_mac_buttons : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout{
|
RowLayout{
|
||||||
id:layout_row
|
id:layout_standard_buttons
|
||||||
|
height: parent.height
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
height: control.height
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Component.onCompleted: {
|
|
||||||
setHitTestVisible(layout_row)
|
|
||||||
}
|
|
||||||
FluIconButton{
|
FluIconButton{
|
||||||
id:btn_dark
|
id:btn_dark
|
||||||
Layout.preferredWidth: 40
|
Layout.preferredWidth: 40
|
||||||
@ -273,12 +232,9 @@ Rectangle{
|
|||||||
horizontalPadding: 0
|
horizontalPadding: 0
|
||||||
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
|
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
|
||||||
color: {
|
color: {
|
||||||
if(down){
|
if(pressed){
|
||||||
return maximizePressColor
|
return maximizePressColor
|
||||||
}
|
}
|
||||||
if(FluTools.isWindows11OrGreater()){
|
|
||||||
return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor
|
|
||||||
}
|
|
||||||
return hovered ? maximizeHoverColor : maximizeNormalColor
|
return hovered ? maximizeHoverColor : maximizeNormalColor
|
||||||
}
|
}
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
@ -312,36 +268,13 @@ Rectangle{
|
|||||||
onClicked: closeClickListener()
|
onClicked: closeClickListener()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function _maximizeButtonHover(){
|
FluLoader{
|
||||||
var hover = false
|
id:layout_macos_buttons
|
||||||
if(btn_maximize.visible && FluTools.isWindows11OrGreater() && d.resizable){
|
anchors{
|
||||||
if(d.containsPointToItem(FluTools.cursorPos(),btn_maximize)){
|
verticalCenter: parent.verticalCenter
|
||||||
hover = true
|
left: parent.left
|
||||||
}else{
|
leftMargin: 10
|
||||||
if(btn_maximize.down){
|
|
||||||
btn_maximize.down = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
d.hoverMaxBtn = hover
|
sourceComponent: isMac ? com_macos_buttons : undefined
|
||||||
return hover;
|
|
||||||
}
|
|
||||||
function _appBarHover(){
|
|
||||||
var cursorPos = FluTools.cursorPos()
|
|
||||||
for(var i =0 ;i< d.hitTestList.length; i++){
|
|
||||||
var item = d.hitTestList[i]
|
|
||||||
if(item.visible){
|
|
||||||
if(d.containsPointToItem(cursorPos,item)){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(d.containsPointToItem(cursorPos,control)){
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
function setHitTestVisible(id){
|
|
||||||
d.hitTestList.push(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,29 +56,20 @@ Window {
|
|||||||
event.accepted = false
|
event.accepted = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal showSystemMenu
|
|
||||||
signal initArgument(var argument)
|
signal initArgument(var argument)
|
||||||
signal firstVisible()
|
signal lazyLoad()
|
||||||
property int _realHeight
|
|
||||||
property int _realWidth
|
|
||||||
property int _appBarHeight: appBar.height
|
|
||||||
property var _windowRegister
|
property var _windowRegister
|
||||||
property string _route
|
property string _route
|
||||||
id:window
|
id:window
|
||||||
color:"transparent"
|
color:"transparent"
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluRouter.addWindow(window)
|
FluRouter.addWindow(window)
|
||||||
_realHeight = height
|
|
||||||
_realWidth = width
|
|
||||||
useSystemAppBar = FluApp.useSystemAppBar
|
useSystemAppBar = FluApp.useSystemAppBar
|
||||||
if(useSystemAppBar && autoCenter){
|
if(useSystemAppBar && autoCenter){
|
||||||
moveWindowToDesktopCenter()
|
moveWindowToDesktopCenter()
|
||||||
}
|
}
|
||||||
fixWindowSize()
|
fixWindowSize()
|
||||||
initArgument(argument)
|
initArgument(argument)
|
||||||
if(!useSystemAppBar){
|
|
||||||
loader_frameless_helper.sourceComponent = com_frameless_helper
|
|
||||||
}
|
|
||||||
if(window.autoVisible){
|
if(window.autoVisible){
|
||||||
if(window.autoMaximize){
|
if(window.autoMaximize){
|
||||||
window.showMaximized()
|
window.showMaximized()
|
||||||
@ -87,33 +78,30 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onShowSystemMenu: {
|
|
||||||
if(loader_frameless_helper.item){
|
|
||||||
loader_frameless_helper.item.showSystemMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if(visible && d.isFirstVisible){
|
if(visible && d.isLazyInit){
|
||||||
window.firstVisible()
|
window.lazyLoad()
|
||||||
d.isFirstVisible = false
|
d.isLazyInit = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QtObject{
|
QtObject{
|
||||||
id:d
|
id:d
|
||||||
property bool isFirstVisible: true
|
property bool isLazyInit: true
|
||||||
}
|
}
|
||||||
Connections{
|
Connections{
|
||||||
target: window
|
target: window
|
||||||
function onClosing(event){closeListener(event)}
|
function onClosing(event){closeListener(event)}
|
||||||
}
|
}
|
||||||
Component{
|
FluFrameless{
|
||||||
id:com_frameless_helper
|
id: frameless
|
||||||
FluFramelessHelper{
|
appbar: window.appBar
|
||||||
onLoadCompleted:{
|
maximizeButton: appBar.buttonMaximize
|
||||||
if(autoCenter){
|
fixSize: window.fixSize
|
||||||
window.moveWindowToDesktopCenter()
|
topmost: window.stayTop
|
||||||
}
|
disabled: FluApp.useSystemAppBar
|
||||||
}
|
Component.onCompleted: {
|
||||||
|
frameless.setHitTestVisible(appBar.layoutMacosButtons)
|
||||||
|
frameless.setHitTestVisible(appBar.layoutStandardbuttons)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component{
|
Component{
|
||||||
@ -198,9 +186,6 @@ Window {
|
|||||||
border.color: window.resizeBorderColor
|
border.color: window.resizeBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluLoader{
|
|
||||||
id:loader_frameless_helper
|
|
||||||
}
|
|
||||||
FluLoader{
|
FluLoader{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
sourceComponent: background
|
sourceComponent: background
|
||||||
@ -256,11 +241,6 @@ Window {
|
|||||||
return com_border
|
return com_border
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showLoading(text = qsTr("Loading..."),cancel = true){
|
|
||||||
loader_loading.loadingText = text
|
|
||||||
loader_loading.cancel = cancel
|
|
||||||
loader_loading.sourceComponent = com_loading
|
|
||||||
}
|
|
||||||
function hideLoading(){
|
function hideLoading(){
|
||||||
loader_loading.sourceComponent = undefined
|
loader_loading.sourceComponent = undefined
|
||||||
}
|
}
|
||||||
@ -298,12 +278,17 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showMaximized(){
|
function showMaximized(){
|
||||||
if(FluTools.isWin()){
|
frameless.showMaximized()
|
||||||
if(loader_frameless_helper.item){
|
}
|
||||||
loader_frameless_helper.item.showMaximized()
|
function showLoading(text = "",cancel = true){
|
||||||
}
|
if(text===""){
|
||||||
}else{
|
text = qsTr("Loading...")
|
||||||
window.visibility = Window.Maximized
|
|
||||||
}
|
}
|
||||||
|
loader_loading.loadingText = text
|
||||||
|
loader_loading.cancel = cancel
|
||||||
|
loader_loading.sourceComponent = com_loading
|
||||||
|
}
|
||||||
|
function setHitTestVisible(val){
|
||||||
|
frameless.setHitTestVisible(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,17 +65,26 @@ Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
name: "FluFramelessHelper"
|
name: "FluFrameless"
|
||||||
defaultProperty: "data"
|
defaultProperty: "data"
|
||||||
prototype: "QQuickItem"
|
prototype: "QQuickItem"
|
||||||
exports: ["FluentUI/FluFramelessHelper 1.0"]
|
exports: ["FluentUI/FluFrameless 1.0"]
|
||||||
exportMetaObjectRevisions: [0]
|
exportMetaObjectRevisions: [0]
|
||||||
Signal { name: "loadCompleted" }
|
Property { name: "appbar"; type: "QQuickItem"; isPointer: true }
|
||||||
Method {
|
Property { name: "topmost"; type: "bool" }
|
||||||
name: "showSystemMenu"
|
Property { name: "maximizeButton"; type: "QQuickItem"; isPointer: true }
|
||||||
Parameter { name: "point"; type: "QPoint" }
|
Property { name: "minimizedButton"; type: "QQuickItem"; isPointer: true }
|
||||||
}
|
Property { name: "closeButton"; type: "QQuickItem"; isPointer: true }
|
||||||
|
Property { name: "disabled"; type: "bool" }
|
||||||
|
Property { name: "fixSize"; type: "bool" }
|
||||||
|
Method { name: "showFullScreen" }
|
||||||
Method { name: "showMaximized" }
|
Method { name: "showMaximized" }
|
||||||
|
Method { name: "showMinimized" }
|
||||||
|
Method { name: "showNormal" }
|
||||||
|
Method {
|
||||||
|
name: "setHitTestVisible"
|
||||||
|
Parameter { type: "QQuickItem"; isPointer: true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
name: "FluNavigationViewType"
|
name: "FluNavigationViewType"
|
||||||
@ -2180,49 +2189,52 @@ Module {
|
|||||||
Property { name: "iconSize"; type: "int" }
|
Property { name: "iconSize"; type: "int" }
|
||||||
Property { name: "isMac"; type: "bool" }
|
Property { name: "isMac"; type: "bool" }
|
||||||
Property { name: "borerlessColor"; type: "QColor" }
|
Property { name: "borerlessColor"; type: "QColor" }
|
||||||
Property { name: "systemMoveEnable"; type: "bool" }
|
|
||||||
Property { name: "maxClickListener"; type: "QVariant" }
|
Property { name: "maxClickListener"; type: "QVariant" }
|
||||||
Property { name: "minClickListener"; type: "QVariant" }
|
Property { name: "minClickListener"; type: "QVariant" }
|
||||||
Property { name: "closeClickListener"; type: "QVariant" }
|
Property { name: "closeClickListener"; type: "QVariant" }
|
||||||
Property { name: "stayTopClickListener"; type: "QVariant" }
|
Property { name: "stayTopClickListener"; type: "QVariant" }
|
||||||
Property { name: "darkClickListener"; type: "QVariant" }
|
Property { name: "darkClickListener"; type: "QVariant" }
|
||||||
Property { name: "systemMenuListener"; type: "QVariant" }
|
|
||||||
Property {
|
Property {
|
||||||
name: "buttonStayTop"
|
name: "buttonStayTop"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Property {
|
Property {
|
||||||
name: "buttonMinimize"
|
name: "buttonMinimize"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Property {
|
Property {
|
||||||
name: "buttonMaximize"
|
name: "buttonMaximize"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Property {
|
Property {
|
||||||
name: "buttonClose"
|
name: "buttonClose"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Property {
|
Property {
|
||||||
name: "buttonDark"
|
name: "buttonDark"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Method { name: "_maximizeButtonHover"; type: "QVariant" }
|
Property {
|
||||||
Method { name: "_appBarHover"; type: "QVariant" }
|
name: "layoutMacosButtons"
|
||||||
Method {
|
type: "FluLoader_QMLTYPE_13"
|
||||||
name: "setHitTestVisible"
|
isReadonly: true
|
||||||
type: "QVariant"
|
isPointer: true
|
||||||
Parameter { name: "id"; type: "QVariant" }
|
}
|
||||||
|
Property {
|
||||||
|
name: "layoutStandardbuttons"
|
||||||
|
type: "QQuickRowLayout"
|
||||||
|
isReadonly: true
|
||||||
|
isPointer: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
@ -2894,15 +2906,15 @@ Module {
|
|||||||
defaultProperty: "data"
|
defaultProperty: "data"
|
||||||
Property { name: "logo"; type: "QUrl" }
|
Property { name: "logo"; type: "QUrl" }
|
||||||
Property { name: "title"; type: "string" }
|
Property { name: "title"; type: "string" }
|
||||||
Property { name: "items"; type: "FluObject_QMLTYPE_128"; isPointer: true }
|
Property { name: "items"; type: "FluObject_QMLTYPE_168"; isPointer: true }
|
||||||
Property { name: "footerItems"; type: "FluObject_QMLTYPE_128"; isPointer: true }
|
Property { name: "footerItems"; type: "FluObject_QMLTYPE_168"; isPointer: true }
|
||||||
Property { name: "displayMode"; type: "int" }
|
Property { name: "displayMode"; type: "int" }
|
||||||
Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true }
|
Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true }
|
||||||
Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true }
|
Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true }
|
||||||
Property { name: "topPadding"; type: "int" }
|
Property { name: "topPadding"; type: "int" }
|
||||||
Property { name: "pageMode"; type: "int" }
|
Property { name: "pageMode"; type: "int" }
|
||||||
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
|
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_32"; isPointer: true }
|
||||||
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
|
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_32"; isPointer: true }
|
||||||
Property { name: "navCompactWidth"; type: "int" }
|
Property { name: "navCompactWidth"; type: "int" }
|
||||||
Property { name: "navTopMargin"; type: "int" }
|
Property { name: "navTopMargin"; type: "int" }
|
||||||
Property { name: "cellHeight"; type: "int" }
|
Property { name: "cellHeight"; type: "int" }
|
||||||
@ -2910,13 +2922,13 @@ Module {
|
|||||||
Property { name: "hideNavAppBar"; type: "bool" }
|
Property { name: "hideNavAppBar"; type: "bool" }
|
||||||
Property {
|
Property {
|
||||||
name: "buttonMenu"
|
name: "buttonMenu"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
Property {
|
Property {
|
||||||
name: "buttonBack"
|
name: "buttonBack"
|
||||||
type: "FluIconButton_QMLTYPE_18"
|
type: "FluIconButton_QMLTYPE_20"
|
||||||
isReadonly: true
|
isReadonly: true
|
||||||
isPointer: true
|
isPointer: true
|
||||||
}
|
}
|
||||||
@ -3777,24 +3789,14 @@ Module {
|
|||||||
Property { name: "resizeBorderColor"; type: "QColor" }
|
Property { name: "resizeBorderColor"; type: "QColor" }
|
||||||
Property { name: "resizeBorderWidth"; type: "int" }
|
Property { name: "resizeBorderWidth"; type: "int" }
|
||||||
Property { name: "closeListener"; type: "QVariant" }
|
Property { name: "closeListener"; type: "QVariant" }
|
||||||
Property { name: "_realHeight"; type: "int" }
|
|
||||||
Property { name: "_realWidth"; type: "int" }
|
|
||||||
Property { name: "_appBarHeight"; type: "int" }
|
|
||||||
Property { name: "_windowRegister"; type: "QVariant" }
|
Property { name: "_windowRegister"; type: "QVariant" }
|
||||||
Property { name: "_route"; type: "string" }
|
Property { name: "_route"; type: "string" }
|
||||||
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
|
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
|
||||||
Signal { name: "showSystemMenu" }
|
|
||||||
Signal {
|
Signal {
|
||||||
name: "initArgument"
|
name: "initArgument"
|
||||||
Parameter { name: "argument"; type: "QVariant" }
|
Parameter { name: "argument"; type: "QVariant" }
|
||||||
}
|
}
|
||||||
Signal { name: "firstVisible" }
|
Signal { name: "lazyLoad" }
|
||||||
Method {
|
|
||||||
name: "showLoading"
|
|
||||||
type: "QVariant"
|
|
||||||
Parameter { name: "text"; type: "QVariant" }
|
|
||||||
Parameter { name: "cancel"; type: "QVariant" }
|
|
||||||
}
|
|
||||||
Method { name: "hideLoading"; type: "QVariant" }
|
Method { name: "hideLoading"; type: "QVariant" }
|
||||||
Method {
|
Method {
|
||||||
name: "showSuccess"
|
name: "showSuccess"
|
||||||
@ -3837,6 +3839,17 @@ Module {
|
|||||||
Parameter { name: "data"; type: "QVariant" }
|
Parameter { name: "data"; type: "QVariant" }
|
||||||
}
|
}
|
||||||
Method { name: "showMaximized"; type: "QVariant" }
|
Method { name: "showMaximized"; type: "QVariant" }
|
||||||
|
Method {
|
||||||
|
name: "showLoading"
|
||||||
|
type: "QVariant"
|
||||||
|
Parameter { name: "text"; type: "QVariant" }
|
||||||
|
Parameter { name: "cancel"; type: "QVariant" }
|
||||||
|
}
|
||||||
|
Method {
|
||||||
|
name: "setHitTestVisible"
|
||||||
|
type: "QVariant"
|
||||||
|
Parameter { name: "val"; type: "QVariant" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
prototype: "QQuickWindowQmlImpl"
|
prototype: "QQuickWindowQmlImpl"
|
||||||
@ -3870,24 +3883,14 @@ Module {
|
|||||||
Property { name: "resizeBorderColor"; type: "QColor" }
|
Property { name: "resizeBorderColor"; type: "QColor" }
|
||||||
Property { name: "resizeBorderWidth"; type: "int" }
|
Property { name: "resizeBorderWidth"; type: "int" }
|
||||||
Property { name: "closeListener"; type: "QVariant" }
|
Property { name: "closeListener"; type: "QVariant" }
|
||||||
Property { name: "_realHeight"; type: "int" }
|
|
||||||
Property { name: "_realWidth"; type: "int" }
|
|
||||||
Property { name: "_appBarHeight"; type: "int" }
|
|
||||||
Property { name: "_windowRegister"; type: "QVariant" }
|
Property { name: "_windowRegister"; type: "QVariant" }
|
||||||
Property { name: "_route"; type: "string" }
|
Property { name: "_route"; type: "string" }
|
||||||
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
|
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
|
||||||
Signal { name: "showSystemMenu" }
|
|
||||||
Signal {
|
Signal {
|
||||||
name: "initArgument"
|
name: "initArgument"
|
||||||
Parameter { name: "argument"; type: "QVariant" }
|
Parameter { name: "argument"; type: "QVariant" }
|
||||||
}
|
}
|
||||||
Signal { name: "firstVisible" }
|
Signal { name: "lazyLoad" }
|
||||||
Method {
|
|
||||||
name: "showLoading"
|
|
||||||
type: "QVariant"
|
|
||||||
Parameter { name: "text"; type: "QVariant" }
|
|
||||||
Parameter { name: "cancel"; type: "QVariant" }
|
|
||||||
}
|
|
||||||
Method { name: "hideLoading"; type: "QVariant" }
|
Method { name: "hideLoading"; type: "QVariant" }
|
||||||
Method {
|
Method {
|
||||||
name: "showSuccess"
|
name: "showSuccess"
|
||||||
@ -3930,6 +3933,17 @@ Module {
|
|||||||
Parameter { name: "data"; type: "QVariant" }
|
Parameter { name: "data"; type: "QVariant" }
|
||||||
}
|
}
|
||||||
Method { name: "showMaximized"; type: "QVariant" }
|
Method { name: "showMaximized"; type: "QVariant" }
|
||||||
|
Method {
|
||||||
|
name: "showLoading"
|
||||||
|
type: "QVariant"
|
||||||
|
Parameter { name: "text"; type: "QVariant" }
|
||||||
|
Parameter { name: "cancel"; type: "QVariant" }
|
||||||
|
}
|
||||||
|
Method {
|
||||||
|
name: "setHitTestVisible"
|
||||||
|
type: "QVariant"
|
||||||
|
Parameter { name: "val"; type: "QVariant" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
prototype: "QQuickItem"
|
prototype: "QQuickItem"
|
||||||
|
@ -34,7 +34,13 @@ Rectangle{
|
|||||||
property int iconSize: 20
|
property int iconSize: 20
|
||||||
property bool isMac: FluTools.isMacos()
|
property bool isMac: FluTools.isMacos()
|
||||||
property color borerlessColor : FluTheme.primaryColor
|
property color borerlessColor : FluTheme.primaryColor
|
||||||
property bool systemMoveEnable: true
|
property alias buttonStayTop: btn_stay_top
|
||||||
|
property alias buttonMinimize: btn_minimize
|
||||||
|
property alias buttonMaximize: btn_maximize
|
||||||
|
property alias buttonClose: btn_close
|
||||||
|
property alias buttonDark: btn_dark
|
||||||
|
property alias layoutMacosButtons: layout_macos_buttons
|
||||||
|
property alias layoutStandardbuttons: layout_standard_buttons
|
||||||
property var maxClickListener : function(){
|
property var maxClickListener : function(){
|
||||||
if(FluTools.isMacos()){
|
if(FluTools.isMacos()){
|
||||||
if (d.win.visibility === Window.FullScreen)
|
if (d.win.visibility === Window.FullScreen)
|
||||||
@ -71,16 +77,6 @@ Rectangle{
|
|||||||
FluTheme.darkMode = FluThemeType.Dark
|
FluTheme.darkMode = FluThemeType.Dark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property var systemMenuListener: function(){
|
|
||||||
if(d.win instanceof FluWindow){
|
|
||||||
d.win.showSystemMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property alias buttonStayTop: btn_stay_top
|
|
||||||
property alias buttonMinimize: btn_minimize
|
|
||||||
property alias buttonMaximize: btn_maximize
|
|
||||||
property alias buttonClose: btn_close
|
|
||||||
property alias buttonDark: btn_dark
|
|
||||||
id:control
|
id:control
|
||||||
color: Qt.rgba(0,0,0,0)
|
color: Qt.rgba(0,0,0,0)
|
||||||
height: visible ? 30 : 0
|
height: visible ? 30 : 0
|
||||||
@ -108,29 +104,6 @@ Rectangle{
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseArea{
|
|
||||||
id:mouse_app_bar
|
|
||||||
anchors.fill: parent
|
|
||||||
onPositionChanged:
|
|
||||||
(mouse)=>{
|
|
||||||
if(systemMoveEnable){
|
|
||||||
d.win.startSystemMove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDoubleClicked:
|
|
||||||
(mouse)=>{
|
|
||||||
if(systemMoveEnable && d.resizable && Qt.LeftButton){
|
|
||||||
btn_maximize.clicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acceptedButtons: Qt.LeftButton|Qt.RightButton
|
|
||||||
onClicked:
|
|
||||||
(mouse)=>{
|
|
||||||
if (systemMoveEnable && mouse.button === Qt.RightButton){
|
|
||||||
control.systemMenuListener()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row{
|
Row{
|
||||||
anchors{
|
anchors{
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
@ -153,9 +126,8 @@ Rectangle{
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component{
|
Component{
|
||||||
id:com_mac_buttons
|
id:com_macos_buttons
|
||||||
RowLayout{
|
RowLayout{
|
||||||
FluImageButton{
|
FluImageButton{
|
||||||
Layout.preferredHeight: 12
|
Layout.preferredHeight: 12
|
||||||
@ -186,24 +158,11 @@ Rectangle{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FluLoader{
|
|
||||||
anchors{
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 10
|
|
||||||
}
|
|
||||||
sourceComponent: isMac ? com_mac_buttons : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout{
|
RowLayout{
|
||||||
id:layout_row
|
id:layout_standard_buttons
|
||||||
|
height: parent.height
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
height: control.height
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Component.onCompleted: {
|
|
||||||
setHitTestVisible(layout_row)
|
|
||||||
}
|
|
||||||
FluIconButton{
|
FluIconButton{
|
||||||
id:btn_dark
|
id:btn_dark
|
||||||
Layout.preferredWidth: 40
|
Layout.preferredWidth: 40
|
||||||
@ -273,12 +232,9 @@ Rectangle{
|
|||||||
horizontalPadding: 0
|
horizontalPadding: 0
|
||||||
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
|
iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize
|
||||||
color: {
|
color: {
|
||||||
if(down){
|
if(pressed){
|
||||||
return maximizePressColor
|
return maximizePressColor
|
||||||
}
|
}
|
||||||
if(FluTools.isWindows11OrGreater()){
|
|
||||||
return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor
|
|
||||||
}
|
|
||||||
return hovered ? maximizeHoverColor : maximizeNormalColor
|
return hovered ? maximizeHoverColor : maximizeNormalColor
|
||||||
}
|
}
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
@ -312,36 +268,13 @@ Rectangle{
|
|||||||
onClicked: closeClickListener()
|
onClicked: closeClickListener()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function _maximizeButtonHover(){
|
FluLoader{
|
||||||
var hover = false
|
id:layout_macos_buttons
|
||||||
if(btn_maximize.visible && FluTools.isWindows11OrGreater() && d.resizable){
|
anchors{
|
||||||
if(d.containsPointToItem(FluTools.cursorPos(),btn_maximize)){
|
verticalCenter: parent.verticalCenter
|
||||||
hover = true
|
left: parent.left
|
||||||
}else{
|
leftMargin: 10
|
||||||
if(btn_maximize.down){
|
|
||||||
btn_maximize.down = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
d.hoverMaxBtn = hover
|
sourceComponent: isMac ? com_macos_buttons : undefined
|
||||||
return hover;
|
|
||||||
}
|
|
||||||
function _appBarHover(){
|
|
||||||
var cursorPos = FluTools.cursorPos()
|
|
||||||
for(var i =0 ;i< d.hitTestList.length; i++){
|
|
||||||
var item = d.hitTestList[i]
|
|
||||||
if(item.visible){
|
|
||||||
if(d.containsPointToItem(cursorPos,item)){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(d.containsPointToItem(cursorPos,control)){
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
function setHitTestVisible(id){
|
|
||||||
d.hitTestList.push(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,29 +55,20 @@ Window {
|
|||||||
event.accepted = false
|
event.accepted = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal showSystemMenu
|
|
||||||
signal initArgument(var argument)
|
signal initArgument(var argument)
|
||||||
signal firstVisible()
|
signal lazyLoad()
|
||||||
property int _realHeight
|
|
||||||
property int _realWidth
|
|
||||||
property int _appBarHeight: appBar.height
|
|
||||||
property var _windowRegister
|
property var _windowRegister
|
||||||
property string _route
|
property string _route
|
||||||
id:window
|
id:window
|
||||||
color:"transparent"
|
color:"transparent"
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
FluRouter.addWindow(window)
|
FluRouter.addWindow(window)
|
||||||
_realHeight = height
|
|
||||||
_realWidth = width
|
|
||||||
useSystemAppBar = FluApp.useSystemAppBar
|
useSystemAppBar = FluApp.useSystemAppBar
|
||||||
if(useSystemAppBar && autoCenter){
|
if(useSystemAppBar && autoCenter){
|
||||||
moveWindowToDesktopCenter()
|
moveWindowToDesktopCenter()
|
||||||
}
|
}
|
||||||
fixWindowSize()
|
fixWindowSize()
|
||||||
initArgument(argument)
|
initArgument(argument)
|
||||||
if(!useSystemAppBar){
|
|
||||||
loader_frameless_helper.sourceComponent = com_frameless_helper
|
|
||||||
}
|
|
||||||
if(window.autoVisible){
|
if(window.autoVisible){
|
||||||
if(window.autoMaximize){
|
if(window.autoMaximize){
|
||||||
window.showMaximized()
|
window.showMaximized()
|
||||||
@ -86,33 +77,30 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onShowSystemMenu: {
|
|
||||||
if(loader_frameless_helper.item){
|
|
||||||
loader_frameless_helper.item.showSystemMenu()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if(visible && d.isFirstVisible){
|
if(visible && d.isLazyInit){
|
||||||
window.firstVisible()
|
window.lazyLoad()
|
||||||
d.isFirstVisible = false
|
d.isLazyInit = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QtObject{
|
QtObject{
|
||||||
id:d
|
id:d
|
||||||
property bool isFirstVisible: true
|
property bool isLazyInit: true
|
||||||
}
|
}
|
||||||
Connections{
|
Connections{
|
||||||
target: window
|
target: window
|
||||||
function onClosing(event){closeListener(event)}
|
function onClosing(event){closeListener(event)}
|
||||||
}
|
}
|
||||||
Component{
|
FluFrameless{
|
||||||
id:com_frameless_helper
|
id: frameless
|
||||||
FluFramelessHelper{
|
appbar: window.appBar
|
||||||
onLoadCompleted:{
|
maximizeButton: appBar.buttonMaximize
|
||||||
if(autoCenter){
|
fixSize: window.fixSize
|
||||||
window.moveWindowToDesktopCenter()
|
topmost: window.stayTop
|
||||||
}
|
disabled: FluApp.useSystemAppBar
|
||||||
}
|
Component.onCompleted: {
|
||||||
|
frameless.setHitTestVisible(appBar.layoutMacosButtons)
|
||||||
|
frameless.setHitTestVisible(appBar.layoutStandardbuttons)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component{
|
Component{
|
||||||
@ -197,9 +185,6 @@ Window {
|
|||||||
border.color: window.resizeBorderColor
|
border.color: window.resizeBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FluLoader{
|
|
||||||
id:loader_frameless_helper
|
|
||||||
}
|
|
||||||
FluLoader{
|
FluLoader{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
sourceComponent: background
|
sourceComponent: background
|
||||||
@ -255,11 +240,6 @@ Window {
|
|||||||
return com_border
|
return com_border
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showLoading(text = qsTr("Loading..."),cancel = true){
|
|
||||||
loader_loading.loadingText = text
|
|
||||||
loader_loading.cancel = cancel
|
|
||||||
loader_loading.sourceComponent = com_loading
|
|
||||||
}
|
|
||||||
function hideLoading(){
|
function hideLoading(){
|
||||||
loader_loading.sourceComponent = undefined
|
loader_loading.sourceComponent = undefined
|
||||||
}
|
}
|
||||||
@ -297,12 +277,17 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showMaximized(){
|
function showMaximized(){
|
||||||
if(FluTools.isWin()){
|
frameless.showMaximized()
|
||||||
if(loader_frameless_helper.item){
|
}
|
||||||
loader_frameless_helper.item.showMaximized()
|
function showLoading(text = "",cancel = true){
|
||||||
}
|
if(text===""){
|
||||||
}else{
|
text = qsTr("Loading...")
|
||||||
window.visibility = Window.Maximized
|
|
||||||
}
|
}
|
||||||
|
loader_loading.loadingText = text
|
||||||
|
loader_loading.cancel = cancel
|
||||||
|
loader_loading.sourceComponent = com_loading
|
||||||
|
}
|
||||||
|
function setHitTestVisible(val){
|
||||||
|
frameless.setHitTestVisible(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user