Unable to check whether Capslock is on or off in VB.Net

97 Views Asked by At

I am trying to write code to check whether or not Capslock is on using VB.net. I have found some code online but there seems to be a problem. Here is what I have tried so far.

If My.Computer.Keyboard.CapsLock = True Then
   Dim intmessage As Long
   intmessage = MsgBox("Would you like to exit the loop and close the application?", vbYesNo)
   If intmessage = vbYes Then Application.Exit()
End If
If Control.IsKeyLocked(Keys.CapsLock) = True Then
   Dim intmessage As Long
   intmessage = MsgBox("Would you like to exit the loop and close the application?", vbYesNo)
   If intmessage = vbYes Then Application.Exit()
End If

I have a long series of repetitive tasks that I want to run on my computer. But I also want the ability to pause these tasks with the press of a button. The idea is that I will loop through these tasks, periodically checking the Capslock, which I will use if I desire to interrupt the tasks. As the loop continues, if I turn on Capslock, I will have the option of pausing or exiting the loop. For whatever reason, these two attempts are only catching the initial keystate of Capslock when the application is launched. If Capslock is on when I launch the application and begin the loop, these always return True. If Capslock is off when I launch the application and begin the loop, these always return False. Its like I need to refresh the keyboard control or something. What I need is to begin with Capslock off, but to properly be updated whenever I turn on Capslock.

Thanks.

2

There are 2 best solutions below

2
dbasnett On

On the Form designer add a timer, under Components. Set the interval to 1000 and enable to true.

Then add this code.

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Timer1.Stop()
    Static wasOn As Boolean = False
    If My.Computer.Keyboard.CapsLock Then
        If Not wasOn Then
            Dim dr As DialogResult
            dr = MessageBox.Show("Quit app?", "C A P T I O N", MessageBoxButtons.YesNo, MessageBoxIcon.Stop)
            If dr = Windows.Forms.DialogResult.Yes Then
                Me.Close()
            Else
                wasOn = True
            End If
        End If
    Else
        wasOn = False
    End If
    Timer1.Start()
End Sub

This code forces CapsLock to be cycled off / on before asking question again. Notice the use of MessageBox and DialogResult.

EDIT:

Another approach using WndProc

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    CapsLockOn = My.Computer.Keyboard.CapsLock 'get initial state
End Sub

Private CapsLockOn As Boolean = False

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Select Case m.Msg
        Case WM_KEYDOWN
            Dim WParam As Integer = CInt(m.WParam)
            If WParam = _CAPITAL Then
                CapsLockOn = Not CapsLockOn 'toggle
            End If
    End Select
    MyBase.WndProc(m)
End Sub

Private Shared ReadOnly WM_KEYDOWN As Integer = &H100 'The WM_KEYDOWN message is posted to the window with the keyboard focus when a nonsystem key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed.
Private Shared ReadOnly _CAPITAL As Integer = &H14   ' CAPS LOCK key

Then in your code call this periodically,

Private Sub ChkCapsLock()
    If CapsLockOn Then
        Dim dr As DialogResult
        dr = MessageBox.Show("Quit app?", "C A P T I O N", MessageBoxButtons.YesNo, MessageBoxIcon.Stop)
        If dr = Windows.Forms.DialogResult.Yes Then
            If Me.InvokeRequired Then
                Me.BeginInvoke(Sub()
                                   Me.Close()
                               End Sub)
            Else
                Me.Close()
            End If
        End If
    End If
End Sub

BUT - If you have the UI locked up this won't work either.

0
Luke Krell On

I never did truly solve this problem. However I came up with a workaround that is practical for my situation. This might not be practical for everyone, but there are several ways someone could use a similar strategy.

I use MYSQL frequently. So I set up a table(tblStop) that holds only one row and in that row it holds either a 1 or a 0 in the onoff column. Now I have the loop set up to check and see which number is held there after every iteration. I have it break on 0 just like I was intending to have it break on capslockon.

I created two very simple applications, one called ON and the other called OFF. These toggle tblStop onoff appropriately. I then pinned them to my taskbar so I could easily toggle them.