键盘类函数

来源:互联网 发布:网络麻将赌博平台 编辑:程序博客网 时间:2024/05/17 06:37

 


----------------------------------
获得当前整个键盘上所有按键的按下状态:GetKeyBoardState函数
这个函数获得在调用时一刹那,整个键盘上哪些(个)键正处于按下状态。它传入一个包含256个元素的字节数组,在实参中写入数组的第一个元素地址,就会返回整个键盘上256个虚拟键的对应状态到字节数组的相应下标元素中。声明:
Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
调用如:
Dim lxn(0 To 255) As Byte
Private Sub Timer1_Timer()
GetKeyboardState lxn(0)
If lxn(66) And &H80 Then Unload Me
If lxn(65) And &H80 Then MsgBox "你按下了字母A,它的虚拟键值为65."
End Sub
这个函数只一个参数pbKeyState,但很特别:它传入一个字节(Byte)数组,且这个数组应声明为下标0-255共256个元素,如--Dim lxnKey(0 to 255) As Byte。然后在实参写入其第一个元素lxnKey(0):为x=GetKeyboardState(lxnKey(0));这时,整个lxnKey数组就全部被写入了返回值,且是有顺序的--对应按键的值写入对应下标的元素中,如下标为65的元素lxnKey(65)中就放入A键的状态值;lxnKey(66)中放入B键的状态值,lxnKey(49)放入数字1键的状态值等。
每个按键的状态值原本是用二进制值表示的,如果某个键当时正按下,则返回值的位7为1;如已经抬起,则为0;如果开关键打开,则位0设为1(开关键包括CapsLock, NumLock, ScrollLock);说明:位7 ?位0 ?一个字节数用二进制表示有八位,如10010011,从右向左第一位叫位0(相当于十进制的个位),第二位叫位1(相当于十进制中的十位),最左边的就是位7(虽然象有八位--但因第一位从0开始)。也就是说,如果一个按键正按下,那么对应的返回值就为二进制10000000(十进制128或十六进制&H80),但如果此时键盘上有开关键处于打开,则有可能就为10000001(十进制129或十六进制&H81)等。 一般地,我们对有位的内容的,应先想到位操作:--要检测某个二进制值的位7是否为1,只要将它与&H80进行AND操作,然后看结果是否非0就可以了,为什么呢?我们知道,&H80二进制值为10000000,一个数与之进行AND操作:101001 and 1000000,如果这个数的位7不为1,那么结果总是是0的,自己看看便明白,也有一种土办法:直接用十进制值如128,再编一个十进制化二进制的模块来化一下--那可是能检测任意位上的值哦!
------------------------------------------------------
判断是否按下了特定的键:GetKeyState函数
这个函数常用于给程序定义系统级热键,它支持同时检测多个按键是否被一起按下,声明:
Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
参数很简单,只要传入特定键的虚拟键码即可,关于虚拟键码--就是API浏览器中VK_类的常数,而一般字母、数字就用其ASCII码值(注意要用大写字母的ASCII值),如keys=GetKeyState(Asc("A"))不要写成keys=GetKeyState(Asc("a"))!有趣的是也可以检测鼠标按键是否按下,声明键码VK_LBUTTON(左键),VK_RBUTTON(右键)传入即可,如:
Dim keys As Integer
keys = GetKeyState(VK_CONTROL) '检测是否按下Ctrl键
If keys And &H8000 Then '如果按下Ctrl键,则返回值keys的二进制位15值1.
keys = GetKeyState(VK_MENU) '如果接连又按下Alt键.
If keys And &H8000 Then 'keys第15位是否为1,:&H8000=(1000000000000000)2
MsgBox "你同时按下了Ctrl+Alt热键."
End If
End If 
该函数的返回值为一个Integer型数(双字节),要判断是否按下特定键,就看返回值,如果开关键打开,则位0设为1(开关键包括CapsLock, NumLock,ScrollLock);即(0000000000000001)2,如果某键正处于按下状态,则位15为1;即(1000000000000000)2,如已经抬起,则为0。
问题:按函数的说明,该函数应能检测任意一个按键是否被按下,但我却发现它对个别键不能区分,如数字小键盘上的数字键。
-------------------------------------------------------
判断是否正按下特定键:GetAsyncKeyState函数
该函数与GetKeyState函数类似,都是判断特定键是否按下,但好象有一点观念上的不同,GetKeyState应在按过某键之后再调用,判断刚按过了某键,GetAsyncKeyState应在按下某键的同时调用,判断正在按下某键;而且,按一些资料上说,GetAsyncKeyState只限于本程序范围,不是系统级范围,但实际不是这样的,也可用它定义系统级热键。
声明:
Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
参数和返回值都和GetKeyState函数一样。
下面是一个定义热键:Ctrl键+鼠标右键的例子(有趣),当按下Ctrl+鼠标右键时会弹出个对话框,当然用GetKeyState也可以:
Private Sub Timer2_Timer()
Dim keys As Integer
keys = GetAsyncKeyState(VK_CONTROL)
If keys And &H8000 Then
keys = GetAsyncKeyState(VK_RBUTTON)
If keys And &H8000 Then MsgBox "Hello,你好吗?"
End If
End Sub
对该函数返回值的补充:返回值为2字节,自从对GetAsyncKeyState函数的上一次调用以来,如果键已被按过,则位0设为1;否则设为0。如果键目前处于按下状态,则位15设为1;如抬起,则为0。微软的win32手册指出:倘若输入焦点从属于与调用函数的输入线程不同的另一个输入线程,则返回值为0(例如,一旦另一个程序拥有焦点,则它应返回零)。证据显示,函数实际是在整个系统的范围内工作的。 
--------------------------------------------------
查询一个键的扫描码:MapVirtualKeyA函数
该函数根据1个键的虚拟键码返回该键的扫描码,也可根据一个键的扫描码返回该键的虚拟键码,还可以已知虚拟键码求得该键的对应ASCII值。声明:
Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long
第一个参数wCode为已知的一个虚拟键码(如果求的是虚拟键码,则是已知的扫描码值),第二个参数wMapType为0或1或2之一,为0-- 前一参数wCode是个虚拟键码。函数返回相应的扫描码;为1-- 第一个参数wCode是个扫描码。函数返回相应的虚拟键码;为2-- wCode是个虚拟键码。函数返回相应的ASCII值(未加Shift组合键)。
函数返回值就是要求的扫描码(或虚拟键码)。注:对不同类型的键盘,其扫描码是各不相同的,而对到达Windows后的虚拟键码,则所有电脑上全部都统一了。
调用如:我想知道我的这个键盘上的Ctrl键的扫描码是多少。
x& = MapVirtualKey(VK_CONTROL, 0)
Print x&
-------------------------------------------------------
取得键盘上一个键的物理键名:GetKeyNameTextA函数
由于各键盘型号不同,所以要确定一个键盘上具体某个键的名称,要依靠其扫描码,声明:
Declare Function GetKeyNameText Lib "user32" Alias "GetKeyNameTextA" (ByVal lParam As Long, ByVal lpBuffer As String, ByVal nSize As Long) As Long
第一个参数指明一个键的扫描码值,再乘上&H10000,第二个参数指定一个用来装载键名称的字符串缓冲区,第三个参数为缓冲区长度。函数的返回值是实际写入字符串缓冲区的字符数。
调用如:
Private Sub Command1_Click()
Dim abuf As String
abuf = String(255, " ")
x& = MapVirtualKey(VK_CONTROL, 0)
lng& = GetKeyNameText(x& * &H10000, abuf, 255)
Print Left(abuf, lng&)
End Sub
说明:第一个参数为什么要乘上&H10000呢?这是因为其原本是以二进制数来表示的,位0到5=0;位16到23=按键的扫描码;位24=增强型键盘上的扩展位;位25=如设为1,表示忽略左右Shift和Ctrl键的区别。为了使原本在位0-7上的扫描码值x&到位16-23位上去,就要乘上二进制数1000000000000000(16个0)--十六进制值就是&H10000。
-----------------------------------------------------------------------
模拟击键动作:keybd_event过程
模拟在键盘上按下或抬起了哪个键,要同时传入键的虚拟键码和扫描码(实验中我发现可以不要扫描码),由于按下按键和抬起按键是两个动作,因此对于单击键,应分两次调用函数,第二次调用时将第三个参数设为2,表示抬起。注意对于一些功能键,如Ctrl和Alt等,必须分两次调用函数(实际上,任一键都应调用两次为妥,因为都会保持按下状态,只是别的键嘛,因是虚拟键,与物理键还是有点不同,无妨碍)。声明:
Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
参数如下:
bVk: Byte,欲模拟的虚拟键码 
bScan: Byte,键的OEM扫描码 
dwFlags: Long,零;或设为下述两个标志之一 
KEYEVENTF_EXTENDEDKEY(值1) 指出是一个扩展键,且在前面冠以0xE0代码 
KEYEVENTF_KEYUP(值2) 模拟松开一个键 
dwExtraInfo: Long,零。通常不用的一个值。api函数GetMessageExtraInfo可取得这个值。允许使用的值取决于特定的驱动程序。
调用如:模拟单击空格键。
x& = MapVirtualKeyA(VK_SPACE, 0)
keybd_event VK_SPACE, x&, 0, 0 '单击空格键。
再如模拟Ctrl+V键:
x& = MapVirtualKeyA(VK_CONTROL, 0)
keybd_event VK_CONTROL, x&, 0, 0 '按下Ctrl,它自动保持按下状态。
keybd_event vbKeyV, 0, 0, 0 '单击V键,这里直接用VB常数,且扫描码也无,简便法。
keybd_event VK_CONTROL, x&, 2, 0 '抬起Ctrl键。
再如抓取活动窗口(Alt+Print Screen键):
keybd_event VK_MENU, 0, 0, 0
keybd_event VK_SNAPSHOT, 0, 0, 0 
keybd_event VK_MENU, 0, 2, 0
(抓屏是直接按Print Screen键即可,只抓取活动窗口就要同时按Alt键。)
也可模拟其他特殊键,如Windows键的虚拟键码值为91(在API浏览器中查不到),直接用:keybd_event 91, 0, 0, 0
keybd_event 91, 0, 2, 0 可以弹出"开始"菜单,因为是在"抬起"按键时会弹出,所以要调用两次。只要知道虚拟键码,我们就可以模拟任何的击键动作,所有的虚拟键码值(普通十进制)如下:
--------第一排F键和主键盘上键---------
F1-F12键:值从112-123。 主键盘上数字0-9键:值从48-57。
字母A-Z键:值从65-90。 ESC键:值27。
"~"符号键:值192。 "-"减号键:189。 
"="等号键:187。 " / "键:220。
退格键Backspace:8。 TAB键:9。
"["左中括号键:219。 "]"右中括号键:221。
回车键Enter:13. 大小写转换键Caps Lock:20。
";"分号键:186。 "'"引号键:222。
Shift键:16。(也可另只指左Shift键:160,只指右Shift键:161。)
","逗号键:188。 "。"句号键:190。
"/"键:191。 
Ctrl键:17。(也可左:162;右:163)Alt键:18。(也可左:164;右:165)
Windows键:左:91;右:92。 
------功 能 键---------
上下左右键头键:左:37;上:38:右:39;下:40。
Sleep进入休眠键:95。
Print Screen抓屏键:44。 Scroll Lock键:145。
Insert插入键:45。 Delete删除键:46。
Home开始位置键:36。 END结束位置键:35。
Page Up向上翻页键:33。 Page Down向下翻页键:34。
------数字小键盘上的键-------
NumLock键:144。 "/"号键:111。
"*"号键:106。 "-"号键:109。
"+"号键:107。 回车键:13。
其余键分两种情况,当NumLock键关上时:
Num 1键:35。 Num 2键:40。 Num 3键:34。 Num 4键:37。 Num 5键:12。Num 6键:39。 Num 7键:36。 Num 8键:38。 Num 9键:33。 Num 0键:45。
Del键:46。
当NumLock键打开时:(键盘上Numlock指示灯亮)
Num 1键:97。 Num 2键:98。 Num 3键:99。 Num 4键:100。 Num 5键:101。Num 6键:102。 Num 7键:103。 Num 8键:104。 Num 9键:105。 Num 0键:96。
Del键:110。
-----鼠 标 键------- 
鼠标左键:值1。 鼠标右键:值2。 
主要就是以上这些,这可是我自己用GetKeyboardState函数试出来的。