modify frameless

This commit is contained in:
brige 2025-11-16 16:50:17 +08:00
parent 9a24595873
commit dfa0d513e6
2 changed files with 24 additions and 40 deletions

View File

@ -24,10 +24,9 @@ namespace Gdiplus
#include "FrameTitleBar.h"
#pragma comment (lib,"Dwmapi.lib") // Adds missing library, fixes error LNK2019: unresolved external symbol __imp__DwmExtendFrameIntoClientArea
#pragma comment (lib,"Dwmapi.lib")
#pragma comment (lib,"user32.lib")
// 无边框样式:不使用 CAPTION 与系统按钮,避免在 Win7 显示原生按钮
constexpr unsigned long BorderlessFlag = WS_POPUP | WS_THICKFRAME | WS_SYSMENU;
inline bool IsCompositionEnabled() {
@ -103,10 +102,9 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
return true;
}
NCCALCSIZE_PARAMS* ncParam = reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam);
// 最大化时将客户区严格对齐到工作区,避免左右空隙
ncParam->rgrc[0].left = rc->left();
ncParam->rgrc[0].top = rc->top();
ncParam->rgrc[0].right = rc->right();
ncParam->rgrc[0].right = rc->right() + 1;
ncParam->rgrc[0].bottom = rc->bottom();
*result = 0;
return true;
@ -123,7 +121,7 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
} else {
clientRect->top = before.top;
clientRect->left = before.left;
clientRect->right = before.right;
clientRect->right = before.right + 1;
clientRect->bottom = before.bottom + 1;
}
}
@ -132,12 +130,8 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
return true;
}
case WM_NCPAINT: {
if (!IsCompositionEnabled()) {
*result = 0;
return true;
} else {
break;
}
*result = 0;
return true;
}
case WM_SETFOCUS: {
Qt::FocusReason reason;
@ -153,17 +147,13 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
}
break;
case WM_NCACTIVATE: {
if (!IsCompositionEnabled()) {
*result = 1;
return true;
}
*result = 1;
return true;
}
break;
case WM_NCHITTEST: {
return OnNCTitTest(msg, result);
}
case WM_GETMINMAXINFO: {
// 使用工作区定义最大化位置与大小,避免遮挡任务栏
MINMAXINFO* mmi = reinterpret_cast<MINMAXINFO*>(msg->lParam);
HMONITOR monitor = MonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
@ -172,17 +162,19 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
if (monitor && GetMonitorInfo(monitor, &mi)) {
const RECT& work = mi.rcWork;
const RECT& rcMon = mi.rcMonitor;
mmi->ptMaxPosition.x = work.left;
mmi->ptMaxPosition.y = work.top;
mmi->ptMaxSize.x = work.right - work.left;
mmi->ptMaxSize.y = work.bottom - work.top;
// 限制拖动最大尺寸为监视器大小(非必须,但较合理)
mmi->ptMaxTrackSize.x = rcMon.right - rcMon.left;
mmi->ptMaxTrackSize.y = rcMon.bottom - rcMon.top;
const int frameX = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
const int frameY = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
mmi->ptMaxPosition.x = work.left - frameX;
mmi->ptMaxPosition.y = work.top - frameY;
mmi->ptMaxSize.x = (work.right - work.left) + frameX * 2;
mmi->ptMaxSize.y = (work.bottom - work.top) + frameY * 2;
mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2;
mmi->ptMaxTrackSize.y = (rcMon.bottom - rcMon.top) + frameY * 2;
}
if (::IsZoomed(msg->hwnd)) {
// 最大化时不叠加系统边框内边距
frames_.setLeft(0);
frames_.setTop(0);
frames_.setRight(0);
@ -230,7 +222,6 @@ void FramelessDelegateWin::OnShow() {
}
mainWidget_->setAttribute(Qt::WA_Resized);
// 仅当存在有效的窗口放置信息length 已设置)时才恢复窗口位置,避免首次显示使用未初始化的数据
if (!isFirstShow_ && mainWidget_->isMaximized() && wndPlaceMent_.length == sizeof(wndPlaceMent_)) {
QMetaObject::invokeMethod(
this,
@ -374,15 +365,12 @@ void FramelessDelegateWin::SetNativeWindowLong() {
}
HWND hwnd = reinterpret_cast<HWND>(mainWidget_->winId());
unsigned long style = BorderlessFlag;
// 避免父窗口与子窗口重叠绘制导致闪烁,启用剪裁样式
style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
// 显式清理可能由 Qt 或系统设置的标题栏与系统按钮标志,确保不显示原生按钮
style &= ~WS_CAPTION;
style &= ~WS_MINIMIZEBOX;
style &= ~WS_MAXIMIZEBOX;
// 根据 Qt 窗口标志与大小约束,启用系统最小化/最大化按钮能力
const bool canResize = (mainWidget_->maximumSize() == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
if (mainWidget_->windowFlags().testFlag(Qt::WindowMinimizeButtonHint) && canResize) {
style |= WS_MINIMIZEBOX;
@ -394,7 +382,7 @@ void FramelessDelegateWin::SetNativeWindowLong() {
::SetWindowLongPtr(hwnd, GWL_STYLE, style);
if (IsCompositionEnabled()) {
ExtendFrameIntoClientArea(mainWidget_->windowHandle(), 1, 0, 0, 0);
ExtendFrameIntoClientArea(mainWidget_->windowHandle(), 1, 1, 0, 0);
}
RECT rect;
GetWindowRect(hwnd, &rect);
@ -445,10 +433,6 @@ bool FramelessDelegateWin::OnNCTitTest(MSG* msg, qintptr* result) {
*result = HTTOP;
return true;
}
if (y > rect.top() + borderY && y < rect.top() + borderY) {
*result = HTCAPTION;
return true;
}
if (!maxSized && y >= rect.bottom() - borderY && y <= rect.bottom()) {
*result = HTBOTTOM;
return true;

View File

@ -18,16 +18,16 @@
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
<number>6</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
<number>6</number>
</property>
<item>
<widget class="FrameTitleBar" name="titleFrame">
@ -55,7 +55,7 @@
<widget class="QWidget" name="body" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
@ -64,10 +64,10 @@
<number>3</number>
</property>
<property name="rightMargin">
<number>0</number>
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
<number>6</number>
</property>
<item>
<widget class="QStackedWidget" name="menuWidget">