Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在多个显示器之间切换时,界面错位并失效 #10

Open
wavexiang opened this issue Jan 17, 2020 · 11 comments
Open

在多个显示器之间切换时,界面错位并失效 #10

wavexiang opened this issue Jan 17, 2020 · 11 comments

Comments

@wavexiang
Copy link

wavexiang commented Jan 17, 2020

在多个显示器之间切换时,界面错位并失效,编译环境VS2015/2017都试过
显示器【1】正常
image
拖动到显示器【2】错位并失效
image

@simonezhang
Copy link

same problem

@LeeGaning
Copy link

Qt 5.12.9 + Mingw,same problem

@LeeGaning
Copy link

简单处理了下,跨屏幕移动时resize下,有概率失败。
另外副屏幕通过最大化时,再最小化时恢复一定白屏(原因屏幕识别错误)。

 .../FramelessHelper/Kernels/NativeWindowHelper.cpp | 30 ++++++++++++++--------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/ThirdParty/FramelessHelper/Kernels/NativeWindowHelper.cpp b/ThirdParty/FramelessHelper/Kernels/NativeWindowHelper.cpp
index 0c2cefa..b75da1f 100644
--- a/ThirdParty/FramelessHelper/Kernels/NativeWindowHelper.cpp
+++ b/ThirdParty/FramelessHelper/Kernels/NativeWindowHelper.cpp
@@ -110,7 +110,13 @@ bool NativeWindowHelper::nativeEventFilter(void *msg, long *result)
         LPMINMAXINFO lpMinMaxInfo = reinterpret_cast<LPMINMAXINFO>(lParam);
 
         QRect g = d->availableGeometry();
+        static QRect old_g = g;
         QMargins m = d->maximizedMargins();
+        if(g != old_g) {
+            //fix:screen swtich window size change bug
+            old_g = g;
+            d->window->resize(d->window->size());
+        }
 
         lpMinMaxInfo->ptMaxPosition.x = - m.left();
         lpMinMaxInfo->ptMaxPosition.y =  - m.top();
@@ -329,15 +335,17 @@ QMargins NativeWindowHelperPrivate::maximizedMargins() const
 
 QRect NativeWindowHelperPrivate::availableGeometry() const
 {
-    MONITORINFO mi{0};
-    mi.cbSize = sizeof(MONITORINFO);
-
-    auto hWnd = reinterpret_cast<HWND>(window->winId());
-    auto hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
-    if (!hMonitor || !GetMonitorInfoW(hMonitor, &mi)) {
-        Q_ASSERT(NULL != hMonitor);
-        return window->screen()->availableGeometry();
-    }
-
-    return QRect(mi.rcWork.left, mi.rcWork.top, mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top);
+    //fix:restore form max window,get wrong geometry size(multi screens)
+    return window->screen()->availableGeometry();
+
+//    MONITORINFO mi{0};
+//    mi.cbSize = sizeof(MONITORINFO);
+
+//    auto hWnd = reinterpret_cast<HWND>(window->winId());
+//    auto hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
+//    if (!hMonitor || !GetMonitorInfoW(hMonitor, &mi)) {
+//        Q_ASSERT(NULL != hMonitor);
+//        return window->screen()->availableGeometry();
+//    }
+//    return QRect(mi.rcWork.left, mi.rcWork.top, mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top);
 }

@wuxinmao2008
Copy link

已遇到同样的问题。从一个屏幕到另一个屏幕的拖动过程中,绘制的区域变小了(水平方向上大约1016个像素,垂直方向上大约3040个像素)。还不知道如何修改

@liyangfamily
Copy link

同样遇到相同的问题,不知道如何修改

@liyangfamily
Copy link

我尝试在nativeEventFilter函数中处理WM_MOVE消息,执行如下代码SetWindowPos(msg->hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); RedrawWindow(msg->hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
即可解决多个显示器之间切换问题,但是程序还是会有其他问题。
这个方法我在VS调试诊断中看到,使用这个方法CPU性能前后都是在25左右。
感觉是歪门邪道,但是目前确实解决了我的问题,大家可以参考一下。

@winsoft666
Copy link

我尝试在nativeEventFilter函数中处理WM_MOVE消息,执行如下代码SetWindowPos(msg->hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); RedrawWindow(msg->hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
即可解决多个显示器之间切换问题,但是程序还是会有其他问题。
这个方法我在VS调试诊断中看到,使用这个方法CPU性能前后都是在25左右。
感觉是歪门邪道,但是目前确实解决了我的问题,大家可以参考一下。

HOOK本就不是正道

@feipeng8848
Copy link

在多个显示器之间切换时,界面错位并失效,编译环境VS2015/2017都试过
显示器【1】正常
image
拖动到显示器【2】错位并失效
image

按钮其实并没有失效,只是坐标没变。我在做无边框的时候用的也是nativeEventFilter拦截系统消息,出现了完全一样的问题。

@feipeng8848
Copy link

feipeng8848 commented Feb 4, 2021

我尝试在nativeEventFilter函数中处理WM_MOVE消息,执行如下代码SetWindowPos(msg->hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); RedrawWindow(msg->hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
即可解决多个显示器之间切换问题,但是程序还是会有其他问题。
这个方法我在VS调试诊断中看到,使用这个方法CPU性能前后都是在25左右。
感觉是歪门邪道,但是目前确实解决了我的问题,大家可以参考一下。

HOOK本就不是正道

感觉不涉及到什么正道不正道的问题,用win32开发无边框也是拦截消息的做法(msdn 的文档 https://docs.microsoft.com/en-us/windows/win32/dwm/customframe ) 更觉得这是windows系统做的不好

@Will-Zhu-27
Copy link

Will-Zhu-27 commented Aug 10, 2021

我尝试在nativeEventFilter函数中处理WM_MOVE消息,执行如下代码SetWindowPos(msg->hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); RedrawWindow(msg->hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
即可解决多个显示器之间切换问题,但是程序还是会有其他问题。
这个方法我在VS调试诊断中看到,使用这个方法CPU性能前后都是在25左右。
感觉是歪门邪道,但是目前确实解决了我的问题,大家可以参考一下。

确实解决了,还可以精简下只设置SetWindowPos就行。

RECT rcClient;
GetWindowRect(msg->hwnd, &rcClient);
SetWindowPos(msg->hwnd, NULL, rcClient.left, rcClient.top, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_FRAMECHANGED);

@lowbees
Copy link

lowbees commented Oct 19, 2021

在构造函数添加以下代码就可以了,好像是屏幕变化的时候Qt又给窗口加上了边框导致的

connect(window, &QWindow::screenChanged, this, [=]
{
    auto hWnd = reinterpret_cast<HWND>(window->winId());
    SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants