Qt 集成miniblink浏览器库之4 解决兼容性问题

19 篇文章 1 订阅
2 篇文章 0 订阅

之前介绍了如何miniblink集成到qt,采用wkeCreateWebWindow来创建一个浏览器窗口,wkeCreateWebWindow有三种方式

typedef enum _wkeWindowType {
    WKE_WINDOW_TYPE_POPUP,
    WKE_WINDOW_TYPE_TRANSPARENT,
    WKE_WINDOW_TYPE_CONTROL
} wkeWindowType;

WKE_WINDOW_TYPE_POPUP 创建一个弹出式窗体,模态窗体。

WKE_WINDOW_TYPE_TRANSPARENT 透明父窗口窗体

WKE_WINDOW_TYPE_CONTROL  创建一个弹出式窗体,非模态窗体。

因为要实现成一个qtwidget的子窗体,所以用了WKE_WINDOW_TYPE_TRANSPARENT来创建浏览器窗口,qt两种方式其实应用场景很有限。

这个属性创建的窗体在win7,surface系统表现异常,出现渲染布出来问题, 只有win10 表现还过得去。最后发现是因为我同时使用了两种浏览器QtWebengineView和miniblink浏览器,这两种窗体在不同系统中兼容性存在问题。

如果只是放到qtwidget上面没有啥问题。

尝试了如下方法:

1.使用WKE_WINDOW_TYPE_POPUP/WKE_WINDOW_TYPE_CONTROL表现正常,但是跟其他窗体存在层级问题

2.使用WKE_WINDOW_TYPE_TRANSPARENT创建,将窗体独立,跟上面的基本一样,不止存在层级问题,win10多桌面显示也存在问题。

所以wkeCreateWebWindow无法满足需求。

看了一下接口文件发现一个wkeCreateWebView,该函数只是创建一个对象,并不会真正绘制,绘制需要自己处理。

1.创建对象

    _hWebView = wkeCreateWebView();
    wkeSetTransparent(_hWebView, false);
    wkeOnPaintUpdated(_hWebView, onPaintUpdatedCallback, this);
    wkeOnLoadUrlBegin(_hWebView, onLoadUrlBegin, (void *)this);
    wkeOnLoadUrlEnd(_hWebView, onLoadUrlEnd, (void *)this);
    wkeOnLoadUrlFail(_hWebView, onLoadUrlFailed, (void *)this);
    wkeOnLoadingFinish(_hWebView, onLoadingFinish, (void *)this);

最重要的回调函数是onPaintUpdatedCallback,因为要自己绘制,改接口在需要绘制时会回调回来。原型为:

static void onPaintUpdatedCallback(wkeWebView webView, void* param, const HDC hdc, int x, int y, int cx, int cy);

返回的是HDC,所以我们需要一个绘制窗口

2.创建一个windows 窗口对象

注册窗口类:

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_DBLCLKS;// CS_HREDRAW | CS_VREDRAW; //
    wcex.lpfnWndProc = webViewWndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hIcon = 0;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground = 0;
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = wkeWebViewClassName;
    wcex.hIconSm = 0;

    return !!RegisterClassEx(&wcex);

创建窗口:

 _hWnd = CreateWindow(wkeWebViewClassName, 0,
        WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
        x, y, nWeight, nHeight,
        hParent,
        0,
        0, 0);

3. 使用GDI绘制

将miniblink dc的内同绘制到我们创建窗体之上

        HDC hScreenDC = ::GetDC(m_hView);
        ::BitBlt(m_hDC, x, y, m_width, m_height, hBlinkDC, x, y, SRCCOPY);
        ::BitBlt(hScreenDC, x, y, m_width, m_height, m_hDC, x, y, SRCCOPY);
        ::ReleaseDC(m_hView, hScreenDC);

4.事件处理

这种方式需要我们自己处理键盘事件,鼠标事件 如下:

