我是靠谱客的博主 无奈方盒,这篇文章主要介绍[Win32]键盘接口简介,现在分享给大家,希望可以做个参考。

1. 键盘输入焦点:

    1) 一台电脑只有一个键盘,因此键盘必须为所有应用程序锁共享;

    2) 同样,如果一个应用程序在使用键盘,那么该应用程序的所有窗口也应该共享键盘;

    3) 输入焦点:根据消息循环的机制,当敲击键盘产生键盘消息后只有一个窗口会接收到键盘消息,而该窗口就是具有输入焦点的窗口;

    4) 如何判断一个具有输入焦点的窗口:必定为活动窗口或者是活动窗口的各个子孙窗口中的一个;

    5) 活动窗口及其子孙窗口:活动即顶层窗口(其父指针为NULL),活动窗口的标题栏会高亮(非活动窗口,即被盖在下面的窗口标题栏通常是灰色的),如果没有标题栏,则其边框是高亮的,并且活动窗口最小化到任务栏后也会被凸显(就像一个被按下的按钮一样),子窗口不能是活动窗口(子窗口只能沾活动窗口的光),即活动窗口的子孙窗口可以获得输入焦点,比如对话框中的编辑框就是当前活动窗口对话框中的一个子窗口;

特殊情况:没有窗口但是具有输入焦点(当程序最小化的时候),焦点的含义就是当前正在被使用的那个对象窗口,只要这么简单地理解就行了!

    6) 一个窗口如何判断自己是否获得焦点:如果收到WM_SETFOCUS消息就表明自己获得了输入焦点,如果收到WM_KILLFOCUS消息则表示自己失去了焦点,一般当一个窗口被用户点击被显示在了最顶层时就会收到WM_SETFOCUS消息,当用户点击了另一个窗口而导致另一个窗口处于最顶层而当前窗口被盖在了下面,此时该窗口就会收到一个WM_KILLFOCUS消息;


2. 系统消息队列和同步:

    1) 由于来自键盘和鼠标的消息不一定都是集中在一个窗口的,用户想将一部分来自键盘和鼠标的消息给一个窗口处理,另一部分交给另一个窗口处理,但是用户无法直接干涉消息如何分发,因此这就需要先创建一个系统消息队列来暂时收容来自键盘和鼠标的消息,然后系统根据当前哪个窗口具有焦点来决定将收容的消息分配给哪个应用程序的消息队列;

    2) 系统需要同步:用户可能连续产生若干个消息,比如WM1、WM2、WM3、WM4...,其中1和2是交给当前焦点窗口处理的,而3是一个将焦点转向另一个窗口的消息,而后面的消息都是交由新焦点窗口处理的消息,如果此时一股脑儿将所有消息都先扔给当前焦点窗口则必然会发生错误和混乱,因此系统消息队列最重要的一个特征就是同步,同步就是指只有当上一个消息处理完之后才会继续从系统消息队列中取走下一个消息分发给当前焦点窗口,这样就能避免将消息发送给错误的窗口;


3. 击键消息机器虚拟键代码:

    1) 击键仅仅代表一个物理动作,键按下和放开都是一次击键(也就是两次击键),表示有一个键按下的消息是WM_KEYDOWN消息,而键放开的消息是WM_KEYUP消息;

    2) 通常击键消息是连续追踪的,当按下一个键不放时将会产生连续击键行为,窗口会收到一连串WM_KEYDOWN消息,但是WM_KEYUP是不连续的,一次按键只能对应一个释放动作;

    3) 系统击键和非系统击键:

         i) 击键消息汇总:


         ii) 系统击键通常是指和Alt键组合的击键,系统击键通常对于Windows操作系统来说比对应用程序更加重要,因此这类消息通常应用程序都不处理而直接交由DefWindowProc来处理,它会直接将这些消息交由系统处理完成一些系统任务,如调用程序菜单功能或者是系统菜单功能,其中有些功能是当前应用程序是无法处理的,比如Alt+Tab键是用来切换应用程序的,对于这种功能一般应用程序办不到,只能交由操作系统来完成,因此这类消息直接通过DefWindowProc交由操作系统来处理;

         iii) 当然应用程序如果有需要也可以响应系统击键消息,比如在WM_SYSKEYDOWN下写上消息处理代码,但一般处理完之后还是要将该消息在发送给DefWindowProc处理,以免影响Windows操作系统的运行,当然在某些特殊情况下洗完组织系统处理这样的按键消息,比如某个应用程序想独占Alt+Tab按键作为自己的快捷键而不希望操作系统也响应它(有时也有Windows键),特别是在一些游戏程序中,为了避免玩家误按下这些件而切换到游戏以外的画面,这是就可以使用如下模板来处理:

