CEF3 C++接口實現自定義瀏覽器[simple version]

目錄

目錄... 1

一、工具準備... 2

二、編譯C++接口... 2

三、實現瀏覽器... 5

瀏覽器定製... 5

瀏覽器默認最大化,標題從配置文件讀取... 5

設置瀏覽器中文環境,開啓npapi插件功能,並註冊身份證閱讀器插件(見第四節)    7

文件下載... 8

首先瀏覽器處理類要繼承CefDownloadHandler 類... 8

並提供回調接口(繼承任何處理類都要提供類似的回調接口)... 8

文件下載具體重載函數... 8

文件下載重載函數實現... 9

F5刷新功能... 10

繼承按鍵處理類... 10

提供回調接口... 10

重載聲明... 11

重載實現... 11

右鍵菜單添加刷新按鈕... 12

繼承菜單處理類... 12

提供回調接口... 12

重載聲明... 12

重載實現... 13

四、身份證閱讀器插件開發... 14

工程建立... 14

首先下載npapi插件開發包,解壓進入... 14

新建win32 dll工程,工程名以NP開頭,將上圖的文件引入工程。... 14

新建stdafx.h頭文件,加入... 15

設置預處理... 16

設置頭文件包含... 16

功能實現... 17

加載身份證識別模塊... 17

定義功能標識... 17

實現具體功能... 18

定義插件模塊,其中MIMEType,是在html中調用的關鍵字... 19

生成插件... 20

插件部署... 20

插件測試... 21

插件調試... 23

瀏覽器增加啓動參數... 23

啓動瀏覽器... 24

在vs中打好斷點,附加到進程... 24

進入斷點... 25

 

一、工具準備

  1. vs 2017 community
  2. cmake 3.7 +
  3. cef_binary_3.2357.1271.g8e0674e_windows32,包含已編譯好的c接口動態庫和c++接口源碼,C++接口默認沒有編譯,以源碼提供

 

 

二、編譯C++接口

生成vs工程

進入cef源碼根目錄,進入libcef_dll。此目錄是c++接口源碼目錄。C接口動態庫放在根目錄的Release目錄中。輸入命令cmake -G "Visual Studio 15",生成VS工程

 

打開vs工程

 

右擊項目“libcef_dll_wrapper”,設置頭文件包含目錄

 

加入預處理命令  NOMINMAX

 

生成“libcef_dll_wrapper”項目

生成的c++接口

三、實現瀏覽器

瀏覽器定製

新建一個win32GUI的空工程,將cef目錄下的cefsimple相關文件拷貝進來,cefsimple實現很簡單就是打開一個網頁,我們來新增一些功能

 

 

瀏覽器默認最大化,標題從配置文件讀取

void SimpleApp::OnContextInitialized() {

  CEF_REQUIRE_UI_THREAD();

 

  // Information used when creating the native window.

  CefWindowInfo window_info;

 

#if defined(OS_WIN)

  // On Windows we need to specify certain flags that will be passed to

  // CreateWindowEx().

  window_info.SetAsPopup(NULL, "cefsimple");

#endif

 

  // 設置窗口樣式

  window_info.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE;

  UINT width = GetSystemMetrics(SM_CXSCREEN);

  UINT height = GetSystemMetrics(SM_CYSCREEN);

  window_info.parent_window = NULL;

  window_info.x = -1;

  window_info.y = -1;

  window_info.width = width;

  window_info.height = height;

 

  // SimpleHandler implements browser-level callbacks.

  CefRefPtr<SimpleHandler> handler(new SimpleHandler());

 

  // Specify CEF browser settings here.

  CefBrowserSettings browser_settings;

  char * code = "UTF-8";

  cef_string_t encode = {};

  cef_string_utf8_to_utf16(code, strlen(code), &encode);

  browser_settings.default_encoding = encode;

 

  //設置窗口標題

  WCHAR window_name[1024];

  GetPrivateProfileStringW(L"GMS", L"title", L"", window_name, 1024, L".\\gms.ini");

  cef_string_wide_to_utf16(window_name, wcslen(window_name), &window_info.window_name);

 

  // 設置訪問地址

  char url[1024];

  GetPrivateProfileStringA("GMS", "url", "", url, 1024, ".\\gms.ini");

 

 

  // Create the first browser window.

 

  CefBrowserHost::CreateBrowser(window_info, handler.get(), url, browser_settings, NULL);

}

 

