我用了网上的进度条类CProgressWnd,结果进度条显示过程中,程序中的图像(尤其是矢量图)闪的厉害,调试发现是由CProgressWnd中的函数PeekAndPump引起的,函数PeekAndPump如下:
void CProgressWnd::PeekAndPump(BOOL bCancelOnESCkey /*= TRUE*/)
{
   if (m_bModal && ::GetFocus() != m_hWnd)
        SetFocus();    MSG msg;
    while (!m_bCancelled && ::PeekMessage(&msg, NULL,0,0,PM_NOREMOVE)) 
    {
        if (bCancelOnESCkey && (msg.message == WM_CHAR) && (msg.wParam == VK_ESCAPE))
            OnCancel();        // Cancel button disabled if modal, so we fake it.
        if (m_bModal && (msg.message == WM_LBUTTONUP))
        {
            CRect rect;
            m_CancelButton.GetWindowRect(rect);
            if (rect.PtInRect(msg.pt))
                OnCancel();
        }
        if (!AfxGetApp()->PumpMessage()) 
        {
            ::PostQuitMessage(0);
            return;
        } 
    }
}
PeekAndPump应该是用来刷新进度条窗口的,结果它居然连图像窗口也刷新了,请问这个问题怎么解决?

解决方案 »

  1.   

    问题可能出在PeekAndPump中的AfxGetApp()->PumpMessage(),它使进度条重画的同时,使主窗口也重画了,但我对这个函数不熟悉,不知道怎么限制它,请大家帮忙!
      

  2.   

    可是我把 proWnd.PeekAndPump();这句删掉的话,连进度条也不重画了
    加上的话,进度条和主窗口都重画
    我觉得问题就在AfxGetApp()->PumpMessage()上,它用了消息泵
      

  3.   

    如果你是用的这个
    http://www.codeproject.com/KB/miscctrl/progresswnd.aspx
    那么应该是你本身绘制有问题
    我这里测试没有发现问题你操作的时候不显示进度看看会不会闪
      

  4.   

    我用的就是这个类,可是我spy++查看,它确实触发了WM_PAINT
    不过hdc为0x0000000
      

  5.   

    不可能是这个函数的问题。他处理消息,并不产生消息,你得找到产生消息的地方,看他是不是使父窗口无效了,或把CProgressWnd的背景色屏蔽掉。onerasebkgnd();
      

  6.   

    我也觉得是你的绘图代码有问题,就算CProgressWnd触发了窗口的WM_PAINT消息,也不一定使窗口全部重绘,导致闪烁。
    如果你的绘图代码没使用双缓存机制,可能会闪烁。
      

  7.   

    我画透明矩形的代码如下:
    CDC dcMem; 
    CBitmap bmp; 
    dcMem.CreateCompatibleDC(pDC); 
    bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
    dcMem.SelectObject(&bmp); 
    CPen pen(PS_SOLID, 2, RGB(255,0,0));
    CPen *pOldPen = dcMem.SelectObject(&pen);
    CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
    CBrush *pOldBrush=dcMem.SelectObject(pBrush);
    dcMem.Rectangle(0,0,rect.Width(),rect.Height());
    BLENDFUNCTION blendFunction = {AC_SRC_OVER, 0, 255, 0x01};
    ::AlphaBlend(pDC->GetSafeHdc(),rect.left,rect.top,rect.Width(),rect.Height(),
    dcMem.GetSafeHdc(),0,0,rect.Width(),rect.Height(),blendFunction);
    dcMem.DeleteDC(); 
    大家看看该怎么改,才能不闪屏,但一定要透明
      

  8.   

     ::AlphaBlend(pDC->GetSafeHdc(),rect.left,rect.top,rect.Width(),rect.Height(), 
    这里的pDC是主图像所在的屏幕DC吧,如果将它换成对应的内存DC就可以实现你所期望的了。
    即创建一个与主图像所在的屏幕DC兼容的内存memDC(不知你是不是已经为栅格图像建了一个),矩形直接叠加在其上面。
    最后在OnDraw里直接bitblt就行。
      

  9.   

     ::AlphaBlend(pDC->GetSafeHdc(),rect.left,rect.top,rect.Width(),rect.Height(), 
    这里的pDC是主图像所在的屏幕DC吧,如果将它换成对应的内存DC就可以实现你所期望的了。
    即创建一个与主图像所在的屏幕DC兼容的内存memDC(不知你是不是已经为栅格图像建了一个),矩形直接叠加在其上面。
    最后在OnDraw里直接bitblt就行。
      

  10.   

    能不能拦截WM_PAINT 消息,不然主窗口响应呢
      

  11.   

    问题已经解决!谢谢大家
    顺便再问个问题:
      OnEraseBkGnd、OnPaint、OnDraw三个函数之间的关系是什么?
    我只知道在OnPaint里面隐含的调用了OnEraseBkGnd,他们到底和闪屏有啥关系?
      

  12.   

    自己顶!
    OnEraseBkGnd、OnPaint、OnDraw三个函数之间的关系是什么?
    我只知道在OnPaint里面隐含的调用了OnEraseBkGnd,他们到底和闪屏有啥关系?
      

  13.   

    OnPaint是不会调用OnEraseBkgnd的,而是由WM_ERASEBKGND消息调用该函数;OnPaint调用的是OnDraw