这是以前的没解决的问题,现在重新发帖。
我做了一个基于单文档视图的的绘图程序,因为画的图比较大,需要添加滚动条。现在滚动条添加上去了,但是拖拉滚动条的时候图片来回闪烁,不起作用。有高手教我说先把图画到内存中,然后调用,我想请教这个怎么做呢?下面是我的部分代码:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(rect);
DocToClient(rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000,1000);                            //把屏幕分成(1000,1000)的大小--设置坐标大小
pDC->SetViewportExt(rect.right,-rect.bottom);            //设立坐标方向
// pDC->SetViewportOrg(rect.right/2,rect.bottom/2);
pDC->SetViewportOrg(50,900);                             //设置坐标原点

pDC->MoveTo(0,0);                                        //设置纵坐标
pDC->LineTo(0,850); pDC->MoveTo(0,850);                                      //画箭头
pDC->LineTo(-3,840);
pDC->MoveTo(0,850);
pDC->LineTo(3,840);

pDC->MoveTo(0,0);                                        //设置横坐标,以(0,0)为原点
pDC->LineTo(1900,0);

pDC->MoveTo(900,0);                                      //画箭头
pDC->LineTo(893,3);
pDC->MoveTo(900,0);
pDC->LineTo(893,-3);

pDC->MoveTo(0,200);                                      //设置横坐标,以(0,200)为原点
pDC->LineTo(900,200);

pDC->MoveTo(900,200);                                    //画箭头
pDC->LineTo(893,203);
pDC->MoveTo(900,200);
pDC->LineTo(893,197);

pDC->MoveTo(0,400);                                      //设置横坐标,以(0,400)为原点
pDC->LineTo(900,400);

pDC->MoveTo(900,400);                                    //画箭头
pDC->LineTo(893,403);
pDC->MoveTo(900,400);
pDC->LineTo(893,397);

pDC->MoveTo(0,600);                                      //设置横坐标,以(0,600)为原点
pDC->LineTo(900,600);

pDC->MoveTo(900,600);                                    //画箭头
pDC->LineTo(893,603);
pDC->MoveTo(900,600);
pDC->LineTo(893,597);
}void CTestView::OnInitialUpdate()
{
CSize sizeTotal(10000,100); 

SetScrollSizes(MM_TEXT,sizeTotal); 

}int               m_ImgVScrollPos ;                                    //       VScroll distance 
int               m_ImgHScrollPos ;                                    //       HScroll distance void CTestView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default

SCROLLINFO si ; 

    GetScrollInfo ( SB_VERT ,& si , SIF_ALL ); 

    m_ImgHScrollPos = si . nPos ; 

    Invalidate ( TRUE ); 

    CScrollView :: OnHScroll ( nSBCode , nPos , pScrollBar ); 
}void CTestView::DocToClient(CRect &rect)
{
CClientDC dc(this);
    OnPrepareDC(&dc, NULL);    
    dc.LPtoDP(rect);
    rect.NormalizeRect(); 
}

