Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 810
  • Last Modified:

CTRL + Numlock key (Guru's on systemwide keys)

Hi Experts,

I'm able to block system wide keys using this project

http://vbnet.mvps.org/index.html?code/hooks/lowlevelkeyboardproc.htm

I able to block ctrl.
I able to block numlock.

Problem is I can't block "Ctrl + numlock".

Please kindly guide me how to implement to block "Ctrl + numlock". vb6

Private Const VK_NUMLOCK = &H90

Thanks.

already tried this too:
http://www.vbaccelerator.com/home/VB/Code/Libraries/Subclassing/Registered_Hotkeys/article.asp
couldn't catch ctrl+numlock
0
lynnton
Asked:
lynnton
  • 15
  • 13
  • 3
2 Solutions
 
nffvrxqgrcfqvvcCommented:
Option Explicit

Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer


Private Const VER_PLATFORM_WIN32_NT = 2
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VK_NUMLOCK = &H90
Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2

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

' API declarations:

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
Public Function NumLockOn() As Boolean
    Dim iKeyState As Integer
    iKeyState = GetKeyState(vbKeyNumlock)
    NumLockOn = (iKeyState = 1 Or iKeyState = -127)
End Function
Public Sub ToggleNumLock(TurnOn As Boolean)

    'To turn numlock on, set turnon to true
    'To turn numlock off, set turnon to false
   
      Dim bytKeys(255) As Byte
      Dim bnumLockOn As Boolean
     
'Get status of the 256 virtual keys
      GetKeyboardState bytKeys(0)
     
      bnumLockOn = bytKeys(VK_NUMLOCK)
      Dim typOS As OSVERSIONINFO
     
      If bnumLockOn <> TurnOn Then 'if current state <>
                                     'requested stae
       
       If typOS.dwPlatformId = _
           VER_PLATFORM_WIN32_WINDOWS Then  '=== Win95/98

          bytKeys(VK_NUMLOCK) = 1
          SetKeyboardState bytKeys(0)

        Else    '=== WinNT/2000

        '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 If
      End If
     
End Sub

Private Sub Timer1_Timer()
If NumLockOn = True Then
'Disable control key here
Call ToggleNumLock(False)
DoEvents
End If

End Sub
0
 
nffvrxqgrcfqvvcCommented:
add the following code to a form_
add 1 timer
set its interval to 10
0
 
nffvrxqgrcfqvvcCommented:
I mean this is an example:

What you should really do is check if the CTRL is press than turn off the numlock key

Private Sub Timer1_Timer()
If CTRLkey was pressed Then
'Disable control key here
Call ToggleNumLock(False)
DoEvents
End If
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
nffvrxqgrcfqvvcCommented:
may I ask what CTRL + numlock does, because when I use CTRL + numlock the light does not even show..if i use an other combination besides CTRL + numlock the numock light shows.  U might not be able to use CTRL + Numlock you need to look into this.
0
 
nffvrxqgrcfqvvcCommented:
Also want to mention that if the numlock keys is on and you hold down ctrl you can't toggle the numlock key so evidentally when you use CTRL with the numlock key it blocks and keyboard interaction
0
 
nffvrxqgrcfqvvcCommented:
0
 
lynntonAuthor Commented:
egl1044,

Ctrl+numlock is a unique combination, if you could kindly guide me how we can block it, i would really appreciate it.

Thanks.
0
 
lynntonAuthor Commented:
egl1044,

>>What you should really do is check if the CTRL is press than turn off the numlock key<<

The numlock key is already killed by the posted link. Ctrl+numlock sends a different combination.

Thanks.

0
 
nffvrxqgrcfqvvcCommented:
Use the link I provided above download the project and just change to use the numlock key

Private Const VK_NUMLOCK = &H90
0
 
lynntonAuthor Commented:
egl1044,

Sad to say already did, unfortunately it was blocking all the system keys. including crtl+numlock.

Can we only block ctrl+numlock?

Thanks.
0
 
nffvrxqgrcfqvvcCommented:
Just change the module to this:


Option Explicit



Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Const HC_ACTION = 0
Public Const WM_KEYDOWN = &H100
Public Const WM_KEYUP = &H101
Public Const WM_SYSKEYDOWN = &H104
Public Const WM_SYSKEYUP = &H105
Public Const VK_TAB = &H9
Public Const VK_ESCAPE = &H1B
Public Const VK_NUMLOCK = &H90

Public Const VK_CONTROL = &H11  'CTRL key


Public Const VK_LWIN = &H5B  'Left Windows key (Microsoft® Natural® keyboard)
Public Const VK_RWIN = &H5C  'Right Windows key (Natural keyboard)
Public Const VK_APPS = &H5D  'Applications key (Natural keyboard)



Public Const WH_KEYBOARD_LL = 13
Public Const LLKHF_ALTDOWN = &H20

Public Type KBDLLHOOKSTRUCT
    vkCode As Long
    scanCode As Long
    flags As Long
    time As Long
    dwExtraInfo As Long
End Type

Dim p As KBDLLHOOKSTRUCT

Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   Dim fEatKeystroke As Boolean
   
   If (nCode = HC_ACTION) Then
      If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Or wParam = WM_KEYUP Or wParam = WM_SYSKEYUP Then
         CopyMemory p, ByVal lParam, Len(p)
         fEatKeystroke = _
            p.vkCode = VK_LWIN Or _
            p.vkCode = VK_RWIN Or _
            p.vkCode = VK_CONTROL Or _
            p.vkCode = VK_NUMLOCK Or _
            ((GetKeyState(VK_CONTROL) And &H90) <> 0) Or _
            ((p.flags And LLKHF_ALTDOWN) <> 0)
        End If
    End If
   
    If fEatKeystroke Then
        LowLevelKeyboardProc = -1
    Else
        'LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
    End If
End Function


0
 
nffvrxqgrcfqvvcCommented:
make sure before you end the application that you un-check the checkbox to unhook the keyboard..

0
 
nffvrxqgrcfqvvcCommented:
You could use a command button instead of the checkbox..
0
 
nffvrxqgrcfqvvcCommented:
0
 
lynntonAuthor Commented:
egl1044,

Problem is we are also block all the hotkeys like ctrl, alt, ctrl+esc and etc.

can we soley block ctrl+numlock ?

Thanks.
0
 
nffvrxqgrcfqvvcCommented:
Why can't you just block the numlock key if CTRL is pressed?
0
 
nffvrxqgrcfqvvcCommented:
Option Explicit

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 GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Const VK_CONTROL = &H11

Private Sub Command1_Click()
   Static bVal As Boolean
   bVal = Not bVal
   SetNumState bVal
End Sub

Private Function IsNumOn() As Boolean
   IsNumOn = IsBitSet(GetKeyState(vbKeyNumlock), 0)
End Function

Private Sub SetNumState(Optional ByVal bOn As Boolean = True)
  If IsNumOn <> bOn Then
     keybd_event vbKeyNumlock, &H45, 1, 3
     keybd_event vbKeyNumlock, &H45, 3, 0
  End If
End Sub

Private Function IsBitSet(iBitString As Long, ByVal lBitNo As Integer) As Boolean
    If lBitNo = 31 Then
        IsBitSet = iBitString < 0
    Else
        IsBitSet = iBitString And (2 ^ lBitNo)
    End If
End Function

Private Sub Form_Activate()
Call SetNumState(False)
End Sub

Private Sub Form_Load()
Call SetNumState(False)
End Sub


Private Sub Timer1_Timer()
If GetKeyState(VK_CONTROL) = 1 Then
     'or disable/lock numlock key numlock
     Call SetNumState(False)
   End If
DoEvents
End Sub
0
 
lynntonAuthor Commented:
egl1044,

Ctrl +numlock sends a different key. blocking the numlock doesn't work.(already tried it in the first post).

to test weather ctrl numlock is disabled:
open a cmd prompt >tracert yahoo.com >press ctrl+numlock

Thanks.
0
 
lynntonAuthor Commented:
egl1044,

The code below blocks ctrl+numlock, it we could tweak it a little to open other hotkeys like "ctrl", "numlock", "alt"
it would be then perfect.

Thanks


   If (nCode = HC_ACTION) Then
      If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Or wParam = WM_KEYUP Or wParam = WM_SYSKEYUP Then
         CopyMemory p, ByVal lParam, Len(p)
         fEatKeystroke = _
            p.vkCode = VK_NUMLOCK Or _
            ((GetKeyState(VK_CONTROL) And &H8000) <> 0) Or _
            ((p.flags And LLKHF_ALTDOWN) <> 0)
        End If
    End If
0
 
nffvrxqgrcfqvvcCommented:
Change it to this then: This works I just tested it using tracert

Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   Dim fEatKeystroke As Boolean
   
   If (nCode = HC_ACTION) Then
      If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Or wParam = WM_KEYUP Or wParam = WM_SYSKEYUP Then
         CopyMemory p, ByVal lParam, Len(p)
         fEatKeystroke = _
            p.vkCode = VK_LWIN Or _
            p.vkCode = VK_RWIN Or _
            p.vkCode = VK_CONTROL Or _
            p.vkCode = VK_NUMLOCK Or _
            ((GetKeyState(VK_NUMLOCK) And &H90)) Or _
            ((p.flags And VK_CONTROL) <> 0)
        End If
    End If
   
    If fEatKeystroke Then
        LowLevelKeyboardProc = -1
    Else
        LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
    End If
End Function
0
 
lynntonAuthor Commented:
egl1044,

We are almost there!!! Great idea !!! no doubt one of the best.

The code below disables ctrl+numlock, sadly it also block
"page up"
"page down"
"enter key on numpad"
"->" (left arrow)
"<-" (right arrow)

Please kindly guide me how can we enable those keys

Thanks.

         fEatKeystroke = _
            p.vkCode = VK_NUMLOCK Or _
            (p.flags And (VK_CONTROL) <> 0)
0
 
nffvrxqgrcfqvvcCommented:
Once you issue the unhook command the keys are enabled again.
0
 
lynntonAuthor Commented:
egl1044,

Yes that is correct, once we issue the unhook command, the keys are enabled again, unfortunately we need the other keys open while blocking ctrl+numlock.


Thanks.
0
 
lynntonAuthor Commented:
egl1044,

Is it possible to add a condition that, if these key are press, dont block it..

Thanks.
0
 
ArkCommented:
Take a look on my sample at http://www.freevbcode.com/ShowCode.Asp?ID=1610

Ctrl+Num produce "pause" key
Just add to sh_KeyDown and sh_KeyUp events

Private Sub sh_KeyDown(hWin As Long, KeyCode As Integer, Shift As Integer)
   If KeyCode = vbKeyPause Then
      Debug.Print "Ctrl+Num blocked"
      KeyCode = 0
      Exit Sub
   End If
End Sub

'Same for sh_KeyUp

Regards
Ark
0
 
lynntonAuthor Commented:
Ark,

Amazing it did catch it, is it possible if you could kindly guide me which function, api, module and etc we only need inorder to get this detect the ctrl+numlock?

Thanks.
0
 
lynntonAuthor Commented:
Ark,

The project I've downloaded has frmTest, mHook.bas, and cSystemHook.

Thanks.
0
 
ArkCommented:
Hi
IMHO, code size is not too large. You can just add bas and cls modules to your project, then at any of your form code:

Dim WithEvents sh As cSystemHook

Private Sub Form_Load()
  '.....Your code
   Set sh = New cSystemHook
   sh.SetHook
  '.....Your code
End Sub

Private Sub Form_Unload(Cancel As Integer)
  '.....Your code
   sh.RemoveHook
   Set sh = Nothing
  '.....Your code
End Sub

Private Sub sh_KeyDown(hWin As Long, KeyCode As Integer, Shift As Integer)
   If KeyCode = vbKeyPause Then
      Debug.Print "Ctrl+Num blocked"
      KeyCode = 0
   End If
End Sub

Private Sub sh_KeyUp(hWin As Long, KeyCode As Integer, Shift As Integer)
   If KeyCode = vbKeyPause Then
      Debug.Print "Ctrl+Num blocked"
      KeyCode = 0
   End If
End Sub

If you want to eleminate code size, you can remove all mouse-dependent and system-keys staff from class module:
'Class module:
Option Explicit

Public Event KeyDown(hWin As Long, KeyCode As Integer, Shift As Integer)
Public Event KeyUp(hWin As Long, KeyCode As Integer, Shift As Integer)

Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function GetAsyncKeyState% Lib "user32" (ByVal vKey As Long)
Private Declare Function GetFocus Lib "user32" () As Long

Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101

Private Const WH_JOURNALRECORD = 0
Private Const WH_GETMESSAGE = 3

Private Type EVENTMSG
     wMsg As Long
     lParamLow As Long
     lParamHigh As Long
     msgTime As Long
     hWndMsg As Long
End Type

Dim EMSG As EVENTMSG

Public Function SetHook() As Boolean
   If hJournalHook = 0 Then hJournalHook = SetWindowsHookEx(WH_JOURNALRECORD, AddressOf JournalRecordProc, App.hInstance, 0)
   If hAppHook = 0 Then hAppHook = SetWindowsHookEx(WH_GETMESSAGE, AddressOf AppHookProc, App.hInstance, App.ThreadID)
   SetHook = True
End Function

Public Sub RemoveHook()
   UnhookWindowsHookEx hAppHook
   UnhookWindowsHookEx hJournalHook
End Sub

Private Sub Class_Initialize()
  SHptr = ObjPtr(Me)
End Sub

Private Sub Class_Terminate()
  If hJournalHook Or hAppHook Then RemoveHook
End Sub

Public Function FireEvent(ByVal lParam As Long)
  Dim i%, j%, k%
  Dim s As String
  If lParam = WM_CANCELJOURNAL Then
     hJournalHook = 0
     SetHook
     Exit Function
  End If
 
  CopyMemory EMSG, ByVal lParam, Len(EMSG)
  Select Case EMSG.wMsg
    Case WM_KEYDOWN
         j = 0
         If GetAsyncKeyState(vbKeyShift) Then j = (j Or 1)        'fixed by JJ
         If GetAsyncKeyState(vbKeyControl) Then j = (j Or 2)      'fixed by JJ
         If GetAsyncKeyState(vbKeyMenu) Then j = (j Or 4)         'fixed by JJ
         s = Hex(EMSG.lParamLow)
         k = (EMSG.lParamLow And &HFF)
         RaiseEvent KeyDown(GetFocus, k, j)
         s = Left$(s, 2) & Right$("00" & Hex(k), 2)               'fixed by JJ
         EMSG.lParamLow = CLng("&h" & s)
         CopyMemory ByVal lParam, EMSG, Len(EMSG)
    Case WM_KEYUP
         j = 0                                                    'fixed by JJ
         If GetAsyncKeyState(vbKeyShift) Then j = (j Or 1)        'fixed by JJ
         If GetAsyncKeyState(vbKeyControl) Then j = (j Or 2)      'fixed by JJ
         If GetAsyncKeyState(vbKeyMenu) Then j = (j Or 4)         'fixed by JJ
         s = Hex(EMSG.lParamLow)
         k = (EMSG.lParamLow And &HFF)
         RaiseEvent KeyUp(GetFocus, k, j)
         s = Left$(s, 2) & Right$("00" & Hex(k), 2)               'fixed by JJ
         EMSG.lParamLow = CLng("&h" & s)
         CopyMemory ByVal lParam, EMSG, Len(EMSG)
    Case Else
  End Select
End Function
0
 
lynntonAuthor Commented:
Ark,

I've pasted into the form and left everything untouch on the bas ad class. Unfortunately, nothing happend whne I press ctrl+numlock and also tried vbKeyP.

When closing the program error message,  sh.RemoveHook <----object required

Thanks.
0
 
ArkCommented:
How did you name SystemHook class? Its name should be cSystemHook, or change

Dim WithEvents sh As cSystemHook <--- Your class name
Private Sub Form_Load()
  '.....Your code
   Set sh = New cSystemHook <--- Your class name
0
 
lynntonAuthor Commented:
Ark,

Thanks for your time and patience. It was the vbPause key that solved the problem.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 15
  • 13
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now