Qt工作Windows 8风格无框自定义窗口

黒い雪*_*黒い雪 4 qt github stylesheet windows-8

我最近在我的Windows 7机器上安装了Github for Windows并且喜欢它的自定义框架,它非常适合整个应用程序主题,并且它有自己的标题栏按钮,这些按钮非常好,非常流畅,并且看起来很自然用.

我做了一些挖掘,发现2个标志可以完全清除边框,经过一些自定义后,我的应用程序也有一个很好的自定义外观,直观但与旧的Windows边框的所有应用程序不同.

事情是,它不像其他窗户那样流畅自然地响应,它很奇怪,我很容易让窗户用鼠标移动但它经常出现故障,并且能够移动到它不应该喜欢的区域单击并拖动禁用的按钮.

与showMaximize方法相关联的最大化按钮只是放大整个窗口占据整个桌面,你仍然可以移动它(真的不是真正最大化).

该窗口没有响应任何系统信号,如单击任务栏以最小化它等.

经过大量的修复之后,我终于放弃了,因为我真的很好看,看起来非常直观,就像github for Windows一样非常直观.

我有什么方法可以做到这一点,我还没准备好放弃.

我知道在制作原始Windows API应用程序时,你必须将它链接到XP内置样式,因为它默认继承了Windows 95样式,也许是Qt没有连接的Windows 8样式,我不知道没有我还没去研究那么远.

Pav*_*hov 5

通过单击任务栏最小化窗口

似乎Qt::FramelessWindowHint实施是有限的.设置此标志后,Windows认为此窗口无法最小化或最大化.我试过用纯winapi实现这个解决方案.通过单击任务栏最小化和恢复无框窗口工作正常.显然Qt设置了一些阻止此功能的坏标志.可能是有充分理由的,我不知道.

我们可以一起使用winapi和Qt但是很麻烦.首先,在设置窗口标志并使用Qt显示窗口后,应执行winapi代码.否则Qt将覆盖窗口标志.

另一个问题是当我们使用winapi移除边框时,窗口几何体突然改变,而Qt不知道这一点.渲染和事件映射(包括鼠标单击位置)变为无效.我没有找到任何记录更新映射的方法.我发现我们可以告诉Qt屏幕方向已经改变,并强制它重新计算窗口几何.但这看起来像一个肮脏的黑客.此外QWidget::windowHandle,Qt 4中缺少该功能,Qt 5中的"可能会发生变化".因此该方法不可靠.但无论如何,它现在有效.这是完整的代码(在Windows 8中测试),应放在顶部窗口类构造函数中:

#include "windows.h"
#include <QWindow>
//...
show();
HWND hwnd = reinterpret_cast<HWND>(effectiveWinId());
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
SetWindowLong(hwnd, GWL_STYLE, lStyle);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
windowHandle()->reportContentOrientationChange(Qt::PrimaryOrientation);
Run Code Online (Sandbox Code Playgroud)

解决此问题的真正方法是修改Window Qt平台插件(请参阅Qt源中的QWindowsWindow类).可能有一种方法可以继承默认实现,修改它并在您的应用中使用.你也可以问Qt开发人员这种行为是否合理,还是一个bug.我认为这个问题可以用补丁修复.

如果您仍打算使用此代码并且还应支持其他操作系统,请不要忘记将特定于Windows的实现包装在中#ifdef Q_OS_WIN.

仅在单击标题栏并且窗口未最大化时才启用窗口拖动

其他问题可以更容易解决.处理鼠标事件以实现窗口拖动时,请检查窗口状态和事件位置,并在不需要时禁用移动.

void MainWindow::mousePressEvent(QMouseEvent *e) {
  if (!isMaximized() && 
      e->button() == Qt::LeftButton && 
      ui->title->geometry().contains(e->pos())) {
    window_drag_start_pos = e->pos();
  }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *e) {
  window_drag_start_pos = QPoint(0, 0);
}

void MainWindow::mouseMoveEvent(QMouseEvent *e) {
  if (!window_drag_start_pos.isNull()) {
    move(pos() + e->pos() - window_drag_start_pos);
  }
}

void MainWindow::on_minimize_clicked() {
  showMinimized();
}

void MainWindow::on_maximize_clicked() {
  if (isMaximized()) {
    showNormal();
  } else {
    showMaximized();
  }
}
Run Code Online (Sandbox Code Playgroud)

ui->title是一个用于显示假标题栏的标签,QPoint window_drag_start_pos是一个类变量.