case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
	return 0;
暴力阻止所有系统击键的系统响应

case WM_SYSKEYDOWN:
	if ( VK_TAB == wParam ) return 0;

	switch ( wParam )
	{
		...
	}

	return 0;
仅仅阻止Alt+Tab系统击键的系统响应

一般Alt+各种键都会产生系统击键消息,还有就是Windows键以及Windows键和各种键的组合也会产生系统击键消息!


4. 虚拟键代码——键消息的附加消息:

    1) 击键消息只能代表有某一个键按下或者放开,但是不能具体表名是哪个键被按下后者放开,这是没有任何使用意义,因此击键消息的附加参数必须提供这些信息;

    2) 用来标识按键的代码存放在击键消息的wParam中,这就是虚拟按键代码,注意!虚拟按键代码和ASCII码毫不相关!

    3) 虚拟键代码的由来:因为键盘按键的信号只能用一些简单的编码方法进行编码(根据键盘的物理格局以及键盘上键的排列来决定),无法用复杂的ASCII码进行编码,否则这回大大增加键盘电路的复杂度!因此,最早的键盘按键信号的编码仅仅就是由键的物理顺序来决定的,比如Q、W、E、R的编码就是16、17、18和19,完全按照物理位置从左到右递增,但是这对于编程来说非常不方便,编程需要和设备无关的编码方案,因此Windows就要求键盘厂商提供的键盘驱动程序将这些第一手的基于物理位置的编码转换成一种通用的与设备无关的编码方案(现在的键盘都已经统一标准了,接口驱动程序基本由Windows来提供,而厂商负责生产负荷该标准的键盘即可),该通用的设备无关编码方案就是编程中用到的虚拟键代码,比如键盘上的A键对应的虚拟键代码就是65,和A的ASCII码天差地别,同时从键盘上看A键具体代表大写A还是小写a完全取决于你是否按下Shift键以及Caps Lock键;

    4) 使用虚拟键代码而不直接使用ASCII码的原因:一方面刚刚已经提到过构造ASCII码的硬件电路复杂,另一方面,键盘上很多控制键是屏幕无法显示的(即不带表任何字符),仅仅用来完成一些功能,很多键的功能也无法在ASCII编码中表示,再说了,对于数字键来讲还区分主键盘和数字小键盘,如果都用ASCII编码就无法区别是来自主键盘还是来自小键盘,因此Windows为键盘上的每个键都编制了一个虚拟键代码,而对于那些可以用来显示文本的键(如字母键、数字键等)可以通过TranslateMessage为这些击键消息再产生一条对应的字符消息(WM_CHAR消息),然后将对应的字符ASCII码存储在字符消息的附加参数wParam中,这也就是虚拟键代码和ASCII码之间的区别,ASCII属于上层编码,而虚拟键代码更加偏向底层对硬件信号的编码!

    5) 虚拟键代码汇总:


以上的鼠标键消息无法用键盘产生,只能用鼠标产生,VK_CANCEL是指Ctrl+Pause Break键,现在已经不用了!


通常应用程序不需要监控Shift键、Ctrl键或Alt键,因为监控这些件没有意义,一般都是监控和其组合在一起的那个wParam的内容!


用的最多的几个虚拟键代码就是VK_PRIOR表示Page Up键以及前7个键还有就是VK_INSERT和VK_DELETE

接下来是主键盘的数字键和字母键以及数字小键盘上的键:



接下来是Windows键和特殊的Application键:


剩下的就是功能键F键等键:



