終於封裝完成了,采用離屏渲染方式,支持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。(需要手動調用strip 裁剪掉符號數據)
最終封裝成cpf的控件使用就很方便了,案例源碼:http://cpf.cskin.net/Item/19