【问题标题】:Wrong window painting behaviour in frameless Qt window (win32)无框 Qt 窗口(win32)中错误的窗口绘制行为
【发布时间】:2014-03-04 02:44:41
【问题描述】:

我有一个 QML 应用程序(也使用 QWidgets 对其进行了测试,同样的问题)并使其无边界(但仍支持原生 WM 功能,如 aero snap 等)我遵循 this 通过实现 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 重新呈现的窗口的大小和未绘制的区域宽度,标题的宽度和边框出现:

在移动/调整大小之前

移动/调整大小后

我还通过在 Qt 中添加 FramelessWindowHint 标志找到了解决方法:

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

但是现在,当窗口状态发生变化(最大化、最小化……)时,这个边距会再次出现。通过阻止 WM_SIZE 事件,例如当 SIZE_MAXIMIZED 是参数时,边距不会出现,但是我也无法从 Qt 最大化窗口。这意味着这是 Qt 的一个问题。

我还注意到通过使用 winspector 检查窗口样式,在我将其最大化后会出现一个新的属性原子:

你能帮我解决这个问题吗?

【问题讨论】:

  • 对不起,这是Qt 5.2版

标签: c++ windows qt winapi qml


【解决方案1】:

我想知道这是否是 Qt 消息中继的缺陷,因为我遇到了嵌套窗口上发生的类似问题。如果按下父窗口的 SIZE_MAXIMIZE 或 SIZE_MINIMIZE 按钮,子窗口有时收不到 WM_SIZE 消息。我想大致有两种解决方案:1. 修复 Qt,2. 解决它。

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

我只是使用一个简单的解决方法来解决这个问题,它使用缓存的大小检查当前大小,然后自己手动调整大小。

【讨论】:

    【解决方案2】:

    我认为在窗口句柄上使用 SetWindowLong 并使用 Qt Window Flags/Qt Widget Attributes 是自找麻烦。你可以去查看 Qt 源代码,看看在处理这些窗口标志时会发生什么。

    当我创建无框窗口时,我通常会这样做以防止移动和调整大小,因为我是单独管理所有这些的。

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

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

    希望对您有所帮助。

    【讨论】:

    • 我这样做的原因是我想支持原生平台功能,如拖动调整大小和启用阴影效果。与此同时,我设法让它按预期工作,但这更像是一种肮脏的解决方法,而是一种解决方案。
    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    相关资源
    最近更新 更多