终于封装完成了,采用离屏渲染方式,支持JS和C#互相调用,C#方法自动绑定到JS里,中文输入有自动调整输入法位置。

基于开源的CefGlue 移植,本来想用CefSharp,不过这个里面有很多C++的,而且很多代码还是基于Windows编写的,不好移植成跨平台的。

不过CefGlue 里的功能不够完善,没有带JS远程调用功能,Cef是多进程的,JS调用需要在渲染进程,那就需要主进程发送消息给渲染进程来调用JS,还要把调用结果发送回主进程,很麻烦。我这边是采用管道通讯。

C#注册方法到JS里的时候,需要先反射获取方法名,根据方法名注册到JS里,注册之后的方法在被调用的时候,渲染进程会有回调,把回调里的参数和数据信息发送到主进程,再根据参数以及反射获取的C#方法的参数类型对比,并转换为相应的C#数据类型,再调用该C#方法,最后还要把C#调用的结果返回到渲染进程。现在只做了常用的数据类型转换,比如 string,int,double等这些,其他类型转换暂时不支持。

封装不同系统平台,有很多细节不同,有很多坑,比如:

1、MultiThreadedMessageLoop 在Mac里不支持,那你就需要另外搞个Timer,不断调用DoMessageLoopWork

2、由于Mac里的特殊的进程机制,你还需要在CommandLine调用SetProgram设置程序路径,否则无法启动子进程,关键子进程还自带任务栏图标,你还需要想办法把子进程任务栏图标隐藏,cef默认例子里就是靠多个程序目录,里面配置Info.plist为后台进程来隐藏子进程图标。

3、Linux里的话,还需单独设置CommandLine 禁用GPU,设置no-zygote

4、Mac里必须将键盘事件的Characters和UnmodifiedCharacter传给cef,否则还没法触发事件,另外还必须用系统的原生KeyCode设置给cef的键盘事件的NativeKeyCode,而Windows和Linux是设置WindowsKeyCode

5、Xamarin.Mac里有个坑,你无法继承NSApplication重写并增加方法属性,由于CPF.Mac采用的是精简版的Xamarin.Mac,而Xamarin.Mac采用的是绑定原生API的方式实现的,但是对NSApplication的子类没有实现自动注册功能,就是你继承扩展的子类无法在Object-C里获取到对应的对象。而cef在Mac端要求主程序的NSApplication增加IsHandlingSendEvent属性,没有这个属性就无法运行,好在Object-C支持类的动态增加属性,手动调用注册属性就好了

6、cef里封装的输入法搞的真麻烦,明明只要提供个获取光标位置的接口就行,却还搞个拼写过程输入效果,不调用这些接口还无法触发获取光标位置的回调,本来这个功能输入法提供就行的,cef里搞这个功能很坑,尤其是文本框限制字符数量的时候,比如文本框限制最大字符数是2,那你输入中文的时候,用拼音输入,就无法直接完整的拼写完两个中文字符,因为这个长度限制还会限制拼写过程的字母数量。好在可以规避掉这个拼写功能。

去 https://cef-builds.spotifycdn.com/ 下载cef二进制文件有个大坑,就是Linux的libcef.so文件都是1个G的,太大了,估计是配置文件写错了,就只能自己编译过。其他系统平台的都只有100多M。

最终封装成cpf的控件使用就很方便了,案例源码:http://cpf.cskin.net/Item/19

