这篇文章参考了一位仁兄的博客 mfc坦克定位,但对之做出了一些细节上的修改,主要目的呢是为了加深自己的记忆。文章内提到的有mfc 位图绘制,键盘消息的响应
原文章传送门http://www.cnblogs.com/aarond/archive/2013/07/23/tanke.html
这次的主要内容是使用vc的mfc制作一个很小很小的游戏,功能很简单,窗口上显示一辆坦克,按上下左右即可操作坦克进行不同方向的移动。以后我将把这个游戏功能进行更多的扩展,达到学习目的,以此提升自己。
1.首先在vc中新建一个mfc工程,选择基本对话框。
2.在dialog类中添加几个变量,int m_x,m_y,这两个是为了记录坦克的初始化以及移动位置。
CBitmap m_bitmap 这个变量是为了加载位图资源,也就是坦克的图片。
3.添加坦克的位图,在插入中新建自己画或引入外部资源皆可。
4.接下来就是初始化了。
BOOL CMyDlg::OnInitDialog()
{
...
// TODO: Add extra initialization here
RECT r;
GetWindowRect(&r);//获取窗口大小
m_bitmap.LoadBitmap(IDB_TANK);//加载位图
BITMAP bmpInfo;
m_bitmap.GetBitmap(&bmpInfo);//获取图片的属性
m_x = (r.right - r.left) / 2 - bmpInfo.bmWidth / 2;//计算中心点
m_y = (r.bottom - r.top) / 2 - bmpInfo.bmHeight / 2;//计算中心点
return TRUE; // return TRUE unless you set the focus to a control
}
void CMyDlg::OnPaint()
{
...
CClientDC dc(this);
CDC memDC;
memDC.CreateCompatibleDC(&dc);//使这个设备与dc兼容
memDC.SelectObject(&m_bitmap);//将内存设备与位图资源关联
BITMAP bmpInfo;
m_bitmap.GetBitmap(&bmpInfo);
d.BitBlt(m_x, m_y, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY);//绘制位图在m_x,m_y位置上
}
void CMyDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch (nChar)
{
case VK_LEFT:
m_x-=10;
break;
case VK_RIGHT:
m_x+=10;
break;
case VK_UP:
m_y-=10;
break;
case VK_DOWN:
m_y+=10;
break;
default:
break;
}
this->InvalidateRect(NULL); //擦除原先的图片,重新画出图片(OnPaint中)
CDialogEx::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(pMsg->message == WM_KEYDOWN)
{
SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
}
return CDialog::PreTranslateMessage(pMsg);
}
2.键盘上下左右的响应问题,原因是这样的在对话框中响应键盘消息时存在一些问题,当对话框中没有控件时,可以按普通窗口的方式来响应,即添加OnKeyDown()消息响应,但当对话框中存在控件时,由于窗体处于活动状态,必有一个控件获得焦点,不能通过在ClassWizard中添加WM_KEYDOWN来响应键盘输入。最简单的办法就是重载CWnd::PreTranslateMessage即可,在这个函数中使用sendmessage发送按键消息,使得onkeydown能够捕捉键盘消息,从而响应上下左右。