基于MFC實(shí)現(xiàn)多線程進(jìn)度條
先看下效果,MFC對(duì)話框中實(shí)現(xiàn)多線程進(jìn)度條,對(duì)話框支持拖拽不卡死。

直接上代碼
我這里提供完整的對(duì)話框代碼:
// MultiThreadProgressDlg.h: 頭文件
//
#pragma once
// CMultiThreadProgressDlg 對(duì)話框
class CMultiThreadProgressDlg : public CDialogEx
{
// 構(gòu)造
public:
CMultiThreadProgressDlg(CWnd* pParent = nullptr); // 標(biāo)準(zhǔn)構(gòu)造函數(shù)
// 對(duì)話框數(shù)據(jù)
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MULTITHREADPROGRESS_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 實(shí)現(xiàn)
protected:
HICON m_hIcon;
// 生成的消息映射函數(shù)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
CProgressCtrl m_hThread1;
CProgressCtrl m_hThread2;
CProgressCtrl m_hThread3;
static DWORD _stdcall ThreadOne(LPVOID IpParameter);
static DWORD _stdcall ThreadTwo(LPVOID IpParameter);
static DWORD _stdcall ThreadThree(LPVOID IpParameter);
HANDLE m_hThreadOne;
HANDLE m_hThreadTwo;
HANDLE m_hThreadThree;
};然后是實(shí)現(xiàn)文件
// MultiThreadProgressDlg.cpp: 實(shí)現(xiàn)文件
//
#include "pch.h"
#include "framework.h"
#include "MultiThreadProgress.h"
#include "MultiThreadProgressDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于應(yīng)用程序“關(guān)于”菜單項(xiàng)的 CAboutDlg 對(duì)話框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 對(duì)話框數(shù)據(jù)
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 實(shí)現(xiàn)
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CMultiThreadProgressDlg 對(duì)話框
CMultiThreadProgressDlg::CMultiThreadProgressDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MULTITHREADPROGRESS_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMultiThreadProgressDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PROGRESS1, m_hThread1);
DDX_Control(pDX, IDC_PROGRESS2, m_hThread2);
DDX_Control(pDX, IDC_PROGRESS3, m_hThread3);
}
BEGIN_MESSAGE_MAP(CMultiThreadProgressDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CMultiThreadProgressDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CMultiThreadProgressDlg 消息處理程序
BOOL CMultiThreadProgressDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關(guān)于...”菜單項(xiàng)添加到系統(tǒng)菜單中。
// IDM_ABOUTBOX 必須在系統(tǒng)命令范圍內(nèi)。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 設(shè)置此對(duì)話框的圖標(biāo)。 當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng)
// 執(zhí)行此操作
SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)
SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)
// TODO: 在此添加額外的初始化代碼
m_hThread1.SetRange(0, 100000);
m_hThread2.SetRange(0, 100000);
m_hThread3.SetRange(0, 100000);
//創(chuàng)建線程
m_hThreadOne = CreateThread(NULL, 100, ThreadOne, (void*)this, CREATE_SUSPENDED, NULL); // CREATE_SUSPENDED標(biāo)識(shí)創(chuàng)建的線程可以被掛起的
SetThreadPriority(m_hThreadOne, THREAD_PRIORITY_ABOVE_NORMAL); //標(biāo)識(shí)創(chuàng)建的線程具有的優(yōu)先級(jí)別
m_hThreadTwo = CreateThread(NULL, 100, ThreadTwo, (void*)this, CREATE_SUSPENDED, NULL);
SetThreadPriority(m_hThreadTwo, THREAD_PRIORITY_NORMAL);
m_hThreadThree = CreateThread(NULL, 100, ThreadThree, (void*)this, CREATE_SUSPENDED, NULL);
SetThreadPriority(m_hThreadThree, THREAD_PRIORITY_BELOW_NORMAL);
//啟動(dòng)線程
ResumeThread(m_hThreadOne);
ResumeThread(m_hThreadTwo);
ResumeThread(m_hThreadThree);
return TRUE; // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE
}
void CMultiThreadProgressDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向?qū)υ捒蛱砑幼钚』粹o,則需要下面的代碼
// 來繪制該圖標(biāo)。 對(duì)于使用文檔/視圖模型的 MFC 應(yīng)用程序,
// 這將由框架自動(dòng)完成。
void CMultiThreadProgressDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于繪制的設(shè)備上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使圖標(biāo)在工作區(qū)矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 繪制圖標(biāo)
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//當(dāng)用戶拖動(dòng)最小化窗口時(shí)系統(tǒng)調(diào)用此函數(shù)取得光標(biāo)
//顯示。
HCURSOR CMultiThreadProgressDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMultiThreadProgressDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知處理程序代碼
CDialogEx::OnOK();
}
DWORD _stdcall CMultiThreadProgressDlg::ThreadOne(LPVOID IpParameter)
{
CMultiThreadProgressDlg* pDlg = (CMultiThreadProgressDlg*)IpParameter;
int low, high, pos;
pos = pDlg->m_hThread1.GetPos();
pDlg->m_hThread1.GetRange(low, high);
while (pos < high)
{
pos = pDlg->m_hThread1.GetPos();
Sleep(10);
pDlg->m_hThread1.SetPos(pos + 1);
}
pDlg->m_hThread1.SetPos(0);
return 0;
}
DWORD _stdcall CMultiThreadProgressDlg::ThreadTwo(LPVOID IpParameter)
{
CMultiThreadProgressDlg* pDlg = (CMultiThreadProgressDlg*)IpParameter;
int low, high, pos;
pos = pDlg->m_hThread2.GetPos();
pDlg->m_hThread2.GetRange(low, high);
while (pos < high)
{
pos = pDlg->m_hThread2.GetPos();
Sleep(10);
pDlg->m_hThread2.SetPos(pos + 1);
}
pDlg->m_hThread2.SetPos(0);
return 0;
}
DWORD _stdcall CMultiThreadProgressDlg::ThreadThree(LPVOID IpParameter)
{
CMultiThreadProgressDlg* pDlg = (CMultiThreadProgressDlg*)IpParameter;
int low, high, pos;
pos = pDlg->m_hThread3.GetPos();
pDlg->m_hThread3.GetRange(low, high);
while (pos < high)
{
pos = pDlg->m_hThread3.GetPos();
Sleep(10);
pDlg->m_hThread3.SetPos(pos + 1);
}
pDlg->m_hThread3.SetPos(0);
return 0;
}直接編譯運(yùn)行,即可看到效果。

