微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CefSharp禁止弹出新窗体,在同一窗口打开链接,或者在新Tab页打开链接,并且支持带type="POST" target="_blank"的链接

 说明:在同一窗口打开链接,只要稍加改造就可以实现,这里实现的是在新Tab页打开链接,并且支持带type="POST" target="_blank"的链接

 

github和bitbucket上相关问题:

1、WPF empty POST data when using custom popup    https://github.com/cefsharp/CefSharp/issues/1267

2、CefLifeSpanHandler,customized OnBeforePopup problem    https://bitbucket.org/chromiumembedded/cef/issues/1949/

 

解决(CefSharp版本75.1.143.0):

一、实现IRequestHandler接口

using CefSharp;
 System;
 System.Collections.Generic;
 System.Linq;
 System.Text;
 System.Threading.Tasks;
 System.Security.Cryptography.X509Certificates;

namespace CefSharpDemo
{
    public class RequestHandler : IRequestHandler
    {
        private ExtChromiumbrowser _browser;

        public RequestHandler(ExtChromiumbrowser browser)
        {
            _browser = browser;
        }

        bool GetAuthCredentials(IWebbrowser chromiumWebbrowser,Ibrowser browser,string originUrl,1)">bool isProxy,1)">string host,1)">int port,1)">string realm,1)">string scheme,IAuthCallback callback)
        {
            return false;
        }

        public IResourceRequestHandler GetResourceRequestHandler(IWebbrowser chromiumWebbrowser,IFrame frame,IRequest request,1)">bool isNavigation,1)">bool isDownload,1)">string requestinitiator,1)">ref bool disableDefaultHandling)
        {
            if (request.Method.toupper() == "POST" && request.PostData != null)
            {
                if (request.PostData.Elements.Count > 0)
                {
                    _browser.PostData = new byte[request.PostData.Elements[].Bytes.Length];
                    request.PostData.Elements[0].Bytes.copyTo(_browser.PostData,);
                }
            }
            bool OnBeforebrowse(IWebbrowser chromiumWebbrowser,1)">bool userGesture,1)"> isRedirect)
        {
            bool OnCertificateError(IWebbrowser chromiumWebbrowser,CefErrorCode errorCode,1)"> requestUrl,ISslInfo sslInfo,IRequestCallback callback)
        {
            bool OnopenUrlFromTab(IWebbrowser chromiumWebbrowser,1)">string targetUrl,WindowOpendisposition targetdisposition,1)"> userGesture)
        {
            void OnPluginCrashed(IWebbrowser chromiumWebbrowser,1)"> pluginPath)
        {

        }

        bool OnQuotaRequest(IWebbrowser chromiumWebbrowser,1)">long newSize,1)">void OnRenderProcessterminated(IWebbrowser chromiumWebbrowser,CefTerminationStatus status)
        {

        }

         OnRenderViewReady(IWebbrowser chromiumWebbrowser,Ibrowser browser)
        {

        }

        bool OnSelectClientCertificate(IWebbrowser chromiumWebbrowser,1)">int port,X509Certificate2Collection certificates,ISelectClientCertificateCallback callback)
        {
            ;
        }
    }
}
View Code

二、实现ILifeSpanHandler接口

 System.Collections.Specialized;
 System.Runtime.InteropServices;
 System.Threading;
 System.Windows;
 System.Windows.Interop;
 Utils;

 CefLifeSpanHandler : CefSharp.ILifeSpanHandler
    {
        private static LimitedTaskScheduler _scheduler = new LimitedTaskScheduler(2);

         CefLifeSpanHandler()
        {

        }

         DoClose(IWebbrowser browserControl,CefSharp.Ibrowser browser)
        {
            if (browser.Isdisposed || browser.IsPopup)
            {
                ;
            }

            true OnAfterCreated(IWebbrowser browserControl,1)"> OnBeforeClose(IWebbrowser browserControl,Ibrowser browser)
        {
        }

        bool OnBeforePopup(IWebbrowser browserControl,1)">string targetFrameName,IPopupFeatures popupFeatures,IWindowInfo windowInfo,IbrowserSettings browserSettings,1)">bool noJavascriptAccess,1)">out IWebbrowser newbrowser)
        {
            var chromiumWebbrowser = (ExtChromiumbrowser)browserControl;

            chromiumWebbrowser.dispatcher.Invoke(new Action(() =>
            {
                browserPopupWin win = new browserPopupWin();
                win.ShowInTaskbar = ;
                win.Height = ;
                win.Width = ;
                win.Show();

                IntPtr handle =  WindowInteropHelper(win).Handle;
                windowInfo.SetAsChild(handle);

                _scheduler.Run(() =>
                {
                    WaitUtil.Wait(() => chromiumWebbrowser.PostData);

                    IRequest request = ;
                    if (chromiumWebbrowser.PostData != )
                    {
                        request = frame.CreateRequest();
                        request.Url = targetUrl;
                        request.Method = ";

                        request.InitializePostData();
                        var element = request.PostData.CreatePostDataElement();
                        element.Bytes = chromiumWebbrowser.PostData;
                        request.PostData.AddElement(element);
                        chromiumWebbrowser.PostData = ;
                    }

                    chromiumWebbrowser.dispatcher.Invoke(
                    {
                        NewWindowEventArgs e =  NewWindowEventArgs(targetUrl,request);
                        chromiumWebbrowser.OnNewWindow(e);
                    }));

                    chromiumWebbrowser.dispatcher.Invoke(
                    {
                        win.Close();
                    }));
                });
            }));

            newbrowser = ;
            ;
        }

    }
}
View Code

