需求场景:在查询页面,填写查询条件,查询条件包括上传的图片,根据图片的特征查询,这就需要在提交的时候,使用POST提交,因为GET提交无法提交图片数据,提交查询条件之后,在新的窗口展示查询结果。(当然查询结果页面可能不支持F5刷新页面)

表单HTML代码示意(注意method=\"post\" target=\"_blank\" action指向新页面):

\"\"\"\"
<!DOCTYPE html>
<html>
<head>
    < >提交表单查询</ >
    <  type=\"text/ \" src=\'jquery.js\'></ >
    <  type=\"text/ \">
        //保存
        function save() {
            $(\"#frm\").submit();
        }
    </ >
</head>
<body>
    <form id=\"frm\" action=\"searchResult\" enctype=\"multipart/form-data\" method=\"post\" target=\"_blank\">
        <input type=\"text\" class=\"input-text\" id=\" \" name=\" \" value=\"测试 \" style=\"width: 300px;\" />
        <input type=\"text\" class=\"input-text\" id=\"name\" name=\"name\" value=\"测试name\" style=\"width: 300px;\" />
        <a href=\" :void(0);\"  =\"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. ;
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 window );
        [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   _lock  = new  ();

        private JS  _js ;

        private bool _firstLoad = true;

        /// <summary>
        /// 在此事件中设置URL(此事件已在线程中执行,此事件已对错误情况进行处理)
        /// </summary>
        public event EventHandler SetUrlEvent;

        /// <summary>
        /// URL
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// 浏览器 LoadEnd事件
        /// </summary>
        public event EventHandler  LoadEnd;

        private ExtChromiumBrowser _browser;

        public ExtChromiumBrowser Browser
        {
            get
            {
                return this._browser;
            }
        }

        public BrowserCtrl()
        {
            InitializeComponent();
            if (DesignerProperties.GetIsInDesignMode(this)) return;

            this.Loaded += BrowserCtrl_Loaded;

            lock (_lock )
            {
                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)
        {
            _js .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(  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)
        {
            _js  = new JS ();
            browser.RegisterJs (\"jsObj\", _js , 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. LoadStart += (ss, ee) =>
            {
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    (ss as ExtChromiumBrowser).Focus();
                }));
            };
            browser. LoadEnd += (ss, ee) =>
            {
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    loadingWait.Visibility = Visibility.Collapsed;
                }));
                if ( LoadEnd != null)
                {
                     LoadEnd(null, null);
                }
            };
            browser.KeyDown += (ss, ee) =>
            {
                if (ee.Key == Key.D)
                {
                    //_browser.Execute Async(\"dayOrNightMap\", 0);
                }
                if (ee.Key == Key.N)
                {
                    //_browser.Execute Async(\"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 data s 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. Directory + 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实例,某些操作不便。

 

收藏 打印