Directinput keyboard Programming

Source: Internet
Author: User

Game programming not only involves the development of graphics programs, but also involves many aspects. This article describes how to useDirectinputFor keyboard programming.

In the DOS era, we are generally used to taking over keyboard interruptions and adding our own processing code. However, this method of survival does not work in the evil windows society. We can only get the relief from API or directinput.

In the Windows API, A getasynckeystate () function returns whether to press or release the current status of a specified key. This function can also return whether the specified key has been pressed after the last call of the getasynckeystate () function. Although this function sounds good, there are fewer and fewer programmers who receive such relief funds. There is no such reason, only because directinput's Relief Fund is more generous than this, and it seems to be more professional?

To become a professional relief user as soon as possible, let's start by learning directinput keyboard programming.

Directinput Initialization

As mentioned earlier in DirectDraw, Microsoft designed DirectX Based on COM, so a directinput object is used to represent the input device, and a specific device is represented by the directinputdevice object.

The actual creation process is to first create a directinput object, and then create the directinputdevice object through the createdevice method of this object.

Example:

# Include <dinput. h>

# Define dinput_buffersize 16

Lpdirectinput; // directinput object
Lpdirectinputdevice lpkeyboard; // directinput Device

Bool initdinput (hwnd)
{
Hresult hr;

// Create a directinput object
HR = directinputcreate (hinstancecopy, directinput_version, & lpdirectinput, null );

If failed (HR)
{
// Failed
Return false;
}

// Create a directinputdevice Interface
HR = lpdirectinput-> createdevice (guid_syskeyboard, & lpkeyboard, null );
If failed (HR)
{
// Failed
Return false;
}

// Set to return the query status value through a 256-byte array
HR = lpkeyboard-> setdataformat (& c_dfdikeyboard );
If failed (HR)
{
// Failed
Return false;
}

// Set the collaboration mode
HR = lpkeyboard-> setcooperativelevel (hwnd, discl_nonexclusive | discl_foreground );
If failed (HR)
{
// Failed
Return false;
}

// Set the buffer size
// If this parameter is not set and the default value of the buffer size is 0, the program can only work in the immediate mode.
// If the buffer mode is used, the buffer size must be greater than 0.
Dipropdword property;

Property. diph. dwsize = sizeof (dipropdword );
Property. diph. dwheadersize = sizeof (dipropheader );
Property. diph. dwobj = 0;
Property. diph. dwhow = diph_device;
Property. dwdata = dinput_buffersize;

HR = lpkeyboard-> setproperty (diprop_buffersize, & property. diph );

If failed (HR)
{
// Failed
Return false;
}

HR = lpkeyboard-> acquire ();
If failed (HR)
{
// Failed
Return false;
}

Return true;
}

In this Code, we first define the lpdirectinput and lpkeyboard pointers. The former is used to point to the directinput object, and the latter is directed to a directinputdevice interface.

Using directinputcreate (), we create a directinput object for lpdirectinput. Then we call createdevice to create a directinputdevice interface. The guid_syskeyboard parameter indicates that the keyboard object is created.

Next, setdataformat sets the data format, setcooperativelevel sets the collaboration mode, and setproperty sets the buffer mode. Because these function methods have many parameters, I will not explain their functions in detail one by one. Please directly view the help information of DirectX, which is clearly written.

After completing these tasks, we call the acquire method of the directinputdevice object to activate the access permission to the device. Note that a directinput device cannot be accessed without acquire. Also, when the system switches to another process, the unacquire method must be used to release the access permission. When the system switches back to this process, acquire is called to obtain the access permission again.

Therefore, we usually need to do the following in windowproc:

