• CefSharp.v49.0.1浏览器控件完全WPF版,实现禁止弹出新窗口,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接


        需求场景:在查询页面,填写查询条件,查询条件包括上传的图片,根据图片的特征查询,这就需要在提交的时候,使用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=" 300px;" />
            <input type="text" class="input-text" id="name" name="name" value="测试name" style=" 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实例,某些操作不便。

  • 相关阅读:
    女孩提出分手的N种理由
    Attribute应用,简化ANF自定义控件初始化过程
    关于Web的动态页面与静态页面分开的想法.
    .Net面试题
    算法题,不用递归,构造树型
    花两个小时,做了个分页控件
    事件应用,为系统提供扩展功能
    绘制半透明的图片
    Tile Studio简介(转载)
    Thinking in Java 摘录笔记
  • 原文地址:https://www.cnblogs.com/s0611163/p/10115501.html
Copyright © 2020-2023  润新知