当前课程知识点:VC++面向对象与可视化程序设计(上):Windows编程基础 >  第4章 Windows应用程序中的键盘与鼠标 >  4-1 Windows 应用程序中的键盘与鼠标 >  4-1

返回《VC++面向对象与可视化程序设计(上):Windows编程基础》慕课在线视频课程列表

4-1在线视频

4-1

下一节:4-2

返回《VC++面向对象与可视化程序设计(上):Windows编程基础》慕课在线视频列表

4-1课程教案、知识点、字幕

大家好!

我们现在开始新的一讲内容

Windows的应用程序中的键盘与鼠标的应用

这个也是在应用程序编写过程中

经常会碰到的问题

大家知道 你们现在

在应用程序操作过程中

鼠标是不离手的

所以我们就要讲

鼠标的怎么响应的问题

键盘,肯定是少不了的

你们要从键盘里输入命令

进行相应的操作

所以键盘是不可少的

所以我们这一讲

就介绍键盘与鼠标的应用

首先 我们说键盘在应用程序中的应用

大家知道键盘上的键

它对应着唯一的标识值

这个标识值呢它是一个扫描码

是按下或者释放某一个键的时候

要有这个值标识,这一按键以及状态

所以的话

这个扫描码会在按下或释放键的时候产生

那么扫描码是什么呢?

或者说标识值是什么?

扫描码是依赖于具体设备的

为了达到设备无关性的要求

往往使用与具体设备无关的虚拟码

虚拟码是由Windows系统定义的与设备无关的键的标识

关于虚拟码的问题,我们在第二讲里面

曾经给大家做过介绍

那么具体说

设备驱动程序截取键的扫描码

然后翻译成虚拟码

那么由于键盘的输入

这时候它就会产生一条消息

这个消息,就是字符消息

以及按下或放开的动作消息

它就包含了扫描码

虚拟码和其他按键相关的消息

然后,这个消息

就通过设备驱动程序把消息放到系统的消息队列中

Windows就从系统消息队列中取出信息

然后 发送到相应的线程消息队列当中

这样 窗口过程就WndProc了

就取出键盘消息进行处理

那么从这个页面里面

大家就可以看到键盘它所扮演的角色

以及它的执行的过程

虚拟码是一种与设备无关的键盘编码

它的值就存放在键盘消息的字参数wParam中

用来标识哪一个键被按下或者释放

最常用的虚拟码已经在Windows.h中都给了定义

那么在这里面,我列出常用的虚拟码

比如Vitual key就是VK开头的虚拟码

就是鼠标左键LeftButton

比如右键中键还有退格键

这是键盘上的退格键BackSpace

那么这Return就是键盘上的回车键

以及Control、Pause这些

那么大家可以发现

你在键盘上按下了这些键它是实现某一个的功能

并不能在屏幕上显示你按下键的字符信息

而是完成某一个功能的

那么这个时候

这些键都定义成了是虚拟键

那么这样虚拟键

你在消息响应过程中

就可以对这些键

设置相应的消息响应机制

那么操作系统

在接收到键盘的输入之后

就把消息发送给具有输入焦点的窗口

哪一些窗口具有输入焦点呢?

大家知道Windows它是一个多任务的操作系统

也就是说

根据程序执行的需要

它可以在屏幕上出现多个窗口

应用程序,也就是说一般有几个窗口

但当按下某一个键的时候

只有一个窗口能接收到这个键盘的消息

我们说接收这个键盘消息的窗口就称为

具有“输入焦点”的窗口

有“输入焦点”的窗口

应该是活动窗口或者说是活动窗口的子窗口

那窗口函数,就通过捕捉SETFOCUS和KILLFOCUS这个消息

来确定当前的窗口是否具有输入焦点

那么如果是捕获了SETFOCUS消息

说明这个窗口,正在接收输入

那么如果是KILLFOCUS就失去了输入焦点

也就是说这个窗口不能接收输入了

那我们再说键盘消息

键盘消息实际上包含了字符消息和按键消息

一个按键的组合产生了一个可以显示的字符时

就产生了一个字符消息

那么按键消息是什么?

是按下或者松开一个键时产生的按键消息

那么按键消息有非系统的按键消息和系统的按键消息

非系统的按键消息

是不使用Alt键组合的按键消息

而系统键消息是Alt键与相关输入键的组合产生的消息

这些键,一般由Windows系统内部直接处理

应用程序不处理

如果应用程序处理了这些消息

那么还要调用DefWindowsProc()函数

