----哆啦刘小洋 原创,转载需说明出处

MFC高级通用进度条-目录

  • 1 简介
  • 2 进度条实现基本原理
  • 3 使用方法
    • 3 .1 简单情况
    • 3.2 两个前后独立的进度条
    • 3.3 实际应用的一般情况
    • 3.4 带子进度条
  • 4 其他
    • 4.1 使用限制
    • 4.2 其他全局宏(函数)
    • 4.3 当前进度条设置

1 简介

SegeX组件之一:SegeX EvProgress。应用级源代码,首次公开。EvProgress是基于MFC的通用进度条,功能强大又简单易用。几行代码就可以让你的计算具有进度显示的功能,并且具有多种高级功能:1. 支持任意多个进度条同时存在;2.支持在子函数中继续主函数中的进度;3.支持两级子进度条;4.加入进度条后可避免长时间计算的”应用程序没有响应”;5.支持调节大小、背景颜色、背景图片;6.全自动管理。
源代码下载附后。

2 进度条实现基本原理

“工程地球物理系统(SegeX)“公开的原创组件之一。
本篇文章并不打算深入到实现原理的末端细节,感兴趣的读者可以阅读源代码,这里仅从宏观介绍一下实现原理。
1)全局模式。组件利用专门的处理类CEvProgressManager,管理任意多个进度条窗口CEvProgressWin。用户接口使用全局宏EV_START_NEW_PROGRESS_AUTO()来声明一个新的进度条。
2)栈管理。当声明一个新的进度条后,先前的进度条被压栈,因此这之后所有的进度操作都是针对当前的进度条。
3)自动释放。EV_START_NEW_PROGRESS_AUTO声明时,后台组件辅助类CEvProgressAutoDestroy会记录当前进度条,当EV_START_NEW_PROGRESS_AUTO所在的作用域结束时,CEvProgressAutoDestroy自动释放本次声明的进度条。
4)子函数中仍然可以继续主函数的进度,且子函数与主函数完全脱耦,无参数传递,不用关心也不需要知道是谁调用,也不用关心进度占主进度多少(按100%处理即可)。
5)全局设置。组件利用全局函数设置进度条的尺寸、背景颜色、背景图片等全局参数。
6)局部设置。组件在新开进度条之后,也可以对该进度条进行专门的背景图片设置等。

3 使用方法

首先,该组件是针对MFC Windows桌面应用程序,不支持控制台程序。因此假定你的工程是MFC Windows桌面应用程序,例如对话框程序。
1)将ev_progress.h 、ev_progress.cpp复制到工程指定目录。
2)在要使用的文件中增加头文件:#include “ev_progress.h”
3)ev_progress.cpp会用到预编译头文件,如果这里出错,请改为你的工程预编译头文件。(vc6一般是stdafx.h,而VC2022是pch.h)
4)然后可以开始使用了。详见后续多种使用场景。

3 .1 简单情况

最简单也是最常用的使用场景是在一个函数中,需要长时间计算,这时给一个进度条可提升交互体验,并可避免长时间纯计算引起的计算机假死(应用程序没有响应)现象。
举例说明:

void test_Progress_Simple()
{int i;//开始一个进度条EV_START_NEW_PROGRESS_AUTO(_T("Title"), _T("Prompt..."), NULL, 0, 1, 0);for (i = 0; i < 10000; ++i){//设置进度条进度EV_DO_PROGRESS_CHECK_ABORT(i * 1.0 / 10000, NULL, NULL)return; //如果点击了“取消”按钮EV_END_DO_PROGRESS_CHECK_ABORT()}
}

代码中主要有三行控制进度条的代码:

1)EV_START_NEW_PROGRESS_AUTO(lpstrTitle, lpstrMainPrompt, lpstrSubPrompt, dStart, dEnd, nShowSub):申明一个新的进度条。
lpstrTitle:进度条窗口的标题
lpstrMainPrompt:主进度条提示
lpstrSubPrompt:子进度条提示
dStart:主进度起始值。组件的进度基于0~1。
dEnd:主进度结束值。
nShowSub:是否显示子进度。0:不显示,1:显示。

2)EV_DO_PROGRESS_CHECK_ABORT(dValue, lpstrMainPrompt, lpstrSubPrompt):设置进度条进度的语句。
dValue:进度值。进度基于0~1。
lpstrMainPrompt:主进度条提示。这里可以改变它,不需要改变,设为NULL。
lpstrSubPrompt:子进度条提示。这里可以改变它,不需要改变,设为NULL。

3)EV_END_DO_PROGRESS_CHECK_ABORT():结束进度条进度的设置
组件支持取消操作,因此在这两句中间的代码,就是点击了“取消”之后,你需要执行的代码。如果不允许取消,两句中间可以空着。
组件在执行EV_DO_PROGRESS_CHECK_ABORT时,会处理Windows消息队列,防止消息堵塞,因此可以防止计算机没有响应的现象。

3.2 两个前后独立的进度条

组件支持顺序任意多个进度条,操作总是针对最后一个进度条操作。
举例说明:

//两个前后独立的进度条
void test_Progress_2()
{int i, j;//用应用程序的主图标作为进度条窗口图标EV_SET_PROGRESS_WINDOW_ICON(128);//IDR_MAINFRAME//开始一个进度条EV_START_NEW_PROGRESS_AUTO(_T("Title"), _T("Prompt..."), NULL, 0, 1, 0);for (i = 0; i < 10000; ++i){//插入一个新的进度条if (i == 0){EV_START_NEW_PROGRESS_AUTO(_T("Title2"), _T("Prompt2..."), NULL, 0, 1, 0);for (j = 0; j < 10000; ++j){EV_DO_PROGRESS_CHECK_ABORT(j * 1.0 / 10000, NULL, NULL); //如果点击了“取消”按钮,什么也不做(也即是不能取消)EV_END_DO_PROGRESS_CHECK_ABORT()}}//继续第一个进度条EV_DO_PROGRESS_CHECK_ABORT(i * 1.0 / 10000, NULL, NULL)return; //如果点击了“取消”按钮,终止函数运行EV_END_DO_PROGRESS_CHECK_ABORT()}
}

代码在新建一个进度条之后,马上建立了第二个进度条并操作,第二个进度条结束后,继续第一个进度条的操作。
同时该段代码用EV_SET_PROGRESS_WINDOW_ICON()函数设置了一下窗口的图标。你需要根据你的工程设置图标资源号。

3.3 实际应用的一般情况

实际应用中一般经常遇到进程分几段,每段会占用总进度一定占比,而每段又是调用的子函数,比如下面的示意性代码:

void xxx()
{//第1段 占总进度的 %0 ~ %30 Sub_Function1();//第2段 占总进度的 %30~100%Sub_Function2();
}

想实现上述功能,使用EvProgress将变得十分简单,实例如下:

