This commit is contained in:
朱子楚\zhuzi 2024-02-26 15:50:42 +08:00
parent d0fe68eed3
commit 9ced60de1e
8 changed files with 201 additions and 93 deletions

View File

@ -174,6 +174,9 @@ FluWindow {
loader.reload()
}
}
Component.onCompleted: {
appBar.setHitTestVisible(layout_back_buttons)
}
}
FluRemoteLoader{
id:loader
@ -230,6 +233,9 @@ FluWindow {
ItemsOriginal.paneItemMenu = nav_item_right_menu
ItemsFooter.navigationView = nav_view
ItemsFooter.paneItemMenu = nav_item_right_menu
appBar.setHitTestVisible(nav_view.buttonMenu)
appBar.setHitTestVisible(nav_view.buttonBack)
appBar.setHitTestVisible(nav_view.imageLogo)
setCurrentIndex(0)
}
}
@ -310,9 +316,9 @@ FluWindow {
steps:{
var data = []
if(!window.useSystemAppBar){
data.push({title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>appBar.darkButton()})
data.push({title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>appBar.buttonDark})
}
data.push({title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.logoButton()})
data.push({title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.imageLogo})
return data
}
}
@ -385,5 +391,4 @@ FluWindow {
FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
.go(callable)
}
}

View File

@ -174,6 +174,9 @@ FluWindow {
loader.reload()
}
}
Component.onCompleted: {
appBar.setHitTestVisible(layout_back_buttons)
}
}
FluRemoteLoader{
id:loader
@ -230,6 +233,9 @@ FluWindow {
ItemsOriginal.paneItemMenu = nav_item_right_menu
ItemsFooter.navigationView = nav_view
ItemsFooter.paneItemMenu = nav_item_right_menu
appBar.setHitTestVisible(nav_view.buttonMenu)
appBar.setHitTestVisible(nav_view.buttonBack)
appBar.setHitTestVisible(nav_view.imageLogo)
setCurrentIndex(0)
}
}
@ -310,9 +316,9 @@ FluWindow {
steps:{
var data = []
if(!window.useSystemAppBar){
data.push({title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>appBar.darkButton()})
data.push({title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>appBar.buttonDark})
}
data.push({title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.logoButton()})
data.push({title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.imageLogo})
return data
}
}
@ -385,5 +391,4 @@ FluWindow {
FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest")
.go(callable)
}
}

View File

