关于双缓冲绘图的问题

云风 2008-11-25 08:50:57
我在视区中贴了两张图片,一张作为背景,另一张当鼠标按下时可以在视区中被任意拖放。

我作用了双缓冲,在拖放过程中背景图片没有出现闪烁的情况,但是被拖放的图片在拖放过程中却闪得厉害,

这个问题有没有办法解决呢?

求高手解决!!


先载入一张位图ID为IDB_BITMAP1

//对视中自定义的变量初始化
public:
CPoint m_LeftUpPoint;
CSize m_OffSet;
BOOL m_LBtnDown;
CSize sizebitmap;

CImage2View::CImage2View():m_LBtnDown(false),m_OffSet(0,0),m_LeftUpPoint(20,20),sizebitmap(0,0)
{
}

//在OnDraw函数中
CDC memDC;
CBitmap memBitmap;
CRect rectClient;
GetClientRect(&rectClient);

memBitmap.LoadBitmap(IDB_BITMAP1);
BITMAP bm;
memBitmap.GetObject(sizeof(bm),&bm);

memDC.CreateCompatibleDC(NULL);

// memBitmap.CreateCompatibleBitmap(pDC,rectClient.right,rectClient.bottom);
memDC.FillSolidRect(0,0,rectClient.right,rectClient.bottom,RGB(255,255,255));

CBitmap *pOldBitmap=memDC.SelectObject(&memBitmap);
sizebitmap.cx=bm.bmWidth;
sizebitmap.cy=bm.bmHeight;

pDC->BitBlt(m_LeftUpPoint.x,m_LeftUpPoint.y,bm.bmWidth,bm.bmHeight,&memDC,0,0,SRCCOPY);


pDC->BitBlt(300,150,bm.bmWidth,bm.bmHeight,&memDC,0,0,SRCCOPY);
memBitmap.DeleteObject();
memDC.DeleteDC();


//鼠标消息
void CImage2View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default

CRect rectTrue(m_LeftUpPoint,sizebitmap);
if (rectTrue.PtInRect(point))
{
m_OffSet=point-m_LeftUpPoint;
m_LBtnDown=true;
}

CView::OnLButtonDown(nFlags, point);
}

void CImage2View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default

m_LBtnDown=false;
CView::OnLButtonUp(nFlags, point);
}

void CImage2View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default

if (m_LBtnDown)
{
CRect rectOld(m_LeftUpPoint,sizebitmap);
InvalidateRect(&rectOld/*,false*/);

m_LeftUpPoint=point-m_OffSet;
CRect rectNew(m_LeftUpPoint,sizebitmap);
InvalidateRect(&rectNew,false);
}

CView::OnMouseMove(nFlags, point);
}
...全文
319 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
云风 2008-11-26
  • 打赏
  • 举报
回复
嗯,非常感谢各位的回答。正在学习中……
Tinary3v0 2008-11-26
  • 打赏
  • 举报
回复
对了 程序我刚刚写的 着急 没有清理里面的DC 和资源,楼主别忘记了
Tinary3v0 2008-11-26
  • 打赏
  • 举报
回复
view头文件中声明:
BOOL   DnFg;
CPoint DnPt;
int frx;
int fry;

OnInitialUpdate()中初始化变量:
void C**View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
sizeTotal.cx = sizeTotal.cy = 1200;
SetScrollSizes(MM_TEXT, sizeTotal);

fry = 0;
frx = 0;
DnFg =FALSE;
DnPt = CPoint(0,0);
}

OnLButtonDown()中设定标志并记录鼠标落下点:
void C**View::OnLButtonDown(UINT nFlags, CPoint point) 
{
DnFg = TRUE;DnPt = point;
CScrollView::OnLButtonDown(nFlags, point);
}

OnLButtonUp()中清理标志:
void C**View::OnLButtonUp(UINT nFlags, CPoint point) 
{
DnFg = FALSE;
CScrollView::OnLButtonUp(nFlags, point);
}

