MFC进度条学习笔记
大家好,又见面了,我是你们的朋友全栈君。
最近工作中有使用到进度条的知识,就来学习学习这个控件~~ 先来看看想要达到的效果:
好的,现在开始正题。 我们这里的进度条,在程序里面叫做CProgressCtrl,它是继承自CWnd类的基础控件类,用来展示工作进展度。
1、主线程的处理方式。 1.1先给我们的控件添加一个环境变量,起个名字就叫做:
CProgressCtrl m_progressCtrl;
1.2 接着,在对话框初始化的时候做一些初始化工作:
void CdemoDlg::Init()
{
m_progressCtrl.SetRange(0, 100);//设置进度条数值变化范围
m_progressCtrl.SetPos(0); //设置进度条默认初始进度
m_progressCtrl.SetStep(m_nStep);
//文本框百分比显示
CString str;
int nPos = m_progressCtrl.GetPos(); // 获取进度条的当前位置
str.Format("%d", nPos);
GetDlgItem(IDC_STATIC_PERCENT)->SetWindowText(str + _T("%"));//显示进度条初始进度
}
1.3 然后,需要在头文件里面添加几个重要的方法和变量:
private:
int m_nStopType; //0加载完毕结束1外界干扰结束
public:
int m_nStep; //步长
void UpdateProgress(); //用来更新我们的进度条
void StopUpdate(); //用来结束我们的进度条
afx_msg void OnBnClickedButtonPerLoad(); //手动点击
afx_msg void OnBnClickedButtonAutoLoad(); //自动
afx_msg void OnBnClickedButtonStopLoad(); //停止
afx_msg void OnTimer(UINT_PTR nIDEvent); //定时器
1.4 实现那些关键的函数:
void CdemoDlg::UpdateProgress()
{
m_progressCtrl.SetStep(m_nStep); //设置进度条步长
m_progressCtrl.StepIt(); //按照当前步长更新位置
int nPos = m_progressCtrl.GetPos(); // 获取进度条的当前位置
CString str;
str.Format("%d", nPos);
GetDlgItem(IDC_STATIC_PERCENT)->SetWindowText(str + _T("%"));//显示进度条进度
if (100 == nPos)
{
StopUpdate();
}
}
void CdemoDlg::StopUpdate()
{
KillTimer(1);
if (0 == m_nStopType)
{
MessageBox("加载完毕", "温馨提示", MB_OKCANCEL);
}
else if (1 == m_nStopType)
{
int nPos = m_progressCtrl.GetPos();
CString tips;
tips.Format("您已取消加载,目前进度:%d%%", nPos);
MessageBox(tips, "温馨提示", MB_OKCANCEL);
}
}
void CdemoDlg::OnBnClickedButtonPerLoad()
{
UpdateProgress();
}
void CdemoDlg::OnBnClickedButtonAutoLoad()
{
SetTimer(1, 10, NULL); //开启自动加载
}
void CdemoDlg::OnBnClickedButtonStopLoad()
{
m_nStopType = 1;
StopUpdate();
}
void CdemoDlg::OnTimer(UINT_PTR nIDEvent)
{
if (1 == nIDEvent)
{
UpdateProgress();
}
CDialogEx::OnTimer(nIDEvent);
}
2、工作者线程的处理方式。 有时候,我们需要创建多线程来帮助我们提高程序效率,这种情况下又该怎样处理控件呢? 我们需要思考,这个工作者线程,只需要去计算我们的数据,算完一部分,就向我们的主程序发送消息,更新我们的UI就好。 2.1首先,添加新类,就叫做:CMyThread。
#pragma once
class CMyThread
{
public:
CMyThread();
~CMyThread();
};
2.2 接着,添加功能函数,并实现:
static void Calculate(void *p);
Ps: 至于这里为何需要使用static成员函数,就请移驾到参考里面看下吧,嘤嘤嘤~~
void CMyThread::Calculate(void *p)
{
HWND hWnd = (HWND)p;
const int MM = 100; //为了做模拟,假定进行一百次数据计算
const int NN = 1000000000; //模拟工程计算量
const int nStep = 10; //增量步长
for (int i = 0; i < MM;i++)
{
long long sum = 0;
for (int j = 0; j < NN;j++)
{
sum += j;
}
::PostMessage(hWnd, WM_MSG_UPDATE, WPARAM(nStep), LPARAM(0));
Sleep(100);
}
_endthread();
}
2.3 然后,消息映射:
2.3.1 在CMyThread类头文件里面添加消息声明:
#define WM_MSG_UPDATE WM_USER+119
2.3.2 在对话框类的头文件里面添加新的自定义消息:
afx_msg LRESULT OnMessageProgress(WPARAM w, LPARAM l);
2.3.3 在对话框类的源文件里面实现消息函数:
LRESULT CdemoDlg::OnMessageProgress(WPARAM w, LPARAM l)
{
m_nStep = w;
UpdateProgress();
return TRUE;
}
2.3.4 在对话框类的源文件的消息映射添加条目:
ON_MESSAGE(WM_MSG_UPDATE, &CdemoDlg::OnMessageProgress)
2.4 然后,主程序调用:
void CdemoDlg::OnBnClickedButtonStart()
{
_beginthread(&CMyThread::Calculate, 0, this->GetSafeHwnd());
}
3.总结。 3.1 对话框中启动新线程。把句柄做参数传递。 3.2 线程类中定义静态函数,也可以在对话框类中定义个全局函数。 3.3 线程回调函数必须是静态,且以void*为参数。 3.4 定义自定义消息,线程类发送,对话框类响应。
参考文章:http://greatverve.cnblogs.com/archive/2012/12/21/mfc-thread-CProgressCtrl.html
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157808.html原文链接:https://javaforall.cn
相关文章
- Spring的学习笔记(十七)——SpringDataJpa动态查询和复杂的多表操作
- Spring学习笔记(二十七)——springboot集成MyBatis-Plus学习总结
- python数据分析入门笔记[1]
- HTML笔记(5)
- 力扣刷题笔记--258. 各位相加
- web前端学习/工作笔记(十六)
- mysql中10049是什么错误_【学习笔记】Oracle数据库10049用于分析SQL解析笔记案例
- XML学习笔记1
- 关于 Kubernetes中etcd的一些笔记
- 网络编程学习笔记8-对netcat压力测试
- [学习笔记]unity3d-坐标系统
- 关于 Kubernetes中secret、configmap的一些笔记
- JMeter笔记4 | JMeter界面介绍
- 秘籍:设计模式PDF学习笔记!
- 华为大佬的“百万级”MySQL笔记,基础+优化+架构一键搞定
- Oracle学习笔记之视图及索引的使用
- mysql学习笔记-创建用户以及登录,基本信息查询详解数据库
- Java学习笔记之三java中的变量和常量详解编程语言
- CSS学习笔记10 相对定位,绝对定位与固定定位详解编程语言
- JQuery学习笔记选择器之一
- 《JavaScript高级程序设计》阅读笔记(三)ECMAScript中的引用类型
- jQuery学习笔记操作jQuery对象属性处理
- php笔记之:php函数range()round()和list()的使用说明
- CI框架学习笔记(一)-环境安装、基本术语和框架流程
- Ruby中的String对象学习笔记
- Javascript学习笔记之对象篇(四):forin循环
- C#中面向对象编程机制之继承学习笔记