在某些情况下,有将从某种类型的语言翻译成另一种类型语言的需求。比如在生成实体时,可能需要将中文名称转换成英文。于是利用CEFSharp山寨了一个翻译器。效果图如下:
CEF全称为Chromium Emmbed Framework,是一个开源项目。用于嵌入基于 Google Chromium 项目的 Web 浏览器控件。
CEF是由C++所写,无法直接应用到.NET中。需要通过某种形式进行包装。常见的有Xilium.CefGlue和CEFSharp。我个人比较熟悉CEFSharp一些。
在CEFSharp的众多功能中,我最喜欢CEF执行JS代码、注册本地对象这两项功能,结合上述两项功能,可以作出很多有意思的效果出来。
由于CEFSharp的WPF版本在Win10会出现无法输入中文的问题,所以我一般都使用CEFSharp的WinForm版本,在WPF中,也是通过WindowsFormsHost来进行包装。
山寨翻译器就是在界面上放了一个CEFSharp的浏览器,浏览器访问必应翻译。当在界面上输入中文时,利用JS代码将必应翻译页面的待翻译句子设为界面上的中文,然后利用JS代码模拟点击翻译按钮,当必应翻译获得结果时,利用JS调用本地代码将界面结果设置为必应翻译的结果。
此时,有人会提出疑问了。CEFSharp的浏览器在哪?我怎么没在界面上看到?其实这里用了一个小Trick,将浏览器的宽度和高度都设成了1像素,当然看不到了。
当输入要翻译的中文较快时,如果每次输入一变化,就调用一次前文所说的翻译过程,这样效率比较低。而且还存在交互性问题,如果不阻塞用户的输入,这样在网络不稳定的情况下,先前的翻译结果可能最后才到,这样翻译结果就不准确了。如果阻塞的话,网络快还好说,网络慢输一下卡一下,体验极其不好。
所以我基于Blend的Interactivity新建了ThrottleInvokeCommandAction,可以在无操作后一定的时间调用命令。
由于我们不知道什么时候翻译完成了,此时可以监听DOMNodeInserted事件以得到通知。当事件发生时,会自动调用注册的本地对象的方法,不过在js中的方法名称和C#方法名称是不一样的,需要使用首字母小写的形式。
在CEF中,可以启用开发者工具,这样会方便我们的调试。在我的代码中,监听了CEF的键盘事件,当按下F12时,就显示开发者工具。
上述只是一个简单的翻译,在必应翻译页面上还有其他翻译可选项,可将其整合到山寨翻译器中。比如多个候选项的选择,或是将翻译过程整合到实体生成中。
博客园:Translator
获取cefsharp39可通过nuget,命令如下:Install-Package CefSharp.WinForms -Version 39.0.0
获取Prism可通过nuget,命令如下:Install-Package Prism -Version 4.1.0