在WPF中使用CefSharp嵌入浏览器(转)-程序员宅基地

技术标签: ViewUI  ui  操作系统  javascript  

在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:

复制代码
<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>
复制代码

Code:

复制代码
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:

复制代码
    <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>
复制代码

Code:

复制代码
        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页面:

复制代码
<!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" οnclick="callback()" ID="Button">
</body>
</html>
复制代码

 

增加一个类,叫做:CallbackObjectForJs

复制代码
    public class CallbackObjectForJs
    {
        public void showMessage(string msg)
        {
            MessageBox.Show(msg);
        }
    }
复制代码

 注意这个方法的名称必须小写。

 

改造一下WebPageViewer类,在构造后WebView之后,注册一个JS对象,

复制代码
        //...
        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页面与客户端程序之间的交互。点击这里下载代码。

感谢您的阅读!

 

转载于:https://www.cnblogs.com/ExMan/p/4699882.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30363981/article/details/95012147

智能推荐

前端学PHP之正则表达式基础语法_正则表达式主要用于字符串模式匹配或字符串匹配,即什么操作-程序员宅基地

文章浏览阅读177次。前面的话  正则表达式是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找及替换操作。在PHP中,正则表达式一般是由正规字符和一些特殊字符(类似于通配符)联合构成的一个文本模式的程序性描述。正则表达式有三个作用:1、匹配,也常常用于从字符串中析取信息;2、用新文本代替匹配文本;3、将一个字符串拆分为一组更小的信息块。本文将详细介绍PHP中的正则表达式基础语法 _正则表达式主要用于字符串模式匹配或字符串匹配,即什么操作

桌面上计算机未响应,win7系统打开计算机未响应的解决方法-程序员宅基地

文章浏览阅读415次。很多小伙伴都遇到过win7系统打开计算机未响应的困惑吧,一些朋友看过网上零散的win7系统打开计算机未响应的处理方法,并没有完完全全明白win7系统打开计算机未响应是如何解决的,今天小编准备了简单的解决办法,只需要按照1、点击win7 32位旗舰版系统电脑的开始菜单,打开控制面板; 2、在控制面板中选择外观和个性化;的顺序即可轻松解决,具体的win7系统打开计算机未响应教程就在下文,一起来看看吧!..._电脑打开计算机未响应

【Android】实现键盘收起的时候,输入框UI也消失_安卓收起键盘-程序员宅基地

文章浏览阅读498次。之前对软键盘操作,实现对点击输入框出现软键盘(即手机默认的键盘)现在有一个需求是:软键盘收起的时候,咱的输入框UI也消失。_安卓收起键盘

基于Python实现的电影数据可视化分析系统附完整代码_影视网站的数据可视化分析-程序员宅基地

文章浏览阅读4k次,点赞3次,收藏46次。基于Python实现的电影数据可视化分析系统附完整代码_影视网站的数据可视化分析

Qt入门:3 Qt界面布局管理详解_qt vertical line 移动-程序员宅基地

文章浏览阅读1.4k次,点赞2次,收藏8次。实例讲解ln_2双击dialog.ui进入设计界面,进行如下设计:程序的主要功能是对中间一个文本框的文字字体样式和颜色进行设置。在界面设计时,对需要访问的组件修改其 objectName,如各个按钮、需要读取输入的编辑框、需要显示结果的标签等,以便在程序里区分。对于不需要程序访问的组件则无需修改其 objectName,如用于界面上组件分组的 Gr..._qt vertical line 移动

CRC冗余校验码及查表法_crc4错误概率-程序员宅基地

文章浏览阅读987次。CRC冗余校验码及查表法什么是CRC编码它将一个长度为k的位串看作是系数是0或者1的k-1次多项式使用一个长度为r+1的生成多项式进行模2计算,生成一个长度为r的字符序列,能检测长度小于等于r的所有突发错误,当突发错误长度为r+1时,只有其刚刚好等于生成多项式,才检测不出来。多项式的最高位、最低位系数必须为1(我不知道为什么)计算方法:(此处使用的减法是模2减法,不进位不借位,相当于XOR运算)例如:使用G(x)=11001检测位串1011011010110110000011001----_crc4错误概率

随便推点

计算机视觉图像检测之从EasyDL到BML_easydl paddlex bml-程序员宅基地

文章浏览阅读914次,点赞18次,收藏18次。部署方式选择公有云部署,训练方式均可。增量训练的意思是在之前训练的模型基础上再次进行训练,如果事先没有进行过训练,这一项为不可选中状态。回到Postman,参数栏按如下方式填写,其中第一个KEY-VALUE值直接照写,client_id和client_secret的VALUE值分别为上一步获取的AK、SK。如果数据集质量够高,每种标签标注效果都很好,也可以在模型训练时再进行数据增强,或者直接跳过这一步。在导入界面配置导入信息,选择本地导入,导入压缩包(其他导入方式请自行测试),如图1.1.2。_easydl paddlex bml

红帽oracle关系,redhat和oracle linux kernel对应关系-程序员宅基地

文章浏览阅读1.4k次。Red Hat Enterprise Linux Version / UpdateRed Hat Enterprise Linux – Kernel version / redhat-release stringOracle Linux – Kernel version / release stringsRed Hat Enterprise Linux 7Red Hat Enterprise Li..._oracle linux redhat 对应关系

2020年中南大学研究生招生夏令营机试题_中南大学 计算机 夏令营 笔试-程序员宅基地

文章浏览阅读804次。2020年中南大学研究生招生夏令营机试题题目链接A题题目描述众所周知,彩虹有7种颜色,我们给定七个 字母和颜色 的映射,如下所示:‘A’ -> “red”‘B’ -> “orange”‘C’ -> “yellow”‘D’ -> “green”‘E’ -> “cyan”‘F’ -> “blue”‘G’ -> “purple”但是在某一..._中南大学 计算机 夏令营 笔试

Cmake的option与cmake_dependent_option-程序员宅基地

文章浏览阅读2.9k次。一、介绍cmake提供了一组内置宏,用户可以自己设置。只有当该集合中的其他条件为真时,该宏才会向用户提供一个选项。语法include(CMakeDependentOption)CMAKE_DEPENDENT_OPTION(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF)如果USE_BAR为true而USE_ZOT为false,则提供一个默认为ON的选项USE_FOO。否则,它将USE_FOO设._cmake_dependent_option

C++ =default-程序员宅基地

文章浏览阅读5.2k次,点赞10次,收藏34次。在c++中如果我们自行定义了一个构造函数,那么编译器就不会再次生成默认构造函数,我们先看如下的代码我们定义一个类,这个类没有定义构造函数,此时在下面一段代码依然可以正常使用,我们加上一个自定义构造函数:此时编译器会报错,原因很简单,我们自定义了一个构造函数,以前的默认构造函数没了,我们要用如下的方式调用:如果我们还要使用无参构造函数得在定义时自己写个好了此时不报错了,但是这样写代码执行效率没有编译器生成的自定义函数的效率高,为了解决这个问题,C++11 标准引入了一个新特性:default 函数。程_c++ =default

linux gcc 4.8.2,gcc4.8.2 编译异常-程序员宅基地

文章浏览阅读446次。gcc4.8.2 编译错误 求助checkingfor--enable-version-specific-runtime-libs...nocheckingfor--enable-generated-files-in-srcdir...nocheckingbuildsystemtype...i686-pc-linux-gnucheckinghostsystemtype....._gcc libatomic error