設置瀏覽器中文環境,開啓npapi插件功能,並註冊身份證閱讀器插件(見第四節)

void SimpleApp::OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr<CefCommandLine> command_line) {

    //開啓插件

    command_line->AppendSwitch("--enable-npapi");

    //設置中文語言環境

    command_line->AppendSwitchWithValue("--lang", "zh-CN");

    command_line->AppendSwitchWithValue("register-netscape-plugins","NPRDCARD.dll/nprdcard-plugin");

    return;

}

文件下載

首先瀏覽器處理類要繼承CefDownloadHandler 類

並提供回調接口(繼承任何處理類都要提供類似的回調接口)

  virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() //實現 

  {

      return this;

  }

 

文件下載具體重載函數

  //重載文件下載方法

  virtual void OnBeforeDownload(

      CefRefPtr<CefBrowser> browser,

      CefRefPtr<CefDownloadItem> download_item,

      const CefString& suggested_name,

      CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE;

 

  virtual void OnDownloadUpdated(

      CefRefPtr<CefBrowser> browser,

      CefRefPtr<CefDownloadItem> download_item,

      CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE;

 

文件下載重載函數實現

//文件下載方法重載

void SimpleHandler::OnBeforeDownload(

    CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefDownloadItem> download_item,

    const CefString& suggested_name,

    CefRefPtr<CefBeforeDownloadCallback> callback)

{

    callback->Continue(download_item->GetURL(), true);

}

 

void SimpleHandler::OnDownloadUpdated(

    CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefDownloadItem> download_item,

    CefRefPtr<CefDownloadItemCallback> callback)

{

    if (download_item->IsComplete())

    {

        //MessageBox.Show("下載成功");

        if (browser->IsPopup() && !browser->HasDocument())

        {

            //browser->GetHost()->ParentWindowWillClose();

            browser->GetHost()->CloseBrowser(true);

        }

    }

}

F5刷新功能

繼承按鍵處理類

提供回調接口

  virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() //實現 

  {

      return this;

  }

重載聲明

  //按鍵處理

  virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,

      const CefKeyEvent& event,

      CefEventHandle os_event,

      bool* is_keyboard_shortcut) OVERRIDE;

 

  virtual bool OnKeyEvent(CefRefPtr<CefBrowser> browser,

      const CefKeyEvent& event,

      CefEventHandle os_event) OVERRIDE;

 

重載實現

bool SimpleHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,

    const CefKeyEvent& event,

    CefEventHandle os_event,

    bool* is_keyboard_shortcut) {

    if(event.windows_key_code==116)//F5刷新

    browser->Reload();

    return false;

}

 

bool SimpleHandler::OnKeyEvent(CefRefPtr<CefBrowser> browser,

    const CefKeyEvent& event,

    CefEventHandle os_event) {

    return false;

}

 

右鍵菜單添加刷新按鈕

繼承菜單處理類

提供回調接口

  virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() //實現 

  {

      return this;

  }

 

重載聲明

  // 右鍵菜單處理

  virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,

      CefRefPtr<CefFrame> frame,

      CefRefPtr<CefContextMenuParams> params,

      CefRefPtr<CefMenuModel> model) OVERRIDE;

 

  virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,

      CefRefPtr<CefFrame> frame,

      CefRefPtr<CefContextMenuParams> params,

      int command_id,

      EventFlags event_flags) OVERRIDE;

 

重載實現

 

void SimpleHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefFrame> frame,

    CefRefPtr<CefContextMenuParams> params,

    CefRefPtr<CefMenuModel> model) {

    if (model->GetCount() > 0) {// 刷新菜單

        model->AddSeparator();

        model->AddItem(ID_CMD_REFRESH, __TEXT("刷新"));

    }

   

}

 

