第四讲:键盘事件讲解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第四讲:键盘事件
【事件驱动】
所谓的事件驱动其实就是当满足什么样的条件下发生另外一件事情。比如当你按下按钮时就会执行相应的代码一样。由于控制台程序在同一个时刻只能够执行一个任务,这就造成了在处理事件的效率上太过于低下,通常现代的程序都是面向多任务的,也就是说同一个时间段可以完成好几个功能,那么如何才能够做到这一点呢?就依赖于事件驱动机制。
理解事件驱动就必须要先理解事件,所谓的事件(Event)其实就是触发某样事情发生的条件,例如键盘按下、单击按钮、双击图标等等。这些称之为事件。而当这些事件发生之后,就会触发另外一件事情。例如当我们点击“百度搜索”按钮时就会跳转到搜索的结果界面一样。
当然,采用事件驱动的直接原因就是最大化利用CPU,由于控制台程序的限制,我们不能够完成多任务的操作(早期的DOS操作系统是单用户单任务的,即同一个时刻只能够完成一个任务,效率很慢)故此我们需要事件驱动这样的机制为我们提高效率,为我们最大化利用CPU资源。
简而言之,事件驱动就是一个用于提高程序效率的机制。如果上述还没有让你明白过来,你可以看看百度百科上的解释,如下:
【程序查询方式】
通常检测事件有两种方法,一种称为程序查询法,一种称之为程序中断法。由于在控制台中我们无法直接使用系统中断(系统中断只有汇编语言可以直接使用),因此我们无法在高级语言中使用程序中断法检测指令。故此只能够使用程
序查询方式进行事件的检测。
所谓的程序查询方式实际上是利用一个死循环不停地对事件进行查询,如果事件发生则执行相应的代码,当代码执行结束之后继续开始下一轮的查询,由于CPU的计算速度相当快,你不用担心会有延时的问题。这样一轮一轮查询的方式,我们称之为程序查询方式,也叫轮询法。
程序查询法的流程图如下:
【键盘按下事件】
所谓的键盘事件,是指无论在何时只要键盘按键被按下,即可被程序所截获,并执行相应的功能代码。故此负责监听键盘事件的API函数会一直处于工作状态,在MFC中我们可以通过死循环进行操作,当然也可以通过我们即将接触到的多线程编程进行操作。在这里我们介绍如何利用死循环监听键盘。
【DWORD类型】
在MFC中,通常会见到DWORD类型,所谓的DWORD类型就是Double Word类型,即双字节类型,MFC中将unsigned long类型使用typedef关键字重新制定为DWROD类型。MFC框架中的声明如下:
故此,DWROD类型的本质其实是一个无符号的长整型数。在MFC中我们可以使用DWORD类型表示任何双字节的数据。这里笔者将不再重复如何使用DWORD类型的变量的方法。
【INPUT_RECORD结构体】
INPUT_RECORD结构体是用于描述输入设备事件的结构体,声明如下:
当然上述的结构体不像一般的结构体,它有一些复杂,但是也不影响我们的使用,在此要多说一句的是union一词,union也是C/C++语言中的关键字,用于描述“共用体”类型,所谓的共用体实际上是指在进行某些算法编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。也被称之为“联合体”。它是早期的C语言过渡到C++中的产物。当然这里我们只需要了解一下就行,并不需要做太多的深究。
【事件类型】
INPUT_RECORD结构体中的EnventType成员用于说明事件的类型,通常取值如下:
【KEY_EVENT_RECORD结构体】
KEY_EVENT_RECORD用于记录键盘事件的情况,当有键盘事件发生时,我们就可以使用该结构获取此时键盘的情况。KEY_EVENT_RECORD结构体声明如下;
【虚拟键码】
接下来为大家介绍一下虚拟键码的概念,由于键盘上的一些特殊键,例如ctrl、alt、shift、enter等键不能够直接被控制台程序所识别,故此在MFC中引入了虚拟键码的概念。
虚拟指的是假定存在于思想中而不是现实世界中的一些事物,也只有熟练使用DOS组合语言编写应用程式的程式写作者才有可能指出,为什么对Windows 键盘处理如此基本的键码是虚拟的而不是真实的。
对於早期的程序员来说,真实的键码由实际键盘硬体产生。在Windows文件中将这些键码称为「扫描码(scan codes)」。在IBM相容机种上,扫描码16是Q键,17是W键,18是E、19是R,20是T,21是Y等等。这时您会发现,扫描码是依据键盘的实际布局的。Windows开发者认为这些代码过於与设备相关了,於是他们试图通过定义所谓的虚拟键码,以便经由与装置无关的方式处理键
盘。其中一些虚拟键码不能在IBM相容机种上产生,但可能会在其他制造商生产的键盘中找到,或者在未来的键盘上找到。
提出虚拟键盘码的好处就在于可以兼容不同布局的键盘。(不要忘记即使是笔记本电脑也有小键盘和大键盘之分的哦!)
常用的虚拟键盘码如下:
上述是在MFC中常用的一些虚拟键码,更多的大家可以到网上进行查询。使用虚拟键码读者需要注意以下的几个要点:
1、Windows下的程序通常不需要监视shift、ctrl或alt键的状态
2、键盘上的字母和数字使用其ASCII码直接表示,而不采用虚拟键码
3、Windows操作系统中使用VK_LWIN以及VK_RWIN两个键打开“开始菜
单”或者是启动“工作管理员模式”,故此需要谨慎使用这两个虚拟键码。
4、对于键盘上的功能键(F1 – F12)一般不进行处理,当然虚拟键码表中提供
了24个功能键的编码。
【键盘事件的操作步骤】
键盘事件的操作步骤如下:
【监听键盘事件】
在MFC框架中通常使用ReadConsoleInput函数对键盘事件进行侦听,并通过形参将侦听到的结果保存在INPUT_RECORD结构体中。函数声明如下:
【判断是否有键盘事件发生】
判断是否有键盘事件发生通常使用INPUT_RECORD结构体中的EnventType进行判断,如果该成员的值与KEY_ENVENT(键盘事件)等价时,则证明发生了键盘事件,即:
【判断是否有键被按下】
那么如何判断键盘上是否有键被按下呢?这很简单,我们需要通过判断INPUT_RECORD结构体中的成员Event中的KeyEvent中的成员bKeyDown(即Bool KeyDown)是否为true即可。即:
【判断键盘按下的键值】
那么我们怎么才能够知道到底是哪个键被按下呢?此时我们可以通过KeyEvent成员中的uChar成员获取该键的ASCII码或者是Unicode编码,进行判断。
获取该键的ASCII码的代码为: