在windows开发界面时,使用浏览器来请求和显示网页内容,是比较常见的。

但是在请求网页内容时,因网速或者前端功能复杂加载较慢,亦或者加载时遇到各种问题,如空白/黑屏/加载不完整/证书问题等。

因此需要一个加载进度/加载失败的显示界面。

加载进度显示

界面显示

1. 界面显示,加载进度样式可参考: 绕圈进度条

2. 添加Loading状态枚举。不加载/加载中/加载失败

     public enum LoadingState
{
NotLoading,//正常的网页内容界面
Loading, //加载进度显示
Error, //加载失败界面
}

在控件内添加LoadingState附加属性,前端界面通过绑定此附加属性来确定是否显示,LoadingState的变更时,界面显示则直接变更。

进度显示处理

在封装相应浏览器后,针对三个事件DocumentCompleted、ProgressChanged、NavigateError作进度显示的处理。

结束加载进度

  1. DocumentCompleted文档加载完成后,结束加载进度。此事件只有Navigate调用后,才会触发
  2. ProgressChanged进度变更通知,Navigate、Refresh调用后都会触发。因为Navigate调用后,同一进度会重复触发ProgressChanged,ProgressChanged在Navigate调用时触发并没有任何意义,因此在DocumentCompleted之后再添加事件的订阅,ProgressChanged只开放给Refresh方法。
  3. 当前进度大于0时,立即结束Loading,减少延时。
     /// <summary>
/// 文档加载完成
/// </summary>
/// <remark>Navigate方法触发,Refresh方法不会触发</remark>
/// <remark>在首次加载时,添加DocumentCompleted订阅</remark>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Browser_OnDocumentCompleted(object sender, HtmlDocumentCompletedEventArgs e)
{
//当前Loading状态不是Error的情况下,才结束加载
if (LoadingState == LoadingState.Loading)
{
LoadingState = LoadingState.NotLoading;
} //显示网页内容首次加载后,再订阅加载进度事件
_browser.ProgressChanged -= Browser_ProgressChanged;
_browser.ProgressChanged += Browser_ProgressChanged;
OnDocumentCompleted(e);
} /// <summary>
/// 加载进度事件
/// </summary>
/// <remark>Navigate会触发多次ProgressChanged事件,所以此事件订阅不应开放给Navigate</remark>
/// <remark>Refresh调用后,会触发一次</remark>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Browser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
{
//当前进度大于0,且当前Loading状态是Loading的情况下,才结束Loading动画
if (e.CurrentProgress > && LoadingState == LoadingState.Loading)
{
LoadingState = LoadingState.NotLoading;
}
}

值得注意的是,如果按照如上设置,当IE8环境升级到IE11后,因WebBrowserProgressChangedEventArgs事件参数返回异常,不会结束Loading。

问题跟进记录:When IE updates from version 8 to version 11,this eventArgs value for event ProgressChanged is weird.

原因:调用refresh方法。经调试发现ProgressedChanged的事件参数中,MaximumProgress一直等于0。
但是,正常情况下,同样的电脑环境,win7 IE8或者IE11下,refresh方法,返回的MaximumProgress不为0。

推荐分析:升级后,原有IE版本的注册项遗留,导致冲突。

解决方案:添加e.CurrentProgress == e.MaximumProgress的条件判断。

     private void Browser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
{
//当以下俩种条件符合时,才结束Loading动画
//1.当前Loading状态是Loading的情况下
//2.当前进度大于0,或者当前进度等于进度上限阀值
if (LoadingState == LoadingState.Loading && (e.CurrentProgress > || e.CurrentProgress == e.MaximumProgress))
{
LoadingState = LoadingState.NotLoading;
}
}

PS:微软小组成员推荐使用WebView,然而这个只为Win10的Microsoft Edge开发的控件,只能在win10上运行且只支持.NET4.6.2及以上,限制多多。

加载出错

     private void Browser_NavigateError(object sender, BrowserExtendedNavigateErrorEventArgs e)
{
e.Cancel = true;
LoadingState = LoadingState.Error; //当前不是网络问题的异常,记录异常日志
if (e.StatusCode != NavigationErrorHttpStatusCode.INET_E_RESOURCE_NOT_FOUND)
{
Console.WriteLine($"WebBrowser无法连接服务器:{e.Url},异常信息为:{e.StatusCode},异常Code为:{ (int)e.StatusCode }");
}
}

浏览器事件处理

针对如上三个事件,DocumentCompleted、ProgressChanged、NavigateError

winform版IE浏览器

     /// <summary>
/// 在 <see cref="T:System.Windows.Forms.WebBrowser" /> 控件完成加载文档时发生。
/// </summary>
[SRCategory("CatBehavior")]
[SRDescription("WebBrowserDocumentCompletedDescr")]
public event WebBrowserDocumentCompletedEventHandler DocumentCompleted;
     /// <summary>
/// 在 <see cref="T:System.Windows.Forms.WebBrowser" /> 控件已更新有关要导航到的文档的下载进度的信息时发生。
/// </summary>
[SRCategory("CatAction")]
[SRDescription("WebBrowserProgressChangedDescr")]
public event WebBrowserProgressChangedEventHandler ProgressChanged;

NavigateError加载失败事件,需要重写CreateSink、DetachSink。在对应的cookie中添加额外事件的处理:(在此不详述)

     public void NavigateError(object pDisp, ref object url, ref object frame, ref object statusCode, ref bool cancel)
{
_browser?.NavigateError?.Invoke(this, new BrowserExtendedNavigateErrorEventArgs((string)url, (string)frame, (int)statusCode, cancel));
}

Cef浏览器

     private void Register()
{
_cefBrowser.LoadingStateChanged += CefBrowserOnLoadingStateChanged;
_cefBrowser.LoadError += CefBrowserOnLoadError;
}
private void CefBrowserOnLoadError(object sender, LoadErrorEventArgs args)
{
// Don't display an error for downloaded files where the user aborted the download.
if (args.ErrorCode == CefErrorCode.Aborted)
{
return;
}
_isLoadError = true;
DispatcherUtil.Invoke(() =>
{
NavigateError?.Invoke(this, new BrowserExtendedNavigateErrorEventArgs(args.FailedUrl, args.Frame.Name, (int)args.ErrorCode, false));
});
} private void CefBrowserOnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
{
//isLoading为false,代表LoadingCompleted
//_isLoadError为false,代表未加载出错
if (!args.IsLoading && !_isLoadError)
{
DispatcherUtil.Invoke(() =>
{
DocumentCompleted?.Invoke(this, new HtmlDocumentCompletedEventArgs(null));
});
}
}

关键字:客户端浏览器进度Loading、IE浏览器loading、Cef浏览器loading