bool SimpleHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefFrame> frame,

    CefRefPtr<CefContextMenuParams> params,

    int command_id,EventFlags event_flags) {

    switch (command_id)

    {

    case ID_CMD_REFRESH:

        browser->Reload();

        break;

    default:

        break;

    }

    return false;

}

四、身份證閱讀器插件開發

工程建立

首先下載npapi插件開發包,解壓進入

新建win32 dll工程,工程名以NP開頭,將上圖的文件引入工程。

 

新建stdafx.h頭文件,加入

//kk: common and often used headers

 

 

#include <windows.h>

#include <windowsx.h>

#include <stdio.h>

#include <atlstr.h>

 

//Mozilla-API

#include <npfunctions.h>

#include <npruntime.h>

#include "npruntime.h"

 

#define TRACE __noop

並在plugin.cpp中引用此頭文件

 

設置預處理

 

設置頭文件包含

 

功能實現

加載身份證識別模塊

    ScriptablePluginObject(NPP npp)

        : ScriptablePluginObjectBase(npp)

    {

        //***************************加載神思模塊**************

        hInstance = LoadLibrary("RdCard.dll");

        if (!hInstance) {

            ::MessageBox(NULL, __TEXT("加載神思接口失敗,請檢查 RdCard.dll,重新打開頁面"), __T("提示"), MB_OK);

        }

    }

 

    ~ScriptablePluginObject() {

        FreeLibrary(hInstance);

    }

 

定義功能標識

// 拓展 增加方法

 

// 獲取身份證姓名方法

static NPIdentifier sIdCardName_id;

 

//測試閱讀器是否連接

static NPIdentifier sIdCardStatus_id;

 

 

修改插件方法判斷函數

// ********************測試插件是否有此方法**********************

bool

ScriptablePluginObject::HasMethod(NPIdentifier name)

{

    return (name == sFoo_id || name == sIdCardStatus_id || name == sIdCardName_id);

}

 

 

實現具體功能

// 插件提供方法調用接口

bool

ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args,

    uint32_t argCount, NPVariant *result)

{

    if (name == sFoo_id) {// foo 方法

 

        ::MessageBox(NULL, __TEXT("開始調用foo方法"), __T("提示"), MB_OKCANCEL);

        char* m_szTextGui = "我是foo方法調用返回的結果";

 

        STRINGZ_TO_NPVARIANT(toGBK(m_szTextGui), *result);

 

 

        return true;

    }

    else if(name == sIdCardStatus_id) {//測試身份證閱讀器是否連接

        ::MessageBox(NULL, __TEXT("開始調用IsConnect方法"), __T("提示"), MB_OKCANCEL);

 

        typedef int (*FUN)(...);

        FUN fun;

        fun = (FUN)GetProcAddress(hInstance, "IsConnect");

        if (!fun) {

            ::MessageBox(NULL, __TEXT(" RdCard.dll 中沒有 IsConnect 函數"), __T("提示"), MB_OK);

            return false;

        }

           

        bool rst = fun();

        BOOLEAN_TO_NPVARIANT(rst, *result);

        return true;

 

    }

    else if (name == sIdCardName_id) {// 獲取身份證姓名

       

        typedef int (*FUN)(...);

        FUN fun;

        fun = (FUN)GetProcAddress(hInstance, "GetName");

        if (!fun) {

            ::MessageBox(NULL, __TEXT(" RdCard.dll 中沒有 GetName 函數"), __T("提示"), MB_OK);

            return false;

        }

        ::MessageBox(NULL, __TEXT("開始調用getName方法"), __T("提示"), MB_OKCANCEL);

        char name[20];

        fun(name);

        STRINGZ_TO_NPVARIANT(toGBK(name),*result);

        return true;

 

 

    }

 

    return false;

}

 

定義插件模塊,其中MIMEType,是在html中調用的關鍵字

生成插件

 

插件部署

將生成的NPRDCARD.dll放入瀏覽器目錄的plugins目錄下

身份證閱讀器依賴的dll放在瀏覽器可執行文件目錄下

 

插件測試

測試身份證閱讀器是否連接

 

插件調試

瀏覽器增加啓動參數

啓動瀏覽器

在vs中打好斷點,附加到進程

 

點擊測試是否連接設備

進入斷點

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章