在WPF中使用CefSharp嵌入浏览器
日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中。下面我们使用CefSharp嵌入浏览器来实现。
首先先介绍一下CefSharp嵌入式浏览器,它是基于Google浏览器的一个组件,我们可以在WPF/WinForm客户端软件中使用它。CefSharp的代码托管在GitHub上,.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework。
目前最新版本的CefSharp是41.0版本,如果你的客户端软件需要支持WIN XP操作系统,建议使用CefSharp.Wpf 1.25.7及之前的版本。可以从Nuget上获取到具体的内容。在新版本的CefSharp中,已经取消了对WIN XP系统的支持。
具体的实现:(首先引用CefSharp.dll,CefSharp.Wpf.dll 另外将icudt.dll,libcef.dll这两个Dll放置在bin/Debug或者bin/Release目录下)
先创建一个UserControl,并继承IRequestHandler接口,代码如下:
UI:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <UserControl x:Class= "EmbeddedWebBrowserSolution.WebPageViewer" xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d= "http://schemas.microsoft.com/expression/blend/2008" xmlns:local= "clr-namespace:EmbeddedWebBrowserSolution" xmlns:uc= "clr-namespace:EmbeddedWebBrowserSolution" mc:Ignorable= "d" d:DesignHeight= "300" d:DesignWidth= "300" > <Grid x:Name= "MainGrid" > <uc:MaskLoading x:Name= "maskLoading" /> </Grid> </UserControl> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | public partial class WebPageViewer : UserControl, IRequestHandler { private WebView _view; public WebPageViewer( string url) { InitializeComponent(); CEF.Initialize( new Settings { LogSeverity = LogSeverity.Disable, PackLoadingDisabled = true }); BrowserSettings browserSetting = new BrowserSettings { ApplicationCacheDisabled = true , PageCacheDisabled = true }; _view = new WebView( string .Empty, browserSetting) { Address = url, RequestHandler = this , Background = Brushes.White }; _view.LoadCompleted += _view_LoadCompleted; MainGrid.Children.Insert(0, _view); } private void _view_LoadCompleted( object sender, LoadCompletedEventArgs url) { Dispatcher.BeginInvoke( new Action(() => { maskLoading.Visibility = Visibility.Collapsed; })); } public void View( string url) { if (_view.IsBrowserInitialized) { _view.Visibility = Visibility.Hidden; maskLoading.Visibility = Visibility.Visible; _view.Load(url); } } #region IRequestHandler public bool GetAuthCredentials(IWebBrowser browser, bool isProxy, string host, int port, string realm, string scheme, ref string username, ref string password) { return false ; } public bool GetDownloadHandler(IWebBrowser browser, string mimeType, string fileName, long contentLength, ref IDownloadHandler handler) { return true ; } public bool OnBeforeBrowse(IWebBrowser browser, IRequest request, NavigationType naigationvType, bool isRedirect) { return false ; } public bool OnBeforeResourceLoad(IWebBrowser browser, IRequestResponse requestResponse) { return false ; } public void OnResourceResponse(IWebBrowser browser, string url, int status, string statusText, string mimeType, WebHeaderCollection headers) { } #endregion } |
下一步,在MainWindow上来承载,
UI:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <Grid> <DockPanel> <StackPanel DockPanel.Dock= "Top" Orientation= "Horizontal" > <TextBlock Text= "Address:" Margin= "5" /> <TextBox x:Name= "txtAddress" Width= "350" Margin= "5" /> <Button Content= "Go" Margin= "5" Click= "OnGoClick" IsDefault= "True" /> </StackPanel> <Grid x:Name= "MainGrid" > </Grid> </DockPanel> </Grid> |
1 2 3 4 5 6 7 8 9 10 | private void OnGoClick( object sender, RoutedEventArgs e) { string url = txtAddress.Text; if (! string .IsNullOrWhiteSpace(url)) { WebPageViewer viewer = new WebPageViewer(url); MainGrid.Children.Insert(0,viewer); } } |
注意,需要将工程Platform Target设置为X86。
运行效果:
到这里,一个使用CefSharp来承载Web页面的例子就算完成了。
相比于WPF内置的WebBrowser,CefSharp在处理JS回掉时,比WebBrowser方便很多。请看下面的例子:
我们有这样一个HTML页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE html> <html> <head> <title></title> <meta charset= "utf-8" /> <script type= "text/javascript" > function callback() { callbackObj.showMessage( 'message from js' ); } </script> </head> <body> <input type= "button" value= "Click" onclick= "callback()" ID= "Button" > </body> </html> |
增加一个类,叫做:CallbackObjectForJs
1 2 3 4 5 6 7 | public class CallbackObjectForJs { public void showMessage( string msg) { MessageBox.Show(msg); } } |
注意这个方法的名称必须小写。
改造一下WebPageViewer类,在构造后WebView之后,注册一个JS对象,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //... public WebPageViewer( string url) { InitializeComponent(); CEF.Initialize( new Settings { LogSeverity = LogSeverity.Disable, PackLoadingDisabled = true }); BrowserSettings browserSetting = new BrowserSettings { ApplicationCacheDisabled = true , PageCacheDisabled = true }; _view = new WebView( string .Empty, browserSetting) { Address = url, RequestHandler = this , Background = Brushes.White }; _view.RegisterJsObject( "callbackObj" , new CallbackObjectForJs()); _view.LoadCompleted += _view_LoadCompleted; MainGrid.Children.Insert(0, _view); } //... |
运行效果如下:
通过这样的方式,我们可以很好的实现Web页面与客户端程序之间的交互。点击这里下载代码。
感谢您的阅读!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?