简体   繁体   中英

Send Keys is Disabling NumLock

Issue:<\/h2>

Upon me using SendKeys<\/code> to copy data from an Excel application to another (non-Microsoft) application, my Num Lock becomes disabled.

<\/h2>

What can be done to prevent my code from disabling the NumLock - or how can I go about re-enabling numlock once my code completes?

"

Use this to turn numlock back on. I forget where I found this on the internet. I did not author it.

NumLockClass

Place this in a class module.

Option Explicit

' API declarations
#If VBA7 And Win64 Then
    Private Declare PtrSafe Function GetVersionEx Lib "Kernel32" _
        Alias "GetVersionExA" _
        (lpVersionInformation As OSVERSIONINFO) As Long

    Private Declare PtrSafe Sub keybd_event Lib "user32" _
        (ByVal bVk As Byte, _
        ByVal bScan As Byte, _
        ByVal dwflags As Long, ByVal dwExtraInfo As Long)

    Private Declare PtrSafe Function GetKeyboardState Lib "user32" _
        (pbKeyState As Byte) As Long

    Private Declare PtrSafe Function SetKeyboardState Lib "user32" _
        (lppbKeyState As Byte) As Long
#Else
    Private Declare Function GetVersionEx Lib "Kernel32" _
        Alias "GetVersionExA" _
        (lpVersionInformation As OSVERSIONINFO) As Long

    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 Function GetKeyboardState Lib "user32" _
        (pbKeyState As Byte) As Long

    Private Declare Function SetKeyboardState Lib "user32" _
        (lppbKeyState As Byte) As Long
#End If

' Type declaration
Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type


'Constant declarations
Const VK_NUMLOCK = &H90
Const VK_SCROLL = &H91
Const VK_CAPITAL = &H14
Const KEYEVENTF_EXTENDEDKEY = &H1
Const KEYEVENTF_KEYUP = &H2

Property Get value() As Boolean
'   Get the current state
    Dim keys(0 To 255) As Byte
    GetKeyboardState keys(0)
    value = keys(VK_NUMLOCK)
End Property

Property Let value(boolVal As Boolean)
    Dim o As OSVERSIONINFO
    Dim keys(0 To 255) As Byte
    o.dwOSVersionInfoSize = Len(o)
    GetVersionEx o
    GetKeyboardState keys(0)
'   Is it already in that state?
    If boolVal = True And keys(VK_NUMLOCK) = 1 Then Exit Property
    If boolVal = False And keys(VK_NUMLOCK) = 0 Then Exit Property
'   Toggle it
    'Simulate Key Press
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
    'Simulate Key Release
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or _
      KEYEVENTF_KEYUP, 0
End Property

Sub Toggle()
'   Toggles the state
    Dim o As OSVERSIONINFO
    o.dwOSVersionInfoSize = Len(o)
    GetVersionEx o
    Dim keys(0 To 255) As Byte
    GetKeyboardState keys(0)
    'Simulate Key Press
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
    'Simulate Key Release
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or _
      KEYEVENTF_KEYUP, 0
End Sub

Use it like:

Dim numLock As New NumLockClass
If numLock.value = False Then numLock.value = True  'turn it back on

Based on findwindow 's answer, I did some code optimization and simplified usage, so now you have the global Numlock property instead of needing a class object:

NumLock module:

Option Explicit

' API declarations
#If VBA7 And Win64 Then
    Private Declare PtrSafe Function GetVersionEx Lib "Kernel32" Alias "GetVersionExA" _
                                (lpVersionInformation As OSVERSIONINFO) As Long
    Private Declare PtrSafe Sub keybd_event Lib "user32" ( _
                                ByVal bVk As Byte, _
                                ByVal bScan As Byte, _
                                ByVal dwflags As Long, ByVal dwExtraInfo As Long)
    Private Declare PtrSafe Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
    Private Declare PtrSafe Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As Long
#Else
    Private Declare Function GetVersionEx Lib "Kernel32" Alias "GetVersionExA" _
                                (lpVersionInformation As OSVERSIONINFO) As Long
    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 Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long
    Private Declare Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As Long
#End If

' Type declaration
Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type

'Constant declarations
Private Const VK_NUMLOCK = &H90
Private Const VK_SCROLL = &H91
Private Const VK_CAPITAL = &H14
Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2

'===================================================================
'PROPERTIES
'

'=========================================
'Returns the current Numlock state
Public Property Get Numlock() As Boolean
    Numlock = Numlock_State
End Property

'=========================================
'Sets the Numlock state
'   true = turn numlock on
'   false = turn numlock off
Public Property Let Numlock(State As Boolean)
    If State <> Numlock_State Then Numlock_Toggle
End Property

'===================================================================
'METHODS
'

'=========================================
'Returns the current Numlock state
Private Function Numlock_State() As Boolean
    Dim keys(0 To 255) As Byte
    GetKeyboardState keys(0)
    Numlock_State = keys(VK_NUMLOCK)
End Function

'=========================================
'Sets the Numlock state
'
'   State:  true = turn numlock on
'           false = turn numlock off
Private Sub Numlock_Set(State As Boolean)
    If State <> Numlock_State Then Numlock_Toggle
End Sub

'=========================================
'Toggles the Numlock state
Public Sub Numlock_Toggle()
    'Simulate Numlock key Press
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
    'Simulate Numlock key Release
    keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or _
      KEYEVENTF_KEYUP, 0
End Sub

Usage examples:

Public Sub Example()
    'Turn Numlock on:
    Numlock = True

    'Turn Numlock off:
    Numlock = False
    
    'Check Numlock state:
    Dim IsOn As Boolean
    IsOn = Numlock
    
    'Toggle Numlock state:
    Numlock_Toggle
End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM