void CVEPView::SampleSetup()
{
do{
       FlashCount++;   //启动画黑白棋盘格图
  drawpad.ShowWindow(TRUE);
  drawpad.RunDraw();
   //调用从A/D读取数据的线程
   gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);
    }while(FlashCount<FlashTotalCount);

//关闭闪烁棋盘格以及清零闪烁次数
drawpad.ShowWindow(FALSE);
FlashCount=0; 
//数据保存,并把采样到的数据保存到txt文本文件中
CFile file("tempData.txt",CFile::modeCreate | CFile::modeWrite);
CString str="";
for(int i=0;i<CountReadData;i++)
{
str.Format("%f",firstdata[i]);
if(((i+1)!=0)&&((i+1)%10==0))
str=str+"\r\n";
else
str=str+',';
file.Write(str,str.GetLength());
}
file.Close();

AfxMessageBox("数据采样完成!");
//采样数据计数器清零
CountReadData=0;
}
UINT Thread_IO_InData(LPVOID pParam)//从A/D板读取数据的线程

CVEPView  *pView = NULL;
CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
pView = (CVEPView*) pFrame->GetActiveView(); 
     //采样数据,采样的总时间长度等于闪烁的总次数乘以棋盘格时间频率的倒数;棋盘格时间频率的倒数等于0.5毫秒(采样率为2000次/秒)乘以PerSampleTotalCount
for(pView->PerSampleCount = 0; pView->PerSampleCount < pView->PerSampleTotalCount; pView->PerSampleCount++)
{
pView->SampleData();
pView->DelayTime(470);//进行延时,使读取每个数据的时间接近500毫秒(采样率2000次/秒)
     }  AfxEndThread(0);
return 0;
}
上面的CVEPView::SampleSetup()是我按下界面上一个按钮触发的函数,Thread_IO_InData(LPVOID pParam)是gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);这条语句所调用的线程,此线程完成工作为从A/D板读取数据。drawpad.RunDraw();调用了另一类的成员函数进行画黑白方格相间的图。
我的思路是:在do-while循环中,(1)先调用画图函数,画黑白棋盘格——(2)转到线程中读取数据——回到do-while中重复(1)(2)这两步操作,直到循环退出,将刚才所读取的数据保存成TXT文件。如果正常的话,看到的现象应该是黑白方格图在屏幕上闪烁若干次,然后结束,闪烁的时间间隔应该是相等的。黑白方格图在屏幕上停留的时间是线程运行的时间,也就是读取数据的时间,读取的数目固定,每次时间应该是相等的。我现在看到的现象是,黑白方格图前几次闪的特别快,后几次感觉还正常。单步调试时,发现线程好象正常、但有时又不正常!问题出在哪呢,大家能帮我分析一下吗,只要解决,分好商量!

解决方案 »

  1.   

    drawpad.RunDraw();中的代码如下:
    void CDrawPad::RunDraw()
    {
        
    CPaintDC dc(this); // device context for painting
             Invalidate();
    //dc.SetMapMode(MM_HIMETRIC);//映射模式的设置
    CDC *memDC = new CDC;
    memDC->CreateCompatibleDC(&dc);
    CBitmap *memBmp = new CBitmap;//内存绘图
    CRect ClientRect;
    GetClientRect(ClientRect);
    memBmp->CreateCompatibleBitmap(&dc, ClientRect.Width(), ClientRect.Height());
    CBitmap *pOldBmp = memDC->SelectObject(memBmp);

    if((k%2)==0)
    DrawElement(memDC, ClientRect, TRUE);//DrawElement()这个函数的代码,下面给出了
    else
    DrawElement(memDC, ClientRect, FALSE);

    //把内存绘图拷贝到屏幕
    dc.BitBlt(ClientRect.left, ClientRect.top, ClientRect.Width(), ClientRect.Height(),
    memDC, 0, 0, SRCCOPY);

    memDC->SelectObject(pOldBmp);
    memDC->DeleteDC();
    delete memDC;
    memBmp->DeleteObject();
    delete memBmp;
    k++;
    }
    void CDrawPad::DrawElement(CDC *pDC, const CRect DrawRect, BOOL BlackFirst)//画黑白棋盘格图
    {
        if (!pDC)
    return;
        
    CBrush *pOldBrush = (CBrush*)pDC->SelectStockObject(WHITE_BRUSH);
    CPen *pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);
    pDC->Rectangle(DrawRect);
    pDC->SelectStockObject(BLACK_BRUSH);
    CRect rcBlack(DrawRect.left, DrawRect.top, DrawRect.left + m_size0, DrawRect.top + m_size0);
    if (!BlackFirst)
    {
       rcBlack.OffsetRect(m_size0, 0);
    }
    while (rcBlack.top < DrawRect.bottom)
    {
    while (rcBlack.left < DrawRect.right)
    {
    pDC->Rectangle(rcBlack);
    rcBlack.OffsetRect(m_size0 + m_size0, 0);
    }
    rcBlack.left = DrawRect.left;
    rcBlack.top += m_size0;
    rcBlack.right = rcBlack.left + m_size0;
    rcBlack.bottom = rcBlack.top + m_size0;
    if (BlackFirst)
    {
    rcBlack.OffsetRect(m_size0, 0);
    }
    BlackFirst = !BlackFirst;
    }
    pDC->SelectObject(pOldPen);
    pDC->SelectObject(pOldBrush); //在屏幕中央画小红点部分
        pDC->FillSolidRect(DrawRect.right/2-5, DrawRect.bottom/2-5, 10, 10, RGB(255,0,0) );
    //画红点部分结束

    ReleaseDC(pDC);

    原来我放在void CDrawPad::RunDraw()中的代码是放在void CDrawPad::OnPaint()中的,除了Invalidate();这句。原来我是想在CVEPView::SampleSetup()中通过drawpad.Invalidate();触发画图的,结果出现不了黑白格子图交替出现的情况。别人告诉我:Invalidate触发重画只是发送WM_Paint消息,在此消息没有得到处理的时候,如果再有同样的消息到达,一律被抛弃。所以我就改成现在的情况了。我不知道还是不是Invalidate();的问题。谢谢大家了,欢迎给出意见!^-^
      
      

  2.   

    别的也没细看,不过如果不是响应WM_PAINT绘图,就不要用CPaintDC。
    因此:
    CPaintDC dc(this); // device context for painting
             Invalidate();
    可以改成:
    CDC *pDC = GetDC();最后不要忘了:
    ReleaseDC(pDC);
      

  3.   

    在CDrawPad类中定义全局的CDC m_DCMem和,CBitmap m_bmpMem;
    所有的绘图操作都在m_DCMem上进行,
    更新的话只要绘图完成后调用InvalidDate()函数(函数名记不清了,好像是这个),让它触发CDrawPad的OnPaint()消息函数,
    在OnPaint()函数中加入:
    //把内存绘图拷贝到屏幕
    dc.BitBlt(ClientRect.left, ClientRect.top, ClientRect.Width(), ClientRect.Height(),
    m_DCMem, 0, 0, SRCCOPY);
    Good Luck!
      

  4.   

    do{
           FlashCount++;   //启动画黑白棋盘格图
      drawpad.ShowWindow(TRUE);
      drawpad.RunDraw();
       //调用从A/D读取数据的线程
       gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);
        }while(FlashCount<FlashTotalCount);这里启动了多少线程哦?   FlashCount<FlashTotalCount 循环多少次? 太多的启动线程是个问题
    多问一句? 你的目的是重现下棋过程吗?
      

  5.   

    do{
           FlashCount++;   //启动画黑白棋盘格图
      drawpad.ShowWindow(TRUE);
      drawpad.RunDraw();
       //调用从A/D读取数据的线程
       gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);
        }while(FlashCount<FlashTotalCount);
    ============================
    这里我不是很明白,你一下子创建了那么多的线程(FlashTotalCount-FlashCount个线程)为什么呢?你虽然在线程中进行了500ms的睡眠,但是线程基本上是同时创建的,所以说数据基本上是同时到达,这不符合你的“进行延时,使读取每个数据的时间接近500毫秒(采样率2000次/秒)”的要求了啊?!