asdDiLib.txt - the read-me file for the DiLib library.

Created by: Andrew S. Dunsmore
Date: 09/16/04
Modified: 02/27/05

v1.2 updates from v1.0: The code, along with dinput.lib, has been compiled into a library. This makes using the library easier, but source code is no longer available for learning or modifying the code. A problem was corrected with the variables not being declared as static was causing linking errors when compileing with a project. Added the function WaitForKeyboardData().

The asdDInput Library is a library to make using DirectInput easier. The library takes care of declaring and initializing all required variables and it provides numerous functions to take care of the calls necessary in setting up DirectInput and retrieving data from the keyboard and mouse.

The library is currently only implemented to use the keyboard and mouse. I do not currently have any experience in using the joystick, so I didn't add them here. If I need to use a joystick in the future, I may update this.

THE INCLUDE AND EXTERNAL FILES
The library has been built with the dinput.h library included in the header file, and dinput.lib was compiled into the lib file. When using the library with your projects, all you need to do is add the lib file to your VC++ 6.0 project, or if you're using VC++.net, add asdDInput.lib to your additional input files found under project properties.

THE VARIABLES
The variables declared in the header file and their uses are:

LPDIRECTINPUT8		lpdi			- Used to point to COM interface
LPDIRECTINPUTDEVICE8	lpdiKey			- Pointer to keyboard device
LPDIRECTINPUTDEVICE8	lpdiMouse		- Pointer to mouse device
UCHAR			keyboardState[256]	- Holds keyboard data to determine what keys are being pressed
DIMOUSESTATE		mouseState	- Holds mouse data to determine if the mouse is being moved or buttons pressed
long			mouseX		- Holds the mouse's horizontal position on the screen (measured in pixels from the
					- left side of the screen)
long			mouseY		- Holds the mouse's vertical position of the screen (measured in pixels from the
					- top of the screen)

Except for mouseX and mouseY these variables are all internal and don't need to be accessed directly by the user of the library (we want to make this easy right?). To see an example of how you would use mouseX and mouseY, take a look at the psuedo-code examples at the end of this file.

THE FUNCTIONS
- DirectInput functions
HRESULT	DInputInitialize(HINSTANCE hInstanceApp)
void	DInputShutdown(void)

- Keyboard functions
HRESULT	KeyboardInitialize(HWND mainWindowHandle)
HRESULT	GetKeyboardData(void)
bool	TestKeyboardData(DWORD dik)
void	ClearKeyboardData(DWORD dik)
HRESULT	WaitForKeyboardData(DWORD dik)

- Mouse functions
HRESULT	MouseInitialize(HWND mainWindowHandle, long initX = 0, long initY = 0)
HRESULT	GetMouseData(void)
bool	TestMouseLeftButton(void)
bool	TestMouseRightButton(void)
void	MoveMouse(void)
long	MoveMouseX(void)
long	MoveMouseY(void)

