Presentation is loading. Please wait.

Presentation is loading. Please wait.

Programming Input Devices

Similar presentations


Presentation on theme: "Programming Input Devices"— Presentation transcript:

1 Programming Input Devices
DirectInput

2 Steps Create a DirectInput object
Create a DirectInput device object(s) Configure the DirectInput device object(s) Acquire the device Read data from the device Release the DirectInput and DirectInput device object(s) DirectInput, like other components of DirectX, is initialized in a similar manner to other DirectX components. It requires the creation of both a DirectInput object and an input device. The DirectInput object provides the interface needed to access DirectInput devices. Through this interface, you can create devices, enumerate the devices on a system, or check the status of a particular device. After you’ve created the DirectInput object, you must create the device. The DirectInput device that you’ll create will enable you to gain specific access to an input device, be it a keyboard, joystick, or other gaming device. After creating the device, you need to gain access to its input. This is done through a process called “acquiring a device.” When you acquire a device, you can initialize the device, get a list of its capabilities, or read its input. It might seem like a lot of trouble to go through just to get a couple of keystrokes from a keyboard or gamepad, but having direct access to your input device will make your life a lot more simple later on. Now that you have access to the device, you can read input from it for each frame. For example, if you are using a gamepad as your input device, you can check to see if the user has pressed the direction buttons or one of the predefined action buttons. If so, you can act on this information. At this point, you should have a clear understanding of getting DirectInput up and running and getting data from an input device. I’m now going to step you through the code needed to do just that.