以便不影响系统对它们的处理

那么消息里面呢

系统键消息和非系统消息

比如系统是SYSKEYDOWN和SYSKEYUP这两个都是系统消息

那么按下系统键消息

KEYUP和KEYDOWN的话,是非系统键消息

那么按键消息,它有两个变量

一个变量是字参数wParam

一个变量是lParam

wParam它包含了识别按下键的虚拟码

而lParam它是一个32位的变量

它包含了按键的重复计数位

OEM的扫描码

扩展键的标识

保留位关联码

键的先前状态以及转化状态等等等等

关于这32位标量里包含了哪一些码的问题

哪一些标志的问题

这个大家不用去管它

这个系统会处理

我们只是把这个机制给大家做个介绍

关键是大家要掌握字参数

因为它识别了案件的虚拟码

那么在WinMain函数中呢

消息循环里面包含了TranslateMessage

这个 在前面构架里面

只是告诉大家有TranlateMessage和DispatchMessage

我们还没讲

按键消息的时候只是告诉大家构架里必须有这一个

那么到了今天,大家就知道了为什么要有这个

因为有了TranlateMessage这个函数

它功能是什么?

是把按键消息转化为字符消息

但只有当键盘驱动程序把键盘字符映射成ASCII码后

才能产生字符消息

那么也就是说

我们从键盘上输入相应的字符

为什么系统会接收我们的字符并进行相应的操作呢?

很重要的是TranlateMessage在起作用

那么我们说系统键字符消息里面,也有系统字符消息

和非系统字符消息

这个比如说

CHAR就是非系统的消息

SYSCHAR就是系统消息

还有一些死字符消息

那么SYSDEADCHAR

那么死字符消息是什么呢

这里面给出了MSDN的解释

因为,大家知道在某些非美式的英语键盘上

有些键是给字母加上音调的

因为它们本身不产生字元

所以称为死键

比如说德语键盘

德语键盘的话,对美式键盘上的这个加号和等号键

德语键盘上对应的就是一个死键

那么没有按下shift键时它标识锐音

按下shift键时,这标识抑音

那么这个是不同语种为了实现相应字符的输出

它设置的一些特殊的字符

我们平常用的是这个英语的键盘,不会用到死字符

那么也就是说当使用者按下这个死字符

系统接收到wParam等于音调本身的ASCII码

或UNICODE代码的死字符DEADCHAR消息

当使用者再按下时,可以带有此音调的字母键

关于死字符的一些知识

我们就简单的和大家说一下

大家如果有兴趣

去看MSDN上面相应网址的内容

因为在我们的中文里面不会遇到

好了下面

我们通过一个例子来介绍一下字符的使用

这个例子是这样的

设计一个窗口

在这个窗口中练习键盘的响应

我们要求是这样的

单击键盘上向上箭头时

窗口中显示“You had hit the UP key”

单击shift键时

窗口中显示“You had hit the SHIFT key”

单机Ctrl键时

窗口中显示“You had hit the CTRL key”

当单击Ctrl+A键的时候

窗口中显示“You had hit the CTRL A key”

单击Shift+B时候呢

窗口中显示“You had hit the SHIFT B key”

那么对于这个应用程序

我们呢也是重点介绍一下WndProc函数

WndProc函数里面呢我们同样定义了一个DC

一个PAINTSTRUCT

这个大家都很清楚

然后,我们定义了画笔跟画刷

由于我们要用到一系列的消息提示

我们把需要提示的消息都做成字符串的

比如说Up key

那么当单击向上箭头的时候

提示信息“You had hit the UP key”

我们放在cUp这个字符数组里面

同样呢cCtrl

那么我们已经预设了五个需要显示的字符串

然后,我们在WndProc里面

要定义几个标志的变量

好了定义什么呢

就是nUpKeyDown

就是向上箭头刚开始没有按下的时候状态一定是FALSE

shift键初始也是FALSE

Ctrl键初始也是FALSE

Ctrl+A键Shift+B键初始也是FALSE

那么就是说刚开始的时候所有按下键的状态都是FALSE

也就是都没按下

因为我们程序刚刚运行时

不可能你是按照某一个键去运行的

所以刚开始所有的按键都是FALSE

那么进入消息循环

首先,我们考虑KEYDOWN

KEYDOWN里面,按下键

按下键的字参数

我们说识别它的字参数

识别它的字参数

如果遇到了向上箭头的虚拟键

这个case 那么就是说按下了这个键

