forked from github_mirror/framelesshelper
parent
7f1f2dffc3
commit
eefb3feb44
|
@ -0,0 +1,25 @@
|
|||
# 已知问题
|
||||
|
||||
## 拖拽窗口边框时窗口内容不能及时跟随,能看到窗口的白底
|
||||
|
||||
- 复现步骤:运行使用了样式表的*QWidget*程序(不使用样式表则无此问题);运行任意*Qt Quick*程序
|
||||
- 原因:暂时未知
|
||||
- 解决方案:对于*QWidget*程序,可以启用`Qt::WA_NoSystemBackground`属性,来禁用窗口默认的白色背景,但窗口背景会变成黑色,且无法改变,如果程序使用深色主题,则无大碍,如果使用浅色主题,体验应该不会太好。*Qt Quick*程序暂时无解。
|
||||
|
||||
## 拖拽窗口边框时能看到右上角的三个系统按钮/自绘内容消失(变白)
|
||||
|
||||
- 复现步骤:在窗口构造前执行`WinNativeEventFilter::install()`函数
|
||||
- 原因:暂时未知
|
||||
- 解决方案:不要全局安装过滤器,应针对每一个窗口,单独调用`addFramelessWindow`函数
|
||||
|
||||
## 自绘内容(例如D3D)错位或不能及时刷新
|
||||
|
||||
- 复现步骤:在窗口中放置一个完全由Windows API绘制的控件
|
||||
- 原因:暂时未知
|
||||
- 解决方案:暂无
|
||||
|
||||
## resize后发现尺寸不对
|
||||
|
||||
- 复现步骤:在构造函数中调用`resize`函数;在安装过滤器之前调用`resize`函数
|
||||
- 原因:构造函数中获取的几何位置和大小是不准确的;调用`resize`这一类的函数时,Qt默认会考虑边框和标题栏的宽度,但安装过滤器后,边框和标题栏没了,所以尺寸就不对了
|
||||
- 解决方案:在控件或窗口显示出来以后再去获取或设置它们的几何位置及尺寸;先安装过滤器,再调整尺寸。
|
|
@ -28,7 +28,9 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QMargins>
|
||||
#include <QVariant>
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
#include <QWidget>
|
||||
#endif
|
||||
#include <QWindow>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
|
@ -37,8 +39,10 @@
|
|||
#else
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
#include <QStyle>
|
||||
#include <QStyleOption>
|
||||
#endif
|
||||
#include <QTouchEvent>
|
||||
#endif
|
||||
|
||||
|
@ -58,6 +62,7 @@ FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {
|
|||
// is 96. Don't know how to acquire these values on UNIX platforms.
|
||||
m_borderWidth = 8;
|
||||
m_borderHeight = 8;
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
QWidget widget;
|
||||
QStyleOption styleOption;
|
||||
styleOption.initFrom(&widget);
|
||||
|
@ -65,6 +70,9 @@ FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {
|
|||
widget.style()->pixelMetric(QStyle::PixelMetric::PM_TitleBarHeight,
|
||||
&styleOption) +
|
||||
m_borderHeight;
|
||||
#else
|
||||
m_titlebarHeight = 30 + m_borderHeight;
|
||||
#endif
|
||||
qDebug().noquote() << "Window device pixel ratio:"
|
||||
<< widget.devicePixelRatioF();
|
||||
qDebug().noquote() << "Window border width:" << m_borderWidth
|
||||
|
@ -208,7 +216,9 @@ void FramelessHelper::setFramelessWindows(const QVector<QObject *> &val) {
|
|||
window->setFlags(flags);
|
||||
// MouseTracking is always enabled for QWindow.
|
||||
window->installEventFilter(this);
|
||||
} else {
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else {
|
||||
const auto widget = qobject_cast<QWidget *>(object);
|
||||
if (widget) {
|
||||
widget->setWindowFlags(flags);
|
||||
|
@ -218,6 +228,7 @@ void FramelessHelper::setFramelessWindows(const QVector<QObject *> &val) {
|
|||
widget->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -230,11 +241,14 @@ void FramelessHelper::setFramelessWindows(const QVector<QObject *> &val) {
|
|||
bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
|
||||
const auto isWindowTopLevel = [](QObject *window) -> bool {
|
||||
if (window) {
|
||||
if (window->isWidgetType()) {
|
||||
return qobject_cast<QWidget *>(window)->isTopLevel();
|
||||
} else if (window->isWindowType()) {
|
||||
if (window->isWindowType()) {
|
||||
return qobject_cast<QWindow *>(window)->isTopLevel();
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else if (window->isWidgetType()) {
|
||||
return qobject_cast<QWidget *>(window)->isTopLevel();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -367,7 +381,9 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
|
|||
}
|
||||
window->setCursor(Qt::CursorShape::ArrowCursor);
|
||||
}
|
||||
} else if (object->isWidgetType()) {
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else if (object->isWidgetType()) {
|
||||
const auto widget = qobject_cast<QWidget *>(object);
|
||||
if (widget) {
|
||||
if (widget->isFullScreen()) {
|
||||
|
@ -381,6 +397,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
|
|||
widget->setCursor(Qt::CursorShape::ArrowCursor);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -406,7 +423,9 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
|
|||
getWindowEdges(mouseEvent->localPos(), window->width(),
|
||||
window->height())));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else {
|
||||
const auto widget = qobject_cast<QWidget *>(object);
|
||||
if (widget) {
|
||||
if (!widget->isMinimized() && !widget->isMaximized() &&
|
||||
|
@ -417,6 +436,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -443,12 +463,16 @@ QWindow *FramelessHelper::getWindowHandle(QObject *val) {
|
|||
};
|
||||
if (val->isWindowType()) {
|
||||
return validWindow(qobject_cast<QWindow *>(val));
|
||||
} else if (val->isWidgetType()) {
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else if (val->isWidgetType()) {
|
||||
const auto widget = qobject_cast<QWidget *>(val);
|
||||
if (widget) {
|
||||
return validWindow(widget->windowHandle());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
qWarning().noquote() << "Can't acquire the window handle: only "
|
||||
"QWidget and QWindow are accepted.";
|
||||
}
|
||||
|
@ -480,12 +504,15 @@ void *FramelessHelper::getWindowRawHandle(QObject *object) {
|
|||
if (handle) {
|
||||
return handle;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
else {
|
||||
const auto widget = qobject_cast<QWidget *>(object);
|
||||
if (widget) {
|
||||
return reinterpret_cast<void *>(widget->winId());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
3
main.cpp
3
main.cpp
|
@ -18,11 +18,14 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
FramelessHelper helper;
|
||||
|
||||
QWidget widget;
|
||||
widget.setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
helper.setFramelessWindows({&widget});
|
||||
widget.show();
|
||||
|
||||
|
|
|
@ -251,6 +251,20 @@ BOOL IsFullScreened(HWND handle) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL IsWindowTopLevel(HWND handle) {
|
||||
if (handle && m_lpIsWindow(handle)) {
|
||||
if (m_lpGetWindowLongPtrW(handle, GWL_STYLE) & WS_CHILD) {
|
||||
return FALSE;
|
||||
}
|
||||
const HWND parent = m_lpGetAncestor(handle, GA_PARENT);
|
||||
if (parent && (parent != m_lpGetDesktopWindow())) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The thickness of an auto-hide taskbar in pixels.
|
||||
const int kAutoHideTaskbarThicknessPx = 2;
|
||||
const int kAutoHideTaskbarThicknessPy = kAutoHideTaskbarThicknessPx;
|
||||
|
@ -400,13 +414,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
}
|
||||
if (m_framelessWindows.isEmpty()) {
|
||||
// Only top level windows can be frameless.
|
||||
// Try to avoid this case because it will result in strange behavior,
|
||||
// use addFramelessWindow if possible.
|
||||
if (m_lpGetWindowLongPtrW(msg->hwnd, GWL_STYLE) & WS_CHILD) {
|
||||
return false;
|
||||
}
|
||||
const HWND parent = m_lpGetAncestor(msg->hwnd, GA_PARENT);
|
||||
if (parent && (parent != m_lpGetDesktopWindow())) {
|
||||
if (!IsWindowTopLevel(msg->hwnd)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!m_framelessWindows.contains(msg->hwnd)) {
|
||||
|
@ -456,7 +464,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
// window. On exit, the structure should contain the screen coordinates
|
||||
// of the corresponding window client area.
|
||||
const auto getClientAreaInsets = [](HWND _hWnd) -> RECT {
|
||||
if (IsMaximized(_hWnd)) {
|
||||
if (IsMaximized(_hWnd) || IsFullScreened(_hWnd)) {
|
||||
// Windows automatically adds a standard width border to all
|
||||
// sides when a window is maximized.
|
||||
int frameThickness_x = borderWidth(_hWnd);
|
||||
|
@ -520,17 +528,13 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||
m_lpSHAppBarMessage(ABM_GETAUTOHIDEBAREX, &_abd));
|
||||
return hTaskbar != nullptr;
|
||||
};
|
||||
const bool onTop = hasAutohideTaskbar(ABE_TOP);
|
||||
const bool onBottom = hasAutohideTaskbar(ABE_BOTTOM);
|
||||
const bool onLeft = hasAutohideTaskbar(ABE_LEFT);
|
||||
const bool onRight = hasAutohideTaskbar(ABE_RIGHT);
|
||||
if (onTop) {
|
||||
if (hasAutohideTaskbar(ABE_TOP)) {
|
||||
clientRect->top += kAutoHideTaskbarThicknessPy;
|
||||
} else if (onBottom) {
|
||||
} else if (hasAutohideTaskbar(ABE_BOTTOM)) {
|
||||
clientRect->bottom -= kAutoHideTaskbarThicknessPy;
|
||||
} else if (onLeft) {
|
||||
} else if (hasAutohideTaskbar(ABE_LEFT)) {
|
||||
clientRect->left += kAutoHideTaskbarThicknessPx;
|
||||
} else if (onRight) {
|
||||
} else if (hasAutohideTaskbar(ABE_RIGHT)) {
|
||||
clientRect->right -= kAutoHideTaskbarThicknessPx;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue