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

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

  1. Klik in de VBA-editor op Invoegen.
  2. Kies Klassenmodule invoegen.
  3. In de projectmap Klassenmodules wordt nu een nieuwe klasse met de naam Klasse1 ingevoegd.
  4. 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?