MFC无限循环进度条示例

匿名 (未验证) 提交于 2019-12-02 23:00:14
版权声明:本文为博主原创文章,不需博主允许即可随意转载。 https://blog.csdn.net/a_dev/article/details/84579678

项目中,从对用户友好的方面来讲,耗时功能需要给个进度条是非常有必要的。

一般来说,对已知上限的循环(比如for循环),用正常的进度条就可以了,而对于事先不知上限的循环(比如while循环),无限循环进度条就比较适合。

本例为一个无限循环进度条,有限循环进度条与之类似。

首先,设计窗体界面:

窗体资源ID为IDD_DIALOG_PROGRESS,包含一个进度条,ID为IDC_PROGRESS_INFO,一个进度文本框,ID为IDC_PROGRESS_TIP。

窗体设置Border为“对话框外观”,Style为Popup弹出式,Topmost属性为true即进行置顶。

在.rc文件中,该窗体资源如下:

IDD_DIALOG_PROGRESS DIALOGEX 0, 0, 381, 55 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_TOPMOST FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN     CONTROL         "",IDC_PROGRESS_INFO,"msctls_progress32",WS_BORDER,7,8,367,21     LTEXT           "当前正在读取...",IDC_PROGRESS_TIP,7,33,367,13 END

接下来,为窗体添加一个类,名为CDialogProgress,并为两个控件添加对应的成员变量,添加实现虚函数。

完整的头文件如下:

#pragma once #include "resource.h"  // CDialogProgress 对话框  class CDialogProgress : public CDialog { 	DECLARE_DYNAMIC(CDialogProgress)  public: 	CDialogProgress(CWnd* pParent = nullptr);   // 标准构造函数 	virtual ~CDialogProgress();  // 对话框数据 //#ifdef AFX_DESIGN_TIME 	enum { IDD = IDD_DIALOG_PROGRESS }; //#endif  protected: 	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持  	DECLARE_MESSAGE_MAP() public: 	virtual BOOL OnInitDialog();  	void StepIt(); 	void SetTip(CString sTip); 	void Stop(); 	afx_msg void OnClose();  private: 	CStatic m_progressTip; 	CProgressCtrl m_progressInfo; 	bool m_bProcessing; };

设置进度范围为0~10,实现窗体初始化、更新进度、更新提示信息、停止进度等方法。完整的CPP文件如下:

// CDialogProgress.cpp: 实现文件 //  #include "stdafx.h" #include "CDialogProgress.h" //#include "afxdialogex.h"  CDialogProgress* g_pDialogProgress = NULL;  // CDialogProgress 对话框  IMPLEMENT_DYNAMIC(CDialogProgress, CDialog)  CDialogProgress::CDialogProgress(CWnd* pParent /*=nullptr*/) 	: CDialog(IDD_DIALOG_PROGRESS, pParent) {  }  CDialogProgress::~CDialogProgress() { }  void CDialogProgress::DoDataExchange(CDataExchange* pDX) { 	CDialog::DoDataExchange(pDX); 	DDX_Control(pDX, IDC_PROGRESS_TIP, m_progressTip); 	DDX_Control(pDX, IDC_PROGRESS_INFO, m_progressInfo); }   BEGIN_MESSAGE_MAP(CDialogProgress, CDialog) 	ON_WM_CLOSE() END_MESSAGE_MAP()   // CDialogProgress 消息处理程序   BOOL CDialogProgress::OnInitDialog() { 	CDialog::OnInitDialog();  	// TODO:  在此添加额外的初始化 	m_progressInfo.SetRange32(0, 10); 	m_progressInfo.SetStep(1); 	m_progressInfo.SetPos(0); 	m_progressTip.SetWindowTextW(_T("正在等待执行...")); 	m_bProcessing = false; 	return TRUE;  // return TRUE unless you set the focus to a control 				  // 异常: OCX 属性页应返回 FALSE }   void CDialogProgress::StepIt() { 	// TODO: 在此处添加实现代码. 	m_bProcessing = true; 	if (m_progressInfo.GetPos() >= 10) 	{ 		m_progressInfo.SetPos(0); 	} 	else 	{ 		m_progressInfo.StepIt(); 	} 	m_progressInfo.SetRedraw(TRUE); }   void CDialogProgress::SetTip(CString sTip) { 	// TODO: 在此处添加实现代码. 	m_bProcessing = true; 	m_progressTip.SetWindowTextW(sTip); 	m_progressTip,SetRedraw(TRUE); }   void CDialogProgress::Stop() { 	// TODO: 在此处添加实现代码. 	m_bProcessing = false; 	m_progressInfo.SetPos(10); 	m_progressTip.SetWindowTextW(_T("结束...")); 	SetRedraw(TRUE); }   void CDialogProgress::OnClose() { 	// TODO: 在此添加消息处理程序代码和/或调用默认值 	if (m_bProcessing) 		return; 	CDialog::OnClose(); }

需要注意的是,我们定义了一个窗体指针变量g_pDialogProgress,供外部调用。

调用时,首先导入进度窗体:

extern CDialogProgress* g_pDialogProgress;

窗体控制(创建、显示、进度与提示更新、结束、销毁)示例代码如下:

