加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-14 03:53:59 所属栏目:Windows 来源:网络整理
导读:我最近在我的 Windows 7机器上安装了 Github for Windows,并且喜欢它拥有的自定义框架,它非常适合整个应用程序主题,并且有自己的标题栏按钮,这些按钮非常好,非常流畅,看起来非常自然用. 我做了一些挖掘,发现2个标志可以完全清除边框,经过一些自定义后,我得到
我最近在我的 Windows 7机器上安装了 Github for Windows,并且喜欢它拥有的自定义框架,它非常适合整个应用程序主题,并且有自己的标题栏按钮,这些按钮非常好,非常流畅,看起来非常自然用.

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

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

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

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

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

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

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

解决方法

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

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

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

另一个问题是当我们使用winapi移除边框时,窗口几何体突然改变,而Qt不知道这一点.渲染和事件映射(包括鼠标单击位置)变为无效.我没有找到任何记录更新映射的方法.我发现我们可以告诉Qt屏幕方向已经改变,并强制它重新计算窗口几何.但这看起来像一个肮脏的黑客. Qt 4中缺少QWidget :: windowHandle函数,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);

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

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

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

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

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();
  }
}

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读