一起学libcef--一个应用libcef的简单例子(windows程序)

之前博客《一起学libcef–搭建自己的libcef运行环境(Win32程序,错误C2220解决方案)》讲述了如何在win32程序中搭建libcef的环境,今天就通过一个简单的例子,在windows程序中使用libcef。

现在再重新写一下如何搞?直接在源代码上搞起!
1 打开源码cefclient解决方案
2 确保cefclient例子可以完美运行
3 在cefclient中,除了util.h之外,全部移除
4 manifests 和 resources文件也可以移除(you must remember to remove the additional manifest files from the Visual Studio project file.)
5 libcef_dll_wrapper 是静态链接,所以我们需要更改项目为动态链接。

接下来就要干我们的事儿了:
1 创建一个自己的头文件ExampleCefApp.h, 在这里新建一个类,继承自CefApp:
CefApp 负责所有的工作, 但是这是一个抽象类,需要计数实现
这样, 我们继承自CefApp创建了一个傀儡类,实际上也什么都没做

#include "include/cef_app.h"
class ExampleCefApp : public CefApp
{
   public:
      ExampleCefApp ()
      {
      }
      virtual ~ExampleCefApp ()
      {
      }

   private:
      IMPLEMENT_REFCOUNTING (ExampleCefApp);
};

2创建一个ExampleCefHandler.h文件,这里面实现一个类继承自所有的event handling classes。

#pragma once

#include "include/cef_client.h"
#include "cefclient/util.h"

class ExampleCefHandler : public CefClient,
                          public CefContextMenuHandler,
                          public CefDisplayHandler,
                          public CefDownloadHandler,
                          public CefDragHandler,
                          public CefGeolocationHandler,
                          public CefKeyboardHandler,
                          public CefLifeSpanHandler,
                          public CefLoadHandler,
                          public CefRequestHandler
{
 public:
      ExampleCefHandler();
      virtual ~ExampleCefHandler();
      CefRefPtr<CefBrowser> GetBrowser();

#pragma region CefClient
      // since we are letting the base implementations handle all of the heavy lifting,
      // these functions just return the this pointer
      virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler () OVERRIDE;
      virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler () OVERRIDE;
      virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler () OVERRIDE;
      virtual CefRefPtr<CefDragHandler> GetDragHandler () OVERRIDE;
      virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler () OVERRIDE;
      virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler () OVERRIDE;
      virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler () OVERRIDE;
      virtual CefRefPtr<CefLoadHandler> GetLoadHandler () OVERRIDE;
      virtual CefRefPtr<CefRequestHandler> GetRequestHandler () OVERRIDE;
#pragma endregion // CefClient

#pragma region CefDownloadHandler
      // 这个函数为虚函数,我们必须实现它。但是我们什么也没做,所以下载文件的操作不会工作
      virtual void OnBeforeDownload (CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback);
#pragma endregion // CefDownloadHandler 

#pragma region CefLifeSpanHandler
      // 缓存一个指向browser的引用
      virtual void OnAfterCreated (CefRefPtr<CefBrowser> browser) OVERRIDE;

      // 释放browser引用
      virtual void OnBeforeClose (CefRefPtr<CefBrowser> browser) OVERRIDE;
#pragma endregion // CefLifeSpanHandler 

 protected:
      // the browser reference
      CefRefPtr<CefBrowser> browser;

      // Include the default reference counting implementation.
      IMPLEMENT_REFCOUNTING (ExampleCefHandler);
      // Include the default locking implementation.
      IMPLEMENT_LOCKING (ExampleCefHandler);
};

3.创建一个源文件 ExampleCefHandler.cc:

#include "cefclient/ExampleCefHandler.h"

// defined in main.cppp
extern void AppQuitMessageLoop ();

ExampleCefHandler::ExampleCefHandler ()
{
}

ExampleCefHandler::~ExampleCefHandler ()
{
}

CefRefPtr<CefBrowser> ExampleCefHandler::GetBrowser ()
{
   return browser;
}

CefRefPtr<CefContextMenuHandler> ExampleCefHandler::GetContextMenuHandler () 
{
   return this;
}

