Браузер CEF3 неправильно отображает страницы

Я работал над отображением окна браузера Chromium Embedded Framework в моем окне win32 без полей. Пока что окно создано и браузер загружается, но возникли две проблемы.

  1. Похоже, что сообщения не отправляются в мой обратный вызов окна (что, конечно, приводит к тому, что перетаскивание окна не работает).
  2. Браузер искажает страницы (почти как загружается только какой-то css)

Я предполагаю, что это связано с какой-то вопиющей ошибкой, которую я допустил при реализации CEF3. То, что у меня есть, собрано из двух примеров проектов, которые поставляются с ночной сборкой CEF3. Итак, вопрос в том, видит ли кто-нибудь какие-либо явные ошибки, которые я допустил при реализации браузера?

Вот мой Main.cpp

#include <Windows.h>

#include "include/cef_base.h"
#include "include/cef_app.h"
#include "ClientApp.h"
#include "ClientHandler.h"

#pragma comment(lib, "lib/libcef.lib")
#pragma comment(lib, "lib/libcef_dll_wrapper.lib")

// Fix Conflicting Macros
#define GET_X_LPARAM(lp)    ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp)    ((int)(short)HIWORD(lp))

// Window Variables
HINSTANCE g_instance;
HWND g_hwnd;
LPCWSTR g_window_class = L"MyUI";
INT g_window_width = 670;
INT g_window_height = 540;
BOOL g_drag_window = false;
SHORT g_mouse_x, g_mouse_y, g_mouse_x_prev, g_mouse_y_prev;

// CEF Variables
CefRefPtr<ClientApp> g_app;
CefRefPtr<ClientHandler> g_client_handler;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
        {
            CefQuitMessageLoop();
            PostQuitMessage(0);
            break;
        }

        case WM_CREATE:
        {
            // Set window attributes
            RECT rect;
            GetClientRect(hWnd, &rect);
            CefWindowInfo info;
            info.SetAsChild(hWnd, rect);

            // Set browser settings
            CefBrowserSettings settings;

            //Create handler
            ::g_client_handler = new ClientHandler();

            // Create browser
            CefBrowserHost::CreateBrowserSync(info, ::g_client_handler.get(), 
                "http://wikipedia.com", settings, NULL);

            break;
        }

        case WM_LBUTTONDOWN:
        {
            g_mouse_x = GET_X_LPARAM(lParam);
            g_mouse_y = GET_Y_LPARAM(lParam);
            if (g_mouse_y < 41)
            {
                g_mouse_x_prev = g_mouse_x;
                g_mouse_y_prev = g_mouse_y;
                SetCapture(hWnd);
                g_drag_window = true;
            }
            MessageBox(NULL, L"FLDKSJA", L"", MB_OK);
            break;
        }

        case WM_LBUTTONUP:
        {
            if (g_drag_window)
            {
                g_drag_window = false;
                ReleaseCapture();
            }
            break;
        }

        case WM_MOUSEMOVE:
        {
            if (g_drag_window && (wParam & MK_LBUTTON))
            {
                // code executed when the dialog window is moved around on the screen
                RECT win_rect;
                GetWindowRect(hWnd, &win_rect);
                int x_coord = GET_X_LPARAM(lParam);
                int y_coord = GET_Y_LPARAM(lParam);
                MoveWindow(hWnd,
                    win_rect.left + x_coord - g_mouse_x_prev,
                    win_rect.top + y_coord - g_mouse_y_prev,
                    win_rect.right - win_rect.left,
                    win_rect.bottom - win_rect.top,
                    false
                    );
                return 0;
            }
            break;
        }

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

BOOL InitWindow()
{
    WNDCLASSEX wc;

    // Register window class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_DROPSHADOW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = ::g_instance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = ::g_window_class;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        wchar_t msg[100];
        wsprintf(msg, L"Unable to register class!\nError: %i", GetLastError());
        MessageBox(NULL, msg, L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return FALSE;
    }

    // Create window
    ::g_hwnd = CreateWindowEx(
        0,                        // Optional window styles.
        ::g_window_class,         // Window class
        L"",                      // Window text
        WS_POPUP,     // Window style

        // Position and size
        CW_USEDEFAULT, CW_USEDEFAULT, ::g_window_width, ::g_window_height,

        NULL,       // Parent window    
        NULL,       // Menu
        ::g_instance,  // Instance handle
        NULL        // Additional application data
        );

    if (!::g_hwnd)
    {
        wchar_t msg[100];
        wsprintf(msg, L"Unable to create window!\nError: %i", GetLastError());
        MessageBox(NULL, msg, L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return FALSE;
    }

    //Display window
    ShowWindow(::g_hwnd, SW_SHOWNORMAL);
    UpdateWindow(::g_hwnd);

    return TRUE;
}

INT APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, INT nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    ::g_instance = hInstance;

    // Provide CEF with command-line arguments.
    CefMainArgs main_args(hInstance);

    // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
    // that share the same executable. This function checks the command-line and,
    // if this is a sub-process, executes the appropriate logic.
    int exit_code = CefExecuteProcess(main_args, NULL, NULL);
    if (exit_code >= 0) {
        // The sub-process has completed so return here.
        return exit_code;
    }

    // Specify CEF global settings here.
    CefSettings settings;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = false;
    settings.pack_loading_disabled = true;

    // ClientApp implements application-level callbacks for the browser process.
    ::g_app = new ClientApp();

    // Initialize CEF.
    CefInitialize(main_args, settings, ::g_app.get(), NULL);

    // Create main window.
    if (!InitWindow())
    {
        CefShutdown();
        return 1;
    }

    // Process messages.
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);

        CefDoMessageLoopWork();
    }

    // Shut down CEF.
    CefShutdown();

    return 0;
}

ClientApp.h

#pragma once
#include "include/cef_app.h"

class ClientApp : public CefApp,
                  public CefBrowserProcessHandler,
                  public CefRenderProcessHandler
{
public:
    ClientApp();
    ~ClientApp();

    // CefBase
    IMPLEMENT_REFCOUNTING(ClientApp);

    // CefApp
    virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
    {
        return this; 
    }

    virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()
    {
        return this;
    }

    //Context
    virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
        CefRefPtr<CefFrame> frame,
        CefRefPtr<CefV8Context> context);
};

ClientHandler.h

#pragma once
#include "include\cef_client.h"

class ClientHandler : public CefClient,
                      public CefLifeSpanHandler,
                      public CefLoadHandler
{
public:
    ClientHandler();
    ~ClientHandler();

    // CefClient
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler()
    {
        return this;
    }
    virtual CefRefPtr<CefLoadHandler> GetLoadHandler()
    { 
        return this;
    }


    // CefBase
    IMPLEMENT_REFCOUNTING(ClientHandler);
};

И вот как браузер отображает Wikipedia.com:  введите описание изображения здесь


person Dalton Sandbothe    schedule 22.01.2016    source источник


Ответы (1)


Вот общий код для однопоточных и многопоточных.

if (!settings.multi_threaded_message_loop) {
  // Run the CEF message loop. Blocks until recieves a WM_QUIT message.
  CefRunMessageLoop();
} else {
  MSG msg;
  // Run the application message loop.
  while (GetMessage(&msg, NULL, 0, 0)) {
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

Другими словами, попробуйте только CefRunMessageLoop ().

person AlienRancher    schedule 23.01.2016