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

问题
-
我用双缓冲实现绘图,希望用较小的内存块---使用和客户显示区同样大小位图! 但在客户区显示不出来 !!!! 我的具体做法是:
建立一个和客户区一样大小的位图,代表内存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:
etMapMode(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:
nPaint()
{
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
答案
-
- 已标记为答案 Sheng Jiang 蒋晟Moderator 2009年2月7日 21:37
全部回复
-
- 已标记为答案 Sheng Jiang 蒋晟Moderator 2009年2月7日 21:37
-
多谢! KeFang Chen - MSFT 兄的热情! 虽然没有给出直接的答案!
现在还没有完全成功! 但已经找到了部分原因了! 看来稍复杂的东西还得靠自己摸索!!!!!