Long Far Pascal windowproc (hwnd, uint message, wparam, lparam)
{
Switch (Message)
{
Case wm_activateapp:
If (bactive)
{
If (lpkeyboard) lpkeyboard-> acquire ();
}
Else
{
If (lpkeyboard) lpkeyboard-> unacquire ();
}
Break;
...
}

Oh, by the way, the instant mode and buffer mode are also mentioned in the previous routine. In directinput, the two working modes are different.

If the current mode is used, only the device status at the time of query can be returned when querying data. The buffer mode records the status changes of all devices. In my personal preferences, I prefer the latter, because this generally does not lose any key information. Correspondingly, if the query frequency is too low when the former is used, it is difficult to guarantee the integrity of the collected data.

Directinput Data Query

Data Query in instant mode is relatively simple. See the following example:

Byte diks [256]; // directinput keyboard state buffer keyboard State Data Buffer

Hresult updateinputstate (void)
{
If (lpkeyboard! = NULL) // If the lpkeyboard object interface exists
{
Hresult hr;

HR = dierr_inputlost; // prepare for loop detection

// If input is lost then acquire and keep trying
While (hR = dierr_inputlost)
{
// Read the input device status value to the status data buffer
HR = lpkeyboard-> getdevicestate (sizeof (diks), & diks );

If (hR = dierr_inputlost)
{
// Directinput reports that the input stream is interrupted
// You must call the acquire method again and try again.
HR = lpkeyboard-> acquire ();
If (failed (HR ))
Return hr;
}
}

If (failed (HR ))
Return hr;
}

Return s_ OK;
}

In the preceding example, the key is to use the getdevicestate method to read the input device status value and handle exceptions. By using the getdevicestate method, we put the status value of the input device in a 256-byte array. If the highest bit of an array element in the array is 1, it indicates that the key encoded accordingly is being pressed. For example, if diks [1] & 0x80> 0, the ESC key is being pressed.

After learning the data query in the instant mode, we will start to study the buffer mode:

Hresult updateinputstate (void)
{
Dword I;

If (lpkeyboard! = NULL)
{
Dideviceobjectdata didod [dinput_buffersize]; // calls es buffered data
DWORD dwelements;
Hresult hr;

HR = dierr_inputlost;

While (HR! = Di_ OK)
{
Dwelements = dinput_buffersize;
HR = lpkeyboard-> getdevicedata (sizeof (dideviceobjectdata), didod, & dwelements, 0 );
If (HR! = Di_ OK)
{
// An error occurred.
// This error may be caused by a buffer overflow error in di_bufferoverflow.
// But whatever the error is, the connection with the input device is lost.

// The most serious consequence of this error is that if you press a key and haven't released it yet
// If an error occurs, the message with the key released later is lost. In this way, your program
// You may think that the key has not been released, so unexpected situations may occur.

// The current Code does not handle this error

// One way to solve this problem is to call
// Getdevicestate (), and then compare the result with the State recorded at the end of the program
// Compare to correct possible errors

HR = lpkeyboard-> acquire ();
If (failed (HR ))
Return hr;
}
}

If (failed (HR ))
Return hr;
}

// Getdevicedata () is different from getdevicestate (). After calling it,
// Dwelements indicates that several buffer records have been read for this call.

// We use a loop to process each record.

For (INT I = 0; I <dwelements; I ++)
{
// Put the processing code here
// Didod [I]. dwofs indicates that the key is pressed or released.
// Didod [I]. dwdata records the state of the key. The highest bit of low byte is 1, which indicates that the key is pressed, and 0 indicates that the key is released.
// Generally, didod [I]. dwdata & 0x80 is used for testing.
}
Return s_ OK;
}

In fact, each record also contains the dwtimestamp and dwsequence fields to record the message occurrence time and sequence number for more complex processing. This article is intended for beginners and is not intended to be discussed.

Directinput End Processing

When using directinput, we should also note that when the program ends, it must be released. The Demo code is as follows:

Void releasedinput (void)
{
If (lpdirectinput)
{
If (lpkeyboard)
{
// Always unacquire the device before calling release ().
Lpkeyboard-> unacquire ();
Lpkeyboard-> release ();
Lpkeyboard = NULL;
}
Lpdirectinput-> release ();
Lpdirectinput = NULL;
}
}

This code is very simple, that is, to call the release method to release resources for each directinput object. This process is basically the same as when using other parts of DirectX.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.