解决方案 »

  1.   

      如何实现双缓冲   
      在OnDraw(CDC   *pDC)中:   
        
      CDC   MemDC;   //首先定义一个显示设备对象   
      CBitmap   MemBitmap;//定义一个位图对象   
        
      //随后建立与屏幕显示兼容的内存显示设备   
      MemDC.CreateCompatibleDC(NULL);   
      //这时还不能绘图,因为没有地方画   
      //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小   
      MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);   
          
      //将位图选入到内存显示设备中   
      //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上   
      CBitmap   *pOldBit=MemDC.SelectObject(&MemBitmap);   
        
      //先用背景色将位图清除干净,这里我用的是白色作为背景   
      //你也可以用自己应该用的颜色   
      MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));   
        
      //绘图   
      MemDC.MoveTo(……);   
      MemDC.LineTo(……);   
        
      //将内存中的图拷贝到屏幕上进行显示   
      pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);   
        
      //绘图完成后的清理   
      MemBitmap.DeleteObject();   
      MemDC.DeleteDC();  
    在网上找了个,基本上能说的都说完了。。
    链接http://topic.csdn.net/t/20041101/18/3511692.html
      

  2.   

    意图是,把最终呈现的图形先画到一个临时dc里,然后在一次性的把临时dc的内容画到显示dc上
      

  3.   

    你可以将CTestView类继承于CScrollView类,就没有来回闪烁,不起作用的问题了
      

  4.   

    这个用CMemDC类. 
    如果lz用的是vs2008, 本身自带这个类, 如果不是网上下个. 用法google下, 很简单.
      

  5.   

    这里CTestView类就是继承于CScrollView类
      

  6.   

    //绘图  
      MemDC.MoveTo(……);  
      MemDC.LineTo(……);  
    //绘图部分,如果不绘图,那么可以根据图片大小和滚动条位置,在原图片中计算显示的区域并BitBlt到MemDC上。比如原图片是4000x2000,显示大小是400x200,那么就需要根据滚动条位置计算出显示部分。
      

  7.   

    我按照3楼的做了,现在是没图像了,请诸位帮我看一看:
    void CTestView::OnDraw(CDC* pDC)
    {
    CTestDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
    CDC  MemDC;  //首先定义一个显示设备对象  
    CBitmap  MemBitmap;//定义一个位图对象  
        int nWidth=0;
    int nHeight=0;
    //随后建立与屏幕显示兼容的内存显示设备  
    MemDC.CreateCompatibleDC(NULL);  
    //这时还不能绘图,因为没有地方画  
    //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小  
    MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);  

    //将位图选入到内存显示设备中  
    //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上  
    CBitmap  *pOldBit=MemDC.SelectObject(&MemBitmap);  
        
    //先用背景色将位图清除干净,这里我用的是白色作为背景  
    //你也可以用自己应该用的颜色  
    MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));  

    CRect rect;
    GetClientRect(rect);
    DocToClient(rect);
    MemDC.SetMapMode(MM_ANISOTROPIC);
    MemDC.SetWindowExt(1000,1000);                            //把屏幕分成(1000,1000)的大小--设置坐标大小
    MemDC.SetViewportExt(rect.right,-rect.bottom);            //设立坐标方向
    // pDC->SetViewportOrg(rect.right/2,rect.bottom/2);
    MemDC.SetViewportOrg(50,900);                             //设置坐标原点

    MemDC.MoveTo(0,0);                                        //设置纵坐标
    MemDC.LineTo(0,850); MemDC.MoveTo(0,850);                                      //画箭头
    MemDC.LineTo(-3,840);
    MemDC.MoveTo(0,850);
    MemDC.LineTo(3,840);

    MemDC.MoveTo(0,0);                                        //设置横坐标,以(0,0)为原点
    MemDC.LineTo(1900,0);

    MemDC.MoveTo(900,0);                                      //画箭头
    MemDC.LineTo(893,3);
    MemDC.MoveTo(900,0);
    MemDC.LineTo(893,-3);

    MemDC.MoveTo(0,200);                                      //设置横坐标,以(0,200)为原点
    MemDC.LineTo(900,200);

    MemDC.MoveTo(900,200);                                    //画箭头
    MemDC.LineTo(893,203);
    MemDC.MoveTo(900,200);
    MemDC.LineTo(893,197);

    MemDC.MoveTo(0,400);                                      //设置横坐标,以(0,400)为原点
    MemDC.LineTo(900,400);

    MemDC.MoveTo(900,400);                                    //画箭头
    MemDC.LineTo(893,403);
    MemDC.MoveTo(900,400);
    MemDC.LineTo(893,397);

    MemDC.MoveTo(0,600);                                      //设置横坐标,以(0,600)为原点
    MemDC.LineTo(900,600);

    MemDC.MoveTo(900,600);                                    //画箭头
    MemDC.LineTo(893,603);
    MemDC.MoveTo(900,600);
    MemDC.LineTo(893,597); CPen pen;
    pen.CreatePen(PS_SOLID,1,RGB(255,0,0));
    MemDC.SelectObject(&pen);
    // pDC->SetTextColor(RGB(255,0,0));
    for(int m=1,n=0,x=0;m<10;m++,x=x+280)                     //画原始波形,周期是280
    {                                                        //波形的横坐标5个屏幕坐标作为单位时间长度
    MemDC.MoveTo(x,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,0);
    MemDC.LineTo(n=n+5,47);
    MemDC.LineTo(n=n+5,175);
    MemDC.LineTo(n=n+5,251);
    MemDC.LineTo(n=n+5,335);
    MemDC.LineTo(n=n+5,431);
    MemDC.LineTo(n=n+5,479);
    MemDC.LineTo(n=n+5,510);
    MemDC.LineTo(n=n+5,543);
    MemDC.LineTo(n=n+5,543);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,558);
    MemDC.LineTo(n=n+5,557);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,527);
    MemDC.LineTo(n=n+5,555);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,555);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,559);
    MemDC.LineTo(n=n+5,551);
    MemDC.LineTo(n=n+5,543);
    MemDC.LineTo(n=n+5,431);
    MemDC.LineTo(n=n+5,255);
    MemDC.LineTo(n=n+5,189);
    MemDC.LineTo(n=n+5,127);
    MemDC.LineTo(n=n+5,63);
    MemDC.LineTo(n=n+5,31);
    MemDC.LineTo(n=n+5,0);
    }
    pen.DeleteObject();
    DocToClient(rect);

    pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);  
        
    //绘图完成后的清理  
    MemBitmap.DeleteObject();  
    MemDC.DeleteDC();