Keys |
| Description: | |
| This class simulates keystrokes using the keybd_event API. If offers two advantages over SendKeys. First, it doesn't cause the num lock light to flicker unless you specifically press the num lock key. Secondly, it's possible to press and hold a key. 8/5/1999: Added scan codes, allowing the keystrokes to be sent to a dos window. 9/29/1999: Added compatibility flag to PressKeyVK to attempt to make extended keys work with some dos applications. 11/29/1999: Added PressSendKeys function, which attempts to parse SendKeys() style commands. | |
| Code: | |
'--------- Class Name: clsKeys
Option Explicit
Private Declare Function MapVirtualKey Lib "user32" Alias _
"MapVirtualKeyA" (ByVal wCode As Long, _
ByVal wMapType As Long) As Long
Private Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" (ByVal _
cChar As Byte) As Integer
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal _
bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As _
Long) As Integer
Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2
Public Enum enumKeys
keyBackspace = &H8
keyTab = &H9
keyReturn = &HD
keyShift = &H10
keyControl = &H11
keyAlt = &H12
keyPause = &H13
keyEscape = &H1B
keySpace = &H20
keyPageUp = &H21
keyPageDown = &H22
keyEnd = &H23
keyHome = &H24
keyLeft = &H25
KeyUp = &H26
keyRight = &H27
KeyDown = &H28
keyInsert = &H2D
keyDelete = &H2E
keyF1 = &H70
keyF2 = &H71
keyF3 = &H72
keyF4 = &H73
keyF5 = &H74
keyF6 = &H75
keyF7 = &H76
keyF8 = &H77
keyF9 = &H78
keyF10 = &H79
keyF11 = &H7A
keyF12 = &H7B
keyNumLock = &H90
keyScrollLock = &H91
keyCapsLock = &H14
End Enum
'Presses the single key represented by sKey
Public Sub PressKey(sKey As String, Optional bHold As Boolean, Optional _
bRelease As Boolean)
Dim nVK As Long
nVK = VkKeyScan(Asc(sKey))
If nVK = 0 Then
Exit Sub
End If
Dim nScan As Long
Dim nExtended As Long
nScan = MapVirtualKey(nVK, 2)
nExtended = 0
If nScan = 0 Then
nExtended = KEYEVENTF_EXTENDEDKEY
End If
nScan = MapVirtualKey(nVK, 0)
Dim bShift As Boolean
Dim bCtrl As Boolean
Dim bAlt As Boolean
bShift = (nVK And &H100)
bCtrl = (nVK And &H200)
bAlt = (nVK And &H400)
nVK = (nVK And &HFF)
If Not bRelease Then
If bShift Then
keybd_event enumKeys.keyShift, 0, 0, 0
End If
If bCtrl Then
keybd_event enumKeys.keyControl, 0, 0, 0
End If
If bAlt Then
keybd_event enumKeys.keyAlt, 0, 0, 0
End If
keybd_event nVK, nScan, nExtended, 0
End If
If Not bHold Then
keybd_event nVK, nScan, KEYEVENTF_KEYUP Or nExtended, 0
If bShift Then
keybd_event enumKeys.keyShift, 0, KEYEVENTF_KEYUP, 0
End If
If bCtrl Then
keybd_event enumKeys.keyControl, 0, KEYEVENTF_KEYUP, 0
End If
If bAlt Then
keybd_event enumKeys.keyAlt, 0, KEYEVENTF_KEYUP, 0
End If
End If
End Sub
'Loop through a string and calls PressKey for each character (Does not
' parse strings like SendKeys)
Public Sub PressString(ByVal sString As String, _
Optional bDoEvents As Boolean = True)
Do While sString <> ""
PressKey Mid(sString, 1, 1)
Sleep 20
If bDoEvents Then
DoEvents
End If
sString = Mid(sString, 2)
Loop
End Sub
'Presses a specific key (this is used for keys that don't have a
' ascii equilivant)
Public Sub PressKeyVK(keyPress As enumKeys, Optional bHold As Boolean, _
Optional bRelease As Boolean, Optional bCompatible As Boolean)
Dim nScan As Long
Dim nExtended As Long
nScan = MapVirtualKey(keyPress, 2)
nExtended = 0
If nScan = 0 Then
nExtended = KEYEVENTF_EXTENDEDKEY
End If
nScan = MapVirtualKey(keyPress, 0)
If bCompatible Then
nExtended = 0
End If
If Not bRelease Then
keybd_event keyPress, nScan, nExtended, 0
End If
If Not bHold Then
keybd_event keyPress, nScan, KEYEVENTF_KEYUP Or nExtended, 0
End If
End Sub
'Returns (in the boolean variables) the status of the various Lock keys
Public Sub GetLockStatus(bCapsLock As Boolean, bNumLock As Boolean, _
bScrollLock As Boolean)
bCapsLock = GetKeyState(enumKeys.keyCapsLock)
bNumLock = GetKeyState(enumKeys.keyNumLock)
bScrollLock = GetKeyState(enumKeys.keyScrollLock)
End Sub
'Presses a sequence of keys, attempts to parse strings like
'SendKeys() does.
Public Sub PressSendKeys(ByVal sKeys As String)
Dim nPos As Long
Dim sPart As String
Dim colModify As Collection: Set colModify = New Collection
Dim bBrace As Boolean
Dim i As Long
Dim nCount As Long
Dim nVK As Long
nPos = 1
Do While nPos <= Len(sKeys)
Select Case UCase(Mid(sKeys, nPos, 1))
Case "+", "^", "%"
If Mid(sKeys, nPos, 1) = "+" Then
nVK = keyShift
ElseIf Mid(sKeys, nPos, 1) = "^" Then
nVK = keyControl
Else 'Mid(sKeys, nPos, 1) = "%" then
nVK = keyAlt
End If
PressKeyVK nVK, True
colModify.Add nVK
If Mid(sKeys, nPos + 1, 1) <> "(" And Mid(sKeys, _
nPos + 1, 1) <> "{" Then
sKeys = Mid(sKeys, 1, nPos) & "(" & Mid(sKeys, _
nPos + 1, 1) & ")" & Mid(sKeys, nPos + 2)
End If
Case "~" 'enter
PressKeyVK keyReturn
Case "("
'do nothing
Case ")", "}"
If colModify.Count > 0 Then
If colModify.Item(colModify.Count) <> 0 Then
PressKeyVK colModify.Item(colModify.Count) _
, , True
End If
colModify.Remove colModify.Count
End If
Case "{" 'Brace
colModify.Add 0
nCount = 0
FindSpecial nPos, sKeys, sPart, nCount, nVK
If Mid(sKeys, nPos, 1) = " " Then
nCount = 0
Do Until Mid(sKeys, nPos, 1) = "}" Or _
nPos > Len(sKeys)
nCount = (nCount * 10) + _
Val(Mid(sKeys, nPos, 1))
nPos = nPos + 1
Loop
Else
nCount = 1
End If
For i = 1 To nCount
If nVK = 0 Then
PressKey sPart
Else
PressKeyVK nVK
DoEvents
End If
Next
nPos = nPos - 1
Case Else
PressKey Mid(sKeys, nPos, 1)
End Select
DoEvents
nPos = nPos + 1
Loop
End Sub
Private Sub FindSpecial(nPos As Long, sKeys As String, _
sPart As String, nCount As Long, nVK As Long)
Dim bFound As Boolean
nCount = 1
nVK = 0
sPart = ""
nPos = nPos + 1
bFound = True
Select Case UCase(Mid(sKeys, nPos, 2))
Case "BS": nVK = keyBackspace
Case "UP": nVK = KeyUp
Case "F1": nVK = keyF1
Case "F2": nVK = keyF2
Case "F3": nVK = keyF3
Case "F4": nVK = keyF4
Case "F5": nVK = keyF5
Case "F6": nVK = keyF6
Case "F7": nVK = keyF7
Case "F8": nVK = keyF8
Case "F9": nVK = keyF9
Case Else
bFound = False
End Select
If bFound Then
nPos = nPos + 2
Exit Sub
End If
bFound = True
Select Case UCase(Mid(sKeys, nPos, 3))
Case "F10": nVK = keyF10
Case "F11": nVK = keyF11
Case "F12": nVK = keyF12
Case "DEL": nVK = keyDelete
Case "END": nVK = enumKeys.keyEnd
Case "ESC": nVK = enumKeys.keyEscape
Case "INS": nVK = enumKeys.keyInsert
Case "TAB": nVK = enumKeys.keyTab
Case Else
bFound = False
End Select
If bFound Then
nPos = nPos + 3
Exit Sub
End If
bFound = True
Select Case UCase(Mid(sKeys, nPos, 4))
Case "BKSP": nVK = enumKeys.keyBackspace
Case "DOWN": nVK = enumKeys.KeyDown
Case "HOME": nVK = enumKeys.keyHome
Case "LEFT": nVK = enumKeys.keyLeft
Case "PGDN": nVK = enumKeys.keyPageDown
Case "PGUP": nVK = enumKeys.keyPageUp
Case Else
bFound = False
End Select
If bFound Then
nPos = nPos + 4
Exit Sub
End If
bFound = True
Select Case UCase(Mid(sKeys, nPos, 5))
Case "ENTER": nVK = enumKeys.keyReturn
Case "RIGHT": nVK = enumKeys.keyRight
Case Else
bFound = False
End Select
If bFound Then
nPos = nPos + 5
Exit Sub
End If
bFound = True
Select Case UCase(Mid(sKeys, nPos, 6))
Case "DELETE": nVK = enumKeys.keyInsert
Case "INSERT": nVK = enumKeys.keyDelete
Case Else
bFound = False
End Select
If bFound Then
nPos = nPos + 6
Exit Sub
End If
If UCase(Mid(sKeys, nPos, 7)) = "NUMLOCK" Then
nVK = enumKeys.keyNumLock
nPos = nPos + 7
Exit Sub
End If
If UCase(Mid(sKeys, nPos, 8)) = "CAPSLOCK" Then
nVK = enumKeys.keyCapsLock
nPos = nPos + 8
Exit Sub
End If
If UCase(Mid(sKeys, nPos, 9)) = "BACKSPACE" Then
nVK = enumKeys.keyBackspace
nPos = nPos + 9
Exit Sub
End If
If UCase(Mid(sKeys, nPos, 10)) = "SCROLLLOCK" Then
nVK = enumKeys.keyScrollLock
nPos = nPos + 10
Exit Sub
End If
nVK = 0
sPart = Mid(sKeys, nPos, 1)
nPos = nPos + 1
End Sub
'--------- End of class: clsKeys
| |
| Sample Usage: | |
Dim keys As New clsKeys
Dim bCapsLock As Boolean
keys.GetLockStatus bCapsLock, True, True
If bCapsLock Then
keys.PressKeyVK keyCapsLock
End If
keys.PressString "Now is the time for all good men to come to " & _
"the aid of their country."
| |