代码如下:
CDC* pDC=GetDC();
CDC memDC;
memDC.CreateCompatibleDC(NULL);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,1024,768);
CBitmap* pOld=(CBitmap*)memDC.SelectObject(&bmp);
memDC.BitBlt(0,0,1024,768,pDC,0,0,SRCCOPY);
memDC.SelectObject(pOld); memDC.DeleteDC(); BYTE* lpBits=new BYTE[1024*768*4];
int n=bmp.GetBitmapBits(1024*768*4,lpBits);
//处理数据,暂未加
delete lpBits;
bmp.DeleteObject();只要加了int n=bmp.GetBitmapBits(1024*768*4,lpBits);这句,界面就会停顿(MOUSE移动是跳动的了,即使此程序不是当前窗口也一样)。另外,把GetBitmapBits改成GetDIBBits也一样,或者开线程执行这段也这样!各位可以试一下,只需要建一个项目,把这段代码COPY到OnTimer里面就是这样了。我的目的是不断截取一个窗口的显示到内存,然后检取一小块区域,最后识别其中的某些符号,所以需要检索位图数据,用GetPixel太慢了。而且如果循环用GetPixel来检取各点,CPU占用率会很高,怎么办才好呢?

解决方案 »

  1.   

    int n=bmp.GetBitmapBits(1024*768*4,lpBits);
    这句话要比较长的cpu周期,所以处理跟不上了。
    你这里不应该在OnTimer内处理那么多绘图操作,所有初始化都应该在外部完成。
      

  2.   

    RE: harry202(harry) 我检查了函数执行时间,GetBitmapBits耗时464.146毫秒,一次OnTimer耗时702.305毫妙,可是我即使把OnTimer的间隔设成5s,也会在OnTimer触发那一刻产生停顿。而且我把这段代码放到一个单独的线程里面同样有停顿。我需要不停的检测另一个程序的窗口显示,好象上面那些都必须在OnTimer里做吧?
      

  3.   

    放到另一线程,
    while(1)
    {
    WaitForSingleObject(Event.....);
    ...}ontimer()
    {
    SetEvent(Event);
    }
    不知道行不行
      

  4.   

    CDC memDC;
    memDC.CreateCompatibleDC(NULL);
    CBitmap bmp;
    bmp.CreateCompatibleBitmap(pDC,1024,768);
    CBitmap* pOld=(CBitmap*)memDC.SelectObject(&bmp);
    memDC.BitBlt(0,0,1024,768,pDC,0,0,SRCCOPY);
    memDC.SelectObject(pOld); memDC.DeleteDC(); BYTE* lpBits=new BYTE[1024*768*4];
    这些都不应该放在OnTimer里面,应该变成全局或者成员变量。还有,最好不要全屏分析,应该加上你的算法,比如只处理你需要处理的窗口。
    建立MemDC和new一个大的数组都需要相对比较多的cpu周期。
      

  5.   

    to HeShe(呵呵) :放到单独线程里面试过了,还是那样。:(to  harry202(harry) :应该不是这个问题。只要不要GetBitmapBits那句,就一切正常,你列出那些语句不会产生阻塞。从执行时间上看也是。况且即使阻塞也应该只阻塞自己的进程,没有道理连WINDOWS也阻塞了吧?我想知道GetBitmapBits和GetDIBBits这类函数究竟都干了些什么,如果只是内存COPY和数组运算,不应该会这样啊?看起来就象某个系统对象被锁定一样。
      

  6.   

    当cpu占用100%的时候,你说还有什么能正常运行(不管他们是否同一进程)?
    GetBitmapBits和GetDIBits做的工作是把放在2GB以上的系统内存空间的位图数据复制到2GB以下的用户内存区,因为需要地址转换(2GB+的内存要在核心态下才能访问),所以速度上会有些慢。如果你是用DIB会快一些,因为DIB数据段本身就是放在用户内存区的。这也就是为什么我建议你不要反复创建大片的图片数据的原因。
    按照你的设计,估计要完全避免停顿是不可能的,因为你要处理的区域比较大,而你没有做任何的算法优化
      

  7.   

    SORRY,你试过没有?(那段代码也很短)如果不加GetBitmapBits的话CPU占用0%。我的是赛洋433+256M,即使在单独的线程里面也是。算法优化是下一步的事。我总需要得到图象数据才能进行算法优化吧?另外,当我在另外的线程里用GetPixel循环处理象素点,CPU占用是要到100%,但如果把线程优先级降低,看上去整个系统运行很正常(当别的程序要用CPU的时候,我的程序的CPU占用会马上降下来,不过也只是看上去正常,因为我没有具体测试过,也没有长时间运行。:))MOUSE跳动我在前面也遇到过,就是用SDK的时候没有及时清除HDC和HBITMAP,结果导致系统资源耗尽,出现的现象和现在一样。
      

  8.   

    BTW,我觉得不是速度的问题。一个再怎么耗时的操作,如果在一个单独的线程里面而且只是进行数值处理,我觉得怎么也不能使MOUSE停止移动。
      

  9.   

    试试加如下语句
    static bool bFlag=false;
    if (bFlag)
       return;bFlag = true;onTime结束时加
    bFlag = false;
      

  10.   

    你的程序我是过了,确实好像GetBitmapBits执行时独占了处理器,用GetDIBits一行一行取数据不知行不行
      

  11.   

    如果不相信,你按printscreen看看你鼠标什么反应,你的操作和printscreen 应该是一样的八。
      

  12.   

    lsgt():
    我想问的是你有没有试过我说的方法。和你一样的功能,我SetTimer 100ms
    鼠标没有任何停顿,cpu占用最多不过10%。
    请你写代码不要想当然。
    下面是我的OnTimer代码
    void CWmfLoadView::OnTimer(UINT nIDEvent) 
    {
    //int n=bmp.GetBitmapBits(1024*768*4,lpBits);
             //GetBitmapBits根本就是个淘汰的16位函数,建议不要使用
             //但是这里就算使用也不会有停顿
             
    BITMAPINFO bi;
    GetDIBits(memDC.GetSafeHdc(),(HBITMAP)bmp.m_hObject,
    0,768,lpBits,&bi,DIB_RGB_COLORS);
    CView::OnTimer(nIDEvent);
    }void CWmfLoadView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
    if(nChar=='s')
    {
    CDC* pDC=GetDC();
    memDC.CreateCompatibleDC(NULL);
    bmp.CreateCompatibleBitmap(pDC,1024,768);
    CBitmap* pOld=(CBitmap*)memDC.SelectObject(&bmp);
    memDC.BitBlt(0,0,1024,768,pDC,0,0,SRCCOPY);
    memDC.SelectObject(pOld);

    CBitmap bmp;

    BYTE* lpBits=new BYTE[1024*768*4]; SetTimer(1000,100,NULL);
    }
    if(nChar=='e')
    {
    KillTimer(1000);
    //处理数据,暂未加
    memDC.DeleteDC();
    delete lpBits;
    lpBits=NULL;
    bmp.DeleteObject();
    }
    CView::OnChar(nChar, nRepCnt, nFlags);
    }
    /////////////////////////////////////////////////////////
    //上面代码我没有处理内存/资源释放问题,自己加上就可以了PS:我的机器是PIII 667+256MB VC6 sp5 win2000pro sp3
      

  13.   

    TO wuchuncai(sssss) :我也觉得是,请教是什么资源没有释放?
      

  14.   

    感谢大家帮助,特别是harry202(harry) ,虽然你给的代码并不能达到效果,但你的热心帮助还是令我感动。我现在是接受了HeShe(呵呵) 的建议,用GetDIBBits一段一段的取数据,虽然耗时会延长15%左右,但不再出现停顿,这个结果是可以接受的。我考虑是否是这样的原因,在单独的线程可能更容易说明问题,由于GetDIBits是一个独占系统资源的操作,当线程执行到它时,别的进程由于需要等待此系统资源,因此被挂起(其中包含了一些系统关键进程,因为此时MOUSE不能移动了),直到该函数执行完毕,释放了该资源,其他进程才恢复正常。如果用GetDIBits只取少量数据,函数能够在系统分配给线程执行的时间片内结束,因此即使依然是一个独占操作,但不会对其他进程产生影响。这么说不知道对不对。不过帖子挂了这么久,也该结了。
      

  15.   

    不能达到效果?不会把,这个代码是我以前的代码里面copy出来的,从来没有碰到过你的问题。