当我们在处理大程序时,常常需要耗很长时间,为了不让用户错误的认为系统已经死机,我们要给程序添加进度条,但是大家知道如果就直接添加进度条,并在程序里面控制它的进度,往往得到的结果是程序仍然像死机状态,直到处理完毕才显示进度条进度为100%,中间的过程看不到了,那么怎么办呢,是为什么呢?原因是我们处理大程序和进度条显示是在同一个线程中进行的,这样往往因为处理大程序导致界面无法实时更新。解决办法就是把处理大程序的这段逻辑让一个单独的线程在处理,并利用postmessage或sendmessage给主界面发送消息,让主界面去更新。
具体代码实现如下:
// =========================CAsyncProgressDlg.h 对话框==========================
protected:
LRESULT OnUpdateData(WPARAM wParam, LPARAM lParam);
int ProcessLogFile(char *pRtnMsgBuf, int ibufLen);
CProgressCtrl m_Progress;
CWinThread *m_pMyThread;
CStatic *m_pStatic;
friend UINT MyThread(LPVOID pParam);
// =========================CAsyncProgressDlg.cpp 对话框==========================
#define WM_UPDATEDATA WM_USER + 1999 //定义事件
//注意返回类型为UINT
static UINT MyThread(LPVOID pParam)
{
CAsyncProgressDlg *pProgDlg = (CAsyncProgressDlg *)pParam;
//这里添加计算过程
char sRtnMsgBuf[MAX_PATH];
memset(sRtnMsgBuf, 0, MAX_PATH);
//调用具体处理大程序的逻辑函数
int iRec = pProgDlg->ProcessLogFile(sRtnMsgBuf, MAX_PATH);
return 0;
}
BEGIN_MESSAGE_MAP(CSimpleProgressDlg, CDialog)
ON_MESSAGE(WM_UPDATEDATA, &CSimpleProgressDlg::OnUpdateData) //让事件关联程序
END_MESSAGE_MAP()
// CAsyncProgressDlg消息处理程序
BOOL CAsyncProgressDlg::OnInitDialog()
{
........
// TODO: 在此添加额外的初始化代码
// TODO: 在此添加额外的初始化代码
m_pStatic = (CStatic*)GetDlgItem(IDC_STATIC);
m_Progress.SetRange(0, 100);
m_Progress.SetPos(0);
//MyThread为该大程序处理的入口函数,this为入口函数的参数
m_pMyThread = AfxBeginThread(MyThread, this);
m_pMyThread = NULL;
.......
}
LRESULT CAsyncProgressDlg::OnUpdateData(WPARAM wParam, LPARAM lParam)
{
int iTmp = (int)wParam;
m_Progress.SetPos(iTmp);//设置进度条的值
if (100 == iTmp)
{
m_pStatic->SetWindowText(_T("Completed !!!"));
}
UpdateData(false);//实时更新主界面
return 0;
}
int CAsyncProgressDlg::ProcessLogFile(char *pRtnMsgBuf, int ibufLen)
{
int value = 0;
while(1)
{
//作为测试我只是睡眠0.1秒后更新value的值
Sleep(100);
value++;
//向主线程发送消息更新进度条
SendMessage(WM_UPDATEDATA, value);
}
return 0;
}