Qt 集成miniblink浏览器库之4 解决兼容性问题
之前介紹了如何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就可以拿到,這樣就實現這種方法的集成。經測試這種方法表現良好。
?
如果需要完整源碼可以留言
總結
以上是生活随笔為你收集整理的Qt 集成miniblink浏览器库之4 解决兼容性问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【超详细】手把手教你搭建MongoDB集
- 下一篇: 支持harmonyOS的穿戴设备,鸿蒙2