我用MFC写了一个仿windows画图板的程序。我打开一幅位图后,再选择画线的功能进行画线,画线时图片闪烁的厉害。
在图片下画的线也显示不出来。我在OnDraw中调用了两次BitBlt,我觉得错误在这。应该如何修改?请各位指点,谢谢

解决方案 »

  1.   

    帖你的代码:OnDraw()以及绘图的.
      

  2.   

    是的!还有,OnEraseBkgnd重载后,直接返回TRUE;什么都不要做!反正你是贴图!
      

  3.   

    void CPaintView::OnDraw(CDC* pDC)
    { CPaintDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here CMemDC dc(pDC);
    GetClientRect(rect);
    dc.Create(pDC, rect.Width(), rect.Height());
    rect.right = rect.Width();
    rect.bottom = rect.Height();
    CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd();
    dc.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255, 255, 255));
    POSITION pos = pDoc->m_list.GetHeadPosition();
    while(pos)
    {
    CShape *pLayer = (CShape*)pDoc->m_list.GetNext(pos);
    if (!pLayer->bIsUndo)
    pLayer->Draw(&dc);
    }
    pDC->BitBlt(0, 0, rect.right, rect.bottom, &dc, 0, 0, SRCCOPY); if (State == 1)
    {
    CDC dc;
    if (!dc.CreateCompatibleDC(pDC))
    return; CBitmap *pOldBitmap = NULL;
    m_bitmap.GetBitmap(&bm);
    dc.SelectObject(m_bitmap);
    pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY); dc.SelectObject(pOldBitmap);
    }}
      

  4.   


    代码下面,试了用OnEraseBKgnd不行
      

  5.   

    dc.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255, 255, 255)); 
    是不是显示的刷新是白色的在闪烁?pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY); 
    这句贴出一个位图!应该可能把前面的贴图覆盖了!
    另外,
    CMemDC dc(pDC); 
    GetClientRect(rect); 
    dc.Create(pDC, rect.Width(), rect.Height()); 
    rect.right = rect.Width(); 
    rect.bottom = rect.Height(); 
    CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd(); 
    dc.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255, 255, 255)); 
    不应该这样,应该是申请一块内存,在内存里面FillSolidRect!你这样直接就在屏幕上面,当然闪了!
    最后,一些GDI资源用完要释放!比如自己创建、取得的DC、位图等!
      

  6.   

    CMemDC dc(pDC); // ??这个是CMemDC类么?不要用这个类.反正用双缓冲也就两行代码.
    用这个类后你又自己构建双缓冲去屏幕帖图,当这个类析构时,它又再次自动去屏幕帖图,不闪才怪呢.其次,你的设计逻辑上有问题:
    if (State == 1){} 里面判断的是啥? =1是装载位图然后在上面画,否则就在空白位图上绘制么?
      

  7.   

    是创建了个CMemDC的类。
    那个if语句只是判断加载位图的条件。我就是不太清楚画线和加载位图之间是一个什么关系。
    我考虑过加一个判断鼠标是否点击的参数。因为画图操作要有鼠标的点击操作,而加载位图不用。这样改了之后,画图和加载位图只能实现一个功能。谢谢高手指点。能不能再指点一下画图和加载位图之间的逻辑关系。
      

  8.   


    pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY);
    这句贴出一个位图!应该可能把前面的贴图覆盖了!
    我觉得错误在这,就是不知道到底应该怎么改。下面你提到的问题我也改改,谢谢指点。
      

  9.   

    CDC dc; 
    if (!dc.CreateCompatibleDC(pDC)) 
    return; CBitmap *pOldBitmap = NULL; 
    m_bitmap.GetBitmap(&bm); 
    pOldBitmap = dc.SelectObject(m_bitmap); 
    if (State!=1)
    {
    dc.FillSolidRect(0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 255, 255)); 
    }
    pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY); dc.SelectObject(pOldBitmap); 
    m_bitmap.DeleteObject();你是不是想这样做?如果不贴bmp的话,就直接填充一下?如果贴位图的话,就不用填充,直接贴图了!对吧!
      

  10.   


    我就是想写个仿照windows画图板的程序,如果我贴上bmp后。再画矩形,椭圆,直线什么的。会显示在bmp上,而且画的时候不闪烁。不知道这次我说清楚了没有。请再指点指点。谢谢
      

  11.   

    估计你要的功能是这样的吧:
    // OnDraw()里只管重绘,其它最好不要加上去。void CPaintView::OnDraw(CDC* pDC) 

        CPaintDoc* pDoc = GetDocument(); 
        ASSERT_VALID(pDoc); 
        // TODO: add draw code for native data here 
        // CMemDC dc(pDC); // do not use this.    CDC MemDC;
        MemDC.CreateCompatibleDC( pDC )
        BITMAP bm;
        m_bitmap.GetBitmap( &bm );
        CBitmap *pOldBitmap = ( CBitmap * )MemDC.SelectObject( &m_bitmap );    pDC->BitBlt( 0, 0, bm.bmWidth, bm.bmHeight, &MemDC, 0, 0, SRCCOPY );
        // release
        MemDC.SelectObject( pOldBitmap );
    }
    然后你要绘图的时候,就用那个m_bitmap去绘,例如在OnLButtonDown()里画线:
    CClientDC dc( this );
    CDC MemDC;
    MemDC.CreateCompatibleDC( &dc )
    CBitmap *pOld = ( CBitmap * )MemDC.SelectObject( &m_bitmap );
    MemDC.MoveTo( begin_point.x, begin_point.y );
    MemDC.LineTo( point.x, point. y );
    MemDC.xxxxxxx();
    doSomething();
    // release
    MemDC.SelectObject( pOld );
    // 刷新
    Invalidate();
      

  12.   

    汗,漏了,假如位图未加载的话,ondraw那样写是会崩溃的,应该加上判断:
    BOOL IsDrawing = FALSE;
    void CPaintView::OnDraw(CDC* pDC) 

        CPaintDoc* pDoc = GetDocument(); 
        ASSERT_VALID(pDoc); 
        // TODO: add draw code for native data here 
        // CMemDC dc(pDC); // do not use this.
        
        if( IsDrawing ){
            CDC MemDC;
            MemDC.CreateCompatibleDC( pDC )
            BITMAP bm;
            m_bitmap.GetBitmap( &bm );
            CBitmap *pOldBitmap = ( CBitmap * )MemDC.SelectObject( &m_bitmap );        pDC->BitBlt( 0, 0, bm.bmWidth, bm.bmHeight, &MemDC, 0, 0, SRCCOPY );
            // release
            MemDC.SelectObject( pOldBitmap );
        }
    }那么在m_bitmap加载后就可以设置 : IsDrawing = TRUE;
      

  13.   

    基本上就是按照lambochan说的,只是每次显示的时候,直接贴出结果就可以了!
      

  14.   

    楼主是想要实现如Windows 下的画图工具一样的交互式绘图功能,用双缓冲技术好像并不能实现这一效果。
    还是应该重载OnEraseBkgnd函数才是,楼主说这样做不行,我估计是因为你在Ondraw里重绘了该位图的缘故,你应该在OnSize()之类的函数中绘制该位图,在OnDraw里你只管绘制你的线条之类的东东,即把你事先绘制的位图看作你的画布(背景)。