MFC双缓存,第一次调用OnDraw函数图片显示,之后一直不显示。

奉孝安在 2013-10-31 04:55:55
代码如下:
void CSupervisionView::OnDraw(CDC* pDC)
{
CSupervisionDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

CPoint ptCenter;
CRect rect,ellipseRect;
GetClientRect(rect);
TRACE("OnDraw..........\n");

ptCenter = rect.CenterPoint();

CDC dcMem; //用于缓冲作图的内存DC
CBitmap bmp; //内存中承载临时图象的位图
dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC
bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图
dcMem.SelectObject(&bmp); //将位图选择进内存DC
dcMem.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色

for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象
{
ellipseRect.SetRect(ptCenter,ptCenter);
ellipseRect.InflateRect(i*10,i*10);
dcMem.Ellipse(ellipseRect);
}

BOOL b=pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台
dcMem.DeleteDC(); //删除DC
bmp.DeleteObject(); //删除位图
}

问题描述:启动程序,同心圆图像一闪然后就再也不出来了。
尝试结果:View::OnDraw()函数(BitBlt后图像显示)
----->App::InitInstance()中调用m_pMainWnd->UpdateWindow(); (调用完成之后图像消失)
----->View::OnDraw()函数(BitBlt后图像不显示)

反常处:在上述跟踪中,第一次的rect:0,611,0,1204
第二次及之后的rect:0,611,0,1187
...全文
220 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2013-11-01
  • 打赏
  • 举报
回复
是不是“SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); //设置页面大小等信息 ” 把 图 画到 看不见的 地方 了 ?
xiaohuh421 2013-11-01
  • 打赏
  • 举报
回复
之后一直不显示具体是什么现象? 完全没有图片显示出来, 还是说只显示部分. 我的理解是, 第一次调用了, 正常绘制了你想的图 然后第二次就一片黑, 什么都没有, 是这样吗? 那你可以先调试只绘制一根线,或者一个SolidRect来调试, 看是否正常. 再一步一步来.
worldy 2013-11-01
  • 打赏
  • 举报
回复
CPoint ptCenter; CRect rect,ellipseRect; GetClientRect(rect); TRACE("OnDraw..........\n"); ptCenter = rect.CenterPoint(); CDC dcMem; //用于缓冲作图的内存DC CBitmap bmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图 HGDIOBJ hOld= dcMem.SelectObject(&bmp); //将位图选择进内存DC dcMem.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色 for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象 { ellipseRect.SetRect(ptCenter,ptCenter); ellipseRect.InflateRect(i*10,i*10); dcMem.Ellipse(ellipseRect); } BOOL b=pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 dcMem.SelectObject(hOld); // dcMem.DeleteDC(); //删除DC // bmp.DeleteObject(); //删除位图 经验证,没有什么问题。上述两句可以不要,析构函数会自动删除,另外dcmem应该恢复原来值
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
引用 5 楼 schlafenhamster 的回复:
那就比较这2个文件。
GetClientRect(rect); TRACE("OnInitialUpdate..........\n"); // TODO: 在此添加专用代码和/或调用基类 //CSize sizeTotal(50000,30000);//这里的值是逻辑坐标,20cm,30cm CSize sizeTotal(25000,20000);//这里的值是逻辑坐标,20cm,30cm CSize sizePage(sizeTotal.cx/5,sizeTotal.cy/6); CSize sizeLine(sizeTotal.cx/50,sizeTotal.cy/50); //MM_HIMETRIC映射模式的y轴方向是向下减的 SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); //设置页面大小等信息 GetClientRect(rect); 描述:在这段代码之间,rect的值从0,611,0,1204变为0,611,0,1187。
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
问题已经解决了,把主VIEW的父类从CScrollView改成了CView,然后删掉 ———————————————————————————————— // TODO: 在此添加专用代码和/或调用基类 //CSize sizeTotal(50000,30000);//这里的值是逻辑坐标,20cm,30cm CSize sizeTotal(25000,20000);//这里的值是逻辑坐标,20cm,30cm CSize sizePage(sizeTotal.cx/5,sizeTotal.cy/6); CSize sizeLine(sizeTotal.cx/50,sizeTotal.cy/50); //MM_HIMETRIC映射模式的y轴方向是向下减的 SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); //设置页面大小等信息 —————————————————————————————————— 改为 ———————————————————————————————— SetMapMode(::GetDC(m_hWnd),MM_HIMETRIC); ———————————————————————————————— 然后就解决了,但是原因因为对MFC 的整体构架实在是太陌生了。所以…多谢各位
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
GetClientRect(rect); TRACE("OnInitialUpdate..........\n"); // TODO: 在此添加专用代码和/或调用基类 //CSize sizeTotal(50000,30000);//这里的值是逻辑坐标,20cm,30cm CSize sizeTotal(25000,20000);//这里的值是逻辑坐标,20cm,30cm CSize sizePage(sizeTotal.cx/5,sizeTotal.cy/6); CSize sizeLine(sizeTotal.cx/50,sizeTotal.cy/50); //MM_HIMETRIC映射模式的y轴方向是向下减的 SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); //设置页面大小等信息 GetClientRect(rect); 定位到了这段代码。当注释SetScrollSizes()。图像能够显示了,但是程序会报错。因为没有这个设置映射模式的函数设置工程的映射模式,我去研究一下这个函数。多谢各位~有问题我再来追加
worldy 2013-11-01
  • 打赏
  • 举报
