進度條控件(CProgressCtrl)廣泛用於長時間操作的視覺化回饋。傳統單執行緒實作會阻塞 UI,導致介面凍結。本文提供一個支援多執行緒、可取消、可自訂進度邏輯的 CProgressDialog 封裝類,適用於 VC++ 6.0 / Windows 98/NT 環境。
CProgressDialogclass CProgressDialog : public CDialog
{
public:
CProgressDialog(LPCSTR caption, BOOL enableCancel = TRUE, CWnd* pParent = NULL);
virtual ~CProgressDialog();
// 進度控制介面
void SetProgress(int percent) { m_ProgressCtrl.SetPos(percent); }
void SetMessage(LPCSTR msg) { m_MessageStatic.SetWindowText(msg); }
BOOL IsCancel() { return m_IsCancel; }
// 純虛函數:衍生類實作具體工作邏輯
virtual DWORD ProgressProc() = 0;
protected:
// 對話框資料成員
CStatic m_MessageStatic; // 訊息標籤
CButton m_CancelButton; // 取消按鈕
CProgressCtrl m_ProgressCtrl; // 進度條
CString m_Caption; // 對話框標題
BOOL m_EnableCancel; // 是否啟用取消
BOOL m_IsCancel; // 取消旗標
HANDLE m_Thread; // 工作執行緒控制代碼
// 靜態執行緒入口函數
static DWORD WINAPI ThreadProc(CProgressDialog* dlg);
// 訊息映射
virtual BOOL OnInitDialog();
virtual void OnCancel();
virtual void OnOK();
DECLARE_MESSAGE_MAP()
};
BOOL CProgressDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_ProgressCtrl.SetRange(0, 100);
m_ProgressCtrl.SetPos(0);
SetWindowText(m_Caption);
if (!m_EnableCancel)
m_CancelButton.ShowWindow(SW_HIDE);
DWORD threadID;
m_Thread = CreateThread(
NULL, 0,
(LPTHREAD_START_ROUTINE)ThreadProc,
(LPVOID)this, 0, &threadID
);
return TRUE;
}
DWORD WINAPI CProgressDialog::ThreadProc(CProgressDialog* dlg)
{
DWORD ret = dlg->ProgressProc(); // 呼叫衍生類實作
dlg->PostMessage(WM_COMMAND, IDOK); // 工作完成通知 UI
return ret;
}
void CProgressDialog::OnCancel()
{
if (m_EnableCancel) m_IsCancel = TRUE; // 只設旗標,不直接關閉
}
void CProgressDialog::OnOK()
{
WaitForSingleObject(m_Thread, INFINITE); // 等待執行緒結束
CDialog::OnOK();
}
CProgressDialog::~CProgressDialog()
{
if (m_Thread) CloseHandle(m_Thread);
}
class CMyProgressDialog : public CProgressDialog
{
public:
CMyProgressDialog(LPCSTR caption) : CProgressDialog(caption) {}
virtual DWORD ProgressProc();
};
DWORD CMyProgressDialog::ProgressProc()
{
SetMessage("Progress...");
for (int i = 0; i < 100; i++)
{
if (IsCancel()) break; // 檢查取消旗標
Sleep(100); // 模擬工作負載
SetProgress(i); // 更新進度
}
return 0;
}
void CMainDlg::OnStartTask()
{
CMyProgressDialog dlg("資料處理中...");
dlg.DoModal(); // 模態對話框,自動管理執行緒生命週期
}
IsCancel() 實作優雅中止SetRange(min, max) 支援非 0-100 進度範圍PostMessage 自訂訊息回報詳細狀態CWinThread 替代原生 CreateThread 以利 MFC 同步物件此封裝類展示了 MFC 中結合 Worker Thread 與 UI 控件的經典模式。透過純虛函數隔離業務邏輯,開發者只需專注 ProgressProc() 實作,即可快速建立專業級進度對話框。