DirectX:DirectInput:Tutorials:VBNET:DX9:Keyboard Handling Immediate
This tutorial covers the basics of accessing the Keyboard using managed DirectX in VB.Net.
DirectInput (The portion of DirectX we'll be dealing with) handles the keyboard in 2 ways: buffered and Immediate. Buffered means that DirectX will store all the sequential keycodes for you and is real handy for processes that involve actual typing. Immediate means that you'll just get the instant state of the keyboard returned the moment you poll it. This is real cool if you're making a game that requires split second reflexes, but less handy if you want to enter your name in the highscore list, unless of course, you happen to be called rrrrrrrrryyyaaaannnn.
Because I'm a very lazy person, I'm only going to cover the unbuffered part, if you feel that this is cheating, then I invite you to write your own buffered variant and press the nice edit button on top of this page. It's a wikki after all.
Now on to the code!
Public Class KeyboardEngine
Private Const COOPLEVELKB As Microsoft.DirectX.DirectInput.CooperativeLevelFlags = Microsoft.DirectX.DirectInput.CooperativeLevelFlags.Foreground _
Private Dev As Microsoft.DirectX.DirectInput.Device = Nothing Private KeyboardAquired As Boolean = False Private KeyBoardState As Microsoft.DirectX.DirectInput.KeyboardState = Nothing
Well, this is our class, cunningly named "KeyboardEngine", it contains some variables that we want to store for internal use. We'll store the Directinput device here.(Dev) We'll also store the state of the keyboard(KeyboardAquired) here. This way we know if we actually have access to the keyboard, or if some other application stole it from us. I've also put the COOPLEVELKB constant here, this will tell windows on how we want use the device.
our options for that are:
- NoWindowsKey = As long as your application has focus, the windows key doesn't work.
- Background = A device with a background cooperative level can be acquired and used by an application at any time.
- Foreground = Foreground cooperative level means that the application has access to data only when in the foreground.
- NonExclusive = Other Applications can aquire the device in exclusive mode.
- Exclusive = No other applications can aquire the device in exclusive mode.
I've set it to ForeGround and Exclusive, A combination that you'll probably want to use if you're writing your own game. Note, btw, that not all combinations are compatible, for instance, Background & exclusive cannot be set. And obviously, Foreground & Background cannot be set together either.
Finally, We'll store the state of the keyboard here( KeyBoardState) This variable is set every time we poll, and our Keypress function will use this to check on the state of our keys
That takes care of storing everything, now let's go on the actual programming. Our first task is to get the keyboard from DirectX, what we need for this is a window. Don't ask me why, this is just the way Windows works. It probably has to do with the fact that it's called Windows.
Public Sub New(ByVal ContainerWindow As Windows.Forms.Control) Try Dev = New Microsoft.DirectX.DirectInput.Device(Microsoft.DirectX.DirectInput.SystemGuid.Keyboard) Dev.SetCooperativeLevel(ContainerWindow, COOPLEVELKB) Dev.Acquire() KeyboardAquired = True Catch Console.Write("Could not acquire keyboard:") Console.Write(e.Message) KeyboardAquired = False End Try End Function
The constructor tries to aquire the keyboard, if for some reason, it can't aquire the keyboard, it'll return an error message in the console and dispose of the DirectInput device.
Public Function Poll() As Boolean 'Return true if device is still aquired, return false if it isn't Try If Not KeyboardAquired Then 'We don't have the keyboard, try to get it back. Dev.Acquire() KeyboardAquired = True End If
KeyBoardState = Dev.GetCurrentKeyboardState
Return True Catch 'Ack! probably lost the Device, return panicked false and set phasers to re-aquire. KeyboardAquired = False Return False End Try End Function
Our polling function, this function get's the current state and stores it in our internal KeyboardState. It should be called in once every gameloop. Actually, it should be called every time you're planning on doing any actual processing, There is no need to poll the keyboard if you're just rendering that loop. It returns True if everything was fine and dandy, it returns False if somehow the keyboard device was lost, a good indication that your game is not in the foreground anymore. It'll also try to automatically reaquire the keyboard if at all possible.
Public Function KeyPress(ByVal Key As Microsoft.DirectX.DirectInput.Key) As Boolean If (Not (KeyBoardState Is Nothing)) AndAlso KeyBoardState.Item(Key) Then Return True Else Return False End If
Well, this is the second most important part of our function. After polling, Use this function to read out the state of the various keys. It'll see if Key in KeyBoardState has been set, indicating that it is currently in the down position.
Protected Overrides Sub Finalize() If Not (Dev Is Nothing) Then Dev.Dispose() Dev = Nothing KeyBoardState = Nothing KeyboardAquired = False End Sub
Our cleanup Function, this function makes sure that all the objects have been properly disposed off, you probably want to call this in the Finalize event.
And there you have it, A very simple Keyboard Catcher. This example could be extended to include keypress events, the DirectInput Buffered mode and a whole host of other nifty features. If, however, you just want some basic Keyboard functionality, this is a good basis.