暑假期间,在学校做项目。项目中,有需要实现类似播放器的模块。本科非计算机专业出身,大一下也上过MFC的训练课程。但是那时候很苦逼啊,还没电脑。。在以前甚至很少接触电脑。所以听课的时候完全是云里雾里的,尽管也想学好,那种情况下,也只是想想而已。后来也折腾过MFC,没有专门训练、不具有针对性,学习效率可谓低下至极有了笔记本之后,狂补各种计算机方面的知识,从电脑小白也慢慢长成了电脑小黑了。因为大一学习C++,第一次接触到编程,后来也尝试各种编程,C/C++、Matlab、Python、Java,各种语言虽有涉猎,却博而不精,甚至连广度也不广。在CSDN上看到一些大牛的本科经历,实在有点自惭形秽……总的来说,本科期间,也没怎么玩,也没成为老师心中的“好学生”。但是,感谢那时候的折腾,不断的试错,也让自己有了点喜好吧,也增长了一些见识。起码到目前小硕阶段,还是有点用途的……唉,人到了年级,难免要啰嗦吐槽一下,各位看官见谅哈!
昨天老师又开始催了,说以后要阅读文献和做项目,"两手都要抓,两手都要硬"。并且每两周要开一次会,做一个阶段性的总结。本来还可以很慵懒的,三天打鱼两天晒网,以后就不行了。
相信有过编程经历的同学都知道,当编写MFC的界面程序,点击按钮,常常会有一段时间的界面”卡死“的状况。在跟这个按钮对应的操作(Function)没有执行结束时,MFC没法响应用户的其他操作。当要实现“播放”-”暂停“-”结束“等跟播放器相关的功能模块时,普通的程序就显得无能为力了。这是就需要多线程来实现。
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;
}
}
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);
}
}