5. 击键消息的标记信息:

    1) 击键消息的虚拟键代码存储在wParam中,而其标记信息则存储在lParam中,32位的lParam被分成了六段如图:


    2) 重复计数字段:通常情况下被设为1,只有在相同消息连续堆积的情况下才会进行计数,也就是窗口过程处理速率跟不上输入速率的时候才会出现这种情况,在这种情况下连续的多个WM_KEYDOWN或者WM_SYSKEYDOWN消息会合并成一个消息,只不过就是该字段变成了一个计数值而已;

    3) OEM扫描码:现在已经不用了;

    4) 扩展键标记:是指一些大键盘(通常超过100个键)上的一些比正常标准键盘多出来一些键的按键标记,比如右侧Alt和Ctrl,数字小键盘上的Num Lock键以及Enter键等,这些键的击键消息,该位会被置为1;

    5) 内容代码:击键的同时按下Alt键该位就会被置为1,因此所有WM_SYSKEYDOWN和WM_SYSKEYUP的该位都是1,而WM_KEYDOWN和WM_KEYUP该位都是0,但是某些和Alt键组合的击键消息不一定是系统击键消息,比如一些非英语键盘通过Alt键的组合产生一些带重音符号的字符;

    6) 键的先前状态:先前处于释放则为0,处于按下则为1,因此WM_KEYUP和WM_SYSKEYUP的该标记始终为1,而对于WM_SYSKEYDOWN和WM_KEYDOWN则可能为1也可能为0,为1表示连续按着键;

    7) 转换状态:如果当前正在被按下则为0,正在被释放则为1,因此DOWN始终为0而UP始终为1;


6. 利用GetKeyState函数检查转义状态:

    1) 转义键是指Shift、Ctrl、Alt、Caps Lock等键,和它们组合的键的含义将会别转变,特别是大小写输入的时候;

    2) 函数原型为:SHORT GetKeyState( int nVirtKey );

    3) 参数即为虚拟键代码,如果改建被按下则返回一个负值(最高位为1),否则就表示被释放(最高位为0),当然最高位用来表示一个键按下和释放者两种状态;

    4) 返回值的最低位标志一个键的功能是否被锁定,这常用于具有指示灯的按键,诸如Caps Lock、Num Lock、Scroll Lock的各种Lock键,当这些键被锁定(即响应的指示灯亮),则返回值最低位为1,否则为0,因此诸如Shift、Alt、Ctrl等的判断只用最高位,而那些Lock键的状态只用最低位来判断,而上述这些键的虚拟键代码也只能用于该函数以及GetAsyncKeyState函数;

    5) GetKeyState只能检查当前状态而不能检查当前实时状态,比如在判断组合键Shift + Tab的时候,按照标准习惯都是先按Shift再按Tab(即功能键优先按,还有Ctrl、Alt等,而字符键之后按,包括字母键、空格、Tab等),因此就在处理Tab的WM_KEYDOWN消息中调用GetKeyState( VK_SHIFT )来判断这一组合键,这是你只能知道按Tab之前Shift先被按下了,之后是两个一起按下的,而此时此刻Shift有没有释放我们不知道,这很合理很方便;

小结:先被按下的是用GetKeyState检查的,外面的包含他的WM_KEYDOWN响应一定是后按下的,这是Windows的内部机制,只要遵守该原则就行了!

因此如果想获得实时的状态就必须调用GetAsyncKeyState函数了;


7. 如何使用击键消息:

    1) 通常击键消息很少使用,应用程序用的最多的是字符消息,即能产生字符的按键都监控它们的字符消息,因为单单一个按键动作没有任何意义;

    2) 因此通常是能产生字符的按键监控其字符消息,而不能产生字符的按键则监控其击键消息,但是真正值得应用程序去监控的击键消息也是少得可怜的;

    3) 关于菜单快捷键命令:很多人喜欢大量监控Alt、Ctrl、Shift、Delete、Insert等的击键消息来定义自己的快捷键,但是Windows不支持这样做,通常这些键的组合通常用于重复应用程序的菜单命令,如果定义大量这些快捷键将不利于用户快速学习你的程序,因此这些键的击键消息通常也是直接交由DefWindowProc处理(即由操作系统自动处理);

    4) 击键消息监控的真正用途:主要用在文本编辑、查看中的光标移动,也只有这些情况下Windows是没有默认的功能的,Shift、Ctrl键和Insert、Delete、光标键的组合可以扩大文本处理的范围,比如Ctrl和左右键组合可以选中一个单词等,Shift和上下键组合可以翻页等,而具体移动多少范围等意义可以由应用程序自己按照需求定义;

还有就是Page Up、Page Down等用来滚条的翻页,基本上都是跟文本显示有关的!


最后

以上就是无奈方盒最近收集整理的关于[Win32]键盘接口简介的全部内容,更多相关[Win32]键盘接口简介内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部