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." |