需求場景:在查詢頁面,填寫查詢條件,查詢條件包括上傳的圖片,根據圖片的特征查詢,這就需要在提交的時候,使用POST提交,因為GET提交無法提交圖片數據,提交查詢條件之後,在新的視窗展示查詢結果。(當然查詢結果頁面可能不支持F5刷新頁面) 表單HTML代碼示意(註意method="post" targ ...
需求場景:在查詢頁面,填寫查詢條件,查詢條件包括上傳的圖片,根據圖片的特征查詢,這就需要在提交的時候,使用POST提交,因為GET提交無法提交圖片數據,提交查詢條件之後,在新的視窗展示查詢結果。(當然查詢結果頁面可能不支持F5刷新頁面)
表單HTML代碼示意(註意method="post" target="_blank" action指向新頁面):
<!DOCTYPE html> <html> <head> <title>提交表單查詢</title> <script type="text/javascript" src='jquery.js'></script> <script type="text/javascript"> //保存 function save() { $("#frm").submit(); } </script> </head> <body> <form id="frm" action="searchResult" enctype="multipart/form-data" method="post" target="_blank"> <input type="text" class="input-text" id="title" name="title" value="測試title" style="width: 300px;" /> <input type="text" class="input-text" id="name" name="name" value="測試name" style="width: 300px;" /> <a href="javascript:void(0);" onclick="save()">保存</a> </form> </body> </html>View Code
請先大致看下Winform版的CefSharp瀏覽器控制項實現方式:
https://www.cnblogs.com/s0611163/p/7716692.html
下麵是WPF版的CefSharp瀏覽器控制項的實現方式,與Winform版相同的代碼這裡不再粘貼:
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 } }View Code
核心代碼(StartNewWindow):
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); } };View Code
核心代碼(資源釋放):
/// <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(); } }View Code
難點:彈出視窗和原來的視窗似乎共用同一個ChromiumWebBrowser實例的某些東西,但是彈出的視窗本身又獲取不到ChromiumWebBrowser實例,某些操作不便。