//一般情况
bool Sub_Function1(int n)
{int j;for (j = 0; j < n * 1000; j++){//只需关心本过程的进度值EV_DO_PROGRESS_CHECK_ABORT(j * 1.0 / (n * 1000), NULL, NULL);//按占比100%进度处理return false;EV_END_DO_PROGRESS_CHECK_ABORT();}return true;
}
void test_Progress_Normal()
{//开始一个进度条EV_START_NEW_PROGRESS_AUTO(_T("Title"), _T("Prompt..."), NULL, 0, 1, 0);//第1段 %0~%30 EV_SET_PROGRESS_RANGE(0, 0.3); //设置后续进度在总进度的占比范围Sub_Function1(30);//第2段 %30~100%EV_SET_PROGRESS_RANGE(0.3, 1); //设置后续进度在总进度的占比范围Sub_Function1(70);
}

如代码所示,在第一段,只需要用EV_SET_PROGRESS_RANGE设置该段在总进度的占比范围,然后调用子函数即可。而在子函数呢,只需按照100%的进度去赋进度值即可。第二段和第一段一样,只需要先设置该段在总进度的占比范围(0.3, 1)即可。

3.4 带子进度条

有时计算时间很长,主函数调用子函数,或主循环中带大计算量的子循环,为了防止看上去一动不动,组件支持一级子进度。
举例说明:

//带子进度条
bool Sub_Function();
void test_Progress_Sub()
{int i;EV_START_NEW_PROGRESS_AUTO(_T("waiting..."), _T("Main:"), _T("Sub"), 0.0, 1.0, 1/*子进度条数为1(1个子进度*/);for(i =0 ; i< 50; i++){//因为外层循环是50次,所以每次子循环占据主进度1/50。模式为按比例。EV_START_SUB_PROGRESS(1.0/50/*本次子进度占主进度设置范围的1/50*/, EV_PROGRESS_MODE_SCALE_ABSOLUTE/*子进度按主进度占比通知主进度*/);if(!Sub_Function())return;EV_END_SUB_PROGRESS();}
}
bool Sub_Function()
{int j;for(j =0; j< 1000; j++){//只需关心本过程的进度值EV_DO_PROGRESS_CHECK_ABORT((j*1.0 / 999), NULL, NULL);return false;EV_END_DO_PROGRESS_CHECK_ABORT();}return true;
}

EV_START_SUB_PROGRESS(dRange, nMode):开始一个子进度。
dRange:子进度占总进度值(0~1)。
nMode:
EV_PROGRESS_MODE_SCALE_ABSOLUTE:占主进度总范围比例(取值:0~1)
EV_PROGRESS_MODE_RANGE_ABSOLUTE:占主进度初始范围值(取值:0~1)

注意EV_DO_PROGRESS_CHECK_ABORT()总是针对当前计算过程中赋值。因此组件使用非常灵活实用。比如一个子过程可能被2个主函数调用(上面代码中Sub_Function作为一个子函数),并且占2个主函数的计算量不一样,但通过上述代码,只需主函数指定子函数的进度比,子函数就可以在2个不同地方良好工作。
甚至还有第三个主函数调用了子函数,但主函数并没有申请进度条,子函数中的EV_DO_PROGRESS_CHECK_ABORT()也会正常工作,只是什么都不做而已,但不会引起程序崩溃。

4 其他

4.1 使用限制

在一个作用域(就是一对{})里,只能声明一次EV_START_NEW_PROGRESS_AUTO()。例如下代码会产生编译错误:

void test_error()
{EV_START_NEW_PROGRESS_AUTO(_T("waiting1..."), _T("Main1:"), _T("Sub1"), 0.0, 1.0, 1);//...EV_START_NEW_PROGRESS_AUTO(_T("waiting2..."), _T("Main2:"), _T("Sub2"), 0.0, 1.0, 1);
}

增加一个作用域,可以解决,代码如下:

void test_error()
{EV_START_NEW_PROGRESS_AUTO(_T("waiting1..."), _T("Main1:"), _T("Sub1"), 0.0, 1.0, 1);//...{EV_START_NEW_PROGRESS_AUTO(_T("waiting2..."), _T("Main2:"), _T("Sub2"), 0.0, 1.0, 1);   }
}

4.2 其他全局宏(函数)

必须放在EV_START_NEW_PROGRESS_AUTO之前, 之后对所有进度条有效:

//   1)EV_SET_PROGRESS_WINDOW_ICON(UINT idIcon);//指定进度条对话框图标
//  2)EV_SET_PROGRESS_CONFIRM_CANCEL(BOOL bConfirm); //指定取消是否需要确认
//  3)EV_SET_PROGRESS_COLOR(DWORD forecolor, DWORD backcolor); //指定进度条前景色和背景色
//  4)EV_SET_PROGRESS_CTRL_SIZE(int width, int height); //指定进度条的宽度和高度
//  5)EV_SET_PROGRESS_BITMAP(UINT idFore, UINT idBack); //指定全局进度条的位图

4.3 当前进度条设置

必须放在EV_START_NEW_PROGRESS_AUTO之后,对当前进度条有效:

//   1)EV_SET_PROGRESS_STRINGS(LPCTSTR lpstrTitle, LPCTSTR lpstrMainPrompt, LPCTSTR lpstrSubPrompt);//指定显示的文本
//  2)EV_SET_SHOW_SUBPROGRESS(int nSubMark = 0, BOOL bUpdateWin = TRUE);
//  3)EV_GET_PROGRESS_RANGE(double& dStart, double& dEnd);//获取进度限定范围
//  4)EV_SET_PROGRESS_BITMAP_CURRENT(IDB_BITMAP_MAIN[, IDB_BITMAP_SUB]);//指定当前进度条的位图(优先于全局)

下载完整的代码资源。代码资源附带完整的VC实例工程。

SegeX Progress:MFC通用进度条相关推荐

  1. Xamarin XAML语言教程隐藏文件使用Progress属性设置进度条

    Xamarin XAML语言教程隐藏文件使用Progress属性设置进度条 Xamarin XAML语言教程隐藏文件中使用Progress属性设置进度条进度,开发者除了可以在XAML中使用Progre ...

  2. Xamarin XAML语言教程Progress属性设置进度条进度

    Xamarin XAML语言教程Progress属性设置进度条进度 在图12.19~12.21中我们看到的是没有实现加载的进度条,即进度条的当前进度为0,如果开发者想要修改当前进度,可以使用两种方式: ...

  3. progress组件(进度条)

    progress组件:进度条 progress组件的属性: percent:类型:number 设置百分比 (0~100) show-info:类型:布尔 在进度条右侧显示百分比 border-rad ...

  4. input加progress组合写进度条的简单音乐播放器实现

    主要解释一下实现图中的音量进度条效果. 仅供大家参考,勿喷. 查阅了很多资料看了挺多人的代码,但是ajax对于我这个新手小白来说,可能还难以理解,因此分享一个本小白的方法. 本人编程小白,分享实现的方 ...

  5. MFC基于Progress动态滚动进度条

    1. 在对话框上新建一个滚动条控件IDC_PROGRESS1 2. 关联一个control类型的变量m_progress 具体步骤:右击进度条,添加变量 常用方法: **SetRange方法用来设置进 ...

  6. MFC中进度条的学习

    缘起 作为MFC开发的一枚老鸟,最近感觉自己写的程序太low.于是决定学习一下进度条,在自己的程序中加入进度条,提高自己程序的逼格.于是便有个此文. 1 2 3 环境 配置   系统 WIN7 SP1 ...

  7. MFC环形进度条实现

    MFC只支持横/竖条形进度条,并不支持环形进度条,而环形进度条在实际中使用很是广泛,以下使用GDI+自绘具有环形效果的进度条. 其实GDI+里封装有一个函数DrawArc可以画环形进度条,但它有一个缺 ...

  8. MFC之进度条CProgressCtrl

    一.成员函数简介 1.create() 针对不是通过资源文件上拖拉进度条控件生成的进度条,需要用此函数创建一个. 2.SetRange() 设置进度条的起始值和终止值. 3.SetPos() 设置进度 ...

  9. MFC中进度条控件的使用方法

    进度条控件是程序开发中基础控件之一,常用于显示程序的进度.在进行程序安装.文件传输时经常用到.其用法也比较简单固定. 转自:http://jingyan.baidu.com/article/95c9d ...

最新文章

  1. Tomcat 服务器的端口号的修改
  2. netty源码分析系列——EventLoop
  3. 17. javacript高级程序设计-错误处理与调试
  4. ASP.NET服务器端控件原理分析
  5. Notepad++ 列编辑操作实例二则
  6. 代码+实例:深度学习中的“轴”全解
  7. Find non-overlap jobs with max cost
  8. 2010/9/12学习历程
  9. 致敬各位10年阿里的前端开发
  10. 为了完成月入三万的目标,我都做了哪些准备?
  11. 开启 ASA 5505 snmp协议
  12. ci github 通知_GitHub 欢迎一切 CI 工具
  13. Qt--优秀开源项目
  14. 如何做项目总结与汇报
  15. Ramda 函数库参考教程
  16. 21个免费学习编程的网站
  17. 2021-09-13 多组EQ切换
  18. J-LinK-OB改造版 仿真/调试器 使用说明
  19. Http的各种请求方法(详解)
  20. 目前国内几大著名报表软件

热门文章

  1. R数据分析:网络分析的做法,原理和复现方法
  2. 推荐系统(9):推荐系统评测之评测方法
  3. 巴别塔——问答平台调研
  4. JAVA类似ABP框架_使用ABP框架踩过的坑系列5
  5. wine常见问题集合
  6. QQ浏览器将完整网页保存为PDF
  7. sprinngboot分库分表中间件
  8. JavaScript笔记(一)
  9. java vector的排序_Java用vector容器排序
  10. 火车票余票问题的算法解析