如果按下这个键后我们就把nUpKeyDown给设成TRUE

因为我们的初值都是FALSE

如果shift键按下了

我们就把nShiftKeyDown变成TRUE

如果Ctrl按下了就把nCtrlKeyDown变成TRUE

那么这是按键消息

那么对于按下键我们识别是按下的是什么键

箭头键shift键Ctrl键

那么KeyUp呢 松开键

一旦这个键按下后 松开了

我们就要在屏幕上看到我们的操作效果

这个时候,为了看到效果

我们就要对屏幕进行刷新

那么这时候,就是进行用户区的刷新

好!那么刚才我们识别是KEYDOWN

那么这是非系统键

这是非系统键的消息

和KEYUP

我们识别的都是这两个非系统键消息

所以我们识别的是非系统的UP键

向上箭头

Shift键和Ctrl键

我们下面要识别什么呢?

字符

因为我们有Ctrl+A

Shift+B等等等等

我们如果要判断按下的是Ctrl+A

这时候Ctrl+A是Ctrl+A还是Ctrl+a

所以这个时候

我们说对字符键我们要识别

这个65、97实际上是A的大写的ASCII码和小写的ASCII码

那么这时候按下Ctrl+A或者

这个是或的关系

或者是Ctrl+a

那么这个时候

如果nCtrlKeyDown是TRUE

那么就是按下Ctrl Key

这个时候,仍然是把nCtrlAKeyDown变成TRUE

那这个时候,就是说

我们由于这里有A的ASCII码的字符

A、a都可以

只是按下A、Ctrl+A

那么也就是说,如果先前按下的Ctrl键

我们给它变为nCtrlAKeyDown为TRUE

那么这时候,单纯的Ctrl键给它变成FALSE

这样来标识他按的是Ctrl+A而不是Ctrl和A

两个分别按的

不作为组合键的

Ctrl+A是认为Ctrl和A是一个组合键

如果是把A变成TRUE

Ctrl变成TRUE

那么实际上是分别上是两个键

而不是Ctrl+A的组合键

所以这个地方大家要注意

else if呢,如果字参数是98或者66

那么就按下了B键

如果这个时候

nShiftKeyDown原来是TRUE的

给它改成nShiftBDown是TRUE的

而单纯的Shift是FALSE

那么这个和Ctrl+A应该是如出一辙的

那么这里面

大家可能会说

你Ctrl+A时候,是用65跟Ctrl的或者是97跟Ctrl的

那你下面Shift+B的时候为什么不用

shift跟98或者66跟shift

实际上这两种写法都是可以的

我只是用不同的写法给大家表示一个不同的编程方法而已

这个第一个写法,是同时考虑Ctrl和A

而第二种写法是考虑B之前考虑有没有Shift

如果有的话认为是Shift、B同时按

是这么个意思

好了那么我们已经处理了字符消息

也处理了Up、Ctrl、Shift消息

然后,我们就要看我们到底接收了什么消息

然后进行刷新

那么进入PAINT里面 刷新里面

我们首先仍然通过BeginPaint创建一个DC

然后,我们用系统定义的白画刷

所以大家看到应用程序的背景是白的

大家如果感兴趣的话,可以把这个画刷变成别的颜色

大家可以试一下,把这个程序改一改

那么笔的话,我们用了这个WHITE_PEN

那么白笔的话,大家可能会说这个笔是白的

怎么写字呢?

我们先把这个笔选入

然后再设置它的颜色

所以把这个笔和画刷都选入当前的设备环境之后

我们把这个字体的颜色变成红的

所以这样

写出来字就是红的

所以大家看到我们的提示

通过应用程序的运行大家看到我们的提示

是红色的

那么这个时候,我们就要对输入的字符信息进行判断

如果nUpKeyDown就是向上的箭头为TRUE的话

在这个用户区里面输出我们的关于cUp的提示

nUpKeyDown为TRUE的时候

当你显示完之后

你的nUpKeyDown应该马上变为FALSE了

你不能老在那里是TRUE

然后,如果是nCtrlAKeyDown是TRUE

我们仍然在矩形区域里面

输出关于Ctrl+A按下的时候它的提示内容

那么输出之后,我们要把nCtrlAKeyDown状态变成FALSE

当然也得把nCtrlKeyDown变成FALSE

那么如果nCtrlKeyDown是TRUE而nCtrlAKeyDown是FALSE

那么这个时候

显示是当前按下时Ctrl键

那么Ctrl键完了你这个nCtrlKeyDown马上又变FALSE了