@ -2,6 +2,7 @@
#include <QGuiApplication>
#include <QScreen>
#include <QQuickItem>
#include "FluTools.h"
#ifdef Q_OS_WIN
@ -83,7 +84,7 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
int offsetSize = 0;
bool isMaximum = IsZoomed(hwnd);
offsetXY = QPoint(abs(clientRect->left - originalLeft),abs(clientRect->top - originalTop));
if(isMaximum || _helper->window->visibility() == QWindow::FullScreen){
if(isMaximum || _helper->fullScreen()){
_helper->setOriginalPos(QPoint(originalLeft,originalTop));
offsetSize = 0;
}else{
@ -110,6 +111,52 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
}
return true;
}
*result = 0;
short x = LOWORD(msg->lParam);
short y = HIWORD(msg->lParam);
int margins = _helper->getMargins();
QPointer<QQuickWindow> win = _helper->window;
QPoint pos = win->mapFromGlobal(QPoint(x, y));
bool left = pos.x() < margins;
bool right = pos.x() > win->width() - margins;
bool top = pos.y() < margins;
bool bottom = pos.y() > win->height() - 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()){
auto item = appBar.value<QQuickItem*>();
if(item->contains(pos)){
QPoint appBarTopLeft = item->mapToItem(_helper->window->contentItem(),QPoint(0, 0)).toPoint();
QRect rcAppBar = QRect(appBarTopLeft, QSize(item->width(), item->height()));
if (rcAppBar.contains(pos) && _helper->hoverAppBar())
{
*result = HTCAPTION;
return true;
}
}
}
*result = HTCLIENT;
return true;
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
@ -140,6 +187,10 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
minmaxInfo->ptMaxSize.y = geometry.height()*pixelRatio + offsetXY.y()*2;
#endif
return false;
}else if(uMsg == WM_NCRBUTTONDOWN){
if (wParam == HTCAPTION) {
_helper->showSystemMenu();
}
}
return false;
#endif
@ -181,7 +232,6 @@ void FluFramelessHelper::_updateCursor(int edges){
bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
if (!window.isNull() && window->flags()) {
static int margin = 8;
switch (ev->type()) {
case QEvent::MouseButtonPress:
if(_edges!=0){
@ -196,7 +246,7 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
_edges = 0;
break;
case QEvent::MouseMove: {
if(_maximized() || _fullScreen()){
if(maximized() || fullScreen()){
break;
}
if(!resizeable()){
@ -209,7 +259,7 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
#else
event->position().toPoint();
#endif
if(p.x() >= margin && p.x() <= (window->width() - margin) && p.y() >= margin && p.y() <= (window->height() - margin)){
if(p.x() >= _margins && p.x() <= (window->width() - _margins) && p.y() >= _margins && p.y() <= (window->height() - _margins)){
if(_edges != 0){
_edges = 0;
_updateCursor(_edges);
@ -217,16 +267,16 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
break;
}
_edges = 0;
if ( p.x() < margin ) {
if ( p.x() < _margins ) {
_edges |= Qt::LeftEdge;
}
if ( p.x() > (window->width() - margin) ) {
if ( p.x() > (window->width() - _margins) ) {
_edges |= Qt::RightEdge;
}
if ( p.y() < margin ) {
if ( p.y() < _margins ) {
_edges |= Qt::TopEdge;
}
if ( p.y() > (window->height() - margin) ) {
if ( p.y() > (window->height() - _margins) ) {
_edges |= Qt::BottomEdge;
}
_updateCursor(_edges);
@ -256,7 +306,11 @@ void FluFramelessHelper::componentComplete(){
_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);
_nativeEvent =new FramelessEventFilter(this);
qApp->installNativeEventFilter(_nativeEvent);
@ -283,6 +337,7 @@ void FluFramelessHelper::componentComplete(){
});
#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();
@ -295,7 +350,6 @@ void FluFramelessHelper::componentComplete(){
_onStayTopChange();
_stayTop.connectNotifySignal(this,SLOT(_onStayTopChange()));
_screen.connectNotifySignal(this,SLOT(_onScreenChanged()));
window->installEventFilter(this);
Q_EMIT loadCompleted();
}
}
@ -315,16 +369,18 @@ void FluFramelessHelper::showSystemMenu(){
DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_SYSMENU);
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
DeleteMenu(hMenu, SC_MOVE, MF_BYCOMMAND);
DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
if(_maximized() || _fullScreen()){
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()){
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);
@ -361,25 +417,38 @@ FluFramelessHelper::~FluFramelessHelper(){
}
bool FluFramelessHelper::hoverMaxBtn(){
QVariant appBar = window->property("appBar");
if(appBar.isNull()){
if(_appBar.isNull()){
return false;
}
QVariant var;
QMetaObject::invokeMethod(appBar.value<QObject*>(), "maximizeButtonHover",Q_RETURN_ARG(QVariant, var));
QMetaObject::invokeMethod(_appBar.value<QObject*>(), "_maximizeButtonHover",Q_RETURN_ARG(QVariant, var));
if(var.isNull()){
return false;
}
return var.toBool();
}
QObject* FluFramelessHelper::maximizeButton(){
QVariant appBar = window->property("appBar");
if(appBar.isNull()){
return nullptr;
bool FluFramelessHelper::hoverAppBar(){
if(_appBar.isNull()){
return false;
}
QVariant var;
QMetaObject::invokeMethod(appBar.value<QObject*>(), "maximizeButton",Q_RETURN_ARG(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;
}
QObject* FluFramelessHelper::maximizeButton(){
if(_appBar.isNull()){
return nullptr;
}
QVariant var = _appBar.value<QObject*>()->property("buttonMaximize");
if(var.isNull()){
return nullptr;
}
@ -394,10 +463,14 @@ bool FluFramelessHelper::resizeable(){
return !_fixSize.read().toBool();
}
bool FluFramelessHelper::_maximized(){
bool FluFramelessHelper::maximized(){
return window->visibility() == QWindow::Maximized;
}
bool FluFramelessHelper::_fullScreen(){
bool FluFramelessHelper::fullScreen(){
return window->visibility() == QWindow::FullScreen;
}
int FluFramelessHelper::getMargins(){
return _margins;
}

View File

@ -38,7 +38,12 @@ public:
void classBegin() override;
void componentComplete() override;
bool hoverMaxBtn();
bool hoverAppBar();
bool resizeable();
int getMargins();
bool maximized();
bool fullScreen();
QVariant getAppBar();
QObject* maximizeButton();
void setOriginalPos(QVariant pos);
Q_INVOKABLE void showSystemMenu();
@ -47,8 +52,6 @@ protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
void _updateCursor(int edges);
bool _maximized();
bool _fullScreen();
Q_SLOT void _onStayTopChange();
Q_SLOT void _onScreenChanged();
public:
@ -62,7 +65,9 @@ private:
QQmlProperty _realHeight;
QQmlProperty _realWidth;
QQmlProperty _appBarHeight;
QVariant _appBar;
int _edges = 0;
int _margins = 8;
};
#endif // FLUFRAMELESSHELPER_H

View File

@ -33,6 +33,7 @@ Rectangle{
property int iconSize: 20
property bool isMac: FluTools.isMacos()
property color borerlessColor : FluTheme.primaryColor
property bool systemMoveEnable: true
property var maxClickListener : function(){
if(FluTools.isMacos()){
if (d.win.visibility === Window.FullScreen)
@ -70,6 +71,11 @@ Rectangle{
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
color: Qt.rgba(0,0,0,0)
height: visible ? 30 : 0
@ -77,6 +83,7 @@ Rectangle{
z: 65535
Item{
id:d
property var hitTestList: []
property bool hoverMaxBtn: false
property var win: Window.window
property bool stayTop: {
@ -89,21 +96,24 @@ Rectangle{
property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth)
}
MouseArea{
id:mouse_app_bar
anchors.fill: parent
onPositionChanged:
(mouse)=>{
if(systemMoveEnable){
d.win.startSystemMove()
}
}
onDoubleClicked:
(mouse)=>{
if(d.resizable && Qt.LeftButton){
if(systemMoveEnable && d.resizable && Qt.LeftButton){
btn_maximize.clicked()
}
}
acceptedButtons: Qt.LeftButton|Qt.RightButton
onClicked:
(mouse)=>{
if (mouse.button === Qt.RightButton){
if (systemMoveEnable && mouse.button === Qt.RightButton){
control.systemMenuListener()
}
}
@ -174,9 +184,13 @@ Rectangle{
}
RowLayout{
id:layout_row
anchors.right: parent.right
height: control.height
spacing: 0
Component.onCompleted: {
setHitTestVisible(layout_row)
}
FluToggleSwitch{
id:btn_dark
Layout.alignment: Qt.AlignVCenter
@ -267,23 +281,8 @@ Rectangle{
onClicked: closeClickListener()
}
}
function stayTopButton(){
return btn_stay_top
}
function minimizeButton(){
return btn_minimize
}
function maximizeButton(){
return btn_maximize
}
function closeButton(){
return btn_close
}
function darkButton(){
return btn_dark
}
function maximizeButtonHover(){
var hover = false;
function _maximizeButtonHover(){
var hover = false
var pos = btn_maximize.mapToGlobal(0,0)
if(btn_maximize.visible){
var rect = Qt.rect(pos.x,pos.y,btn_maximize.width,btn_maximize.height)
@ -295,4 +294,21 @@ Rectangle{
d.hoverMaxBtn = hover
return hover;
}
function _appBarHover(){
for(var i =0 ;i< d.hitTestList.length; i++){
var item = d.hitTestList[i]
var pos = item.mapToGlobal(0,0)
if(item.visible){
var rect = Qt.rect(pos.x,pos.y,item.width,item.height)
pos = FluTools.cursorPos()
if(pos.x>rect.x && pos.x<(rect.x+rect.width) && pos.y>rect.y && pos.y<(rect.y+rect.height)){
return false
}
}
}
return true
}
function setHitTestVisible(id){
d.hitTestList.push(id)
}
}

View File

@ -21,6 +21,9 @@ Item {
property int cellHeight: 38
property int cellWidth: 300
property bool hideNavAppBar: false
property alias buttonMenu: btn_menu
property alias buttonBack: btn_back
property alias imageLogo: image_logo
signal logoClicked
id:control
Item{
@ -755,7 +758,7 @@ Item {
}
}
FluIconButton{
id:btn_nav
id:btn_menu
iconSource: FluentIcons.GlobalNavButton
iconSize: 15
Layout.preferredWidth: d.isMinimal ? 30 : 0
@ -787,7 +790,7 @@ Item {
Layout.preferredWidth: 20
source: control.logo
Layout.leftMargin: {
if(btn_nav.visible){
if(btn_menu.visible){
return 12
}
return 5
@ -1337,13 +1340,4 @@ Item {
}
}
}
function backButton(){
return btn_back
}
function navButton(){
return btn_nav
}
function logoButton(){
return image_logo
}
}

View File

@ -33,6 +33,7 @@ Rectangle{
property int iconSize: 20
property bool isMac: FluTools.isMacos()
property color borerlessColor : FluTheme.primaryColor
property bool systemMoveEnable: true
property var maxClickListener : function(){
if(FluTools.isMacos()){
if (d.win.visibility === Window.FullScreen)
@ -70,6 +71,11 @@ Rectangle{
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
color: Qt.rgba(0,0,0,0)
height: visible ? 30 : 0
@ -77,6 +83,7 @@ Rectangle{
z: 65535
Item{
id:d
property var hitTestList: []
property bool hoverMaxBtn: false
property var win: Window.window
property bool stayTop: {
@ -89,21 +96,24 @@ Rectangle{
property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth)
}
MouseArea{
id:mouse_app_bar
anchors.fill: parent
onPositionChanged:
(mouse)=>{
if(systemMoveEnable){
d.win.startSystemMove()
}
}
onDoubleClicked:
(mouse)=>{
if(d.resizable && Qt.LeftButton){
if(systemMoveEnable && d.resizable && Qt.LeftButton){
btn_maximize.clicked()
}
}
acceptedButtons: Qt.LeftButton|Qt.RightButton
onClicked:
(mouse)=>{
if (mouse.button === Qt.RightButton){
if (systemMoveEnable && mouse.button === Qt.RightButton){
control.systemMenuListener()
}
}
@ -174,9 +184,13 @@ Rectangle{
}
RowLayout{
id:layout_row
anchors.right: parent.right
height: control.height
spacing: 0
Component.onCompleted: {
setHitTestVisible(layout_row)
}
FluToggleSwitch{
id:btn_dark
Layout.alignment: Qt.AlignVCenter
@ -267,23 +281,8 @@ Rectangle{
onClicked: closeClickListener()
}
}
function stayTopButton(){
return btn_stay_top
}
function minimizeButton(){
return btn_minimize
}
function maximizeButton(){
return btn_maximize
}
function closeButton(){
return btn_close
}
function darkButton(){
return btn_dark
}
function maximizeButtonHover(){
var hover = false;
function _maximizeButtonHover(){
var hover = false
var pos = btn_maximize.mapToGlobal(0,0)
if(btn_maximize.visible){
var rect = Qt.rect(pos.x,pos.y,btn_maximize.width,btn_maximize.height)
@ -295,4 +294,21 @@ Rectangle{
d.hoverMaxBtn = hover
return hover;
}
function _appBarHover(){
for(var i =0 ;i< d.hitTestList.length; i++){
var item = d.hitTestList[i]
var pos = item.mapToGlobal(0,0)
if(item.visible){
var rect = Qt.rect(pos.x,pos.y,item.width,item.height)
pos = FluTools.cursorPos()
if(pos.x>rect.x && pos.x<(rect.x+rect.width) && pos.y>rect.y && pos.y<(rect.y+rect.height)){
return false
}
}
}
return true
}
function setHitTestVisible(id){
d.hitTestList.push(id)
}
}

View File

@ -22,6 +22,9 @@ Item {
property int cellHeight: 38
property int cellWidth: 300
property bool hideNavAppBar: false
property alias buttonMenu: btn_menu
property alias buttonBack: btn_back
property alias imageLogo: image_logo
signal logoClicked
id:control
Item{
@ -756,7 +759,7 @@ Item {
}
}
FluIconButton{
id:btn_nav
id:btn_menu
iconSource: FluentIcons.GlobalNavButton
iconSize: 15
Layout.preferredWidth: d.isMinimal ? 30 : 0
@ -788,7 +791,7 @@ Item {
Layout.preferredWidth: 20
source: control.logo
Layout.leftMargin: {
if(btn_nav.visible){
if(btn_menu.visible){
return 12
}
return 5
@ -1338,13 +1341,4 @@ Item {
}
}
}
function backButton(){
return btn_back
}
function navButton(){
return btn_nav
}
function logoButton(){
return image_logo
}
}