The two DirectInput functions need to be used if you are using DirectInput for the keyboard, mouse, or both in your application. When to call these are pretty self-explanitory. Call DInputInitialize() at the beginning of your application (or before you use any of the other functions), and call DInputShutdown() at the end of your application (or after you're finished with all the other DirectInput functions).

The one difficult thing about using these functions is the parameter passed into DInputInitialize() (and no, it's not THAT difficult). This parameter comes from the first argument passed into your WinMain() function. See the psuedo-code examples below for more details.

The return value for the DInputInitialize() function is the DirectX return value that results from the DirectInput API functions used in this function. If everything works out, the function will return DI_OK, but if something fails, the return value will be the DirectX error code. See DInput.h for a list of all the possible error codes. An easy way to test if the function completes with no problems if to use the DirectX FAILED() function. See the psuedo-code for an example of this as well.

The four keyboard functions are only nessesary if you are using DirectInput to access the keyboard. To use this group of functions first call KeyboardInitialize() before trying to access data from the keyboard. After initializing the keyboard, call GetKeyboardData to fill the keyboardState array with data that symbolizes the key states. Once the array is filled, call TestKeyboardData() to test if the user pressed the key code passed into the function. The ClearKeyboardData() is used to hold the program until the user releases a pressed key (a better name for this function should've been ClearKeyboardBuffer(), but you get the point right?). WaitForKeyboardData(), a function new to v1.2, will hold your program until the user presses the key passed into the function (i.e. "Press 'Enter' to continue").

The dik parameter of TestKeyboardData(), ClearKeyboardData(), and WaitForKeyboardData() is the DIK code for the key you want
to test for, clear, or wait for. The DIK codes can be found in the dinput.h file, or (since I'm such a nice guy) you can get the some of the codes from the list below:

A - Z keys	DIK_A - DIK_Z
0 - 9 keys	DIK_0 - DIK_9
Esc key		DIK_ESCAPE
Tab key		DIK_TAB
Enter key	DIK_RETURN
Left Shift	DIK_LSHIFT
Right Shift	DIK_RSHIFT
Cursor Keys	DIK_UP, DIK_DOWN, DIK_LEFT, DIK_DOWN

Ok, that's enough. I got bored with it, so that's all I'm giving you :-P. Check out dinput.h for the whole list. Just so you know, every key on the keyboard has its own DIK code, so if your left and right shift key do they same thing you'll need to 'or' [ | ] two TestKeyboardData() functions together. Also of note, number keys at the top of the keyboard have different DIK codes than the digits on the keypad.

The other parameter that you'll have to worry about here is mainWindowHandle in the KeyboardInitialize() function. This parameter is filled by the handle to the window where you want DirectInput to control your keyboard data.

The return type from KeyboardInitialize(), GetKeyboardData(), and WaitForKeyboardData() is similar to the return values from the DirectInputInitialize() function. The return value from TestKeyboardData() is true if the user is pressing the key for the passed in value and false otherwise.

The MouseInitialize(), GetMouseData(), TestLeftMouseButton(), and TestRightMouseButton() are similar to the functions found in the keyboard section, so I'll save time and not go over them. Hopefully you'll be able to figure it out.

The three other mouse functions, MoveMouse(), MoveMouseX(), and MoveMouseY() will move the mouse by updating the values in mouseX and mouseY. MoveMouse() updates both values, but it doesn't return anything. The MoveMouseX() and MoveMouseY() functions return the value of how much the mouse was moved in their respective directions.

EXAMPLE CODE
This section shows how to use the libary.

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{
  HWND hwnd;

  // fill in the values of your window class structure, to include the following call
  winclass.hInstance = hinstance;

  // register your window class and create your window class kinda like this
  hwnd = CreateWindowEx(/*your parameters*/);

  // now set up DirectInput
  if(FAILED(DInputInitialize(hinstance)))
  {
    // error
    MessageBox("DirectInput failed to initialize"); // I know this isn't the way to call this, but know what I mean, right?
	return;
  }

  // if you're going to use the keyboard, initialize it like this
  if(FAILED(KeboardInitialize(hwnd)))
  {
    MessageBox("Keyboard failed to initialize");
	return;
  }

  // and initialize the mouse like this:
  if(FAILED(MouseInitialize(hwnd))
  {
    MessageBox("Mouse failed to initialize");
	return;
  }

  // or initialize the location of the mouse to the center of the screen like this
  MouseInitialize(hwnd, centerOfScreenX, centerOfScreenY);

  // note: DirectInput does not have any control over the mouse cursor added to your windows class.
  //  If you want a DirectInput controlled mouse pointer, you'll need to use a bitmap that you
  //  center at the location specified by mouseX and mouseY.

  // Another note: you get the idea to test for errors when calling functions that return an HRESULT
  //  yet? I'm going to cut the whole if(FAILED) thing out of the rest of the example to save some
  //  space, but just realize if a function returns and HRESULT value you can test for the function's
  //  success like I did above.

  // now that everything is set up, let's enter a loop
  while(1)
  {
    // get data from our keyboard
	GetKeyboardData();

	// get data from the mouse
	GetMouseData();

	// now that we've got our data filled in, do something with it

	// test if the user is pressing the escape key, and if so quit
	if(TestKeyboardData(DIK_ESCAPE))
	{
	  // wait right here until the user releases the escape key
      ClearKeyboardData(DIK_ESCAPE);

	  // the escape key has now been released, so let's get out of the loop
	  break;
	}

	// the user didn't press the escape key, so let's check some more data
	if(TestMouseLeftButton())
	{
	  MessageBox("You pressed the left mouse button");
	}

	if(TestMouseRightButton())
	{
	  MessageBox("You pressed the right mouse button");
    }
  } // end while loop

  // since the only way to get out of the above loop is by the user pressing the escape key, and
  // since we're using the escape key to exit the application, it's time to shutdown DirectInput
  DInputShutdown();

  // now that DirectInput is properly shutdown, kill the app
  return msg.wParam;
}

CONTACT INFO
If you have any questions, comments, or concerns, please do not hesitate to shoot me an e-mail at
drewdunsmore@hotmail.com.

Andrew S. Dunsmore