Symptomen
- In een van uw macro’s gebruikt u herhaaldelijk de opdracht SendKeys om toetsaanslagen naar een programma te sturen. Gewoonlijk werkt u met ingeschakelde NumLock-toets, maar telkens wanneer de macro gedraaid is, staat de NumLock-toets uit.
Remedie
- Leg in het begin van uw macro, zeker vóórdat u de eerste SendKeys-opdracht geeft, vast wat de status van de NumLock-toets is:
Const VK_NUMLOCK = &H90 Private blnIsNumLockOn As Boolean Sub GetToetsStatussen() blnIsNumLockOn = GetKeyState(VK_NUMLOCK) End Sub
- Plaats net voor het einde van de macro de volgende statements:
Sub ResetToetsStatussen() Dim resultaat As Long ' If blnIsScrollLockOn <> _ GetKeyState(VK_SCROLLLOCK) Then ' Application.SendKeys ("{SCROLLLOCK}") ' DoEvents ' End If ' ' If blnIsCapsLockOn <> _ GetKeyState(VK_CAPSLOCK) Then ' Application.SendKeys ("{CAPSLOCK}") ' DoEvents ' End If If blnIsNumLockOn <> _ GetKeyState(VK_NUMLOCK) Then Call clsSendKeys.ZendToetsen _ ("{NUMLOCK}") End If ' resultaat = _ apiSetKeyboardState(vKeys:=VK) End Sub
- Voor het gebruik van de methoden die in deze statements worden gebruikt, is een aantal bibliotheken nodig. Helemaal bovenin de module waarin de macro staat, moet u daarom de volgende statements opnemen:
Private Declare Function GetKeyState Lib _ "user32" (ByVal nVirtKey As Long) As Integer Private Declare Function apiGetKeyboardState _ Lib "user32" Alias "GetKeyboardState" _ (ByRef vKeys() As Byte) As Long Private Declare Function apiSetKeyboardState _ Lib "user32" Alias "SetKeyboardState" _ (ByRef vKeys() As Byte) As Long
Verdieping
Wordt de methode SendKeys meer dan één keer in een macro gebruikt, dan is de kans groot dat de status van de NumLock-toets verandert. Stond deze toets ‘aan’, dan verandert deze in ‘uit’, en andersom.
Hetzelfde geldt voor de toetsen CapsLock en ScrollLock.
De code die onder Remedie is beschreven, vereist de aanwezigheid van een klasse.
- Klik in de VBA-editor op Invoegen.
- Kies Klassenmodule invoegen.
- In de projectmap Klassenmodules wordt nu een nieuwe klasse met de naam Klasse1 ingevoegd.
- Neem de volgende programmacode over in de module:
Private m_colKeyMap As New Collection Private Declare Sub keybd_event Lib _ "user32" _ (ByVal bVk As Byte, _ ByVal bScan As Byte, _ ByVal dwFlags As Long, _ ByVal dwExtraInfo As Long) Private Const KEYEVENTF_EXTENDEDKEY = &H1 Private Const KEYEVENTF_KEYUP = &H2 Private Declare Function VkKeyScanW Lib _ "user32" ( _ ByVal cChar As Integer) As Integer Private Declare Sub CopyMemory Lib _ "kernel32" _ Alias "RtlMoveMemory" (lpvDest As Any, _ lpvSource As Any, ByVal cbCopy As Long) Public Sub ZendToetsen _ (ByVal sKey As String) Dim vKey As Variant vKey = m_colKeyMap(sKey) vKey = KeyCode(sKey) keybd_event vKey, 0, _ KEYEVENTF_EXTENDEDKEY, 0 keybd_event vKey, 0, _ KEYEVENTF_EXTENDEDKEY _ Or KEYEVENTF_KEYUP, 0 End Sub Public Function KeyCode _ (ByVal sChar As String) _ As Variant Dim iKeyCode As Integer Dim b() As Byte Dim iKey As Integer Dim vKey As Variant 'KeyCodeConstants Dim iShift As Variant 'ShiftConstants b = sChar CopyMemory iKey, b(0), 2 iKeyCode = VkKeyScanW(iKey) KeyCode = (iKeyCode And &HFF&) End Function Private Sub Class_Initialize() m_colKeyMap.Add vbKeyNumlock, "NUMLOCK" End Sub
Tips
De bovenstaande klasse is een sterk vereenvoudigde variant van de klasse die nodig is om elke willekeurige serie toetsen te versturen. De volledige versie kunt u op diverse plaatsen op het internet vinden. Bijvoorbeeld op http://www.pinvoke.net/default.aspx/user32.vkkeyscan
Zie ook
Kan een programma het toetsenbord bedienen?