Solved

Keyboard Events in VB ?

Posted on 2008-10-23
11
1,215 Views
Last Modified: 2013-11-27
I am trying to create a very simple keyboard test app for non-standard keyboard and just can't get going...
I would like to change the colour of a form panel when a corresponding key is pressed.
e.g. create PanelA and change the backcolour to red while key "A" is pressed and green when released.
I have managed to do this with a button using the button text "&A" on the button but this will cause problems as half the keys on the non-standard keyboard are combinations, ie ALT+A, ALT+B etc.
i have some code, but as it may be completely wrong/misleading i have not posted it here.
If anyone could help me start off with just one or two keys i'm sure i can take it from there and it will be apreciated, thanks
0
Comment
Question by:lewisma2
  • 6
  • 5
11 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
Use a low level keyboard hook via WH_KEYBOARD_LL.

Below is a simple example to get you started.

*** NOTE *** The hook does NOT work while running in the IDE!  Build the solution and run the executable located in your ..\bin\release folder.
Imports System.Runtime.InteropServices

Public Class Form1
 

    Private WithEvents llkb As LowLevelKeyBoardhook
 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        llkb = New LowLevelKeyBoardhook

    End Sub
 

    Private Sub llkb_KeyDown(ByVal vkCode As Integer) Handles llkb.KeyDown

        Label1.BackColor = Color.Red

        Label1.Text = "KeyDown: " & vkCode
 

        Select Case vkCode

            Case Keys.A

                lblA.BackColor = Color.Red
 

        End Select

    End Sub
 

    Private Sub llkb_KeyUp(ByVal vkCode As Integer) Handles llkb.KeyUp

        Label1.BackColor = Control.DefaultBackColor

        Label1.Text = "KeyUp: " & vkCode
 

        Select Case vkCode

            Case Keys.A

                lblA.BackColor = Control.DefaultBackColor
 

        End Select

    End Sub
 

    Public Class LowLevelKeyBoardhook
 

        Private Const HC_ACTION As Integer = 0

        Private Const WH_KEYBOARD_LL As Integer = 13

        Private Const WM_KEYDOWN As Integer = &H100

        Private Const WM_SYSKEYDOWN As Integer = &H104

        Private Const WM_KEYUP As Integer = &H101

        Private Const WM_SYSKEYUP As Integer = &H105
 

        Public Structure KBDLLHOOKSTRUCT

            Public vkCode As Integer

            Public scancode As Integer

            Public flags As Integer

            Public time As Integer

            Public dwExtraInfo As Integer

        End Structure
 

        Private Declare Function SetWindowsHookEx Lib "user32" _

            Alias "SetWindowsHookExA" ( _

            ByVal idHook As Integer, _

            ByVal lpfn As LowLevelKeyboardProcDelegate, _

            ByVal hmod As Integer, _

            ByVal dwThreadId As Integer) As Integer
 

        Private Declare Function CallNextHookEx Lib "user32" ( _

            ByVal hHook As Integer, _

            ByVal nCode As Integer, _

            ByVal wParam As Integer, _

            ByVal lParam As KBDLLHOOKSTRUCT) As Integer
 

        Private Declare Function UnhookWindowsHookEx Lib "user32" ( _

            ByVal hHook As Integer) As Integer
 

        Private Delegate Function LowLevelKeyboardProcDelegate( _

            ByVal nCode As Integer, _

            ByVal wParam As Integer, _

            ByRef lParam As KBDLLHOOKSTRUCT) As Integer
 

        Private Declare Function GetAsyncKeyState Lib "user32" _

            (ByVal vKey As Integer) As Integer
 

        Public Event KeyDown(ByVal vkCode As Integer)

        Public Event KeyUp(ByVal vkCode As Integer)
 

        Private hhkLowLevelKeyboard As Integer

        Private keyboardDelegate As LowLevelKeyboardProcDelegate
 

        Public Sub New()

            keyboardDelegate = New LowLevelKeyboardProcDelegate(AddressOf Me.LowLevelKeyboardProc)

            hhkLowLevelKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardDelegate, _

                Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)

        End Sub
 

        Private Function LowLevelKeyboardProc( _

            ByVal nCode As Integer, _

            ByVal wParam As Integer, _

            ByRef lParam As KBDLLHOOKSTRUCT) As Integer
 

            If (nCode = HC_ACTION) Then

                Select Case wParam

                    Case WM_KEYDOWN, WM_SYSKEYDOWN

                        RaiseEvent KeyDown(lParam.vkCode)
 

                    Case WM_KEYUP, WM_SYSKEYUP

                        RaiseEvent KeyUp(lParam.vkCode)
 

                End Select

            End If
 

            Return CallNextHookEx(hhkLowLevelKeyboard, nCode, wParam, lParam)

        End Function
 

        Protected Overrides Sub Finalize()

            UnhookWindowsHookEx(hhkLowLevelKeyboard)

            MyBase.Finalize()

        End Sub
 

    End Class
 