所以,每一次要注意,就是说你做完之后

相应的键都得给它变成FALSE

否则的话,总认为某一个键是按下的

因为我们有对Ctrl的消息响应

有对Ctrl+A的消息响应

那么Ctrl+A里面也包含了Ctrl

所以这个时候

这就是为什么我们前边在做对Ctrl+A判断的时候

Ctrl和A同时按下的时候,我们把Ctrl+A变成TRUE

而单纯把Ctrl变成FALSE

因为Ctrl和Ctrl+A是不一样的

所以它是两个不同的按键消息

同样,如果nShiftBKeyDown是TRUE的情况下

我们仍然在指定的区域输出关于按下Shift+B的消息

然后,我们要把nShiftBKeyDown变成FALSE

也得把nShiftKeyDown变成FALSE

相关键都得变成FALSE

如果nShiftBKeyDown是FALSE

那么就是说没有按下Shift+B

但是你单纯按下Shift的时候

我们就说在这个地方

在指定的位置输出了关于按下Shift键的消息提示之后

再把Shift键变成FALSE

最后,我们把画笔画刷都删除掉后

再EndPaint就结束了

所以,这个DESTROY跟以前一样

所以这个例子

关键大家要掌握一个问题

就是复合键

Ctrl和Ctrl+A

Shift跟Shift+B

他们的区别

所以也就是说,你按Ctrl+A的时候要把Ctrl的状态去掉

不要以为说Ctrl+A里面包含了Ctrl

一定要把Ctrl+A和Ctrl明确区分为两个不同的消息

不要变成包含关系

Ctrl+A消息里面包含了Ctrl消息

或者Shift+B里面包含了Shift消息

那这样

变成消息包含关系就没法处理 会有歧义

到底是Shift还是Shift+B

或者是Ctrl还是Ctrl+A

所以一定要把Ctrl+A和Ctrl分开

Shift+B和Shift分开

也就是说它的这个BOOL变量在Shift+B跟Shift这个地方

或者前边的Ctrl+A和Ctrl这个地方

都要进行相应的设置

不要变成包含关系 而是并列关系

好了,那么这个例子我们就介绍到这

VC++面向对象与可视化程序设计(上):Windows编程基础课程列表:

第0章 课前讨论

-讨论实录

--0-0

第1章 Windows应用程序基础

-1-1 Windows应用程序的特点

--1-1

-1-2 可视化编程

--1-2

-1-3 关于API

--1-3-1

--1-3-2

-1-4 Windows应用程序组成及编程步骤

--1-4-1

--1-4-2

-1-5 应用程序举例

--1-5-1

--1-5-2

--1-5-3

第2章 Windows的图形设备接口及Windows绘图

-02-1 Windows图形设备接口

--02-1-1 GDI

--02-1-2 图形刷新

--02-1-3 获得设备环境方法

--02-1-4 映像模式

-02-2 绘图工具与颜色

--02-2-1 画笔

--02-2-2 画刷和颜色

-02-3 常用绘图函数

--02-3 常用绘图函数

-02-4 例题和作业

--02-4-1 例题1

--02-4-2 例题2

--02-4-3 例题3

--02-4-4 例题4

--02-4-5 作业

-第2章源代码

--外部链接

--外部链接

第3章 文本与字体

-3-1 设置文本的设备环境

--3-1 设置文本的设备环境

-3-2 文本的输出过程

--3-2 文本的输出过程

-3-3 例题和作业

--3-3-1 (例3-1)

--3-3-2 (例3-2)

--3-3-3 (例3-3)

--3-3-4 (例3-4)

--3-3-5 (作业)

-第3章源代码

--外部链接

第4章 Windows应用程序中的键盘与鼠标

-4-1 Windows 应用程序中的键盘与鼠标

--4-1

-4-2 键盘的操作应用举例

--4-2

-4-3 例题

--4-3

-4-3 鼠标在应用程序中的应用

--4-3

-4-4 例题4-4

--4-4

-第4章源代码

--外部链接

第5章 资源在Windows编程中的应用

-5-1 菜单和加速键资源及其应用

--5-1

-5-1(例1)

--5-1(例1)

-5-2 位图资源及其应用

--5-2

-5-3 对话框资源及其应用

--5-3-1

--5-3-2

-5-4 图标资源的应用

--5-4

-第5章源代码

--外部链接

-第一次作业

--第一次作业--作业

-第二次作业

--第二次作业--作业

-第三次作业

--第三次作业--作业

4-1笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。