為了進(jìn)一步研究動(dòng)態(tài)添加進(jìn)度條,于是我寫了下面這個(gè)小程序,可以根據(jù)對(duì)話框的大小,動(dòng)態(tài)增減進(jìn)度條的個(gè)數(shù),其中寬度為當(dāng)前對(duì)話框的寬度:

直接上完整代碼:
// DynamicProgressBarsDlg.h: 頭文件
//
#pragma once
#include <vector>
// CDynamicProgressBarsDlg 對(duì)話框
class CDynamicProgressBarsDlg : public CDialogEx
{
// 構(gòu)造
public:
CDynamicProgressBarsDlg(CWnd* pParent = nullptr); // 標(biāo)準(zhǔn)構(gòu)造函數(shù)
// 對(duì)話框數(shù)據(jù)
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DYNAMICPROGRESSBARS_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
//創(chuàng)建一個(gè)進(jìn)度條
CProgressCtrl* CreateProgressBar(const CRect rect);
//進(jìn)度條指針
std::vector<CProgressCtrl*> m_vpPrgoressCtrl;
int m_nShowCount = 0;
// 實(shí)現(xiàn)
protected:
HICON m_hIcon;
// 生成的消息映射函數(shù)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
};實(shí)現(xiàn)文件:
// DynamicProgressBarsDlg.cpp: 實(shí)現(xiàn)文件
//
#include "pch.h"
#include "framework.h"
#include "DynamicProgressBars.h"
#include "DynamicProgressBarsDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define IDC_PRG_START 1000
// 用于應(yīng)用程序“關(guān)于”菜單項(xiàng)的 CAboutDlg 對(duì)話框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 對(duì)話框數(shù)據(jù)
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 實(shí)現(xiàn)
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CDynamicProgressBarsDlg 對(duì)話框
CDynamicProgressBarsDlg::CDynamicProgressBarsDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DYNAMICPROGRESSBARS_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CDynamicProgressBarsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
CProgressCtrl* CDynamicProgressBarsDlg::CreateProgressBar(const CRect rect)
{
//創(chuàng)建一個(gè)進(jìn)度條
CProgressCtrl* pProgress = new CProgressCtrl;
// 創(chuàng)建進(jìn)度條
if (!pProgress->Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH, rect, this, IDC_PRG_START))
{
TRACE(_T("創(chuàng)建進(jìn)度條失?。n"));
delete pProgress;
return NULL;
}
// 設(shè)置進(jìn)度條范圍和初始位置
pProgress->SetRange(0, 100);
pProgress->SetPos(60);
return pProgress;
}
BEGIN_MESSAGE_MAP(CDynamicProgressBarsDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
END_MESSAGE_MAP()
// CDynamicProgressBarsDlg 消息處理程序
BOOL CDynamicProgressBarsDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關(guān)于...”菜單項(xiàng)添加到系統(tǒng)菜單中。
// IDM_ABOUTBOX 必須在系統(tǒng)命令范圍內(nèi)。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 設(shè)置此對(duì)話框的圖標(biāo)。 當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng)
// 執(zhí)行此操作
SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)
SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)
// TODO: 在此添加額外的初始化代碼
return TRUE; // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE
}
void CDynamicProgressBarsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向?qū)υ捒蛱砑幼钚』粹o,則需要下面的代碼
// 來繪制該圖標(biāo)。 對(duì)于使用文檔/視圖模型的 MFC 應(yīng)用程序,
// 這將由框架自動(dòng)完成。
void CDynamicProgressBarsDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于繪制的設(shè)備上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使圖標(biāo)在工作區(qū)矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 繪制圖標(biāo)
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//當(dāng)用戶拖動(dòng)最小化窗口時(shí)系統(tǒng)調(diào)用此函數(shù)取得光標(biāo)
//顯示。
HCURSOR CDynamicProgressBarsDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CDynamicProgressBarsDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此處添加消息處理程序代碼
CRect rectWindow;
GetWindowRect(&rectWindow);
int nWidth = rectWindow.Width();
int nHeight = rectWindow.Height();
int nNewCount = nHeight / 60;
size_t nProgressBarCount = m_vpPrgoressCtrl.size();
if (nProgressBarCount < nNewCount)
{
for (size_t i = m_nShowCount; i < nNewCount; ++i)
{
CRect rect(0, i * 60, nWidth, i * 60 + 55);
if (CProgressCtrl* pCtrl = CreateProgressBar(rect))
{
m_vpPrgoressCtrl.emplace_back(pCtrl);
}
}
m_nShowCount = nNewCount;
}
else
{
for (size_t i = 0; i < m_nShowCount; ++i)
{
if (CProgressCtrl* pCtrl = m_vpPrgoressCtrl[i])
{
pCtrl->ShowWindow(SW_SHOW);
}
}
for (size_t i = nNewCount; i < nProgressBarCount; ++i)
{
if (CProgressCtrl * pCtrl = m_vpPrgoressCtrl[i])
{
pCtrl->ShowWindow(SW_HIDE);
}
}
}
}關(guān)鍵代碼在OnSize()函數(shù)中。
到此這篇關(guān)于基于MFC實(shí)現(xiàn)多線程進(jìn)度條的文章就介紹到這了,更多相關(guān)MFC多線程進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用代碼和UML圖化解設(shè)計(jì)模式之橋接模式的深入分析
本篇文章是對(duì)橋接模式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
在Visual Studio 2019中修改項(xiàng)目名的方法
這篇文章主要介紹了在Visual Studio 2019中修改項(xiàng)目名的方法,文中通過示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
C語言一看就懂的選擇與循環(huán)語句及函數(shù)介紹
函數(shù)是一個(gè)功能模塊,它把實(shí)現(xiàn)某個(gè)功能的代碼塊包含起來,并起一個(gè)函數(shù)名,供別人調(diào)用,如printf函數(shù),如system函數(shù)。是程序運(yùn)行當(dāng)中包裝起來的一個(gè)步驟;選擇與循環(huán)是編程中最常用的結(jié)構(gòu),本篇文章用最簡(jiǎn)單的文字帶你了解它們2022-04-04