BOOL CDialogXXX::GetFeatureClassInfo(IWorkspacePtr ipWorkspace, std::deque<FeatureClassArchitecture> &arrFeatureClass, CString sUser = "") { 	if (nullptr == ipWorkspace) 		return FALSE;  	if (NULL == g_pDialogProgress) 	{ 		g_pDialogProgress = new CDialogProgress(); 	}  	g_pDialogProgress->Create(CDialogProgress::IDD, GetDlgItem(IDD_DIALOG_PROGRESS)); 	g_pDialogProgress->ShowWindow(SW_NORMAL);  	CString sTip;  	IEnumDatasetPtr ipEnumDataSet; 	HRESULT hr = ipWorkspace->get_Datasets(esriDatasetType::esriDTFeatureDataset, &ipEnumDataSet); 	if (SUCCEEDED(hr)) 	{ 		IDatasetPtr ipDataset = NULL; 		while (SUCCEEDED(ipEnumDataSet->Next(&ipDataset)) && (NULL != ipDataset)) 		{ 			doevents(NULL); 			g_pDialogProgress->StepIt(); 			BSTR bsDsName = NULL; 			if (SUCCEEDED(ipDataset->get_Name(&bsDsName))) 			{ 				CString sDatasetFullName = bsDsName; 				CString sUserName = ""; 				CString sDatasetName = ""; 				SplitName(sDatasetFullName, sUserName, sDatasetName);  				sTip = _T("正在获取【") + sUserName + _T("】用户【") + sDatasetName + _T("】数据集下的图层信息..."); 				g_pDialogProgress->SetTip(sTip);  				if (sUser.IsEmpty() || 0 == sUser.CompareNoCase(sUserName)) 				{ 					std::vector<IFeatureClassPtr> vecFeatureClass; 					GetFeatureClassFromDataset(ipDataset, vecFeatureClass); 					auto iter = vecFeatureClass.begin(); 					for (; iter != vecFeatureClass.end(); iter++) 					{ 						g_pDialogProgress->StepIt();  						IFeatureClassPtr ipFeatureClass = *iter; 						BSTR bsFeatureClassFullName = NULL; 						BSTR bsAlias = NULL; 						esriFeatureType eFeatureType; 						esriGeometryType eGeometryType; 						GetFeatureClassNameInfo(ipFeatureClass, bsFeatureClassFullName, bsAlias, eFeatureType, eGeometryType); 						CString sFeatureClassFullName = bsFeatureClassFullName; 						CString sFeatureClassName = ""; 						SplitName(sFeatureClassFullName, sUserName, sFeatureClassName);  						sTip = _T("正在获取【") + sUserName + _T("】用户【") + sDatasetName + _T("】数据集下的【") + sFeatureClassName + _T("】图层信息..."); 						g_pDialogProgress->SetTip(sTip);  						arrFeatureClass.push_back(FeatureClassArchitecture(sFeatureClassName, eFeatureType, eGeometryType, (CString)bsAlias, sDatasetName)); 						SysFreeString(bsFeatureClassFullName); 						SysFreeString(bsAlias); 					} 					SysFreeString(bsDsName); 				} 			} 		} 	} 	ipEnumDataSet = NULL; 	hr = ipWorkspace->get_Datasets(esriDatasetType::esriDTFeatureClass, &ipEnumDataSet); 	if (SUCCEEDED(hr)) 	{ 		IDatasetPtr ipDataset = NULL; 		while (SUCCEEDED(ipEnumDataSet->Next(&ipDataset)) && nullptr != ipDataset) 		{ 			doevents(NULL); 			g_pDialogProgress->StepIt(); 			IFeatureClassPtr ipFeatureClass = ipDataset; 			if (nullptr != ipFeatureClass) 			{ 				BSTR bsName = NULL; 				BSTR bsAlias = NULL; 				esriFeatureType eFeatureType; 				esriGeometryType eGeometryType; 				GetFeatureClassNameInfo(ipFeatureClass, bsName, bsAlias, eFeatureType, eGeometryType); 				CString sFullName = (CString)bsName; 				CString sUserName = ""; 				CString sFeatureClassName = ""; 				SplitName(sFullName, sUserName, sFeatureClassName);  				sTip = _T("正在获取【") + sUserName + _T("】用户的【") + sFeatureClassName + _T("】图层信息..."); 				g_pDialogProgress->SetTip(sTip);  				if (sUser.IsEmpty() || 0 == sUser.CompareNoCase(sUserName)) 				{ 					arrFeatureClass.push_back(FeatureClassArchitecture(sFeatureClassName, eFeatureType, eGeometryType, (CString)bsAlias)); 				} 				SysFreeString(bsName); 				SysFreeString(bsAlias); 			} 		} 	}  	g_pDialogProgress->Stop();  	if (NULL != g_pDialogProgress) 	{ 		if (TRUE == ::IsWindow(g_pDialogProgress->GetSafeHwnd())) 		{ 			g_pDialogProgress->DestroyWindow(); 		} 		delete g_pDialogProgress; 		g_pDialogProgress = NULL; 	} }

跑起来,效果如下:

需要注意的是:

1.当正在执行进度时,不要允许进度窗体关闭

2.进度窗体调用完成时,需先销毁窗体,再删除窗体指针

3.添加窗体要继承自CDialog而不要继承CDialogEx

4.添加窗体后,默认编译不过,需要取消cpp包含dialogex.h,头文件添加包含resource.h

转载请标明出处:MFC无限循环进度条示例
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!