三、扩展ChromiumWebbrowser

 CefSharp.Wpf;
 System.Threading.Tasks;

 ExtChromiumbrowser : ChromiumWebbrowser
    {
        byte[] PostData { get; set; }

         ExtChromiumbrowser()
            : base()
        {
            this.LifeSpanHandler =  CefLifeSpanHandler();
            this.DownloadHandler = new DownloadHandler(this);
            this.MenuHandler =  MenuHandler();
            this.KeyboardHandler =  KeyboardHandler();
            this.RequestHandler = new RequestHandler();
        }

        event EventHandler<NewWindowEventArgs> StartNewWindow;

         OnNewWindow(NewWindowEventArgs e)
        {
            if (StartNewWindow != )
            {
                StartNewWindow(,e);
            }
        }

         ClearHandlers()
        {
            //如果不清理Handler,会导致子进程CefSharp.browserSubprocess.exe无法释放
            ;
        }
    }
}
View Code

四、封装ExtChromiumbrowser(browserCtrl控件)

 System.ComponentModel;
 System.IO;
 System.Windows.Controls;
 System.Windows.Data;
 System.Windows.Documents;
 System.Windows.Input;
 System.Windows.Media;
 System.Windows.Media.Imaging;
 System.Windows.Navigation;
 System.Windows.Shapes;
 CefSharpDemo
{
    /// <summary>
    /// 浏览器用户控件
    </summary>
    partial  browserCtrl : UserControl,Idisposable
    {
        #region 外部方法
        /*
        [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);
        */
        #endregion

        #region 变量属性事件
        static bool _isCefInited = ;

        object _lockObject = object();

         JSObject _jsObject;

        bool _firstLoad = ;

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

         URL
        string Url { public IRequest Request { ; }

         浏览器FrameLoadEnd事件
         EventHandler FrameLoadEnd;

         ExtChromiumbrowser browser
        {
            get
            {
                WaitUtil.Wait(() => this._browser != null && this._browser.IsInitialized && _isCefInited);

                ._browser;
            }
        }

        );
        #region 构造函数
         browserCtrl()
        {
            InitializeComponent();
            if (DesignerProperties.GetIsInDesignMode(this)) return;

            this.Loaded += browserCtrl_Loaded;

            lock (_lockObject)
            {
                if (!_isCefInited)
                {
                    _isCefInited = ;
                    InitCef();初始化CefSharp
                }
            }

            _browser =  ExtChromiumbrowser();
            Bindbrowser(_browser);
            grid.Children.Add(_browser);
        }
        #region browserCtrl_Loaded
        void browserCtrl_Loaded( sender,RoutedEventArgs e)
        {

        }
        #region SetMapCtrl
         设置Map控件接口,用于C#和JS互操作
         SetMapCtrl(IMapCtrl mapCtrl)
        {
            _jsObject.MapCtrl = mapCtrl;
        }
        #region dispose 释放资源
         释放资源
         dispose()
        {
            如果有弹出窗口则先释放它
            foreach (UIElement item in grid.Children)
            {
                if (item is browserContainer)
                {
                    (item as browserContainer).ClearResource();
                }
            }

            _browser.ClearHandlers();
            if (_browser != null && !_browser.Isdisposed)
            {
                _browser.dispose();
            }
        }
        #region Load
        void Load( url)
        {
            .IsNullOrWhiteSpace(url))
            {
                loadingWait.Visibility = Visibility.Visible;
                Url = url;
                _scheduler.Run(() =>
                {
                    #region Wait
                    WaitUtil.Wait(() =>
                    {
                        if (this._browser == null) ;
                        this._browser.IsInitialized) if (!_isCefInited) bool isbrowserInitialized = this.dispatcher.Invoke(() =>
                        {
                            isbrowserInitialized = ._browser.IsbrowserInitialized;
                        });
                        if (!isbrowserInitialized) ;
                    });
                    #endregion

                    _browser.Load(Url);
                });
            }
        }
        #region LoadUrl
         LoadUrl()
        {
            if (_firstLoad)
            {
                _firstLoad = ;

                _scheduler.Run(() =>#endregion

                    if (Url == null && SetUrlEvent != )
                    {
                        try
                        {
                            SetUrlEvent(this,1)">);
                        }
                        catch (Exception ex)
                        {
                            LogUtil.Error(ex,browserCtrl LoadUrl error 获取URL失败);
                        }
                    }
                    elsethis.dispatcher.Invoke(
                        {
                            loadingWait.Visibility = Visibility.Collapsed;
                        }));
                    }

                    if (Url != 
                        {
                            if (Request == )
                            {
                                _browser.Load(Url);
                            }
                            
                            {
                                _browser.Load(Url);
                                _browser.GetMainFrame().LoadRequest(Request);
                                Request = ;
                            }
                        }
                        browserCtrl LoadUrl error Load URL失败 Visibility.Collapsed;
                        }));
                    }
                });
            }
        }
        #region Bindbrowser
         Bindbrowser(ExtChromiumbrowser browser)
        {
            _jsObject =  JSObject();
            browser.RegisterJsObject(jsObj",_jsObject,1)">new CefSharp.BindingOptions { CamelCaseJavascriptNames =  });

            browser.IsbrowserInitializedChanged += (ss,ee) =>
            {
                LoadUrl();
            };
            browser.FrameLoadStart += (ss,1)">
            {
                this.dispatcher.BeginInvoke(
                {
                    (ss as ExtChromiumbrowser).Focus();
                }));
            };
            browser.FrameLoadEnd += (ss,1)">
                {
                    loadingWait.Visibility = Visibility.Collapsed;
                }));
                if (FrameLoadEnd != )
                {
                    FrameLoadEnd(null,1)">);
                }
            };
            browser.KeyDown += (ss,1)">if (ee.Key == Key.F5)
                {
                    
                    {
                        browser.Reload();
                    }
                     (Exception ex)
                    {
                        LogUtil.Error(ex,1)">ExtChromiumbrowser Reload error);
                    }
                }
            };
            browser.PreviewTextInput += (o,e) =>foreach (var character in e.Text)
                {
                     把每个字符向浏览器组件发送一遍
                    browser.Getbrowser().GetHost().SendKeyEvent((int)WM.CHAR,(int)character,1)">);
                }

                 不让cef自己处理
                e.Handled = ;
            };
            browser.LoadError += (s,1)"> Visibility.Collapsed;
                }));
            };
        }
        #region RegisterJsObject
        void RegisterJsObject(string name,1)">object objectToBind,BindingOptions options = )
        {
            )
                {
                    _browser.RegisterJsObject(name,objectToBind,options);
                }
            }
             (Exception ex)
            {
                LogUtil.Error(ex,1)">browserCtrl RegisterJsObject 错误);
            }
        }
        #region 初始化CefSharp
         InitCef()
        {
            string cefsharpFolder = CefSharpvar settings =  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 = ;
            CefSharpSettings.FocusednodeChangedEnabled = ;
            CefSharpSettings.LegacyJavascriptBindingEnabled = ;
            CefSharpSettings.ShutdownOnExit = ;
            CefSharpSettings.SubprocessExitIfParentProcessClosed = string logDir = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + /log/Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }

            settings.browserSubprocesspath = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + /CefSharp.browserSubprocess.exe;
            settings.LogFile = logDir + DateTime.Now.ToString(yyyyMMdd") + .log;
            settings.LocalesDirPath = AppDomain.CurrentDomain.BaseDirectory + cefsharpFolder + /locales;
            settings.CefCommandLineArgs.Add(disable-gpu1);
            settings.CefCommandLineArgs.Add(enable-media-stream);

            if (!Cef.Initialize(settings,performDependencyCheck: true,browserProcessHandler:  browserProcessHandler()))
            {
                throw new Exception(Unable to Initialize Cef

    }
}
View Code

五、MainWindow测试代码

 CefSharp Demo 窗体
     MainWindow : Window
    {
         MainWindow()
        {
            InitializeComponent();

            tabControl.AddTabItemEvent += tabControl_AddTabItemEvent;
            Application.Current.MainWindow = void tabControl_AddTabItemEvent(CreateTabItem("https://www.cnblogs.com/");
            CreateTabItem(file:///D:/_程序/CefSharpDemo/post.html);
        }

         新增Tab页
        void CreateTabItem(string url = )
        {
            TabItem tabItem =  TabItem();
            tabItem.Header = 标签;
            browserDemoCtrl ctrl =  browserDemoCtrl();
            ctrl.browserCtrl.browser.StartNewWindow += (s,1)">
            {
                CreateTabItem(e.TargetUrl,e.Request);
            };
            ctrl.browserCtrl.SetUrlEvent += (s,1)">
            {
                ctrl.browserCtrl.Url = url;
                ctrl.browserCtrl.Request = request;
            };
            tabItem.Content = ctrl;
            tabControl.Items.Add(tabItem);
            tabControl.SelectedItem = tabItem;
            ScrollViewer scrollViewer = tabControl.Template.FindName(scrollViewer ScrollViewer;
            scrollViewer.ScrollToRightEnd();
        }

        void Window_Closed(关闭窗体清理资源

            程序退出删除cache
            CefSharp.Cef.Shutdown();
            string cachePath = AppDomain.CurrentDomain.BaseDirectory + CefSharp\\cache (Directory.Exists(cachePath))
            {
                string path  Directory.GetDirectories(cachePath))
                {
                    Directory.Delete(path,);
                }
                string file  Directory.GetFiles(cachePath))
                {
                    if (!file.ToLower().Contains(cookies))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
    }
}
View Code

 六、测试HTML代码post.html

<!DOCTYPE html>
<htmlhead>
    title>CefSharpDemo</>

    Meta charset="utf-8" />
    http-equiv="X-UA-Compatible" content="IE=edge"name="viewport"="width=device-width,initial-scale=1"style type="text/css"stylescript ="text/javascript"scriptbody<!--enctype="multipart/form-data"-->
    form method="post" action="http://localhost:1209/netcms/" target="_blank">
        span>name:><input ="text" name="name" value="测试名称" />
        >code:="code"="测试编码" />

        button ="submit">Post提交buttonform>
View Code

七、测试后台代码

 ActionResult index()
{
    string name = Request.Params[name];
    string code = Request.Params[code];

    ViewBag.name = name;
    ViewBag.code = code;

     View();
}
View Code

八、测试前台csHTML代码

@using Models;
@{
    Layout = "~/Views/Shared/_SiteLayout.cshtml";
}

div ="font-size:50px; height:1200px;">@ViewBag.namebr /><>@ViewBag.codediv>
View Code

 

九:关键代码段:

1、RequestHandler类中获取并保存PostData

 disableDefaultHandling)
{
    )
    {
        )
        {
            _browser.PostData = ].Bytes.Length];
            request.PostData.Elements[);
        }
    }
    ;
}
View Code

 2、CefLifeSpanHandler类中创建IRequest

 IWebbrowser newbrowser)
{
     (ExtChromiumbrowser)browserControl;

    chromiumWebbrowser.dispatcher.Invoke(
    {
        browserPopupWin win =  browserPopupWin();
        win.ShowInTaskbar = ;
        win.Height = ;
        win.Width = ;
        win.Show();

        IntPtr handle =  WindowInteropHelper(win).Handle;
        windowInfo.SetAsChild(handle);

        _scheduler.Run(() =>
        {
            WaitUtil.Wait(() => chromiumWebbrowser.PostData);

            IRequest request = )
            {
                request = frame.CreateRequest();
                request.Url = targetUrl;
                request.Method = ;

                request.InitializePostData();
                 request.PostData.CreatePostDataElement();
                element.Bytes = chromiumWebbrowser.PostData;
                request.PostData.AddElement(element);
                chromiumWebbrowser.PostData = ;
            }

            chromiumWebbrowser.dispatcher.Invoke(
            {
                NewWindowEventArgs e = browser.OnNewWindow(e);
            }));

            chromiumWebbrowser.dispatcher.Invoke(
            {
                win.Close();
            }));
        });
    }));

    newbrowser = ;
    ;
}
View Code

说明:OnBeforePopup方法要return false,用browserPopupWin和windowInfo.SetAsChild方法弹出一个不可见的窗体,这样才能拿到PostData

3、在browserCtrl控件中用LoadRequest方法打开新的URL,并把post数据带过去

)
{
    _browser.Load(Url);
}

{
    _browser.Load(Url);
    _browser.GetMainFrame().LoadRequest(Request);
    Request = ;
}
View Code

 

十、效果图:

效果图

 

完整代码下载:https://files-cdn.cnblogs.com/files/s0611163/CefSharpDemo.zip

源码说明:为了减少源码压缩包的大小,代码中没有依赖的CefSharp文件,请自己下载(使用x86版本),用于测试的网页后台代码也没有,请自己制作测试后台

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