• 01/02/02 02:12 PM
    Sign in to follow this  

    DirectX 8 and the Keyboard

    Graphics and GPU Programming

    Myopic Rhino
    This tutorial assumes that you know basic Win32 programming.

    DirectX is an API that has direct access to your hardware, assuming that you have Windows9X/NT/2000/XP. The beauty of it is that you don't have to write separate code for each graphic card, sound card, and input device. DirectX handles the details, which is good because it isn't the easiest thing in the world to program, anyway. This tutorial will show you how to access the keyboard using DirectInput8. First of all, you have to include dinput.h. Also, you have to link dxguid.lib and dinput8.lib.

    DirectInput is the easiest part of the DirectX API that I have worked with. Let's take a look at some initialization code.

    // Globals
    LPDIRECTINPUT lpdi;
    LPDIRECTINPUTDEVICE m_keyboard;
    unsigned char keystate[256];

    void Init(void)
    {
    if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
    IID_IDirectInput8, (void**)&lpdi, NULL)))
    {
    // error code
    }

    if (FAILED(lpdi->CreateDevice(GUID_SysKeyboard, &m_keyboard, NULL)))
    { /* error code */ }

    if (FAILED(m_keyboard->SetDataFormat(&c_dfDIKeyboard)))
    { /* error code */ }

    if (FAILED(m_keyboard->SetCooperativeLevel(hWND, DISCL_BACKGROUND |
    DISCL_NONEXCLUSIVE)))
    { /* error code */ }

    if (FAILED(m_keyboard->Acquire()))
    { /* error code */ }
    }
    These functions will initiate DirectInput, followed by the keyboard. The FAILED macro return true if the function returns anything other than DI_OK, which basically says that the function was successful.

    The first function starts DirectInput8. I'd be wasting your time explaining all the parameters because they will most likely stay the same.

    The next four functions initiate and calibrate a DIRECTINPUTDEVICE, specifically your keyboard. Again, I won't explain the parameters because you will rarely ever change them. If you must know the billions of insignificant details, just look at the DX8 documentation (although it probably won't help, trust me on this one).

    Now, let's get some input.

    void Render(void)
    {
    if (FAILED(m_keyboard->GetDeviceState(sizeof(unsigned char[256]), (LPVOID)keystate)))
    { /* error code */ }

    if (keystate[DIK_LCONTROL] & 0x80)
    {
    // shoot gun, jump, react somehow
    }
    }
    The GetDeviceState function updates the status of the keyboard and must be called at the beginning of every frame in order to receive input. The parameters are the size of the input variable used to contain the data and the actually variable. In the other two major forms of input, the mouse and the joystick, there are specific data structures defined by DirectX, but the keyboard is so simple that you merely need an array of unsigned chars. The second block of code checks to see if the left control button is down. The array of unsigned chars contains the status of all the keys on the keyboard. This status is updated by GetDeviceState. Since that syntax is a little on the ugly side, I like to use a nifty little macro to handle it.

    #define KeyDown(data, n) ((data[n] & 0x80) ? true : false)
    #define KeyUp(data, n) ((data[n] & 0x80) ? false : true)
    That's much better, isn't it? You could just call it like this:

    if (KeyDown(keystate, DIK_LCONTROL))
    { /* do something */ }
    The last thing that we need to do is create the Destroy function to release DirectInput.

    void Destroy(void)
    {
    if (m_keyboard)
    m_keyboard->Release();

    if (lpdi)
    lpdi->Release();
    }
    Now that we have all of that done, let's see a full pseudo windows program using the code we've created.

    #define WIN32_LEAN_AND_MEAN

    #include
    #include

    // Globals
    LPDIRECTINPUT lpdi;
    LPDIRECTINPUTDEVICE m_keyboard;
    unsigned char keystate[256];
    HWND hWND;
    HINSTANCE g_hinstance;
    bool done = false;

    // Defines
    #define KeyDown(data, n) ((data[n] & 0x80) ? true : false)
    #define KeyUp(data, n) ((data[n] & 0x80) ? false : true)

    // Function declarations
    void Init(void);
    void Render(void);
    void Destroy(void);

    // Message Loop CallBack Function
    LRESULT CALLBACK WinProc ( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
    {
    HDC hDC;

    switch( iMsg )
    {
    // Called when window is first created
    case WM_CREATE:
    Init();
    return( 0 );
    // Called when the window is refreshed
    case WM_PAINT:
    hDC = BeginPaint(hWnd, &paintStruct);
    EndPaint(hWnd, &paintStruct);
    return( 0 );
    // Called when the user closes the window or terminates the application
    case WM_DESTROY:
    Destroy();
    PostQuitMessage( 0 );
    return( 0 );
    }

    return DefWindowProc( hWnd, iMsg, wParam, lParam );
    }

    // Function to Create the Window and Display it
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
    // basic windows creation stuff

    while (!done)
    {
    PeekMessage(&msg, hWnd, NULL, NULL, PM_REMOVE);

    if (msg.message == WM_QUIT) // do we receive a WM_QUIT message?
    {
    done = true; // if so, time to quit the application
    }
    else
    {
    Render();

    TranslateMessage(&msg); // translate and dispatch to event queue
    DispatchMessage(&msg);
    }
    }

    return ( msg.wParam );
    }


    void Init(void)
    {
    if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
    IID_IDirectInput8, (void**)&lpdi, NULL)))
    {
    // error code
    }

    if (FAILED(lpdi->CreateDevice(GUID_SysKeyboard, &m_keyboard, NULL)))
    { /* error code */ }

    if (FAILED(m_keyboard->SetDataFormat(&c_dfDIKeyboard)))
    { /* error code */ }

    if (FAILED(m_keyboard->SetCooperativeLevel(hWND, DISCL_BACKGROUND |
    DISCL_NONEXCLUSIVE)))
    { /* error code */ }

    if (FAILED(m_keyboard->Acquire()))
    { /* error code */ }
    }

    void Render(void)
    {
    if (FAILED(m_keyboard->GetDeviceState(sizeof(unsigned char[256]), (LPVOID)keystate)))
    { /* error code */ }

    if (KeyDown(keystate, DIK_ESCAPE))
    {
    PostQuitMessage(0);
    }
    }

    void Destroy(void)
    {
    if (m_keyboard)
    m_keyboard->Release();

    if (lpdi)
    lpdi->Release();
    }
    Remember to link dxguid.lib and dinput8.lib to your project. If you don't know how, see your complier manual. For a full list of constants for the keyboard, see your DirectX documentation.

    I've included the source code for a very easy to use wrapper system for DirectInput8. To use these in your game/application, all you need to do is call a few functions. The following is a pseudo program that uses the system.

    // whole lot of stuff
    // initiates the program
    void Init(void)
    {
    // other important stuff
    Init_CInput8(hWND); // takes handle to the window as parameter
    Init_Keyboard(g_hinstance); // takes instance handle as parameter
    Init_Mouse(g_hinstance); // takes instance handle as parameter
    // other important stuff
    }

    // renders the program
    void Render(void)
    {
    Read_Keyboard();
    Read_Mouse();

    // stuff

    if (KeyDown(DIK_SPACE))
    {
    shooting = true;
    }

    if (KeyUp(DIK_SPACE))
    {
    shooting = false;
    }

    if (KeyPress(DIK_RETURN))
    {
    FireRockets(5);
    }

    // stuff

    float mx, my;
    Get_Mouse_Movement(mx, my);

    cursor_x += mx;
    cursor_y += my;

    if (Button_Down(LEFT_BUTTON))
    {
    LaunchGrenade();
    }
    }

    // de-initiates the program
    void Destroy(void)
    {
    Release_Mouse();
    Release_Keyboard();
    Shutdown_CInput8();
    }
    There are more functions in the source than this, but they are very self-explanatory.

    For more information on using the mouse, see my follow-up article DirectX 8 and the Mouse.


      Report Article
    Sign in to follow this  


    User Feedback

    Create an account or sign in to leave a review

    You need to be a member in order to leave a review

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    There are no reviews to display.