用计时器实现位图移动问题

dizengrong 2009-07-22 02:53:32
记得Charles Petzold在windows程序设计第五版的662页写了一个小球的运动程序,
于是我就用MFC也想写一个,具体过程如下:
1.由VS创建一个单文档结构程序,且去掉文档/视图支持
2.创建一个位图,并在childView.h中添加:
CBitmap ball;
int cx,cy;
3.在childView.cpp中加入如下代码:

void CChildView::OnPaint()
{
CPaintDC dc(this); // 用于绘制的设备上下文
CRect rect;
GetClientRect(&rect);
cx=rect.Width()/2;cy=rect.Height()/2;

CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
}


int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;

SetTimer(ID_TIMER,500,0);
ball.LoadBitmap(IDB_BALL);

return 0;
}

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
CPaintDC dc(this);
CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();

CWnd::OnTimer(nIDEvent);
}
可小球就是不移动,麻烦大家帮我看看是什么问题。

...全文
221 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
lixing118 2009-07-24
  • 打赏
  • 举报
回复
up
tg15 2009-07-24
  • 打赏
  • 举报
回复
CDC tempDC; // 临时DC
tempDC.CreateCompatibleDC(&dc); // 创建

CBitmap tempBmp, *pTempBmp; // 临时位图
tempBmp.CreateCompatibleBitmap(&dc, 宽, 高); // 这里宽高根据实际情况设置
pTempBmp = tempDC.SelectObject(&tempBmp);

tempDC.FillSolidRect(0, 0, 宽, 高, RGB(226, 226, 255)); // 绘制临时DC背景

//..现在你可以在tempDC上绘制,

dc.BitBlt(0, 0, 宽, 高, &tempDC, 0, 0, SRCCOPY); // 一次将临时DC贴到显示的DC上。。,这个位置你可以自己根据情况设置。。

//最后是清除工作
tempDC.SelectObject(pTempBmp);
tempBmp.DeleteObject();
tempDC.DeleteDC();
dizengrong 2009-07-24
  • 打赏
  • 举报
回复
非常感谢tg15!结贴给分啦!
tg15 2009-07-24
  • 打赏
  • 举报
回复
tempBmp.DeleteObject();
tempDC.DeleteDC();
这两句应该是不需要的,析构时应该会自动释放。
但已养成这习惯。有create就要delete
jianglinghorn 2009-07-24
  • 打赏
  • 举报
回复
后面的 清除 有的不需要 吧。 感觉 只有指针 需要清除。 有高手指点下。。
dizengrong 2009-07-23
  • 打赏
  • 举报
回复
非常感谢大家的热心帮忙。
困惑我的问题还是由marrco2005的点拨解决了。
我又查了一下:CPaintDc是只在响应 WM_PAINT 时使用的,而CClientDC是客户区绘图是可以用上的。
而我在 OnTimer 中用的是 WM_PAINT ,所以一直看不到小球的移动。
另外大家说的在 OnTimer 中调用 Invalidate() 是可以的,但这样重绘导致了闪烁的产生。
dronly 2009-07-23
  • 打赏
  • 举报
回复
我是来学习的
dizengrong 2009-07-23
  • 打赏
  • 举报
回复
不知tg15所讲的把东西画到临时DC上是怎样做的?
tg15 2009-07-23
  • 打赏
  • 举报
回复
Invalidate(FALSE)就不闪烁了。 但这样可能会导致旧的图像没有擦除。所以,在显示时,可以先创建一个临时的DC用为缓冲用,所有东西都绘到临时DC上,最后一次性把临时DC显示出来。
tiger波波 2009-07-22
  • 打赏
  • 举报
回复
测试通过vc6


int CSDI0View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

SetTimer(1,100,0);

cx=50;

// TODO: Add your specialized creation code here

return 0;
}

void CSDI0View::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
cx+=100;
Invalidate();

CWnd::OnTimer(nIDEvent);
CView::OnTimer(nIDEvent);
}

void CSDI0View::OnDraw(CDC* pDC)
{
CSDI0Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

CBitmap bitmap;
bitmap.LoadBitmap(IDB_BALL);
CDC mydc;
mydc.CreateCompatibleDC(pDC);
mydc.SelectObject(&bitmap);

CRect rect;
GetClientRect(&rect);
pDC->BitBlt(cx,50,rect.Width(),rect.Height(),&mydc,0,0,SRCCOPY);
// TODO: add draw code for native data here

}

tg15 2009-07-22
  • 打赏
  • 举报
回复
程序需要绘制时,系统会自动调用OnPaint进行绘制。所以绘图代码应该始终放在OnPaint中,这样才能保证一定被绘制出来。。。

从MVC模式来说,OnPaint就像V一样,只是进行显示。。需要显示什么,根据的数据不同而不同。想要显示不同的东西,只需要修改数据就行。。所以你的OnTimer里只需要修改cx,,然后调用Invalidate强制重绘。。同时,在OnPaint里不要对cx赋值。。cx的初始化工作应该放到Init或OnCreate函数中。
  • 打赏
  • 举报
回复
oyljerry 2009-07-22
  • 打赏
  • 举报
回复
坐标记得修改位置..
Ghost90 2009-07-22
  • 打赏
  • 举报
回复
忘了加Invalidate

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
Invalidate();
CWnd::OnTimer(nIDEvent);
}

Ghost90 2009-07-22
  • 打赏
  • 举报
回复

void CChildView::OnPaint()
{
CPaintDC dc(this); // 用于绘制的设备上下文
CRect rect;
GetClientRect(&rect);
cx=rect.Width()/2;cy=rect.Height()/2;

CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
}

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
CWnd::OnTimer(nIDEvent);
}


cx=rect.Width()/2;cy=rect.Height()/2;
cx,cy的值每次都是定值当然不动了
去掉这句
Ontimer这样就行
aa3000 2009-07-22
  • 打赏
  • 举报
回复
void CChildView::OnPaint()
{
CPaintDC dc(this); // 用于绘制的设备上下文

CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
}


int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;

SetTimer(ID_TIMER,500,0);
ball.LoadBitmap(IDB_BALL);

cx=lpCreateStruct->cx/2;cy=lpCreateStruct->cy/2;

return 0;
}

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
Invalidate(); //发送WM_PAINT消息
UpdateWindow(); //立即处理消息

CWnd::OnTimer(nIDEvent);
}
marrco2005 2009-07-22
  • 打赏
  • 举报
回复
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
CDC *pDC = GetDC();
CDC& dc = *pDC;

CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();

CWnd::OnTimer(nIDEvent);
}
marrco2005 2009-07-22
  • 打赏
  • 举报
回复
CPaintDC dc(this);
把 dc 定义改成下面的代码就行了
CDC *pDC = GetDC();
CDC& dc = *pDC;
zlwzlwzlw 2009-07-22
  • 打赏
  • 举报
回复
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//MessageBeep(1);
cx+=100;
Invalidate(); //发送WM_PAINT消息
UpdateWindow(); //立即处理消息

CWnd::OnTimer(nIDEvent);
}
danxuezx 2009-07-22
  • 打赏
  • 举报
回复
memDc.BitBlt之后再dc.BitBlt。即:
memDc.BitBlt(0,0,24,24,&memDc,0,0,SRCCOPY);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
加载更多回复(1)

16,551

社区成员

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

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

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