VC6.0+MFC+多线程,编写停表小程序

来源:互联网 发布:js生产pdf 编辑:程序博客网 时间:2024/05/22 03:15

【资源下载】http://download.csdn.net/detail/jliuj/8031879

暑假期间,在学校做项目。项目中,有需要实现类似播放器的模块。本科非计算机专业出身,大一下也上过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);
            }
        }
    }
}

 

 

 

 

 

0 0
原创粉丝点击