一、引言
计算机的重要功能之一就是对操作人员通过输入设备对其的控制进行响应。输入设备是指人能对计算机发出指令的设备,通用的这种设备有键盘、鼠标、游戏杆等。由于这些设备的准确使用使计算机程序具备了人-机交互的强大功能,操作者通过输入设备可以实时地控制计算机各种程序的执行,计算机通过屏幕和其它输出设备把执行情况实时地反馈给操作者。这种功能是各种控制程序必须具备的,而实现程序的各种具体编程语言中也都有其相应的实现方法。Visual C++语言是目前最流行的编程语言之一,但对其介绍的书籍资料中少有专门介绍对输入设备响应的编程方法的。因此在本文中,笔者根据自己长期从事对计算机进行人—机相互控制的编程经历,较全面地介绍一下Visual C++ 编程语言中实现对输入设备响应的方法。
二、Visual C++编程语言
Visual C++是由Microsoft 公司在Microsoft C/C++7.0基础上推出的基于Windows的集成开发系统,当时的版本为1.0。到1998年推出Visual C++6.0,这是一种功能最强大的32位Windows可视化开发工具。到目前Microsoft 公司已经把Visual C++的版本发展到了Visual C++.net,应用于Windows 2000以上版本的操作系统。
由于Visual C++可以完成Windows的所有高级功能,而目前Windows操作系统在计算机市场中占据着垄断的地位,因此可以说Visual C++虽然不一定是最易开发和便捷的编程语言,但无疑是功能最强大的流行编程语言。尤其是其对目前流行的虚拟现实开发中必不可少的OpenGL和DirectX技术的直接支持,使得其在对底层程序功能的控制开发上更加方便灵活,在从商业应用、工业控制到娱乐游戏等各方面占据了主要的位置。作为一种Windows下的GUI式的OOP语言,Visual C++有几个明显的优点:
(1)提供了功能强大的向导工具。
(2)Developer Studio以项目工作区的形式组织文件、项目和项目配置。
(3)MFC类库支持多线程应用程序的开发。
(4)具有Windows Socket和MAPI支持,可以与网络和E-mail链接。
(5)最快的集成数据库访问,允许用户建立强有力的数据库应用程序。
(6)具有强有力的Internet支持。
(7)对OLE提供强有力的支持。
三、Visual C++中对输入设备的响应
如图1所示,Visual C++(以下简称VC)中键盘和鼠标的事件响应均可以在其MFC ClassWizard窗口中的Messages下拉的事件中找到。
1.对键盘的输入响应
Messages窗口
图1 MFC ClassWizard窗口
VC中用KeyPress表示键盘响应的所有事件,包括OnKeyDown事件(某个键按下时)、 OnKeyUp事件(某个键按下后弹起时)和 OnKeyPress事件(当按了某个键时)。(在下面用到的Object1均代表象窗体、按钮、文本框等所有可视化的控件或在程序设计中根据需要添加的成员、类等)
OnKeyuUp事件的语法为 void Object1:: OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags );
OnKeyDown事件的语法为 void Object1:: OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags );
这里参数nChar代表的是键盘上各键的代码,是编写程序时必须要写明的,而参数nRepCnt,和nFlags则可以使用默认值而不必编写。
下面说明的是在VC的KeyPress事件中的nChar代码与键盘中各键的对应关系:
VK_0 到VK_9 表示键盘上数字“0”到“9”键(ASCII码为0x30 - 0x39);
VK_A 到VK_Z 表示键盘上字母“A”到“Z”键(ASCII码为0x41 - 0x5a);
VK_ADD 表示数字键盘上的“+”键。
VK_ALT 表示键盘上 “ALT”键。
VK_BACK_QUOTE 表示键盘上 “ `”键。
VK_BACK_SLASH 表示键盘上 “/”键。
VK_BACK_SPACE 表示键盘上 “BACKSPACE“键。
VK_CAPS_LOCK 表示键盘上 “CAPS LOCK”键。
VK_CLOSE_BRACKET 表示键盘上 “]”键。
VK_COMMA 表示键盘上 “,”键。
VK_CONTROL 表示键盘上 “CTRL”键。
VK_DECIMAL 表示数字键盘上 “.”键。
VK_DELETE 表示键盘上 “DELETE”键。
VK_DIVIDE 表示键盘上 “/”键。
VK_DOWN 表示键盘上 “向下箭头”键。
VK_END 表示键盘上 “END”键。
VK_ENTER 表示键盘上 “ENTER”键。
VK_EQUALS 表示键盘上 “=”键。
VK_ESCAPE 表示键盘上 “ESC”键。
VK_F1 到VK_F12表示键盘上 “F1”到“F12”键。
VK_HOME 表示键盘上 “HOME”键。
VK_INSERT 表示键盘上 “INSTERT”键。
VK_LEFT 表示键盘上 “向左箭头”键。
VK_MULTIPLY 表示键盘上 “*”键。
VK_NUMPAD0 到VK_NUMPAD9表示数字键盘上 “0”到“9”键。
VK_OPEN_BRACKET表示键盘上 “[”键。
VK_PAGE_DOWN 表示键盘上 “PAGE DOWN”键。
VK_PAGE_UP 表示键盘上 “PAGE UP”键。
VK_PAUSE表示键盘上 “PAUSE”键。
VK_PRINTSCREEN 表示键盘上 “PRINT SCREEN”键。
VK_RIGHT 表示键盘上 “向右箭头”键。
VK_SCROLL_LOCK 表示键盘上 “SCROLL LOCK”键。
VK_SEMICOLON 表示键盘上 “;”键。
VK_SHIFT 表示键盘上 “SHIFT”键。
VK_SPACE 表示键盘上 “SPACEBAR”键。
VK_SUBTRACT表示键盘上 “-”键。
VK_TAB 表示键盘上 “TAB”键。
VK_UP 表示键盘上 “向上箭头”键。
用键盘在人机交互中完成对屏幕中物体位置移动的控制功能时常会用到上、下、左、右几个方向键。下面的程序可以完成对某一可视控件Object1的位置进行控制(分别按下上、下、左、右键使其分别向上、下、左、右方向移动5个屏幕单位):
{
CWnd::OnKeyDown(UINT nChar, UINT nRecpCnt, UNIT nFlages);
Switch(nChar)
{
case VK_LEFT;
Object1.left=Object1.left-5; //按下左键控件左移5个单位
break;
case VK_RIGHT;
Object1.left=Object1.left+5; //按下右键控件右移5个单位
break;
case VK_UP;
Object1.top=Object1.top-5; //按下上键控件上移5个单位
break;
case VK_DOWN;
Object1.top=Object1.top+5; //按下下键控件下移5个单位
break;
defult:
break;
}
}
2.对鼠标的响应
VC中对鼠标的响应常用的有以下事件:
a. OnLButtonDblClk:语法为void Object1 Wnd::OnLButtonDblClk( UINT nFlags, CPoint point ){},表示控件对双击鼠标左键时的响应。
b. OnLButtonDown:语法为void Object1 Wnd::OnLButtonDown( UINT nFlags, CPoint point ){},表示控件对按下鼠标左键时的响应。
c. OnLButtonUp:语法为void Object1 Wnd::OnLButtonUp( UINT nFlags, CPoint point ){},表示控件对按下的鼠标左键放开后的响应。
d. OnRButtonDblClk:语法为void Object1 Wnd::OnRButtonDblClk( UINT nFlags, CPoint point ){},表示控件对双击鼠标右键时的响应。
e. OnRButtonDown:语法为void Object1 Wnd::OnRButtonDown( UINT nFlags, CPoint point ){},表示控件对按下鼠标右键时的响应。
f. OnRButtonUp:语法为void Object1 Wnd::OnRButtonUp( UINT nFlags, CPoint point ){},表示控件对按下的鼠标右键放开后的响应。
其中的参数nFlags用于指示按下的键的代码,它可以是下面的几个值或它们的组合:
MK_CONTROL 表示按下CTRL键 ;
MK_LBUTTON 表示按下鼠标左键;
MK_MBUTTON 表示按下鼠标中键;
MK_RBUTTON 表示按下鼠标右键;
MK_SHIFT 表示按下 SHIFT键;
Point参数表示鼠标的光标位置相对于所在窗口的左上角的水平和垂直坐标值。
在VC中用鼠标响应事件来完成人机交互中的控制功能是比较容易的。例如把一个控件Object1的位置移动到鼠标光标的位置,下面简单的程序就可完成:
void Object1::OnLButtonDown(UINT nFlags, CPoint point)
{
CPoint Position;
Position = point;
Object1->left=Position.x;
Object1->top=Position.y; //按下鼠标左键后控件的水平和垂直方向的值分别与鼠标的光标位置一致
}
3.对游戏操纵杆的响应
VC中对游戏操纵杆的响应是利用Win32 API的MCI提供的一组检测游戏操纵杆、确定操纵杆性能、位置、按钮信息的函数来实现的。这些函数主要包括:
JoyGetNumDevs 检查驱动器支持的游戏操纵杆数
JoyGetPosEx 确定游戏操纵杆是否已连接
JoyGetDevCaps 获取游戏操纵杆性能的信息
JoySetCapture 通知Windows操纵杆消息应发送到哪里以及发送的频率
JoyReleaseCpture 释放指定的游戏操纵杆
其中最常用是获取游戏操纵杆消息的函数,它的语法为joyGetPos(JoystickID,&JoyInfo)。这里的参数JoystickID,表示连接的游戏杆是ID1还是ID2;JoyInfo表示的是位置信息,它有三个位置信息JoyInfo.wXpos、JoyInfo.wYpos、JoyInfo.wZpos分别代表在空间x、y、z方向上的位置,这些位置信息的值一般为0到65535,反映了游戏杆从一端拉满到另一端的最大位置变化为65535。
游戏操纵杆在某些需要对目标位置进行控制的操作中是非常方便的。下面的程序可以完成利用游戏杆操纵来控制一个控件(Object1)位置的功能:
在程序的头文件中需要加入“#include”语句,
JOYINFO JoyInfo;
joyGetPos (JoystickID,&JoyInfo); // 获取游戏杆信息
int X,Y;
X = JoyInfo.wXpos; //X为游戏杆的水平方向的值
Y=JoyInfo.wYpos; //Y为游戏杆的垂直方向的值
Object1.left=X;
Object1.top=Y; //使控件的位置与游戏杆提供的位置信息一致
JoyReleaseCapture(JoystickID); //释放游戏杆信息
四、结论
由于VC功能强大,又是Microsoft公司大力推广的产品,因此在编写基于Windows操作系统的应用程序方面占有不可替代的位置。尤其在工程开发中,通过编写人-机交互的程序来实现对计算机及外部设备的控制功能非常重要,而这些控制的实施主要是利用文中提到输入设备的响应,因此准确理解和使用其编程方法在工程实践中有重要的意义。本文中的例程均已在Windows98平台上的VC6.0中编译通过。