如何解决在图片上画线的闪烁问题 我用MFC写了一个仿windows画图板的程序。我打开一幅位图后,再选择画线的功能进行画线,画线时图片闪烁的厉害。在图片下画的线也显示不出来。我在OnDraw中调用了两次BitBlt,我觉得错误在这。应该如何修改?请各位指点,谢谢 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 帖你的代码:OnDraw()以及绘图的. 是的!还有,OnEraseBkgnd重载后,直接返回TRUE;什么都不要做!反正你是贴图! 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); }} 代码下面,试了用OnEraseBKgnd不行 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、位图等! CMemDC dc(pDC); // ??这个是CMemDC类么?不要用这个类.反正用双缓冲也就两行代码.用这个类后你又自己构建双缓冲去屏幕帖图,当这个类析构时,它又再次自动去屏幕帖图,不闪才怪呢.其次,你的设计逻辑上有问题:if (State == 1){} 里面判断的是啥? =1是装载位图然后在上面画,否则就在空白位图上绘制么? 是创建了个CMemDC的类。那个if语句只是判断加载位图的条件。我就是不太清楚画线和加载位图之间是一个什么关系。我考虑过加一个判断鼠标是否点击的参数。因为画图操作要有鼠标的点击操作,而加载位图不用。这样改了之后,画图和加载位图只能实现一个功能。谢谢高手指点。能不能再指点一下画图和加载位图之间的逻辑关系。 pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY);这句贴出一个位图!应该可能把前面的贴图覆盖了!我觉得错误在这,就是不知道到底应该怎么改。下面你提到的问题我也改改,谢谢指点。 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的话,就直接填充一下?如果贴位图的话,就不用填充,直接贴图了!对吧! 我就是想写个仿照windows画图板的程序,如果我贴上bmp后。再画矩形,椭圆,直线什么的。会显示在bmp上,而且画的时候不闪烁。不知道这次我说清楚了没有。请再指点指点。谢谢 估计你要的功能是这样的吧:// 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();// releaseMemDC.SelectObject( pOld );// 刷新Invalidate(); 汗,漏了,假如位图未加载的话,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; 基本上就是按照lambochan说的,只是每次显示的时候,直接贴出结果就可以了! 楼主是想要实现如Windows 下的画图工具一样的交互式绘图功能,用双缓冲技术好像并不能实现这一效果。还是应该重载OnEraseBkgnd函数才是,楼主说这样做不行,我估计是因为你在Ondraw里重绘了该位图的缘故,你应该在OnSize()之类的函数中绘制该位图,在OnDraw里你只管绘制你的线条之类的东东,即把你事先绘制的位图看作你的画布(背景)。 请教一个WM_CHAR和WM_KEYDOWN的问题 OpenGL编译器 请问一个有关组播端口的问题 变量的读取 求助:库冲突,如何解决 第三方软件是什么? 高手请指教:dsp,dsw,ncb,opt,clw,plg,aps文件中分别存放的是什么东东,有什么作用? 在线结帐:关天在VC下工程为win32 Application做右键弹出菜单的问题!!! 程序很小,就是看不懂,关于县城的 如何用 IP 得到主机的时间? VC中的COleDateTime类型的时间空间 怎么关联 到数据库时间类型的字段? 关于 std::ifstream 的问题
{ 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);
}}
代码下面,试了用OnEraseBKgnd不行
是不是显示的刷新是白色的在闪烁?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、位图等!
用这个类后你又自己构建双缓冲去屏幕帖图,当这个类析构时,它又再次自动去屏幕帖图,不闪才怪呢.其次,你的设计逻辑上有问题:
if (State == 1){} 里面判断的是啥? =1是装载位图然后在上面画,否则就在空白位图上绘制么?
那个if语句只是判断加载位图的条件。我就是不太清楚画线和加载位图之间是一个什么关系。
我考虑过加一个判断鼠标是否点击的参数。因为画图操作要有鼠标的点击操作,而加载位图不用。这样改了之后,画图和加载位图只能实现一个功能。谢谢高手指点。能不能再指点一下画图和加载位图之间的逻辑关系。
pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dc, 0, 0, SRCCOPY);
这句贴出一个位图!应该可能把前面的贴图覆盖了!
我觉得错误在这,就是不知道到底应该怎么改。下面你提到的问题我也改改,谢谢指点。
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的话,就直接填充一下?如果贴位图的话,就不用填充,直接贴图了!对吧!
我就是想写个仿照windows画图板的程序,如果我贴上bmp后。再画矩形,椭圆,直线什么的。会显示在bmp上,而且画的时候不闪烁。不知道这次我说清楚了没有。请再指点指点。谢谢
// 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();
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;
还是应该重载OnEraseBkgnd函数才是,楼主说这样做不行,我估计是因为你在Ondraw里重绘了该位图的缘故,你应该在OnSize()之类的函数中绘制该位图,在OnDraw里你只管绘制你的线条之类的东东,即把你事先绘制的位图看作你的画布(背景)。