5

QWebView またはより最新の QWebEngineView を介した WebKit サポートが組み込まれているため、Qt でクロスプラットフォーム Web ブラウザーを作成しています。コンパクトなウィンドウ クロムを取得するには、Qt::FramelessWindowHint を介してネイティブ ウィンドウのタイトル バーと境界線を無効にしますが、サイズ変更や Windows の Aero Snap などのネイティブな動作は引き続き取得します。

まず、PKEBorderlessWindowデモを切り詰めました。Windows 8.1 x64 では、ウィンドウのサイズを変更でき、カスタム タイトル バーをドラッグまたはダブルクリックでき、Aero Snap が機能します。

次に、中央の QLabel を QWebEngineView に置き換えてみました。これにより、ウィンドウの周りに灰色のネイティブ サイズの境界線が表示されました。ウィンドウの上部にインタラクティブ ウィジェット (メニューやツールバーなど) がある場合、QWebEngineView の「ゴースト」タイトル バーがそれらを押し下げますが、その場所でカーソル クリックを受け入れます。

2 つのウィンドウを比較したスクリーンショットを次に示します。(暗い背景で表示すると、右側の薄い灰色の境界線がよく見えます。)

QLabel および QWebEngineView ウィンドウ

QWebEngineView はフレームレス ウィンドウとまったく互換性がありますか、それともネイティブ ウィンドウ クロムの無駄なスペースに対処する必要がありますか?


編集: QWebEngineView を QWebView に置き換えると、この問題が回避されます。

QWebView ウィンドウ

ただし、WebView は推奨されておらず、WebEngine にはさらに便利な機能があります。

  • Safari の WebKit の代わりに Chromium の Blink でレンダリングします
  • マルチプロセスなので、UI をロックせずに Javascript を実行できます
  • Panopticlickでブラウザ プラグインの詳細を漏らしません(試してみてください。QWebView は Javascript で navigator.plugins を入力しますが、QWebEngineView はしません)。

それでも、ネイティブ タイトル バーのスペースを無駄にしたくないので、QWebEngineView をフレームレス ウィンドウで動作させることができるなら、その方法を知りたいです。


メインウィンドウ.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;
};

メインウィンドウ.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
4

0 に答える 0