End Class

Open in new window

0
 

Author Comment

by:lewisma2
Comment Utility
That's brilliant mate....
i had been reading about Keyboard Hooks but would not have got that far, i don't think.......
The only bit that troubles me now is all the "special" keys used on my custom keyboard.
They are all ALT + A, ALT + B etc..... From what i read, do these have to be handled by a  must be KeyPress event, as apposed to KeyDown/KeyUp ???
If so, is it as easy to use the colours to indicate keydown and keyup ?
or do i need to use IF...THEN.. statements and variables ?
0
 

Author Comment

by:lewisma2
Comment Utility
I have just "knocked up" a basic GUI without all keys to test on these machines and get an error message that .NET Framework needs to be installed.
I would like to create a stand alone application as the machines the app is for are "stripped down" XP machines and will not have all updates etc on them.
Is this possible in VB Express ?
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
Is it possible?

Yes...and No.

Using only the standard VB.Net tools, you can NOT build an executable that runs WITHOUT the .Net Framework installed on the target machine.

But...if you want to shell out some $$$ then you can purchase various third-party applications that will make your VB.Net app a "stand-alone" application by encapsulating all of the necessary components from the framework into your EXE.

ThinApp (formerly ThinStall) is one such tool:
http://www.vmware.com/products/thinapp/
0
 

Author Comment

by:lewisma2
Comment Utility
I am still struggling to use all the "Combination" keys, i.e. ALT +A, ALT + B etc....
My custom keyboard uses 28 of these and so I need to work something out for it, i have tried online help and IF...THEN statements but can't get it sorted...
any ideas ??
Thank You
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 125 total points
Comment Utility
Unfortunately I don't have a custom keyboard so I can't test this stuff out...  =\

Can you check the Alt key when you get a WM_KEYDOWN msg like this?

        If My.Computer.Keyboard.AltKeyDown Then

        End If

For instance, if you were looking for Alt-A, then look for the "A" part in the WM_KEYDOWN message, then use the above test to see if the Alt key is down.

Again, not sure how the custom keyboard works and I can't test it out here.  =(
0
 

Author Comment

by:lewisma2
Comment Utility
Hi again !!! cool !!
I have added the IF... THEN... ELSE statement and it works !!
            Case Keys.A
                If My.Computer.Keyboard.AltKeyDown Then
                    LabelALTA.BackColor = Color.Red
                Else : LabelA.BackColor = Color.Red
                End If
the only thing i get now is an error "beep" when these keys are pressed as i think the system (Windows) recognises the system key.
Do you know how i can make my App "capture" all keyboard events so that they are not also passed on to the OS ? or disable "System Keys" while my app is running ??
Many Thanks again for any help !!
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
You can "suppress" a keystroke in LowLevelKeyboardProc()...

Instead of:

    Return CallNextHookEx(hhkLowLevelKeyboard, nCode, wParam, lParam)

You would do:

    Return True

Since we are suppressing the keystrokes, you would have to raise a new event to indicate Ctrl-A, because we can't check for it out at the Form level if we suppressed it!

    Public Event CtrlA()

So the My.Computer.Keyboard.AltKeyDown check needs to be done inside LowLevelKeyboardProc().
0
 

Author Closing Comment

by:lewisma2
Comment Utility
Thanks VERY much for your help...
I will have a go at the last bit soon, need to find some time to get my head around it first ! Cheers !! :-D
0
 

Author Comment

by:lewisma2
Comment Utility
OK, the "Return True" DOES remove the error "beep" i was getting when using all the ALT+" " (custom) keys, but as you said, it does not "see" the ALT key down now...
I'm think i'm OK with performing the check with an IF...THEN...ELSE.... statement,
            If My.Computer.Keyboard.AltKeyDown And Keys.A Then
                RaiseEvent ALTA()
but can i use the SELECT.... CASE.... method with this or do i need to check individually for ALT+A, ALT+B, ALT+C etc. (my keyboard uses all letters and 2 numbers)
In addition, when i RaiseEvent for these, i obviously need to "Handle" these new events... is that simply by a Private Sub ??
cheers
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
Comment Utility
You can check for the keys using a Select Case or a series of If Then statements.

As far as events go, you can either:

(1) Create an Enum with all your Key "codes" and then raise ONE event that passes the keypress "code".
(2) Create separate Events for each Key.

The sub that handles the events can be either public or private.  The parameter "signature" has to match though.  You can have the IDE do that for you though by selecting the variable in the left dropdown at the top of the editor (llkb in the original solution I posted).  Then in the right dropdown you will see the available events for that object.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now