WPF 客户端浏览器 添加Loading加载进度的更多相关文章

  1. iOS WKWebView添加网页加载进度条(转)

    一.效果展示 WKWebProgressViewDemo.gif 二.主要步骤 1.添加UIProgressView属性 @property (nonatomic, strong) WKWebView ...

  2. Unity3D 场景切换加载进度条实现

    需要三个场景,场景A,场景B,场景C: 场景A:一个按钮,点击加载场景B: 场景B:从A切换到C过度场景,加载进度条: 场景C:目标场景: 创建OnProgress.cs脚本: using Syste ...

  3. WPF动画 - Loading加载动画

    存在问题: 最近接手公司一个比较成熟的产品项目开发(WPF桌面端),其中,在登陆系统加载时,60张图片切换,实现loading闪烁加载,快有密集恐惧症了!!! 代码如下: private void L ...

  4. WPF loading加载动画库

    原文:WPF loading加载动画库 1. 下载Dll        https://pan.baidu.com/s/1wKgv5_Q8phWo5CrXWlB9dA 2.在项目中添加引用       ...

  5. 《动手实现一个网页加载进度loading》

    loading随处可见,比如一个app经常会有下拉刷新,上拉加载的功能,在刷新和加载的过程中为了让用户感知到 load 的过程,我们会使用一些过渡动画来表达.最常见的比如"转圈圈" ...

  6. 仿UC浏览器图片加载进度条

    前几天用UC浏览器看新闻(无意中给UC打了广告),看到它的图片加载进度条,正好最近有时间,所以就自己写了一个. 效果图如下 进度条的底色和填充颜色都可以调整. 首先中间的笑脸作为一个整体,其实现代码如 ...

  7. react封装简单的浏览器顶部加载进度条全局组件

    在项目中经常会有在请求前后加loading或者加加载进度条,一般这些组件都会抽离出来作为全局组件 进度条的插件貌似都不是很符合自己项目中的需求,于是.. 参考nprogress样式,自己在项目中封装组 ...

  8. 混合开发(一)——WebView开发高级技巧之加载网页以及JavaScript,加载进度条

    混合开发(一)--WebView开发高级技巧之加载网页以及JavaScript,加载进度条 现在关于混合开发也越来越多了,很多人喜欢跟随,比如HB,比如RN,其实这东西很早就有这么一个概念了,而且说实 ...

  9. 【原生JS插件】LoadingBar页面顶部加载进度条

    先展示一下已经实现的效果: 预览地址:http://dtdxrk.github.io/js-plug/LoadingBar/index.html 看到手机上的浏览器内置了页面的加载进度条,想用在pc上 ...

随机推荐

  1. 《SpringMVC从入门到放肆》十三、SpringMVC数据校验

    上一章,我们学习了SpringMVC的自定义类型转换器,但是如果转换后的数据传递到Controller的方法中,忽然发现有某些属性为Null了,这怎么办?我们需要一种有效的数据校验机制,来对数据进行有 ...

  2. 我用linux系统的采坑记

    我的新Ubuntu18,也没安装什么,但是在使用过程中总是莫名其妙的卡死,真的很烦.有时候cpu使用率接近100%,有时候貌似是内存不够了,但是我明明是8GB,这些小问题搞得我很恼火.这样的机器真的不 ...

  3. javascript---split 和 join 的区别

    //相同点 : split 和 join 都是对字符或字符串进行操作的 //split(切割字符串) : 把字符串根据切割符切割,返回数组 //第一个参数 分隔符 //第二个参数 返回数组中元素的个数 ...

  4. 解决Visual Studio 加载符号卡死情况

    VS 加载符号 过慢或卡死的情况都可以用这种方法 打开VS的[工具]-[选项]-[调试]-[符号], 如下图所示: 1. 先取消勾选 ”Microsoft符号服务器” 2. 再点击 “清空符号缓存” ...

  5. emWin表盘界面设计,含uCOS-III和FreeRTOS两个版本

    第4期:简易表盘界面设计 配套例子:V6-906_STemWin提高篇实验_简易表盘界面设计(uCOS-III)V6-907_STemWin提高篇实验_简易表盘界面设计(FreeRTOS) 例程下载地 ...

  6. 主流数据库连接池性能比较 hikari druid c3p0 dbcp jdbc

    背景 对现有的数据库连接池做调研对比,综合性能,可靠性,稳定性,扩展性等因素选出推荐出最优的数据库连接池 . NOTE: 本文所有测试均是MySQL库 测试结论 1:性能方面 hikariCP> ...

  7. [Swift]LeetCode395. 至少有K个重复字符的最长子串 | Longest Substring with At Least K Repeating Characters

    Find the length of the longest substring T of a given string (consists of lowercase letters only) su ...

  8. Java中的数组添加,数组相关代码

    private static void demo() {  // TODO Auto-generated method stub  /**   * @author square 凉   * @功能 实 ...

  9. java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.paipaixiu/com.example.paipaixiu.MASetSomeThing}: android.view.InflateException: Binary XML file line #19: Attempt to invo

    这个报错是因为Android布局的控件 <view android:layout_width="match_parent" android:layout_height=&qu ...

  10. Python内置函数(49)——pow

    英文文档: pow(x, y[, z]) Return x to the power y; if z is present, return x to the power y, modulo z (co ...