using CefSharp;
using log4net;
using SunCreate.Vipf.Base;
using SunCreate.Vipf.Client.Bussiness;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SunCreate.Vipf.Client.UI
{
/// <summary>
/// 浏览器用户控件
/// </summary>
public partial class BrowserCtrl : UserControl, IDisposable
{
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("user32.dll", SetLastError = true)]
public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
[DllImport("user32.dll", SetLastError = true)]
public static extern int CloseWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint = "GetWindowText")]
private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
private ILog _log = LogManager.GetLogger(typeof(BrowserCtrl));
private static bool _isCefInited = false;
private static object _lockObject = new object();
private JSObject _jsObject;
private bool _firstLoad = true;
/// <summary>
/// 在此事件中设置URL(此事件已在线程中执行,此事件已对错误情况进行处理)
/// </summary>
public event EventHandler SetUrlEvent;
/// <summary>
/// URL
/// </summary>
public string Url { get; set; }
/// <summary>
/// 浏览器FrameLoadEnd事件
/// </summary>
public event EventHandler FrameLoadEnd;
private ExtChromiumBrowser _browser;
public ExtChromiumBrowser Browser
{
get
{
return this._browser;
}
}
public BrowserCtrl()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this)) return;
this.Loaded += BrowserCtrl_Loaded;
lock (_lockObject)
{
if (!_isCefInited)
{
_isCefInited = true;
InitCef(true);//初始化CefSharp
}
}
_browser = new ExtChromiumBrowser();
BindBrowser(_browser);
grid.Children.Add(_browser);
}
/// <summary>
/// 设置Map控件接口,用于C#和JS互操作
/// </summary>
public void SetMapCtrl(IMapCtrl mapCtrl)
{
_jsObject.MapCtrl = mapCtrl;
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
//如果有弹出窗口则先释放它
foreach (UIElement item in grid.Children)
{
if (item is BrowserContainer)
{
(item as BrowserContainer).ClearResource();
}
}
if (_browser != null && !_browser.IsDisposed)
{
_browser.Dispose();
}
}
private void BrowserCtrl_Loaded(object sender, RoutedEventArgs e)
{
}
private void LoadUrl()
{
if (_firstLoad)
{
_firstLoad = false;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
if (Url == null && SetUrlEvent != null)
{
try
{
SetUrlEvent(this, null);
}
catch (Exception ex)
{
_log.Error("BrowserCtrl LoadUrl error 获取URL失败", ex);
}
}
this.Dispatcher.Invoke(new Action(() =>
{
_browser.Load(Url);
}));
});
}
}
private void BindBrowser(ExtChromiumBrowser browser)
{
_jsObject = new JSObject();
browser.RegisterJsObject("jsObj", _jsObject, false);
browser.StartNewWindow += (s, e) =>
{
try
{
IntPtr hwndChild = IntPtr.Zero; //浏览器弹出窗口句柄
BrowserContainer browserContainer = new BrowserContainer();
System.Windows.Forms.Control control = new System.Windows.Forms.Control();
control.Dock = System.Windows.Forms.DockStyle.Fill;
control.CreateControl();
browserContainer.host.Child = control;
browserContainer.ClearResourceEvent += (ss, ee) =>
{
CloseWindow(hwndChild);
control.Dispose();
browserContainer.host.Dispose();
};
//释放上一个弹出窗口
foreach (UIElement item in grid.Children)
{
if (item is BrowserContainer)
{
(item as BrowserContainer).ClearResource();
}
}
grid.Children.Clear();
grid.Children.Add(browserContainer);
e.WindowInfo.SetAsChild(control.Handle, 0, 0, (int)browserContainer.ActualWidth, (int)browserContainer.ActualHeight);
browserContainer.SizeChanged += (ss, ee) =>
{
hwndChild = FindWindowEx(control.Handle, IntPtr.Zero, null, null);
MoveWindow(hwndChild, 0, 0, (int)browserContainer.ActualWidth, (int)browserContainer.ActualHeight, true);
};
}
catch (Exception ex)
{
_log.Error("BrowserCtrl BindBrowser error", ex);
}
};
browser.IsBrowserInitializedChanged += (ss, ee) =>
{
LoadUrl();
};
browser.FrameLoadStart += (ss, ee) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
(ss as ExtChromiumBrowser).Focus();
}));
};
browser.FrameLoadEnd += (ss, ee) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
loadingWait.Visibility = Visibility.Collapsed;
}));
if (FrameLoadEnd != null)
{
FrameLoadEnd(null, null);
}
};
browser.KeyDown += (ss, ee) =>
{
if (ee.Key == Key.D)
{
//_browser.ExecuteScriptAsync("dayOrNightMap", 0);
}
if (ee.Key == Key.N)
{
//_browser.ExecuteScriptAsync("dayOrNightMap", 1);
}
};
browser.LoadError += (ss, ee) =>
{
_log.Error("ExtChromiumBrowser LoadError 错误码:" + ee.ErrorCode + ",错误信息:" + ee.ErrorText + ",错误URL:" + ee.FailedUrl);
return; //下面代码不执行
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
if (Url == null && SetUrlEvent != null)
{
try
{
SetUrlEvent(this, null);
}
catch (Exception ex)
{
_log.Error("BrowserCtrl LoadUrl error 获取URL失败", ex);
}
}
Thread.Sleep(500);
this.Dispatcher.BeginInvoke(new Action(() =>
{
(ss as ExtChromiumBrowser).Load(Url);
}));
});
};
}
#region 初始化CefSharp
public static void InitCef(bool multiThreadedMessageLoop)
{
string cefsharpFolder = "CefSharp.v49.0.1";
var settings = new CefSettings();
//The location where cache data will be stored on disk. If empty an in-memory cache will be used for some features and a temporary disk cache for others.
//HTML5 databases such as localStorage will only persist across sessions if a cache path is specified.
// settings.CachePath = cefsharpFolder + "/cache"; //注释掉,不使用cache
settings.MultiThreadedMessageLoop = multiThreadedMessageLoop;
settings.FocusedNodeChangedEnabled = true;
Cef.OnContextInitialized = delegate
{
var cookieManager = Cef.GetGlobalCookieManager();
cookieManager.SetStoragePath(cefsharpFolder + "/cookies", true);
cookieManager.SetSupportedSchemes("custom");
};
settings.BrowserSubprocessPath = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + "/CefSharp.BrowserSubprocess.exe";
settings.LogFile = cefsharpFolder + "/debug.log";
settings.CefCommandLineArgs.Add("disable-gpu", "1");
settings.CefCommandLineArgs.Add("enable-media-stream", "1");
if (!Cef.Initialize(settings, shutdownOnProcessExit: true, performDependencyCheck: true))
{
throw new Exception("Unable to Initialize Cef");
}
}
#endregion
}
}