停表小程序"/>
VC6.0+MFC+多线程,编写停表小程序
【资源下载】
暑假期间,在学校做项目。项目中,有需要实现类似播放器的模块。本科非计算机专业出身,大一下也上过MFC的训练课程。但是那时候很苦逼啊,还没电脑。。在以前甚至很少接触电脑。所以听课的时候完全是云里雾里的,尽管也想学好,那种情况下,也只是想想而已。后来也折腾过MFC,没有专门训练、不具有针对性,学习效率可谓低下至极有了笔记本之后,狂补各种计算机方面的知识,从电脑小白也慢慢长成了电脑小黑了。因为大一学习C++,第一次接触到编程,后来也尝试各种编程,C/C++、Matlab、Python、Java,各种语言虽有涉猎,却博而不精,甚至连广度也不广。在CSDN上看到一些大牛的本科经历,实在有点自惭形秽……总的来说,本科期间,也没怎么玩,也没成为老师心中的“好学生”。但是,感谢那时候的折腾,不断的试错,也让自己有了点喜好吧,也增长了一些见识。起码到目前小硕阶段,还是有点用途的……唉,人到了年级,难免要啰嗦吐槽一下,各位看官见谅哈!
昨天老师又开始催了,说以后要阅读文献和做项目,"两手都要抓,两手都要硬"。并且每两周要开一次会,做一个阶段性的总结。本来还可以很慵懒的,三天打鱼两天晒网,以后就不行了。
扯远了,言归正题。本文主要目的是总结MFC中多线程编程的经验,一步步实现停表功能。
相信有过编程经历的同学都知道,当编写MFC的界面程序,点击按钮,常常会有一段时间的界面”卡死“的状况。在跟这个按钮对应的操作(Function)没有执行结束时,MFC没法响应用户的其他操作。当要实现“播放”-”暂停“-”结束“等跟播放器相关的功能模块时,普通的程序就显得无能为力了。这是就需要多线程来实现。
新建基于对话框的应用程序Mythread
1.实现时钟功能 (1)添加静态文本框,ID:IDC_CLOCK,标题:空
(2)在CMyThreadDlg::OnInitDialog()中,添加定时器 SetTimer(1,500,NULL); //设置500ms定时器 (3)为对话框添加定时器消息响应函数 void CMyThreadDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default
static int halfsecond=0; //静态变量
CTime t=CTime::GetCurrentTime(); CString str=t.Format("%H:%M:%S"); if(halfsecond) { str.Replace(":"," "); //半秒闪烁 } GetDlgItem(IDC_CLOCK)->SetWindowText(str);
halfsecond = ++halfsecond%2;
CDialog::OnTimer(nIDEvent); }
2.实现停表功能 #include<time.h> (1)首先添加按钮 开始:IDC_BTN_WATCH_STU_QG 清零:IDC_BTN_WATCH_RESET (2)为对话框添加线程成员变量 CWinThread* pThdWatch( #include <AFXWIN.H>) 以及 BOOL状态变量 m_bWatchPaused 、 m_bWatchWorking , 并在 BOOL CMyThreadDlg::OnInitDialog()中对状态变量初始化 m_bWatchPaused = FALSE; m_bWatchWorking = FALSE;
(3)双击开始按钮,添加消息响应函数OnBtnWatchStuQg
static INT mymiseconds = 0; //用于保存临时时间 static clock_t start,now; //时间
// //自定义线程函数 UINT _StartWatch(LPVOID lparam) { CMyThreadDlg *pDlg = (CMyThreadDlg*) lparam; //对话框指针变量
int duration=0; CString strWatch;
while(TRUE) / 循环 { MSG msg; //消息变量 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message == WM_THREAD_WATCH_RESET) //运行状态时,产生了WM_THREAD_WATCH_RESET消息 { pDlg->m_bWatchWorking = FALSE; pDlg->m_bWatchPaused = FALSE; pDlg->GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Start"); pDlg->GetDlgItem(IDC_EDIT_WATCH)->SetWindowText("0"); mymiseconds = 0; return 0; // thread completed successfully } else { DispatchMessage(&msg); } }
Sleep(1); now = clock(); duration = 1000*(now - start)/CLOCKS_PER_SEC + mymiseconds; strWatch.Format("%d",duration); pDlg->GetDlgItem(IDC_EDIT_WATCH)->SetWindowText(strWatch); } }
void CMyThreadDlg::OnBtnWatchStuQg() { // TODO: Add your control notification handler code here //一共3种状态:①停止(!m_bWatchWorking) //②运行(m_bWatchWorking && !m_bWatchPaused) //③暂停(m_bWatchWorking && m_bWatchPaused) if(!m_bWatchWorking) //停止状态,需要启动线程,并设置按钮字体为"Pause" { start = clock(); pThdWatch = AfxBeginThread(_StartWatch,this); //启动线程 GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Pause"); m_bWatchWorking = TRUE; m_bWatchPaused = FALSE; } else if(m_bWatchWorking && !m_bWatchPaused) 运行非暂停状态,将暂停(挂起),并设置按钮字体为"Start" { mymiseconds += 1000*(now-start)/CLOCKS_PER_SEC; pThdWatch->SuspendThread(); //挂起线程
GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Start"); m_bWatchWorking = TRUE; m_bWatchPaused = TRUE; } else if(m_bWatchWorking && m_bWatchPaused) 挂起状态,将运行,并设置按钮字体为"Pause" {
start = clock(); pThdWatch->ResumeThread(); //激活线程 GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Pause"); m_bWatchWorking = TRUE; m_bWatchPaused = FALSE; } }
(4)自定义停止消息 ①在Dlg.h中添加自定义消息 #define WM_THREAD_WATCH_RESET 0x1404 //自定义消息 ②在 OnBtnWatchReset()中,添加传递消息响应以及状态设置的语句
// void CMyThreadDlg::OnBtnWatchReset() { // TODO: Add your control notification handler code here if(pThdWatch) { ::PostThreadMessage(pThdWatch->m_nThreadID, WM_THREAD_WATCH_RESET,0,0); //Post消息 //==>暂停时的停止响应
m_bWatchWorking = FALSE; m_bWatchPaused = FALSE; GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Start"); GetDlgItem(IDC_EDIT_WATCH)->SetWindowText("0"); mymiseconds = 0; } }
③在线程启动的循环函数中,添加消息处理函数 UINT _StartWatch(LPVOID lparam)
{ 循环体{ MSG msg; //消息变量 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message == WM_THREAD_WATCH_RESET) //==>运行状态时,产生了WM_THREAD_WATCH_RESET消息,进行一些操作 { pDlg->m_bWatchWorking = FALSE; pDlg->m_bWatchPaused = FALSE; pDlg->GetDlgItem(IDC_BTN_WATCH_STU_QG)->SetWindowText("Start"); pDlg->GetDlgItem(IDC_EDIT_WATCH)->SetWindowText("0"); mymiseconds = 0; return 0; // thread completed successfully } else { DispatchMessage(&msg); } } } }
更多推荐
VC6.0+MFC+多线程,编写停表小程序
发布评论