OnMouseMove()中使用标志和鼠标落下点,并实现移动过程中内存绘图:
void C**View::OnMouseMove(UINT nFlags, CPoint point) 
{
if( DnFg == TRUE )
{
CDC *pdc=this->GetDC();
CDC MenDC;
CBitmap bm;

CRect rt;
GetClientRect(&rt);
MenDC.CreateCompatibleDC(pdc);
bm.CreateCompatibleBitmap(pdc,rt.Width(),rt.Height());
MenDC.SelectObject(&bm);
//-------------------------------------------------------------------
MenDC.FillSolidRect(0,0,rt.Width(),rt.Height(),RGB(255,255,255));

CBitmap bakeBitmap;bakeBitmap.LoadBitmap(IDB_BITMAP2);
CBitmap frntBitmap;frntBitmap.LoadBitmap(IDB_BITMAP1);

BITMAP bkbm; bakeBitmap.GetObject(sizeof(bkbm),&bkbm);
BITMAP frbm; frntBitmap.GetObject(sizeof(frbm),&frbm);

CDC inMDC; inMDC.CreateCompatibleDC(NULL);

inMDC.SelectObject( &bakeBitmap );
MenDC.BitBlt( 0,0,bkbm.bmWidth,bkbm.bmHeight,&inMDC,0,0,SRCCOPY);

inMDC.SelectObject( &frntBitmap );

CPoint mvPt;
mvPt.x = point.x - (DnPt.x - frx);
mvPt.y = point.y - (DnPt.y - fry);
MenDC.BitBlt( mvPt.x,mvPt.y,frbm.bmWidth,frbm.bmHeight,&inMDC,0,0,SRCCOPY);

//-------------------------------------------------------------------
pdc->BitBlt(0,0,rt.Width(),rt.Height(),&MenDC,0,0,SRCCOPY);
MenDC.DeleteDC();
bm.DeleteObject();
ReleaseDC(pdc);
}
CScrollView::OnMouseMove(nFlags, point);
}

OnDraw()中直接绘图即可:
void C**View::OnDraw(CDC* pDC)
{
CMSPrintDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

CBitmap bakeBitmap;bakeBitmap.LoadBitmap(IDB_BITMAP2);
CBitmap frntBitmap;frntBitmap.LoadBitmap(IDB_BITMAP1);

BITMAP bkbm; bakeBitmap.GetObject(sizeof(bkbm),&bkbm);
BITMAP frbm; frntBitmap.GetObject(sizeof(frbm),&frbm);

CDC inMDC; inMDC.CreateCompatibleDC(NULL);

inMDC.SelectObject( &bakeBitmap );
pDC->BitBlt( 0,0,bkbm.bmWidth,bkbm.bmHeight,&inMDC,0,0,SRCCOPY);

inMDC.SelectObject( &frntBitmap );
pDC->BitBlt( frx,fry,frbm.bmWidth,frbm.bmHeight,&inMDC,0,0,SRCCOPY);
}

完了,没有别的地方要改了。

楼主要纠正移动过程中图形闪烁,不应该在OnDraw中去解决,而应该在OnMouseMove中去解决。

你在OnDraw使用内存绘图,使用的代码越多反而越闪,因为OnDraw是在PAINT消息触发的时候响应的,只有它的时间短了才人眼睛看起来不会闪
你往里面狂写代码,反而让速度慢了!
移动的过程中使用内存绘图是为了防止使用Invalidate刷新视图,说白了就是为了不触发PAINT消息,不执行OnDraw的内容。

你看我的代码里面根本没有使用Invalidate,就是极力避免触发PAINT消息。

我知道别人有更高深的内存绘图技巧,我不清楚,我一般都是这么来处理,图形移动过程中闪烁问题的。
楼主去验证吧,如果不行我把我的工程发给你,你再看看。
云风 2008-11-26
  • 打赏
  • 举报
回复
终于懂了,再次感谢各位^-^
cnzdgs 2008-11-25
  • 打赏
  • 举报
回复
你上面的代码不是这样做的。
云风 2008-11-25
  • 打赏
  • 举报
回复
我是这样做的,不过还是闪……

能不能帮我解答下……
cnzdgs 2008-11-25
  • 打赏
  • 举报
回复
把移动的部分做成一个单独的控件(例如static)更简单一些。
cnzdgs 2008-11-25
  • 打赏
  • 举报
回复
响应WM_ERASEBKGND消息,直接return TRUE。在绘制背景的时候,分块来贴图,不要在移动的区域中贴背景。
菜牛 2008-11-25
  • 打赏
  • 举报
回复
说下原理:
背景和拖动图片都绘制到一个内存位图上,然后一次性将内存位图绘制到界面上,这才是双缓冲。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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