CEF3 C++接口实现自定义浏览器[simple version]

2023-05-16

目录

目录... 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中打好断点,附加到进程

 

点击测试是否连接设备

进入断点

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CEF3 C++接口实现自定义浏览器[simple version] 的相关文章

  • Jupyter Notebooks 中的 Python 版本和环境的 VSCode 问题

    Issue 我遇到的问题是 Python 的环境和版本与 VSCode 中的设置不匹配 并导致我尝试在 Jupyter 笔记本中使用的包出现问题 我使用的是安装了 Python 3 9 1 包括旧版本 和 Visual Studio Cod
  • Google 服务的 Android 版本冲突

    我已经为此搜索了很多解决方案 但没有一个适合我的具体情况 我在 Gradle Sync 上收到此错误 错误 任务 app processDebugGoogleServices 执行失败 请通过更新 google services 插件的版本
  • 如何使用两个不同的节点版本运行两个不同的nodejs应用程序[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我们有两个 Node js 应用程序 这两个应用程序不能在同一节点版本中运行 一个应用程序只能在node4 8 3中运行 另一个应用程
  • .data 在 pytorch 中还有用吗?

    我是 pytorch 的新手 我读了很多大量使用张量的 pytorch 代码 data成员 但我搜索 data在官方文档和Google中 发现很少 我猜 data包含张量中的数据 但我不知道什么时候需要它 什么时候不需要 data是一个属性
  • 如何将 TeamCity 构建版本获取到非托管 DLL 和 OCX 控件中?

    我有一个包含托管 C 和非托管 C 项目的 TeamCity 构建解决方案 是否有类似于 Assembly Info Patcher 的 TeamCity 实用程序 可以更改非托管 C DLL 和 OCX 项目的 rc 文件中的版本号以匹配
  • 一台机器上可以有多个Java SDK吗?

    我的机器上可以安装多个 java SDK 版本吗 爪哇1 4 爪哇2 爪哇6 爪哇7 请告知 因为我必须在 Java 1 4 和 Java 2 中为 Maximo 开发解决方案 另外我想学习 Java 6 和 7 的开发 Thanks 我的
  • 需要react-redux v6 v3.*.* 版本的react-redux-firebase

    我一直在使用react redux firebase 开发一个项目 它以前对我有用 今天我收到以下错误 我不确定错误是否出在我的代码中的其他地方 或者我是否必须将react redux firebase更新到版本3 目前似乎还不存在 其他人
  • Flutter:升级Play商店版本号

    我已经使用 flutter 在 Play 商店上发布了一个应用程序 现在我想上传该应用程序的新版本 我正在尝试更改版本代码 flutter 构建 apk build name 1 0 2 build number 3 或像这样更改 loca
  • 从3.4升级后如何在python3.5中使用pip?

    我在 Ubuntu 上 我有 python2 7 它是预安装的 python3 4 今天之前使用过 和 python3 5 我今天升级到的 并行安装 他们自己都工作得很好 但是 我想用pip安装一些软件包 我不知道如何为我的 3 5 安装执
  • 获取我的应用程序的当前 dot net 版本

    如何获取我的 asp net 应用程序的正在运行的 dot net 版本 我尝试了这里的解决方案 有没有一种简单的方法来检查 NET Framework 版本 https stackoverflow com questions 951856
  • 如何升级SQLite版本?

    我正在开发我的第一个应用程序 并使用以下代码查看我的 SQLite 版本 Cursor cursor SQLiteDatabase openOrCreateDatabase memory null rawQuery select sqlit
  • iPhone版本兼容性扫描仪

    好吧 我开发 iPhone 应用程序已经一年多了 但有一件事仍然很糟糕 假设我想让我的应用程序与 iOS 3 0 兼容 我将 sdk 设置为可用的最新版本 并将部署目标设置为 3 0 但是 如果您不小心调用了仅在 3 1 x 或更高版本中可
  • java:在一个Web应用程序中使用同一库的两个版本

    我面临以下问题 我的 web 应用程序中有一个模块需要 jaxb 1 x 而另一个模块需要 jaxb 2 x 第一个模块不适用于新版本的 jaxb 反之亦然 如何在一个项目中使用这两个罐子 谢谢 对于常规应用程序 通常不同的版本使用不同的包
  • 如何比较 Python 中的版本号?

    我正在遍历一个包含鸡蛋的目录 将这些鸡蛋添加到sys path 如果目录中有同一个 egg 的两个版本 我只想添加最新的一个 我有一个正则表达式r P
  • Google BigQuery:检索每行的最后版本

    我有一个 Google BigQuery 表 其中包含所有版本的资源 每次创建 更新 删除资源时 都会添加一个新行 并递增版本号 该数字将是添加行时的时间戳 ID ResourceID Action Count Timestamp ABC
  • 如何查看正在运行的 tcsh 版本?

    如何查看我的 UNIX 终端中运行的 tcsh 的当前版本 看着那 这version多变的 echo version tcsh 6 14 00 Astron 2005 03 25 i386 intel linux options wide
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少
  • R 提交到 CRAN:构建包的 R 版本?

    我想向 CRAN 提交一个包裹 在里面CRAN 存储库政策 http cran r project org web packages policies html它指出 当发布新的 R x y 0 版本时 R CMD 检查给出 错误 的包将被
  • “brew升级节点”后“node -v”显示错误版本

    我升级了 Node js 版本brew upgrade node其中安装了v5 3 0 但是当我得到节点的版本时node v它显示 v0 10 29 I tried brew link overwrite node但这没有用 Brew 已链
  • 如何检查应用程序的 .NET 版本?

    除了在仅具有 NET Framework 版本 3 5 的计算机上运行之外 如何检查 NET 应用程序的版本 NET 框架版本控制在 NET 2 0 之后变为 foobar 一个应用程序的目标是CLR版本 它使用 EXE 的程序集元数据来实

随机推荐

  • 虚拟机使用主机显卡(hyper-v和WSL2)

    我的系统版本WSL2 43 Ubuntu20 04 43 CUDA启用WSL2 43 安装Ubuntu20 04 主机安装WSL Cuda显卡驱动WSL2 Ubuntu安装cuda和cudnncudacudnn安装TensorFlow使用自
  • Linux 系统 “Read-only file system” ” 错误 与 解决方法

    这个问题经常发生在有大量磁盘读写操作且磁盘分区很大的环境中 xff0c 下面简单描述下此案例的应用环境 xff1a 这是一个 Web 服务器故障案例 xff0c 客户利用两台服务器加一个磁盘阵列做了一个双机热备的 Web 系统 xff0c
  • Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPointerEx

    看了以上午 xff0c 终于找到了问题所在0 0 swagger 与 springboot 使用的时候 xff0c 有一个版本问题 xff1a swagger版本springboot版本2 x2 7 x 一下3 x2 7 x 及以上 不多说
  • 黑客圈最受欢迎的21个 Kali Linux 工具,你都用过哪几个?

    这里是最好的 Kali Linux 工具列表 xff0c 它们可以让你评估 Web 服务器的安全性 xff0c 并帮助你执行黑客渗透测试 如果你读过 Kali Linux 点评 xff0c 你就知道为什么它被认为是最好的黑客渗透测试的 Li
  • 今天第一次加入

    64 TOC今天第一次加入进来 欢迎使用Markdown编辑器 你好 xff01 这是你第一次使用 Markdown编辑器 所展示的欢迎页 如果你想学习如何使用Markdown编辑器 可以仔细阅读这篇文章 xff0c 了解一下Markdow
  • 学习OpenStack之环境部署一篇就够啦!!!(带你走进OpenStack世界)

    文章目录 一 xff1a 项目拓扑1 1 xff1a 环境介绍 二 xff1a 系统环境配置2 1 xff1a 安装 配置MariaDB2 2 xff1a 安装RabbitMQ2 3 xff1a 安装memcached 三 xff1a Ke
  • ccf 炉石传说

    import java util ArrayList import java util Scanner span class hljs comment date 9 11 17 author chaomaer span span class
  • python之paramiko文件夹远程上传

    Paramiko模块是一个用来连接远程服务器 xff0c 进行文件上传下载和shell命令执行的PYTHON模块 xff0c 使用方便 但是它不支持整个文件夹的上传 xff0c 近期需要分发上传一个离线工具包到服务器去执行 xff0c 考虑
  • form表单提交后,页面弹出成功或者失败的信息

    Ssm 中用RedirectAttributes做提示消息 96 span class token annotation punctuation 64 RequiresPermissions span span class token pu
  • Oracle提示表空间不足ORA-01653:

    这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题 xff0c 有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中 居左 居右SmartyP
  • 递归删除树节点

    public int delete Long id 删除权限的集合ids List lt Long gt ids 61 new ArrayList lt gt ids add id 递归的将一级分类下的id也加入到集合中 this getI
  • 解决报错:sufficient buffer space or because a queue was full

    An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was
  • java判断字符串(含中文)的内容相似度

    span class token comment 判断地址相似 此处简单的判断字符串的内容80 相似即可 64 param str1 64 param str2 64 return span span class token keyword
  • display:table-cell实现两栏自适应布局

    前面介绍了 float实现两栏自适应布局 float 43 overflow实现两栏自适应布局 xff0c 现在看下table如何实现两栏自适应布局 display table cell lt table gt lt table gt 里的
  • Microsoft Visual C++ 14.0 is required.

    Microsoft Visual C 43 43 14 0 is required Get it with Microsoft Visual C 43 43 Build Tools 当我们安装绝大部分python包的时候可以通过pip in
  • ubuntu20.04离线安装rabbitvcs

    在内网开发的时候 xff0c 管理更新代码非常不方便 xff0c 使用svn是非常普遍的现象 小乌龟svn貌似只有windows版本的 xff0c 在linux系统下与其操作接近的软件rabbitcvs变成了最好的选择 在线安装rabbit
  • 实机安装CentOS7.9操作系统图文(保姆级)教程

    一 制作启动U盘 1 下载Ventoy软件 去Ventoy官网下载Ventoy软件 xff08 Download Ventoy xff09 如下图界面 2 制作启动盘 选择合适的版本以及平台下载好之后 xff0c 进行解压 xff0c 解压
  • Angular8升级至Angular13遇到的问题

    根据项目需求 xff0c 需要把Angular版本从8升级到13 xff0c 无法从8直接升至13 xff0c 需要一级一级的升级 xff0c 本文介绍了在升级Angular版本的时候的一种报错和解决办法 一 开始之前 首先确保你 Node
  • mysql怎么查询表的大小

    通过sql语句查询整个数据库的容量 xff0c 或是单独查看表所占容量 1 要查询表所占的容量 xff0c 就是把表的数据和索引加起来就可以了 1 select sum DATA LENGTH 43 sum INDEX LENGTH fro
  • CEF3 C++接口实现自定义浏览器[simple version]

    目录 目录 1 一 工具准备 2 二 编译C 43 43 接口 2 三 实现浏览器 5 浏览器定制 5 浏览器默认最大化 xff0c 标题从配置文件读取 5 设置浏览器中文环境 xff0c 开启npapi插件功能 xff0c 并注册身份证阅