CMyView继承了CScrollView,采用双缓存显示位图。打开位图显示时不会闪烁,只有当拖动滚动条时,会闪烁,如何解决?部分代码如下,其中CMemDC是Keith Rule 02/11/02 更新的Memory DC类,代码在最后:void CMyView::OnDraw(CDC* pDC)
{
CLPCLR_TestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc); CMemDC memDC(pDC); SetDIBitsToDevice( 
memDC.m_hDC, SPAN_CX, m_cyImgDisplay, // 在不为(0,0)的固定位置显示图像
pDoc->m_Image.cx, 
pDoc->m_Image.cy, 
0, 0, 0, 
pDoc->m_Image.cy, 
pDoc->m_Image.data, 
(BITMAPINFO*) &(pDoc->m_Image.bi), 
DIB_RGB_COLORS 
);
}BOOL CMyView::OnEraseBkgnd(CDC* pDC) 
{
// TODO: Add your message handler code here and/or call default
return TRUE;
}////////////////////////////////////////////////////////////////////////
class CMemDC : public CDC 
{
private:       
    CBitmap    m_bitmap;        // Offscreen bitmap
    CBitmap*   m_oldBitmap; // bitmap originally found in CMemDC
    CDC*       m_pDC;           // Saves CDC passed in constructor
    CRect      m_rect;          // Rectangle of drawing area.
    BOOL       m_bMemDC;        // TRUE if CDC really is a Memory DC.public:
    
    CMemDC(CDC* pDC, const CRect* pRect = NULL) 
: CDC()
, m_oldBitmap(NULL)
, m_pDC(pDC)
    {
        ASSERT(pDC != NULL); 
 
        // Some initialization
        m_bMemDC = !pDC->IsPrinting();
 
        // Get the rectangle to draw
        if (pRect == NULL) 
        {
             pDC->GetClipBox(&m_rect);
        } 
        else 
        {
             m_rect = *pRect;
        }
 
        if (m_bMemDC) 
        {
             // Create a Memory DC
             CreateCompatibleDC(pDC);
             pDC->LPtoDP(&m_rect);
 
             m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());             m_oldBitmap = SelectObject(&m_bitmap);
 
             SetMapMode(pDC->GetMapMode());
 
             SetWindowExt(pDC->GetWindowExt());
             SetViewportExt(pDC->GetViewportExt());
 
             pDC->DPtoLP(&m_rect);
             SetWindowOrg(m_rect.left, m_rect.top);
        } 
else 
{
             // Make a copy of the relevent parts of the current 
             // DC for printing
             m_bPrinting = pDC->m_bPrinting;
             m_hDC       = pDC->m_hDC;
             m_hAttribDC = pDC->m_hAttribDC;
        }
 
        // Fill background 
        FillSolidRect(m_rect, pDC->GetBkColor());
    }
    
    ~CMemDC()      
    {          
        if (m_bMemDC) 
        {
             // Copy the offscreen bitmap onto the screen.
             m_pDC->BitBlt(m_rect.left, m_rect.top, 
                           m_rect.Width(),  m_rect.Height(),
                           this, m_rect.left, m_rect.top, SRCCOPY);            
             
             //Swap back the original bitmap.
             SelectObject(m_oldBitmap);        
        }
        else 
        {
             // All we need to do is replace the DC with an illegal
             // value, this keeps us from accidentally deleting the 
             // handles associated with the CDC that was passed to 
             // the constructor.              
             m_hDC = m_hAttribDC = NULL;
        }       
    }
    
    // Allow usage as a pointer    
    CMemDC* operator->() 
    {
        return this;
    }       
 
    // Allow usage as a pointer    
    operator CMemDC*() 
    {
        return this;
    }
};

解决方案 »

  1.   

    你的代码没什么问题呀。重载一下CXView::OnScrollBy
      

  2.   

    用scrollview需要设置原点。下面部分核心OnDraw代码
    CFEDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CSize size = pDoc->m_ImageSize; // 要显示的图片的大小   int x=0, y=0;
    CRect rt;
    GetClientRect(&rt);

    if (rt.Width() > size.cx) { //窗口宽度大于画布宽度
    x = rt.Width() - size.cx;
    x  /= 2;

    if (rt.Height() > size.cy) { //窗口高度大于画布高度
    y = rt.Height() - size.cy;
    y /= 2;
    }
             // 裁减区域...
    pDC->ExcludeClipRect(0, 0, rt.Width(), y);
    pDC->ExcludeClipRect(0, 0, x, rt.Height());
    pDC->ExcludeClipRect(rt.Width()-x, 0, rt.Width(), rt.Height());
    pDC->ExcludeClipRect(0, rt.Height()-y, rt.Width(), rt.Height()); // 设置原点和视口
    pDC->SetViewportOrg(pDC->GetViewportOrg().x+x, pDC->GetViewportOrg().y+y);
    pDC->SetViewportExt(size);
             pDC->BitBlt(***); // ...将内存dc放到视图上
             //... 其他代码另外OnSize中也要做类似转换:
    CScrollView::OnSize(nType, cx, cy);

    if ((HDC)m_DC == NULL) return;

    CSize size = GetDocument()->m_ImageSize; // 图片大小
    int x=0, y=0;
    CRect rt;
    GetClientRect(&rt);

    if (rt.Width() > size.cx) { //窗口宽度大于画布宽度
    x = rt.Width() - size.cx;
    x  /= 2;

    if (rt.Height() > size.cy) { //窗口高度大于画布高度
    y = rt.Height() - size.cy;
    y /= 2;
    } m_DC.SelectClipRgn(NULL, RGN_COPY); 
    if ((HRGN)(m_clipRgn) != NULL) {
    m_clipRgn.DeleteObject();
    }
    CPoint pos  = GetScrollPosition();
    m_DC.SetViewportOrg(-pos.x+x, -pos.y+y);
    m_clipRgn.CreateRectRgn(-pos.x+x, -pos.y+y, -pos.x+x+size.cx, -pos.y+y+size.cy);
    m_DC.SelectClipRgn(&m_clipRgn, RGN_COPY);
      

  3.   

    To laiyiling(最熟悉的陌生人) :试过了,还是闪。To DentistryDoctor(牙科医生):为何要重载CXView::OnScrollBy?重载后的代码应如何写呢?如屏蔽了“return CScrollView::OnScrollBy(sizeScroll, bDoScroll);”,滚动条就不能正常工作了。To enoloo(努力COM):试过你的代码,图像周围刷新不正确,图像还是在闪。PS:怎么这个回帖的编辑窗口也在狂闪?是不是跟微软拼音输入法不兼容啊?晕!
      

  4.   

    http://www.codeguru.com/Cpp/G-M/bitmap/displayingandsizing/article.php/c4939/Displaying Bitmap Images with Scrolling看看这篇文章。
      

  5.   

    谢谢DentistryDoctor(牙科医生) ,我用他的DEMO打开我的图像,发现是一样的闪,可能是我用的图像有点特殊,那种“闪”也算正常吧。我换了另外一副图像,就基本正常了。多谢大家。如果有人对那副“闪”图有兴趣的话,可以留下Email。
      

  6.   

    让我看看吧
      [email protected]
    or [email protected]