3 Creating the DirectInput Object
HRESULT WINAPI DirectInput8Create( HINSTANCE hinst, // application handle DWORD dwVersion, // The standard value for this parameter is DIRECTINPUT_VERSION. REFIID riidltf, // Using the default value of IID_IDirectInput8 LPVOID *ppvOut, // reference to DirectInput Object LPUNKNOWN punkOuter // NULL );

4 Code HRESULT hr; // variable used to hold return codes LPDIRECTINPUT8 DI_Object; // the DirectInput object // Create the DirectInput object hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void** )&DI_Object, NULL ); // Check the return code for DirectInput8Create if FAILED( hr ) return false;

5 Creating the DirectInput Device
HRESULT CreateDevice( REFGUID rguid, // reference to the GUID of the desired input device • GUID_SysKeyboard • GUID_SysMouse LPDIRECTINPUTDEVICE *lplpDirectInputDevice, // pointer to DirectInput device LPUNKNOWN pUnkOuter // NULL. );

6 Code HRESULT hr; // variable used to hold function return codes LPDIRECTINPUTDEVICE8 DI_Device; // the DirectInput device // Retrieve a pointer to an IDirectInputDevice8 interface hr = DI_object ->CreateDevice( GUID_SysKeyboard, &DI_Device, NULL ); // Check the return code from CreateDevice if FAILED( hr ) return false;

7 Setting the Data Format
After you’ve created a valid DirectInput device, you need to set up the data format that DirectInput will use to read input from the device. The SetDataFormat function requires a DIDATAFORMAT structure as its only parameter. HRESULT SetDataFormat ( LPCDIDATAFORMAT lpdf );

8 Code HRESULT hr; // variable to hold the return code
// Set the data format for the device // Call the SetDataFormat function hr = DI_Device->SetDataFormat(&c_dfDIKeyboard); // Check the SetDataFormat return code if FAILED( hr ) return false;

9 Setting the Cooperative Level
The cooperative level tells the system how the input device that you are creating works with the system. You can set input devices to use either exclusive or nonexclusive access. HRESULT SetCooperativeLevel( HWND hwnd, // handle to the window DWORD dwFlags // series of flags that describe the type of access you are requesting );

10 Code // Set the cooperative level hr = DI_Device->SetCooperativeLevel( wndHandle, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE ); // Check the return code for SetCooperativeLevel if FAILED( hr ) return false;

11 Acquiring Access When you acquire access to an input device, you are telling the system that you are ready to use and read from this device. This function takes no parameters and returns only whether it was successful. HRESULT Acquire(VOID); // The small code example that follows shows how the Acquire function is called. // Get access to the input device. hr = DI_Device->Acquire(); if FAILED( hr ) return false;

12 Getting Input All devices use the function GetDeviceState when reading input. Whether the input device is a keyboard, mouse, or gamepad, the GetDeviceState function is used. HRESULT GetDeviceState( DWORD cbData, // size of the buffer LPVOID lpvData // buffer that will hold the data that’s read from the device );

13 Getting Input from a Keyboard
char buffer[256]; // Define the macro needed to check the state of the keys on the keyboard #define KEYDOWN(name, key) (name[key] & 0x80) // This is the main game loop, read from the input device each frame while ( 1 ) { // Check the keyboard and see if any keys are currently being pressed g_lpDIDevice->GetDeviceState( sizeof( buffer ), (LPVOID )&buffer ); // Here the KEYDOWN macro checks whether the left arrow key was pressed if (KEYDOWN(buffer, DIK_LEFT)){ // Do something with the left arrow } // KEYDOWN is used again to check whether the up arrow key was pressed if (KEYDOWN(buffer, DIK_UP)){ // Do something with the up arrow

14 Getting Input from a Mouse
// Create a device using GUID of Mouse hr = g_lpDI->CreateDevice(GUID_SysMouse, &g_lpDIDevice, NULL); if FAILED(hr) return FALSE; // Set the data format for the mouse hr = g_lpDIDevice->SetDataFormat( &c_dfDIMouse ); if FAILED( hr )

15 DIMOUSESTATE The keyboard needs a character buffer consisting of 256 elements, whereas the mouse needs a buffer of type DIMOUSESTATE typedef struct DIMOUSESTATE { LONG lX; // holds the distance the mouse has traveled in the X dir LONG lY; // holds the distance the mouse has traveled in the Y dir LONG lZ; // holds the distance the mouse has traveled in the Z dir BYTE rgbButtons[4]; // the current state of the mouse buttons } DIMOUSESTATE, *LPDIMOUSESTATE;

16 Getting Input from a Mouse
// Define the macro needed to check the state of the mouse buttons #define BUTTONDOWN (name, key) (name.rgbButtons[key] & 0x80) // This is required to hold the state of the mouse // This variable holds the current state of the mouse device DIMOUSESTATE mouseState; // This variable holds the current X position of the sprite LONG currentXpos; // This variable holds the current Y position of the sprite LONG currentYpos; // Set the default position for the sprite currentXpos = 320; currentYpos = 240;

17 Getting Input from a Mouse
// This is the main game loop, read from the input device each frame while ( 1 ){ // Check the mouse and get the current state of the device being pressed g_lpDIDevice->GetDeviceState (sizeof ( mouseState ), (LPVOID) &mouseState); // Here the BUTTONDOWN macro checks if the first mouse button is pressed if (BUTTONDOWN( mouseState, 0 ) ){ // Do something with the first mouse button } // BUTTONDOWN is used again to check if the second mouse button is pressed if ( BUTTONDOWN( mouseState, 1 ) ){ // Do something with the up arrow // Next, check the movement of the mouse // See how far in the X direction the mouse has been moved currentXpos += mouseState.lX; // See how far in the Y direction the mouse has been moved currentYpos += mouseState.lY; // Do something with the mouse movement

18 Thank You

19 DIDATAFORMAT The DIDATAFORMAT structure describes various elements of the device for DirectInput. typedef struct DIDATAFORMAT { DWORD dwSize; DWORD dwObjSize; DWORD dwFlags; DWORD dwDataSize; DWORD dwNumObjs; LPDIOBJECTDATAFORMAT rgodf; } DIDATAFORMAT, *LPDIDATAFORMAT;

20 DIDATAFORMAT You need to create and use your own DIDATAFORMAT structure if the input device you want to use is not a standard device. Following are the predefined DIDATAFORMAT structures for common input devices: c_dfDIKeyboard. This is the data format structure that represents a system keyboard object. c_dfDIMouse. You use this data format structure when the input device being used is a mouse with up to four buttons. c_dfDIMouse2. You use this data format structure when the input device being used is a mouse or similar device with up to eight available buttons. c_dfDIJoystick. This is the data format structure for a joystick. c_dfDIJoystick2. This is the data format structure for a joystick with extended capabilities.

21 SetCooperativeLevel - Flags
DISCL_BACKGROUND. The application requires background access to the device. This means that you can use the input device even when the game window is not the currently active window. DISCL_EXCLUSIVE. The game requests total and complete control over the input device, restricting other applications from using it. DISCL_FOREGROUND. The game requires input only when the window is the current active window on the desktop. If the game window loses focus, input to this window is halted. DISCL_NONEXCLUSIVE. Exclusive access is not needed for this application. Defining this flag allows other running applications to continue using the device. DISCL_NOWINKEY. This tells DirectInput to disable the Windows key on the keyboard. When this key is pressed, the Start button on the desktop is activated and focus is removed from the currently active window. When this flag is set, the Windows key is deactivated, allowing your game to retain focus.

22 Symbol Description DIK_ESCAPE The Esc key DIK_0-9 Main keyboard 0 through 9 DIK_MINUS Minus key DIK_EQUALS Equals key DIK_BACK Backspace key DIK_TAB Tab key DIK_A-Z Letters A through Z DIK_LBRACKET Left bracket DIK_RBRACKET Right bracket DIK_RETURN Return/Enter on main keyboard DIK_LCONTROL Left control DIK_LSHIFT Left shift DIK_RSHIFT Right shift DIK_LMENU Left Alt DIK_SPACE Spacebar DIK_F1-15 Function keys 1 through 15

23 Symbol Description DIK_NUMPAD0-9 Numeric keypad keys 0 through 9 DIK_ADD + on numeric keypad DIK_NUMPADENTER Enter on numeric keypad DIK_RCONTROL Right control DIK_RMENU Right Alt DIK_HOME Home on arrow keypad DIK_UP Up arrow on arrow keypad DIK_PRIOR PgUp on arrow keypad DIK_LEFT Left arrow on arrow keypad DIK_RIGHT Right arrow on arrow keypad DIK_END End on arrow keypad DIK_DOWN Down arrow on arrow keypad DIK_NEXT PgDn on arrow keypad DIK_INSERT Insert on arrow keypad DIK_DELETE Delete on arrow keypad

24

25

26

27

28

29

30

31

32

33

34

35

36

37 Getting the device state
Schemes for processing input Polling Callbacks Ways to intercept messages from input devices WM_INPUT WM_MOUSEMOVE DirectInput

38 Basic Mouse Interaction
Double Click WM_LBUTTONDBLCLK WM_MBUTTONDBLCLK WM_RBUTTONDBLCLK Button Press WM_LBUTTONDOWN WM_MBUTTONDOWN WM_BBUTTONDOWN Button Release WM_LBUTTONUP WM_MBUTTONUP WM_RBUTTONUP WM_MOUSEMOVE WM_NCMOUSEMOVE

39 Keyboard Input Key inputs are handled through windows messages:
WM_KEYDOWN WM_KEYUP WM_CHAR The way the application uses the keyboard input will dictate which of these three inputs will be used Using only WM_CHAR can enable Windows to factor in other events or keystrokes such as Ctrl or Shift keys being pressed

40 Working with Keyboard Character Code Virtual scan code OEM scan code
ASCII or Unicode char. It is usually the value returned by the C function getchar() Virtual scan code This is the value sent in the wParam variable for WM_CHAR, WM_KEYDOWN and WM_KEYUP messages OEM scan code This is the scan code provided by the OEM. It is useful only if a code is required for a particular type of keyboard.

41 The lParam  Variable This 32-bit variable, with 6 fields, is passed to the WndProc() Bit  0-15      Repeat count; the number of times of keystroke is repeated Bit 16-23     8-bit OEM scan code Bit 24          Extended key flag: 1 – extended key; – otherwise Bit 25-28     Reserved Bit 29          Context code: 1 – if Alt key is pressed; – otherwise Bit 30          Previous key state: 0 -- previous key up, – previous key down Bit 31          Transition state:  0 – WM_KEYDOWN, – WM_KEYUP

42 Keystroke Messages Keystroke messages come in the form of
WM_KEYDOWN WM_KEYUP WM_SYSKEYDOWN WM_SYSKEYUP All keys produce WM_KEYDOWN and WM_KEYUP messages, except Alt and F10 Alt and F10 are “system” keys which have special meaning to Windows.

43 Keystroke Messages cont.
OEM – identifies the key to the keyboard BIOS Extended key flag – allows application to recognize duplicate keys. For these, the value is 1 Ctrl key on right side of keyboard Home, End, Insert, Delete, Page Up, Page Down Number and arrow keys Enter and forward slash (/) Transition state, previous key state, and context code are generally disregarded

44 Key Handling Notes WM_SYSKEYDOWN and WM_SYSKEYUP should not be processed in most cases by your code These must eventually get to ::DefWindowProc, system keyboard commands such as Alt-Tab and Alt-Esc will stop working Failure to pass these messages to the system can result in unusual and unreliable behavior

45 Capturing Special keys
Ctrl keys wParam and extended bit Shift keys wParam and Virtual key mapping Alt keys Listen to WM_SYSCOMMAND

46 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int x=0,y=0; int repeat=0,extended=0,ext = 0,scanCode =0, wasDown=0; char text[100]; switch(message)

47 case WM_CHAR: { repeat = LOWORD(lParam); scanCode = HIWORD(lParam)&0x00FF; extended = (HIWORD(lParam) >>8 ) &1; wasDown = (HIWORD(lParam)>>30)&1; sprintf(text,"WM_CHAR : Code == %d '%c' Repeat == %d SCANCODE == %d Extended = %d wasDown == %d ",wParam,wParam,repeat,extended,wasDown); MessageBox(hWnd, text,"Keyboard Event Handling",MB_OK|MB_ICONINFORMATION); } break;

48 case WM_KEYDOWN: { repeat = LOWORD(lParam); scanCode = HIWORD(lParam)&0x00FF; extended = (HIWORD(lParam)>>8)&1; wasDown = (HIWORD(lParam)>>30)&1; if(wParam == 17) // for Ctrl key if(extended == 1) MessageBox (hWnd, "Right control key Pressed", "Title", MB_OK|MB_ICONINFORMATION); else MessageBox (hWnd, "Left control key Pressed", "Title", MB_OK|MB_ICONINFORMATION);

49 if(wParam == 16) { // Shift key UINT virtualKey = MapVirtualKey(scanCode,3); if(virtualKey == VK_RSHIFT) MessageBox( hWnd,"Right Shift key Pressed","Title", MB_OK|MB_ICONINFORMATION); if(virtualKey == VK_LSHIFT) MessageBox(hWnd,"Left Shift key Pressed","Title", MB_OK|MB_ICONINFORMATION); } else { sprintf(text,"WM_KEYDOWN : Code == %d '%c' Repeat == %d scancode = %d Extended = %d ",wParam, wParam, repeat, extended); MessageBox(hWnd, text,"Keyboard Event Handling", MB_OK|MB_ICONINFORMATION); } } break;

50 case WM_SYSCOMMAND: MessageBox(hWnd,"Alt Key pressed", "Title", MB_OK|MB_ICONINFORMATION); break; case WM_NCMOUSEMOVE: MessageBox(hWnd,"Moved on the Title bar","Mouse Event", MB_OK|MB_ICONINFORMATION);

51 case WM_LBUTTONDOWN:{ x = LOWORD(lParam); y = HIWORD(lParam); sprintf(text,"Mouse left Click x == %d, y == %d",x,y); MessageBox(hWnd, text, "Mouse Event", MB_OK|MB_ICONINFORMATION); } break;


Download ppt "Programming Input Devices"

Similar presentations


Ads by Google