无边框 window,Aero Snap 在最大化状态下太大
Borderless window with Aero Snap too large in maximized state
我正在尝试在 Qt5.6.0 中制作无边框 window,具有 aero-snap 功能。
一切正常,除非我最大化 window :它太大了。
我的屏幕分辨率为 2560x1440
,因此 window 的大小应为 2560x1400
(任务栏为 40 像素),但在 WM_SIZE
消息中,新的尺寸为 2576x1416
。
所以 window 在每个方向上都正好大了 8 个像素。
这也意味着 window 没有在左上角对齐,它在两个方向上都离屏幕正好 8 个像素。
我找不到这个问题的解决方案,我尝试过的所有方法都不起作用并且会导致错误。
解决此问题的唯一方法是删除 WS_CAPTION
和 WS_THICKFRAME
样式,但随后我失去了区域捕捉功能。
我不知何故必须告诉 Qt 或 DWM 将 window 缩小 16 个像素并将其向右和底部移动 8 个像素。有人知道怎么做吗?
I somehow have to tell Qt or DWM to make the window 16 pixels smaller
and move it 8 pixels right, and bottom. Does anybody have an idea on
how to do that?
DWM 是桌面 Window 管理器?那么平台就是Windows然后
只要它是关于 Qt 5.6 的,并且您很可能谈论的是设置了 Qt::CustomizeWindowHint 属性的小部件,那么 Qt 中就有一个尚未修复的已知错误:
https://bugreports.qt.io/browse/QTBUG-4362
我偶然发现了这个错误几次,BiTOk 在上面的 link 中提出的解决方法对我有用。
我的第一次尝试是将 window 几何体设置为可用的几何体:
QRect rect = QApplication::desktop()->availableGeometry();
setGeometry(rect.left() , rect.top(), rect.right(), rect.bottom());
唯一的问题是 window 是右侧和底部的像素太小
setGeometry(rect.left() , rect.top(), rect.right() + 1, rect.bottom() + 1);
给我一个错误:
QWindowsWindow::setGeometry: Unable to set geometry 2560x1400+0+0 on QWidgetWindow/'MainWindowWindow'. Resulting geometry: 2576x1416+-8+-8 (frame: 0, 0, 0, 0, custom margin: 0, 0, 0, 0, minimum size: 45x13, maximum size: 16777215x16777215)
然后我查看了 Visual Studio 2015 的矩形坐标,它们与我实现的无边框 window 的大小相同,每个方向都大 8 个像素。
我可以给 window 的内容留出 8 个边距,这样如果 window 最大化并设置 window 区域,它就不会剪出屏幕:
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
当 window 恢复后,我们需要重置之前的更改。
结果是:
case WM_SIZE:
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &wp);
if (wp.showCmd == SW_MAXIMIZE) {
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
UpdateWindow(hwnd);
is_fullscreen = true;
} else {
if (is_fullscreen) {
setContentsMargins({ 0, 0, 0, 0 });
SetWindowRgn(hwnd, NULL, true);
is_fullscreen = false;
}
}
break;
其他帖子已经回答了这个问题,但我想补充一点,使用 GetSystemMetrics
而不是硬编码值 8
可能是个好主意。
例子
#include <Windows.h>
void MyWindow::changeEvent(QEvent* ev) {
if (ev->type() == QEvent::WindowStateChange) {
const auto state = windowState();
if(state & Qt::WindowMaximized) {
const int x = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
const int y = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
setContentsMargins({x, y, x, y});
}
else {
setContentsMargins({0, 0, 0, 0});
}
}
我正在尝试在 Qt5.6.0 中制作无边框 window,具有 aero-snap 功能。 一切正常,除非我最大化 window :它太大了。
我的屏幕分辨率为 2560x1440
,因此 window 的大小应为 2560x1400
(任务栏为 40 像素),但在 WM_SIZE
消息中,新的尺寸为 2576x1416
。
所以 window 在每个方向上都正好大了 8 个像素。
这也意味着 window 没有在左上角对齐,它在两个方向上都离屏幕正好 8 个像素。
我找不到这个问题的解决方案,我尝试过的所有方法都不起作用并且会导致错误。
解决此问题的唯一方法是删除 WS_CAPTION
和 WS_THICKFRAME
样式,但随后我失去了区域捕捉功能。
我不知何故必须告诉 Qt 或 DWM 将 window 缩小 16 个像素并将其向右和底部移动 8 个像素。有人知道怎么做吗?
I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. Does anybody have an idea on how to do that?
DWM 是桌面 Window 管理器?那么平台就是Windows然后
只要它是关于 Qt 5.6 的,并且您很可能谈论的是设置了 Qt::CustomizeWindowHint 属性的小部件,那么 Qt 中就有一个尚未修复的已知错误:
https://bugreports.qt.io/browse/QTBUG-4362
我偶然发现了这个错误几次,BiTOk 在上面的 link 中提出的解决方法对我有用。
我的第一次尝试是将 window 几何体设置为可用的几何体:
QRect rect = QApplication::desktop()->availableGeometry();
setGeometry(rect.left() , rect.top(), rect.right(), rect.bottom());
唯一的问题是 window 是右侧和底部的像素太小
setGeometry(rect.left() , rect.top(), rect.right() + 1, rect.bottom() + 1);
给我一个错误:
QWindowsWindow::setGeometry: Unable to set geometry 2560x1400+0+0 on QWidgetWindow/'MainWindowWindow'. Resulting geometry: 2576x1416+-8+-8 (frame: 0, 0, 0, 0, custom margin: 0, 0, 0, 0, minimum size: 45x13, maximum size: 16777215x16777215)
然后我查看了 Visual Studio 2015 的矩形坐标,它们与我实现的无边框 window 的大小相同,每个方向都大 8 个像素。
我可以给 window 的内容留出 8 个边距,这样如果 window 最大化并设置 window 区域,它就不会剪出屏幕:
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
当 window 恢复后,我们需要重置之前的更改。 结果是:
case WM_SIZE:
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &wp);
if (wp.showCmd == SW_MAXIMIZE) {
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
UpdateWindow(hwnd);
is_fullscreen = true;
} else {
if (is_fullscreen) {
setContentsMargins({ 0, 0, 0, 0 });
SetWindowRgn(hwnd, NULL, true);
is_fullscreen = false;
}
}
break;
其他帖子已经回答了这个问题,但我想补充一点,使用 GetSystemMetrics
而不是硬编码值 8
可能是个好主意。
例子
#include <Windows.h>
void MyWindow::changeEvent(QEvent* ev) {
if (ev->type() == QEvent::WindowStateChange) {
const auto state = windowState();
if(state & Qt::WindowMaximized) {
const int x = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
const int y = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
setContentsMargins({x, y, x, y});
}
else {
setContentsMargins({0, 0, 0, 0});
}
}