
Visual C++面向对象与可视化程序设计_windows_API_KB课件.ppt
34页Visual C++面向对象与可视化程序设计,--------WINDOWS API之 Keyboard,扫描码是依赖于具体设备的,为达到设备无关性的要求,往往使用与具体设备无关的虚拟码,虚拟码是由Windows系统定义的与设备无关的键的标识,6.1 键盘在应用程序中的应用,虚拟码是一种与设备无关的键盘编码,它的值存放在键盘消息的wParam参数中,用以标识哪一个键被按下或释放,最常用的虚拟码已经在Windows.h中定义,,应用程序一般有几个窗 口,但当按下某一个键 时,只有一个窗口能接 收到该键盘消息,接收 这个键盘消息的窗口称 为有“输入焦点”的窗口,有“输入焦点” 的窗口应是活 动窗口或者活 动窗口的子窗口,活动窗口通常是顶层窗口(即它的父窗口句柄是NULL)如果活动窗口有标题列,Windows将突出显示标题列如果活动窗口只具有对话框架,Windows将突出显示框架如果活动窗口目前是最小化的,Windows将在工作列中突出显示该项,其显示就像一个按下的按钮 如果活动窗口有子窗口,那么有输入焦点的窗口既可以是活动窗口也可以是其子窗口子窗口不能自己成为活动窗口只有当它是活动窗口的衍生窗口时,子窗口才能有输入焦点。
子窗口控件一般通过显示一个闪烁的插入符号或虚线来表示它具有输入焦点 在程序中可以用GetFoucs()和SetFoucs()函数获得和设置输入焦点 GetFoucs()返回拥有键盘输入焦点的窗口句柄,若调用线程的消息队列没有相关的持有键盘输入焦点的窗口,则返回值为NULL SetFoucs()对指定的窗口设置键盘焦点该窗口必须与调用线程的消息队列相关SetFocus函数发送WM_KILLFOCUS消息到失去键盘焦点的窗口,并且发送WM_SETFOCUS消息到接受键盘焦点的窗口它也激活接受键盘焦点的窗口或接受键盘焦点的窗口的父窗口队列和同步,当使用者按下并释放键盘上的键时,Windows和键盘驱动程序将硬件扫描码转换为格式消息这些消息并不保存在消息队列中,Windows在系统消息队列中保存这些消息系统消息队列是独立的消息队列,它由Windows维护,用于初步保存使用者从键盘和鼠标输入的信息只有当Windows应用程序处理完前一个使用者输入消息时,Windows才会从系统消息队列中取出下一个消息,并将其放入应用程序的消息队列中 此过程分为两步:首先在系统消息队列中保存消息,然后将它们放入应用程序的消息队列,其原因是需要同步。
假定接收键盘输入的窗口就是有输入焦点的窗口使用者的输入速度可能比应用程序处理按键的速度快,并且特定的按键可能会使焦点从一个窗口切换到另一个窗口,后来的按键就输入到了另一个窗口但如果后来的按键已经记下了目标窗口的地址,并放入了应用程序消息队列,那么后来的按键就不能输入到另一个窗口键盘消息,,按键消息,字符消息,按下或松开一个键时 就产生了一按键消息,一个按键的组合产生了 一个可以显示的字符时, 就产生了一个字符消息,,系统按键消息,非系统按键消息,Alt键与相关输入键的组合 产生的消息,这些键一般 由Windows系统内部直接 处理,应用程序不处理,若应用程序处理了这 些系统键消息,还要调 用DefWindowsProc()函 数,以便不影响系统对 它们的处理,不使用Alt键组合 的的按键消息,WM_SYSKEYDOWN和WM_SYSKEYUP消息经常由与Alt相组合的按键产生,这些按键启动程序菜单或者系统菜单上的选项,或者用于切换活动窗口等系统功能(Alt-Tab或者Alt-Esc),也可以用作系统菜单快捷键(Alt键与一个功能键相结合,例如Alt-F4用于关闭应用程序) 程序通常忽略WM_SYSKEYUP和WM_SYSKEYDOWN消息,并将它们传送到DefWindowProc。
由于Windows会处理所有Alt键的功能,所以无需拦截这些消息窗口消息处理程序将最后收到关于这些按键结果(如菜单选择)的其它消息 如果想在自己的窗口消息处理程序中加上拦截系统按键的程序代码,那么在处理这些消息之后再传送到DefWindowProc,Windows就仍然可以将它们用于通常的目的32位的变量,包含了识别按下 的键的虚键码,wParam,Backspace、Tab、Enter、Escape和Spacebar通常用于Windows程序不过,Windows一般用字符消息(而不是键盘消息)来处理这些键Windows程序通常不需要监视Shift、Ctrl或Alt键的状态 Windows也包括在主键盘上的字母和数字键的虚拟键码数字和字母的虚拟键码是ASCII码Windows程序几乎从不使用这些虚拟键码;实际上,程序使用的是ASCII码字符的字符消息GetKeyState(),通过调用GetKeyState函数可以知道是否按下了位移键(Shift、Ctrl和Alt)或开关键(Caps Lock、Num Lock和Scroll Lock) 例如: iState = GetKeyState (VK_SHIFT) ; 如果按下了Shift,则iState值为负即设定了最高位置) iState = GetKeyState (VK_CAPITAL) ; 如果Caps Lock键打开iState低位被设为1。
此位与键盘上的小灯保持一致 通常,在使用GetKeyState时,会带有虚拟键码VK_SHIFT、VK_CONTROL和VK_MENU(在说明Alt键时调用)或VK_LSHIFT、VK_RSHIFT、VK_LCONTROL、VK_RCONTROL、VK_LMENU、VK_RMENU这些标识符只用于GetKeyState和GetAsyncKeyState注意:GetKeyState的使用,它并非实时检查键盘状态,而只是检查直到目前为止正在处理的消息的键盘状态如果需要确定使用者是否按下了Shift-Tab,在处理Tab键的WM_KEYDOWN消息时调用GetKeyState,带有参数VK_SHIFT如果GetKeyState传回的值为负,那么就知道在按下Tab键之前按下了Shift键并且,如果在开始处理Tab键之前,已经释放了Shift键也没有关系,因为在按下Tab键的时候Shift键是按下的 GetKeyState不会获得独立于普通键盘消息的键盘信息例如,想暂停窗口消息处理程序的处理,直到您按下F1功能键为止: while (GetKeyState (VK_F1) = 0) ; // WRONG !!! 这将让程序当死(除非在执行此叙述之前早就从消息队列中接收到了F1的WM_KEYDOWN)如果确实需要知道目前某键的状态,那么可以使用GetAsyncKeyState。
重复计数位:重复计数是该消息所表示的按键次数 OEM扫描码:OEM扫描码是由硬件(键盘)产生的代码 扩充键标志:如果按键结果来自IBM增强键盘的附加键之一,那么扩充键旗标为1(IBM增强型键盘有101或102个键对键盘右端的Alt和Ctrl键,以及不是数字键盘那部分的光标移动键(包括Insert和Delete键)、数字键盘上的斜线()和Enter键以及Num Lock键等,此标志均被设定为1 关联码:按键时,假如同时压下ALT键,那么内容代码为1对WM_SYSKEYUP与WM_SYSKEYDOWN而言,此位总视为1;而对WM_KEYUP与WM_KEYDOW消息而言,此位为0但是: 如果活动窗口最小化了,则它没有输入焦点这时候所有的按键都会产生WM_SYSKEYUP和WM_SYSKEYDOWN消息如果Alt键未被按下,则关联码字段被设定为0Windows使用WM_SYSKEYUP和WM_SYSKEYDOWN消息,从而使最小化了的活动窗口不处理这些按键 对于一些外国语文(非英文)键盘,有些字符是通过Shift、Ctrl或者Alt键与其它键相组合而产生的这时内容代码为1,但是此消息并非系统按键消息。
键的先前状态:如果在此之前键是释放的,则键的先前状态为0,否则为1对WM_KEYUP或者WM_SYSKEYUP消息,它总是设定为1;但是对WM_KEYDOWN或者WM_SYSKEYDOWN消息,此位可以为0,也可以为1如果为1,则表示该键是自动重复功能所产生的第二个或者后续消息 转换状态:如果键正被按下,则转换状态为0;如果键正被释放,则转换状态为1对WM_KEYDOWN或者WM_SYSKEYDOWN消息,此字段为0;对WM_KEYUP或者WM_SYSKEYUP消息,此字段为1在WinMain函数的消息循环中包含了TranslateMessage函数,其功能是把按键消息转化为字符消息,但只有当键盘驱动程序把键盘字符映射成ASCII码后才能产生WM_CHAR消息,消息顺序,因为TranslateMessage函数从WM_KEYDOWN和WM_SYSKEYDOWN消息产生了字符消息,所以字符消息是夹在按键消息之间传递给窗口消息处理程序的例如,如果Caps Lock未打开,而使用者按下再释放A键,则窗口消息处理程序将接收到如下表所示的三个消息,如果按下Shift键,再按下A键,然后释放A键,再释放Shift键,就会输入大写的A,而窗口消息处理程序会接收到五个消息, Shift键本身不产生字符消息。
处理控制字符,处理按键和字符消息的基本规则是:如果需要读取输入到窗口的键盘字符,那么可以处理WM_CHAR消息如果需要读取光标键、功能键、Delete、Insert、Shift、Ctrl以及Alt键,那么可以处理WM_KEYDOWN消息通常将Tab、Enter、Backspace和Escape键处理成控制字符 case WM_CHAR: //其它行程序 switch (wParam) case b: // backspace //其它行程序; break ; case t: // tab //其它行程序; break ; case n: // linefeed //其它行程序; break ; case r: // carriage return //其它行程序; break ; default: // character codes //其它行程序; break ; return 0 ;,插入符号(不是光标),当往程序中输入文字时,通常有一个底线、竖条或者方框来指示输入的下一个字符将出现在屏幕上的位置这个标志通常称为光标,但是在Windows下写程序,必须改变这个习惯在Windows中,它称为插入符号。
光标是指表示鼠标位置的那个位图图像 主要有五个插入符号函数: CreateCaret建立与窗口有关的插入符号 SetCaretPos在窗口中设定插入符号的位置 ShowCaret显示插入符号 HideCaret隐藏插入符号 DestroyCaret撤消插入符号 另外还有取得插入符号目前位置(GetCaretPos)和取得以及设定插入符号闪烁时间(GetCaretBlinkTime和SetCaretBlinkTime)的函数在Windows中,插入符号定义为水平线、与字符大小相同的方框,或者与字符同高的竖线如果程序中需要插入符号,那么不应该简单地在窗口消息处理程序的WM_CREATE消息处理期间建立它,然后在WM_DESTROY消息处理期间撤消原因是:一个消息队列只能支持一个插入符号因此,如果程序有多个窗口,那么各个窗口必须有效地共享相同的插入符号只有在窗口有输入焦点时,窗口内显示插入符号才有意义 使用插入符号的主要规则很简单:窗口消息处理程序在WM_SETFOCUS消息处理期间调用CreateCaret,在WM_KILLFOCUS消息处理期间调用DestroyCaret 插入符号刚建立时是隐蔽的。
如果想使插入符号可见,那么在调用CreateCaret之后,窗口消息处理程序还必须调用Sho。
