windows程序最根本就是消息机制。按键盘也会得到相应的消息。我们现在需要让Panel处理相应的键盘消息,使俄罗斯方块可以左右移动,翻转或者往下。
跟处理显示消息的方式类似。打开类视图(大部分的视图或窗口可以在菜单中“视图”菜单项内找到),选中Panel类,打开属性视图,选择上方的消息按钮。找到WM_KEYDOWN消息,添加对KeyDown消息的处理函数 OnKeyDown
OnKeyDown有三个参数,第一个说明按了那个键,第二个是按键次数,第三个参数是一些额外信息。
void Panel::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
我们在这个函数里判断按下的键是不是上下左右箭头,如果是的话,则对方块进行翻转,往下,左移,右移的相应操作。
代码如下:
void Panel::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (element==NULL) return;
switch(nChar)
{
case VK_UP:
element->rotate();
break;
case VK_DOWN:
element->moveDown();
break;
case VK_LEFT:
element->moveLeft();
break;
case VK_RIGHT:
element->moveRight();
break;
default:
return;
}
Invalidate(false);
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
其中VK_DOWN,VK_UP等是微软定义的按键的宏定义。每个按键都有一个对应码,记忆那些对应码有些复杂,所以微软预定义了一些宏值来代表。上下左右键的宏定义就是VK_UP, VK_DOWN,VK_LEFT, VK_RIGHT。
然后调用Invalidate(false);这样方块移动后立即刷新屏幕显示。
然后调用默认的按键消息,让windows继续处理。
===========================================
到这里Panel对按键处理就结束了,但是如果你试着运行一下,还是没有效果。这是因为我们的Panel是嫁接在一个Static Text上的。而Dialog一般情况下,并不会把按键消息发送给Static Text这样原本只是用来显示一句话的控件的。我们如果需要Panel接收按键消息,必须要修改Dialog分发消息的默认方式,也就是重写Dialog分发消息的函数。让它能够把相应的按键消息发送给Panel.
打开类视图,选中。。Dlg类,打开属性窗口,点击上方“重写”按钮,在众多重写函数中找到PreTranslateMessage,对它进行重写。
PreTranslateMessage发生在所有的消息被转发之前。
这个函数只有一个参数,是一个MSG结构 BOOL CTetris4Dlg::PreTranslateMessage(MSG* pMsg)
MSG被设计成一个通用的结构,用来存储所有种类的消息以及该消息相关内容。
这个结构主要包含了message, wParam, lParam三个成员变量。
在KEYDOWN消息中 message就是WM_KEYDOWN, wParam就是按键的值,lParam存储了其他相关内容。
我们需要判断一下,如果当前发送的是一个KEYDOWN消息,而且按键就是上下左右,那么要求把这个消息告诉给Panel
BOOL CTetris4Dlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
if (pMsg->wParam == VK_RIGHT || pMsg->wParam == VK_LEFT || pMsg->wParam == VK_DOWN || pMsg->wParam == VK_UP)
{
m_Panel.SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
return true;
}
return CDialog::PreTranslateMessage(pMsg);
}
对于要处理的消息,调用SendMessage通知具体窗口。
对于已经发送的消息,用return true来代表消息已经处理。
对于其他消息,还是调用原有的PreTranslateMessage,继续进行原有的处理。
这次又完成了。我们运行代码,随机生成的俄罗斯方块可以根据按键自由活动了。