LRESULT QtMiniblinkWebView::webViewClassWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_SETCURSOR:
        return onSetCursor(wParam, lParam);
    case WM_COMMAND:
        return onCommand(wParam, lParam);
    case WM_SIZE:
        return onSize(wParam, lParam);
    case WM_PAINT:
        return onPaint(wParam, lParam);
    case WM_KEYDOWN:
        return onKeyDown(wParam, lParam);
    case WM_KEYUP:
        return onKeyUp(wParam, lParam);
    case WM_CHAR:
        return onChar(wParam, lParam);
    case WM_LBUTTONDOWN:
    case WM_MBUTTONDOWN:
    case WM_RBUTTONDOWN:
    case WM_LBUTTONDBLCLK:
    case WM_MBUTTONDBLCLK:
    case WM_RBUTTONDBLCLK:
    case WM_LBUTTONUP:
    case WM_MBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MOUSEMOVE:
        return onMouseEvent(uMsg, wParam, lParam);

    case WM_MOUSEWHEEL:
        return onMouseWheel(wParam, lParam);
    case WM_SETFOCUS:
        return onSetFocus(wParam, lParam);

    case WM_KILLFOCUS:
        return onKillFocus(wParam, lParam);
    case WM_IME_STARTCOMPOSITION:
        return onIMEStartComposition(wParam, lParam);
    case WM_GETDLGCODE:
        return DLGC_WANTARROWS | DLGC_WANTALLKEYS | DLGC_WANTCHARS;
    default:
        return DefWindowProc(_hWnd, uMsg, wParam, lParam);
    }

    return 0;
}

其实就是将windows定义的消息转化为miniblink定义的对应消息,通过函数调用过去,如鼠标

LRESULT QtMiniblinkWebView::onMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    _cursorInfoType = wkeGetCursorInfoType(_hWebView);

    if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MBUTTONDOWN || uMsg == WM_RBUTTONDOWN) {
        SetFocus(_hWnd);
        SetCapture(_hWnd);
    } else if (uMsg == WM_LBUTTONUP || uMsg == WM_MBUTTONUP || uMsg == WM_RBUTTONUP) {
        ReleaseCapture();
    }

    int x = GET_X_LPARAM(lParam);
    int y = GET_Y_LPARAM(lParam);

    unsigned int flags = 0;

    if (wParam & MK_CONTROL)
        flags |= WKE_CONTROL;
    if (wParam & MK_SHIFT)
        flags |= WKE_SHIFT;

    if (wParam & MK_LBUTTON)
        flags |= WKE_LBUTTON;
    if (wParam & MK_MBUTTON)
        flags |= WKE_MBUTTON;
    if (wParam & MK_RBUTTON)
        flags |= WKE_RBUTTON;

    //flags = wParam;

    wkeFireMouseEvent(_hWebView, uMsg, x, y, flags);

    return 0;
}

 

其他消息类似

5.win7最小化恢复未渲染

    //win7最小化问题
    connect(qApp, &QApplication::applicationStateChanged, this, [=](Qt::ApplicationState state)
        {
            if (Qt::ApplicationActive == state)
            {
                RECT rc;
                ::GetClientRect(_hWnd, &rc);
                int width = rc.right - rc.left;
                int height = rc.bottom - rc.top;
                //repaint
                resize(0, 0, width-1, height-1);
                resize(0, 0, width, height);
            }
        }
        );

6.创建接口

BOOL QtMiniblinkWebView::create(int x, int y, int nWeight, int nHeight, HWND hParent)
{
    if(!_isInit)
        initialize();

    _hWebView = wkeCreateWebView();
    wkeSetTransparent(_hWebView, false);
    wkeOnPaintUpdated(_hWebView, onPaintUpdatedCallback, this);
    wkeOnLoadUrlBegin(_hWebView, onLoadUrlBegin, (void *)this);
    wkeOnLoadUrlEnd(_hWebView, onLoadUrlEnd, (void *)this);
    wkeOnLoadUrlFail(_hWebView, onLoadUrlFailed, (void *)this);
    wkeOnLoadingFinish(_hWebView, onLoadingFinish, (void *)this);
    if (!_hWebView)
    {
        return FALSE;
    }

    if (!registerControlerClass())
    {
        return FALSE;
    }

    _hWnd = CreateWindow(wkeWebViewClassName, 0,
        WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
        x, y, nWeight, nHeight,
        hParent,
        0,
        0, 0);

    if (INVALID_HANDLE_VALUE == _hWnd)
    {
        return FALSE;
    }

    _hParent = hParent;

    wkeSetHandle(_hWebView, _hWnd);
    resize(x, y, nWeight, nHeight);
    SetWindowLong(_hWnd, GWL_USERDATA, (LONG)this);
    SetWindowSubclass(_hParent, subClassProc, 0, (DWORD_PTR)this);
    return _pRender->init(_hWnd);
}

从创建接口可以看到我们可以传递父窗口,通过qt winId就可以拿到,这样就实现这种方法的集成。经测试这种方法表现良好。

 

如果需要完整源码可以留言

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值