none
在使用双缓冲绘图用Bitblt,但在客户显示区,看不到东西?希望版主回复!!!! RRS feed

  • 问题

  • 我用双缓冲实现绘图,希望用较小的内存块---使用和客户显示区同样大小位图!  但在客户区显示不出来 !!!! 我的具体做法是:

           建立一个和客户区一样大小的位图,代表内存DC的绘图区

           因文档比显示区要大,所以用内存DC大小对应需要显示的区域-当然就是客户区大小;同样的坐标系统.但内存DC的原点设在位图块的左下角.---相当于坐标平移. 然后在内存DC上绘好以后用Bitblt或Strechblt 函数拷贝到原来的区域.  ;在 OnSize事件中都改变了位图的大小,使其始终和客户区大小一致.

     每次发生缩放都: 

           CSize  DisplaySize ;  

           DisplaySize.cx = int(m_Layout.cx * m_zoomFactor);
           DisplaySize.cy = int(m_Layout.cy * m_zoomFactor);
           SetScrollSizes(MM_LOMETRIC,m_DisplaySize,m_Page,m_Line);

    关键代码如下:

       所用的变量: 

         m_pdcMemory = new CDC;
         m_pBitmap = new CBitmap;

         m_zoomFactor = 1.0;  

    1.需要缩放.

    2.使用CScrollView 作为视图的基类--因需要滚动.

    3.文档大小为sizeDoc(4000,4000) .

    4.建立和客户显示区域同样大小的位图--作为内存DC绘图区.在OnInitialUpdate()和OnSize(UINT nType, int cx, int cy)函数中:

                GetClientRect(& rcClient) ; 

                CClientDC dc(this); 
                m_pdcMemory->CreateCompatibleDC(&dc);          

                m_pBitmap->CreateCompatibleBitmap(&dc,rcClient.right,rcClient.bottom);

     5.在  OnInitialUpdate()  函数中调用了

               m_Layout.cx = 4000;
               m_Layout.cy = 4000;

               m_Page.cx = m_Layout.cx/20;
               m_Page.cy = m_Layout.cy/20;
               m_Line.cx = m_Layout.cx/200;
               m_Line.cy = m_Layout.cy/200;

               SetScrollSizes(MM_LOMETRIC, m_Layout, m_Page, m_Line);

          // CPoint Pt (m_Layout.cx / 2 , m_Layout.cy / 2);      //刚开始考虑把原点设置在中央,后考虑简化 注释
          //  ScrollToPosition(Pt) ;

     6.SetMapMode 函数:

             int CMyView:Tongue TiedetMapMode(CDC* pDC)
            {
                int previousMode = pDC->SetMapMode(MM_ISOTROPIC);
                pDC->SetWindowExt(100,-100);                //注意这里有个负号,建立标准的笛卡尔坐标系
                pDC->SetViewportExt(int(100*m_zoomFactor), int(100*m_zoomFactor));

                return previousMode;
            }  

    7.OnPaint  函数 --- 重点---问题所在

       void CMyView:SurprisenPaint()
      {
             CPaintDC dc(this); // device context for painting
             OnPrepareDC(&dc);      //中调用了SetMapMode(m_pdcMemory) ;  
             CPoint ptOrg ;
             GetClientRect(&rc) ;
             ptOrg.x = rc.left ;              //取得显示矩形区的逻辑坐标 ---进行坐标平移
             ptOrg.y = rc.Height() ;
             DPtoLP(&ptOrg) ;

     

            SetMapMode(m_pdcMemory) ;          //保证内存DC和客户区坐标系统一致,但原点不一样.
            m_pdcMemory->SetViewportOrg(0, rc.Height ());


            CBitmap* pOldBitmap = m_pdcMemory->SelectObject(m_pBitmap);   
       //这里以下部分,原来希望把更新区缩到更小,但在实验多次在客户显示区,看不到显示时,干脆用整个客户区作为更新区(但还是看不到啊)

            CRect rectUpdate(0,0,0,0);
            dc.GetClipBox(&rectUpdate);
            rectUpdate.InflateRect(10,10,10,10);
            m_pdcMemory->SelectClipRgn(NULL);

            rectUpdate.left = rectUpdate.left - ptOrg.x ;
            rectUpdate.top = rectUpdate.top - ptOrg.y ;
            rectUpdate.right  = rectUpdate.right  - ptOrg.x ;
            rectUpdate.bottom  = rectUpdate.bottom  - ptOrg.y ;

            m_pdcMemory->IntersectClipRect(&rectUpdate);

     

            DPtoLP(&rc) ;
            int cx = rc.Width () ;
            int cy =  rc.Height () ;
            rc2.left = 0 ;
            rc2.bottom = cy;
            rc2.right = cx ;
            rc.top = 0 ;

            /////原来是/m_pdcMemory->FillSolidRect(&rectUpdate,m_crBackGround) ;
          m_pdcMemory->FillSolidRect(&rc2 ,m_crBackGround) ;  //背景色为红色OnEraseBkgnd(CDC* pDC)中 return FALSE;
           //////////////////////////////////////////////////////////////////////////
            // draw section 
            OnDraw(m_pdcMemory);
           //////////////////////////////////////////////////////////////////////////


           rectUpdate.left = rectUpdate.left + ptOrg.x ;
           rectUpdate.top = rectUpdate.top + ptOrg.y ;
           rectUpdate.right  = rectUpdate.right  + ptOrg.x ;
           rectUpdate.bottom  = rectUpdate.bottom  + ptOrg.y ;

        //   dc.BitBlt(rectUpdate.left,rectUpdate.top ,cx,cy,m_pdcMemory,x,y,SRCCOPY);

               刚开始用栽剪区,因我不能非常明确栽剪区在哪里,所以干脆用整个客户区,这样可以更明确
             dc.StretchBlt(0,0,cx, cy, m_pdcMemory,0,0,cx,cy,SRCCOPY);      

    无论我怎么改变 ,cx,cy的正负值多没办法让 内存DC的内容显示到客户区.

           m_pdcMemory->SelectObject(pOldBitmap);

    }

     

     

    我实在是找不到原因????????????    希望大家帮我找找原因!!!!!!!!!!!!!!!!!!!!!!!!!!1

    2009年1月13日 13:07

答案

全部回复