回复
引用 12 楼 tear2210 的回复:
[quote=引用 7 楼 worldy 的回复:] CPoint ptCenter; CRect rect,ellipseRect; GetClientRect(rect); TRACE("OnDraw..........\n"); ptCenter = rect.CenterPoint(); CDC dcMem; //用于缓冲作图的内存DC CBitmap bmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图 HGDIOBJ hOld= dcMem.SelectObject(&bmp); //将位图选择进内存DC dcMem.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色 for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象 { ellipseRect.SetRect(ptCenter,ptCenter); ellipseRect.InflateRect(i*10,i*10); dcMem.Ellipse(ellipseRect); } BOOL b=pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 dcMem.SelectObject(hOld); // dcMem.DeleteDC(); //删除DC // bmp.DeleteObject(); //删除位图 经验证,没有什么问题。上述两句可以不要,析构函数会自动删除,另外dcmem应该恢复原来值
额,看到了。 dcMem.SelectObject(hOld);我试试,多谢[/quote] 你说的问题,和我说应该没关系,你那代码我测试可以显示的很好
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
引用 7 楼 worldy 的回复:
CPoint ptCenter; CRect rect,ellipseRect; GetClientRect(rect); TRACE("OnDraw..........\n"); ptCenter = rect.CenterPoint(); CDC dcMem; //用于缓冲作图的内存DC CBitmap bmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图 HGDIOBJ hOld= dcMem.SelectObject(&bmp); //将位图选择进内存DC dcMem.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色 for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象 { ellipseRect.SetRect(ptCenter,ptCenter); ellipseRect.InflateRect(i*10,i*10); dcMem.Ellipse(ellipseRect); } BOOL b=pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 dcMem.SelectObject(hOld); // dcMem.DeleteDC(); //删除DC // bmp.DeleteObject(); //删除位图 经验证,没有什么问题。上述两句可以不要,析构函数会自动删除,另外dcmem应该恢复原来值
额,看到了。 dcMem.SelectObject(hOld);我试试,多谢
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
引用 8 楼 xiaohuh421 的回复:
之后一直不显示具体是什么现象? 完全没有图片显示出来, 还是说只显示部分. 我的理解是, 第一次调用了, 正常绘制了你想的图 然后第二次就一片黑, 什么都没有, 是这样吗? 那你可以先调试只绘制一根线,或者一个SolidRect来调试, 看是否正常. 再一步一步来.
第二次图片完全没有显示。只是在原点附近多了一条背景色为底色的短线
奉孝安在 2013-11-01
  • 打赏
  • 举报
回复
引用 7 楼 worldy 的回复:
CPoint ptCenter; CRect rect,ellipseRect; GetClientRect(rect); TRACE("OnDraw..........\n"); ptCenter = rect.CenterPoint(); CDC dcMem; //用于缓冲作图的内存DC CBitmap bmp; //内存中承载临时图象的位图 dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC bmp.CreateCompatibleBitmap(&dcMem,rect.Width(),rect.Height());//创建兼容位图 HGDIOBJ hOld= dcMem.SelectObject(&bmp); //将位图选择进内存DC dcMem.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,不然会是黑色 for(int i=20;i>0;i--) //在内存DC上做同样的同心圆图象 { ellipseRect.SetRect(ptCenter,ptCenter); ellipseRect.InflateRect(i*10,i*10); dcMem.Ellipse(ellipseRect); } BOOL b=pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 dcMem.SelectObject(hOld); // dcMem.DeleteDC(); //删除DC // bmp.DeleteObject(); //删除位图 经验证,没有什么问题。上述两句可以不要,析构函数会自动删除,另外dcmem应该恢复原来值
请问怎么恢复,对GDI这一块不是很懂~谢谢
schlafenhamster 2013-10-31
  • 打赏
  • 举报
回复
那就比较这2个文件。
奉孝安在 2013-10-31
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
“TRACE("OnDraw..........\n");” 有没有显示?
新建一个工程并在OnDraw中填入相同的代码,然后同样跟踪。发现图片在第二次进入OnDraw并且调用BitBlt()之后再次出现。并且新工程的两次进入OnDraw()的rect值都是一致的。
奉孝安在 2013-10-31
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
“TRACE("OnDraw..........\n");” 有没有显示?
有的。两次都有,OnDraw函数进入正常
schlafenhamster 2013-10-31
  • 打赏
  • 举报
回复
“TRACE("OnDraw..........\n");” 有没有显示?
奉孝安在 2013-10-31
  • 打赏
  • 举报
回复
困扰小弟两天半了,还望各位不吝赐教~

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