CefRefPtr<CefDisplayHandler> ExampleCefHandler::GetDisplayHandler () 
{
   return this;
}

CefRefPtr<CefDownloadHandler> ExampleCefHandler::GetDownloadHandler () 
{
   return this;
}

CefRefPtr<CefDragHandler> ExampleCefHandler::GetDragHandler () 
{
   return this;
}

CefRefPtr<CefGeolocationHandler> ExampleCefHandler::GetGeolocationHandler ()
{
   return this;
}

CefRefPtr<CefKeyboardHandler> ExampleCefHandler::GetKeyboardHandler () 
{
   return this;
}

CefRefPtr<CefLifeSpanHandler> ExampleCefHandler::GetLifeSpanHandler () 
{
   return this;
}

CefRefPtr<CefLoadHandler> ExampleCefHandler::GetLoadHandler () 
{
   return this;
}

CefRefPtr<CefRequestHandler> ExampleCefHandler::GetRequestHandler () 
{
   return this;
}

void ExampleCefHandler::OnBeforeDownload (CefRefPtr<CefBrowser> browser, 
CefRefPtr<CefDownloadItem> download_item, 
const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback)
{
   UNREFERENCED_PARAMETER (browser);
   UNREFERENCED_PARAMETER (download_item);
   callback->Continue (suggested_name, true);
}

void ExampleCefHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
  REQUIRE_UI_THREAD();
  AutoLock lock_scope (this);

  this->browser = browser;

  CefLifeSpanHandler::OnAfterCreated (browser);
}

void ExampleCefHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) 
{
  REQUIRE_UI_THREAD();
  AutoLock lock_scope (this);

  browser = NULL;
  AppQuitMessageLoop();

  CefLifeSpanHandler::OnBeforeClose (browser);
}

4. 最后,创建一个主函数:

#include "cefclient/ExampleCefApp.hpp"
#include "cefclient/ExampleCefHandler.hpp"
#include "cefclient/util.h"
#include <windows.h>

#define BROWSER_WINDOW_CLASS TEXT("BrowserWindowClass")
#define INVALID_HWND (HWND)INVALID_HANDLE_VALUE
#define MESSAGE_WINDOW_CLASS TEXT("MessageWindowClass")
#define QUIT_CEF_EXAMPLE 0xABAD1DEA

namespace
{
   CefRefPtr<ExampleCefHandler> example_cef_handler;
   HWND application_message_window_handle = INVALID_HWND;
}

LRESULT CALLBACK BrowserWindowWndProc (HWND, UINT, WPARAM, LPARAM);
void CreateBrowserWindow (HINSTANCE instance_handle, int show_minimize_or_maximize)
{
   WNDCLASSEX wcex = { 0 };
   wcex.cbSize        = sizeof (wcex);
   wcex.style         = CS_HREDRAW | CS_VREDRAW;
   wcex.lpfnWndProc   = BrowserWindowWndProc;
   wcex.hInstance     = instance_handle;
   wcex.hCursor       = LoadCursor (NULL, IDC_ARROW);
   wcex.hbrBackground = WHITE_BRUSH;
   wcex.lpszClassName = BROWSER_WINDOW_CLASS;
   RegisterClassEx (&wcex);
   HWND window_handle (CreateWindow (BROWSER_WINDOW_CLASS, BROWSER_WINDOW_CLASS, 
   WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, 0, 
   CW_USEDEFAULT, 0, NULL, NULL, instance_handle, NULL));
   ShowWindow (window_handle, show_minimize_or_maximize);
   UpdateWindow (window_handle);
}

LRESULT CALLBACK MessageWindowWndProc (HWND, UINT, WPARAM, LPARAM);
HWND CreateMessageWindow (HINSTANCE instance_handle)
{
   WNDCLASSEX wcex    = {0};
   wcex.cbSize        = sizeof (wcex);
   wcex.lpfnWndProc   = MessageWindowWndProc;
   wcex.hInstance     = instance_handle;
   wcex.lpszClassName = MESSAGE_WINDOW_CLASS;
   RegisterClassEx (&wcex);
   return CreateWindow (MESSAGE_WINDOW_CLASS, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, instance_handle, 0);
}