C#搞跨平台UI,封装Cef作为Cpf的控件支持Windows,Linux,Mac的更多相关文章

  1. 将webkit内核封装为duilib的浏览器控件

    转载请说明出处,谢谢~~ 原本的duilib是自带浏览器控件的,但是使用了IE内核,我在做仿酷狗音乐播放器时,在右侧乐库要用到浏览器控件,而我使用自带的IE控件却发现了不少缺点,这也是duilib一直 ...

  2. WPF里面多线程访问UI线程、主线程的控件

    如果出现以下错误:调用线程无法访问此对象,因为另一个线程拥有该对象. 你就碰到多线程访问UI线程.主线程的控件的问题了. 先占位.

  3. 【Android】11.0 UI开发(二)——列表控件ListView的简单实现1

    ************************ 转载请注明出处:https://www.cnblogs.com/xiaofu007/p/10342462.html ***************** ...

  4. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  5. Duilib源码分析(五)UI布局—Layout与各子控件

    接下来,继续分析duilib之UI布局Layout,目前提供的布局有:VerticalLayout.HorizontalLayout.TileLayout.TabLayout.ChildLayout分 ...

  6. JavaScript封装一个实用的select控件

    最近一直把精力放在项目上面,导致忽略的一些底层的东西.以前就一直觉得原有的select控件很丑,正好周末有时间,试着做了一个简单封装,实现了它的基本功能.我总结了一下,大概分为三个部分: 1.对显示样 ...

  7. .Net Core使用视图组件(ViewComponent)封装表单文本框控件

    实例程序的界面效果如下图所示: 在表单中的搜索条件有姓名,学号,成绩.他们在一行中按照水平三等分排列. 在cshtml中用html实现上述表单效果的的代码如下: <form class=&quo ...

  8. 如何封装属于自己的WPF控件库

    在网上找了一下,发现这方面的资料并不多.做传统桌面的本来就不多了吧,更别说WPF了.我可能也要另寻出路了,不过我还是觉得做桌面挺有意思的. 言归正传  首先,新建一个WPF自定义控件库项目 这里我们封 ...

  9. Qt项目ui文件中新添加的控件在代码中不识别的问题解决

    今天在学Qt框架的信号槽,然后发现在ui中加的控件,通过ui-> 找不到,没有识别,于是上网查找了一下问题 解决方法 添加ui控件后,执行程序,退出程序,将debug目录下的ui_XXXX.h拷 ...

随机推荐

  1. POJ 3228 二分最大流

    题意:       给你N个位置,每个位置都有金矿数量和仓库数量,然后位置和位置之间的距离给了出来,最后问你吧所有的金矿都放到库里面走的路径 最长的最短 是多少? 思路:      比较简单的一个题, ...

  2. Python中math和cmath模块的使用

    目录 Math模块 Cmath模块 Math模块 pi                数字常量,圆周率 e                 表示一个常量 sqrt(x)         求x的平方根 ...

  3. Python中Scapy网络嗅探模块的使用

    目录 Scapy scapy的安装和使用 发包 发包和收包 抓包 将抓取到的数据包保存 查看抓取到的数据包 格式化输出 过滤抓包 Scapy scapy是python中一个可用于网络嗅探的非常强大的第 ...

  4. 2.逆向分析Hello World!程序-上

    先写一个HelloWorld程序(vs2015 / C++) 编译链接生成可执行文件XX.exe,然后用OD[OllyDbg]打开调试: 代码窗口:默认用于显示反汇编代码,还用于各种注释.标签,分析代 ...

  5. wordpress如何隐藏后台位置?

    2017-02-08 20:43:20 言曌 阅读数 3585更多 分类专栏: WordPress 转载 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本 ...

  6. 去除腾讯视频logo水印

    打开F12,然后再console中输入下面代码,即可. document.querySelectorAll(".txp_waterMark_pic").forEach(functi ...

  7. 多线程-4.wait() notify() notifyAll() 生产者消费者模型

    1.wait()方法 该方法继承于Object类.在调用obj.wait()方法后,当前线程会失去obj的锁.待其他线程调用obj.notify()或notifyAll()方法后进入锁等待池,争抢到锁 ...

  8. 谁动了我的 Linux?原来 history 可以这么强大!

    当我们频繁使用 Linux 命令行时,有效地使用历史记录,可以大大提高工作效率. 在平时 Linux 操作过程中,很多命令是重复的,你一定不希望大量输入重复的命令.如果你是系统管理员,你可能需要对用户 ...

  9. Java中实现SAX解析xml文件到MySQL数据库

    大致步骤: 1.Java bean 2.DBHelper.java 3.重写DefaultHandler中的方法:MyHander.java 4.循环写数据库:SAXParserDemo.java ① ...

  10. 【js】Leetcode每日一题-二叉树的堂兄弟节点

    [js]Leetcode每日一题-二叉树的堂兄弟节点 [题目描述] 在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处. 如果二叉树的两个节点深度相同,但 父节点不 ...