1. 程式人生 > >C# 用XiliumCefGlue做瀏覽器,JS和C#相互呼叫

C# 用XiliumCefGlue做瀏覽器,JS和C#相互呼叫

目錄:

XiliumCefGlue初始化,最精簡Demo

1.解壓壓縮包得到下列檔案。選擇需要的檔案複製到自己工程【pdb為除錯生成檔案不需要】,之後將【Xilium.CefGlue】和【Xilium.CefGlue.WindowsForms】新增到引用。
這裡寫圖片描述
只選取了一部分需要的檔案放到Debug資料夾下。
這裡寫圖片描述
2.其中Form.cs中程式碼如下,新增panl控制元件讓瀏覽器嵌入其中。Form1_Load的引用在Form1.Designer.cs中。程式碼中的網址 http://www.e0575.com/web/ie6bye/test/是對CSS3進行測試的網頁。

using
System.Windows.Forms; using Xilium.CefGlue; using Xilium.CefGlue.WindowsForms; namespace XCdemo { public partial class Form1 : Form { CefWebBrowser browser = new CefWebBrowser(); public Form1() { InitializeComponent(); Form1_Load(); } private
void Form1_Load() { browser.Dock = DockStyle.Fill; browser.StartUrl = @"http://www.e0575.com/web/ie6bye/test/"; panel1.Controls.Add(browser); } } }

3.其中Program.cs中的程式碼要做更改,要在程式啟動前初始化。

using System;
using System.Collections.Generic;
using System.Linq;
using
System.Windows.Forms; using Xilium.CefGlue; namespace XCdemo { static class Program { /// <summary> /// 應用程式的主入口點。 /// </summary> [STAThread] private static void Main(string[] args) { CefRuntime.Load(); var mainArgs = new CefMainArgs(args); var app = new DemoApp(); var exitCode = CefRuntime.ExecuteProcess(mainArgs, app); var settings = new CefSettings { SingleProcess = false, MultiThreadedMessageLoop = true, LogSeverity = CefLogSeverity.Disable, LogFile = "CefGlue.log", }; CefRuntime.Initialize(mainArgs, settings, app); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (!settings.MultiThreadedMessageLoop) { Application.Idle += (sender, e) => { CefRuntime.DoMessageLoopWork(); }; } Application.Run(new Form1()); CefRuntime.Shutdown(); } internal sealed class DemoApp : CefApp { protected override void OnBeforeCommandLineProcessing(string processType, CefCommandLine commandLine) { ; } } } }

Xilium.CefGlue,JS呼叫C#程式碼

1.Xilium.CefGlue中JS呼叫C#比較繁瑣。需要通過反射機制註冊c#函式到JS。因為涉及到的檔案較多,而且已經和別的程式碼混在一起就不一一列舉了,這裡只列舉關鍵部分。詳細參考第2篇:Xilium CefGlue 關於 CLR Object 與 JS 互動類庫封裝報告:導航篇

public CefV8Handler Cef;
//通過反射機制 註冊c#函式到JS
public void RegisterJs()
{
    JsEvent js = new JsEvent();
    Cef = new CefJsV8Handler(js);
    string javascriptCode = CefJavaScriptEx.CreateJsCodeByObject(js, "Cef");
    CefRuntime.RegisterExtension("Cef", javascriptCode, Cef);
}
protected override void OnWebKitInitialized()
{
    //註冊JS函式
    RegisterJs();
}
public class JsEvent
{
    public Object MyParam { get; set; }
    public Object GetMyParam(){
        if (MyParam.GetType().IsArray){
            String s = "[";
            Object[] o = (Object[])MyParam;
            for (int i = 0; i < o.Length; i++){
                s += "'" + o[i].ToString() + "'";
                if (i < (o.Length - 1))
                    s += ",";
            }
            s += "]";
            return s;
        }
        return MyParam;
    }
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    private static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
    [DllImport("User32.dll", EntryPoint = "FindWindow")]
    private static extern int FindWindow(string lpClassName, string lpWindowName);  
    public void openMyPc(String dir){
        if( dir == null)
            dir = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
        Process.Start("explorer.exe", dir);
    }
}

上述程式碼功能為,執行JS頁面的程式碼,呼叫C#的函式,開啟指定的資料夾,引數為空時開啟我的電腦。
這裡寫圖片描述
這裡寫圖片描述

Xilium.CefGlue,C#呼叫JS程式碼(無返回值)

相對於JS呼叫C#函式,C#呼叫JS函式就簡單多了。直接呼叫封裝的庫函式即可,不過此函式之恩那個呼叫JS函式卻不能獲得JS函式的返回值。程式碼如下:

CefFrame frame = browser.Browser.GetMainFrame();
String js = "test();";
if (js.Length > 1)
{
    frame.ExecuteJavaScript(js, frame.Url, 0);
}

上述程式碼為呼叫JS頁面的test()函式,函式圓形如下:

function test(){
    alert("C#中呼叫了此函式!");
}

當C#中執行程式碼時,瀏覽器頁面會彈窗提示“C#中呼叫了此函式!”。

這裡寫圖片描述
這裡寫圖片描述

Xilium.CefGlue,C#呼叫JS程式碼(有返回值)

很多時候當我們用C#呼叫JS函式時,需要JS給的返回值。然而封裝的函式卻不具備此功能。這時候我們需要把JS呼叫C#和C#呼叫JS結合起來實現JS和C#互調。思路如下,C#呼叫JS函式,函式的返回值呼叫C#函式,由於JS呼叫C#函式是一個新的例項,所以我們需要程序間通訊,將得到的資訊傳回給主程式。主要程式碼為註冊下列C#函式到JS。

const int WM_COPYDATA = 0x004A;
public void JS2C(String dir)
{
    int hWnd = FindWindow(null, @"JS和c#程式碼互調");
    if (hWnd == 0)
    {
        MessageBox.Show("555,未找到訊息接受者!");
    }
    else
    {
        byte[] sarr = System.Text.Encoding.Default.GetBytes(dir);
        int len = sarr.Length;
        COPYDATASTRUCT cds;
        cds.dwData = (IntPtr)Convert.ToInt16(1);//可以是任意值  
        cds.cbData = len + 1;//指定lpData記憶體區域的位元組數  
        cds.lpData = dir;//傳送給目標視窗所在程序的資料  
        SendMessage(hWnd, WM_COPYDATA, 0, ref cds);
    }
}

JS中程式碼如下

function testreturn(a){
    var str = "返回值:";
    str = str + a;
    return Cef.JS2C(str);
}

之後我們正常呼叫ExecuteJavaScript函式即可。效果如下:
這裡寫圖片描述