// Program entry point function.
int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
   UNREFERENCED_PARAMETER (hPrevInstance);
   UNREFERENCED_PARAMETER (lpCmdLine);

   int result (0);
   CefMainArgs main_args (hInstance);
   CefRefPtr<ExampleCefApp> app (new ExampleCefApp);

   // CefExecuteProcess returns -1 for the host process
   if (CefExecuteProcess(main_args, app.get()) == -1)
   {
      CefSettings settings;
      settings.multi_threaded_message_loop = true;
      CefInitialize (main_args, settings, app.get ());
      CreateBrowserWindow (hInstance, nCmdShow);
      application_message_window_handle = CreateMessageWindow (hInstance);

      MSG msg;
      while (GetMessage (&msg, NULL, 0, 0))
      {
         TranslateMessage (&msg);
         DispatchMessage (&msg);
      }
      result = static_cast<int>(msg.wParam);

      DestroyWindow (application_message_window_handle);
      application_message_window_handle = INVALID_HWND;

      // disabled due to https://code.google.com/p/chromiumembedded/issues/detail?id=755
      // CefShutdown ();

      UnregisterClass (BROWSER_WINDOW_CLASS, hInstance);
      UnregisterClass (MESSAGE_WINDOW_CLASS, hInstance);
   }
   return result;
}

LRESULT CALLBACK BrowserWindowWndProc (HWND window_handle, UINT message, WPARAM w_param, LPARAM l_param)
{
   LRESULT result (0);
   switch (message)
   {
      case WM_CREATE:
         {
            example_cef_handler = new ExampleCefHandler();

            RECT rect = { 0 };
            GetClientRect (window_handle, &rect);

            CefWindowInfo info;
            info.SetAsChild(window_handle, rect);

            CefBrowserSettings settings;
            CefBrowserHost::CreateBrowser(info, example_cef_handler.get(), 
            CefString ("http://www.google.com"), settings, NULL);
         }
         break;

      case WM_SIZE:
         {
            // from the cefclient example, do not allow the window to be resized to 0x0 or the layout will break;
            // also be aware that if the size gets too small, GPU acceleration disables
            if ((w_param != SIZE_MINIMIZED)
             && (example_cef_handler.get ())
             && (example_cef_handler->GetBrowser ()))
            {
               CefWindowHandle hwnd (example_cef_handler->GetBrowser ()->GetHost ()->GetWindowHandle ()); if (hwnd) { RECT rect = { 0 }; GetClientRect (window_handle, &rect); HDWP hdwp = BeginDeferWindowPos (1); hdwp = DeferWindowPos (hdwp, hwnd, NULL,rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); EndDeferWindowPos (hdwp); } } } break; case WM_ERASEBKGND: { if ((example_cef_handler.get ()) && (example_cef_handler->GetBrowser ())) { CefWindowHandle hwnd (example_cef_handler->GetBrowser()->GetHost()->GetWindowHandle()); // from the cefclient example, don't erase the background // if the browser window has been loaded to avoid flashing result = hwnd ? 1 : DefWindowProc (window_handle, message, w_param, l_param); } } break; case WM_ENTERMENULOOP: { if (!w_param) { CefSetOSModalLoop (true); } result = DefWindowProc (window_handle, message, w_param, l_param); } break; case WM_EXITMENULOOP: { if (!w_param) { CefSetOSModalLoop (false); } result = DefWindowProc (window_handle, message, w_param, l_param); } break; case WM_DESTROY: break; default: { result = DefWindowProc (window_handle, message, w_param, l_param); } break; } return result; } LRESULT CALLBACK MessageWindowWndProc (HWND window_handle, UINT message, WPARAM w_param, LPARAM l_param) { LRESULT result (0); switch (message) { case WM_COMMAND: { if (w_param == QUIT_CEF_EXAMPLE) { PostQuitMessage(0); } } break; default: { result = DefWindowProc (window_handle, message, w_param, l_param); } break; } return result; } void AppQuitMessageLoop () { if (application_message_window_handle != INVALID_HWND) { PostMessage(application_message_window_handle, WM_COMMAND, QUIT_CEF_EXAMPLE, 0); } }

你可能感兴趣的:(windows,libcef)