无边框 Qt 窗口(win32)中窗口绘制行为错误

6

我有一个 QML 应用程序(也在 QWidgets 中进行了测试,问题相同),为了使它无边框(但仍支持本机 WM 功能,如 Aero Snap 等),我遵循了 这个,通过实现 QAbstractNativeEventFilter 并响应 WM_NCCALSIZE 信号并将其设置为零:

switch(msg->message) {
  case WM_NCCALCSIZE:
    *r = 0;
    return 1;
    ...
}

我还设置了一些不在Qt命名空间中的窗口标志,使用以下代码:

SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME);

这在窗口未移动或调整大小时运行良好,但一旦Qt重新渲染,就会出现一个宽度等于标题和边框的未绘制区域:

移动/调整大小之前 Before

移动/调整大小之后 After

我还发现了一个解决方法,即在Qt中添加FramelessWindowHint标志:

window->setFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::Dialog);

但是,现在当窗口状态改变(最大化、最小化等)时,这些边距再次出现。例如,通过阻止 WM_SIZE 事件,当 SIZE_MAXIMIZED 是参数时,边距不会出现,但我也无法从 Qt 最大化窗口。这意味着这是一个 Qt 的问题。
我还注意到,通过使用 winspector 检查窗口样式后,在我将其最大化后会出现一个新的属性原子: 请问你能帮我解决这个问题吗?

抱歉,它是Qt版本5.2。 - user2282732
2个回答

0

我认为在窗口句柄上使用SetWindowLong并使用Qt窗口标志/Qt小部件属性是在寻找麻烦。您可以查看Qt源代码,以了解处理这些窗口标志时会发生什么。

当我创建无框架窗口时,通常是为了防止移动和调整大小,因为我单独管理所有这些内容。

我遇到的一个问题与此有关,就是当屏幕键盘弹出并停靠时,它会调整我的窗口大小。因此,除了调用resize()之外,我还必须使用setFixedSize来防止操作系统尝试更改窗口大小时操纵我的小部件。

换句话说,如果您正在管理无框架窗口,则可以添加一个应用程序范围的QShortcut,监听捕捉键盘快捷方式,并在发生时按您想要的方式调整窗口大小。

希望能对您有所帮助。


我这样做的原因是我想支持本地平台功能,如拖动调整大小和启用阴影效果。同时,我成功地让它按预期工作,但更像是一个不太干净的解决方法而不是真正的解决方案。 - user2282732

0

我想知道这是否是Qt消息传递的一个漏洞,因为我遇到了类似的问题,这个问题发生在嵌套窗口上。如果你按下父窗口的SIZE_MAXIMIZE或SIZE_MINIMIZE按钮,子窗口有时无法接收WM_SIZE消息。我认为大致有两种解决方案:1. 修复Qt,2. 解决方法。

在这里,我有一个OGL渲染子窗口,有时甚至连WM_SIZE消息都无法正确地传递。也就是说,如果你调整父窗口大小,你会得到部分客户区域是黑色的。

我只是使用了一个简单的解决办法来解决这个问题,它检查当前大小与缓存的大小,并进行手动调整大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接