Совместим ли Qt 5.5 QWebEngineView с FramelessWindowHint?

Я пишу кроссплатформенный веб-браузер на Qt, поскольку он имеет встроенную поддержку WebKit через QWebView или более современный QWebEngineView. Чтобы получить компактный оконный хром, я хочу отключить строку заголовка собственного окна и границу с помощью Qt :: FramelessWindowHint, но все же получить собственное поведение, такое как изменение размера и Windows Aero Snap.

Сначала я урезал ПКЕ«s BorderlessWindow демо. Это работало просто отлично: в Windows 8.1 x64 размер окна можно изменять, пользовательскую строку заголовка можно перетащить или дважды щелкнуть мышью, и Aero Snap работает.

Затем я попытался заменить центральный QLabel на QWebEngineView. Это привело к появлению серых границ собственного размера вокруг моего окна. Когда у меня есть интерактивные виджеты в верхней части окна (например, меню или панель инструментов), строка заголовка «призрак» с QWebEngineView опускает их вниз, но принимает щелчки курсора на их месте.

Вот скриншот, сравнивающий два окна. (Просмотрите его на темном фоне, чтобы лучше видеть светло-серую рамку справа.)

Окна QLabel и QWebEngineView

Совместим ли QWebEngineView с безрамным окном или я должен иметь дело с потраченным впустую пространством родного окна Chrome?


Редактировать: Замена QWebEngineView на QWebView позволяет избежать этой проблемы:

Окно QWebView

Тем не менее, WebView устарел и WebEngine имеет более полезные функции:

  • Рендеринг с Blink Chromium вместо WebKit Safari
  • Многопроцессорность, поэтому вы можете запускать Javascript без блокировки пользовательского интерфейса
  • Не пропускает информацию о плагине браузера Panopticlick (попробуйте, QWebView заполняет navigator.plugins в Javascript, но QWebEngineView нет)

Тем не менее, я бы действительно предпочел не тратить место на родной строке заголовка, поэтому, если QWebEngineView можно настроить для работы с безрамным окном, я хотел бы знать, как это сделать.


mainwindow.h:

#include <QtWidgets>
#include <QToolBar>

class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow();
protected:
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
private:
QToolBar *titleBar;
};

mainwindow.cpp:

#include <QtWidgets>
#include <QLabel>
#include <QWebEngineView>
#include <windows.h>
#include <windowsx.h>
#include "mainwindow.h"
MainWindow::MainWindow() : QMainWindow() {
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
titleBar = addToolBar(tr("Title Bar"));
titleBar->setIconSize(QSize(16, 16));
titleBar->setFloatable(false);
titleBar->setMovable(false);
titleBar->setStyleSheet("QToolBar { background: red; border: 0; padding: 0; }");
titleBar->addWidget(new QLabel("Title Bar", titleBar));
// Try QLabel...
QLabel *central = new QLabel("Hello World");
// ...or QWebEngineView
//QWebEngineView *central = new QWebEngineView(this);
//central->load(QUrl("http://www.google.com"));
setCentralWidget(central);
resize(320, 240);
}

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) {
Q_UNUSED(eventType);
MSG *msg = (MSG *)message;
HWND hwnd = isVisible() ? (HWND)winId() : NULL;
LPARAM lparam = msg->lParam;
const LONG border_width = 4;
RECT winrect;
long x, y;
switch (msg->message) {
case WM_NCCALCSIZE:
result = 0;
return true;
case WM_NCHITTEST:
GetWindowRect(hwnd, &winrect);
x = GET_X_LPARAM(lparam);
y = GET_Y_LPARAM(lparam);
if (x >= winrect.left && x < winrect.left + border_width &&
y < winrect.bottom && y >= winrect.bottom - border_width)
*result = HTBOTTOMLEFT;
else if (x < winrect.right && x >= winrect.right - border_width &&
y < winrect.bottom && y >= winrect.bottom - border_width)
*result = HTBOTTOMRIGHT;
else if (x >= winrect.left && x < winrect.left + border_width &&
y >= winrect.top && y < winrect.top + border_width)
*result = HTTOPLEFT;
else if (x < winrect.right && x >= winrect.right - border_width &&
y >= winrect.top && y < winrect.top + border_width)
*result = HTTOPRIGHT;
else if (x >= winrect.left && x < winrect.left + border_width)
*result = HTLEFT;
else if (x < winrect.right && x >= winrect.right - border_width)
*result = HTRIGHT;
else if (y < winrect.bottom && y >= winrect.bottom - border_width)
*result = HTBOTTOM;
else if (y >= winrect.top && y < winrect.top + border_width)
*result = HTTOP;
else if (titleBar->underMouse())
*result = HTCAPTION;
else
break;
return true;
}
return QMainWindow::nativeEvent(eventType, message, result);
}

void MainWindow::showEvent(QShowEvent *event) {
Q_UNUSED(event);
HWND hwnd = (HWND)winId();
DWORD newStyle = WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
SetWindowLongPtr(hwnd, GWL_STYLE, static_cast<LONG>(newStyle));
SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(hwnd, SW_SHOW);
}

main.cpp:

#include <QtWidgets>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow *window = new MainWindow();
window->show();
return app.exec();
}

example.pro:

QT += core gui widgets webenginewidgets
msvc:LIBS += -luser32
TEMPLATE = app
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h

5

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]