Beginners Direct X (3)
1. Get peripheral input - keyboard and mouse
Whether it is to obtain a mouse or keyboard device, you must first initialize DirectInput, but first configure the necessary environment:
the header files and library files to be used are (compared to the previous two):
#include <dinput.h>
#pragma comment(lib,"dinput8.lib")
#pragma comment(lib,"dxguid.lib")
And the DirectInput objects and device (including keyboard and mouse) objects to be used:
LPDIRECTINPUT8 dinput;
LPDIRECTINPUTDEVICE8A dikeyboard;
LPDIRECTINPUTDEVICE8A dimouse;
Start to initialize DirectInput after preparation:
HRESULT DirectInput8Create(
HINSTANCE hinst, // 可以通过GetModuleHandle(NULL)
DWORD dwVersion, // DirectInput版本,通常是DIRECTINPUT_VERSION
REFIID riidltf, // 使用的DirectInput版本的引用标识符,我这儿是IID_IDirectInput8
LPVOID * ppvOut, //指向DirectInput对象指针的指针
LPUNKNOWN punkOuter //总是NULL
);
Here is an example of a call:
HRESULT result = DirectInput8Create(
GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(void **)&dinput,
NULL
);
At this point, the initialization of DirectInput has been completed
2. Initialize the keyboard
After initializing DirectInput, you can create a keyboard device by calling the CreateDevice function
HRESULT CreateDevice(
THIS_ REFGUID,
LPDIRECTINPUTDEVICE8A *lplpDirectInputDevice,
LPUNKNOWN pUnkouter
);
REFGUID : Specifies the type of object to create, such as keyboard or mouse, the keyboard is GUID_SysKeyboard, the mouse is GUID_SysMouse
lplpDirectInputDevice : The address of the device that receives the DirectInput device handle
pUnkouter : always NULL
2.1 Set the data format
This step is to set the data format of the keyboard and tell DirectInput how to pass the data to the program. This is a unified reading method for various input devices on the market.
HRESULT SetDataFormat(
LPCDIDATAFORMAT lpdf
)
lpdf : We don't need to define it ourselves, it is defined in dinput, c_dfDIKeyboard for the keyboard, c_dfDIMouse for the mouse
2.2 Setting the collaboration level
This step is to set the cooperation level, which determines the priority of DirectInput to pass keyboard input to the program
HRESULT SetCooperativeLevel(
HWND hwnd,
DWORD
)
dwFlags : The most commonly used is DISCL_NONEXCLUSIVE | DISCL_FOREGROUND
2.3 Get the device
This step is also a harvest step, which is to use Acquire to obtain the device
HRESULT Acquire()
If you don't use Unacquire() to release the device at the end of the program, it may cause DirectInput and keyboard handles to be in an unknown state, which is not friendly to old Windows, although modern Windows will automatically handle this.
2.4 Get keyboard input
Get the input of the device through GetDeviceState, no matter what the input device is, it is a standard
HRESULT GetDeviceState(
DWORD cbData,
LPVOID lpvData
)
For the keyboard, an array of keys needs to be defined:
// 对应于cbData,sizeof(keys)
// 对应于lpvData,(LPVOID)&keys
char keys[256];
Check the data in the keys array as follows:
if (key[DIK_A] & 0x80){
// do samething
}
2.6 Get the full version of keyboard input
The complete procedure for getting keyboard input is as follows:
bool init_input(HWND window){
// 初始化DirectInput
HRESULT result = DirectInput8Create(
GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(void **)&dinput,
NULL
);
if (result != DI_OK) return false;
// 创建DirectInput的keyboard
result = dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL);
if (result != D3D_OK) return false;
// 设置数据格式
result = dikeyboard->SetDataFormat(&c_dfDIKeyboard);
if (result != DI_OK) return false;
// 设置协作级别
result = dikeyboard->SetCooperativeLevel(window,DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
if (result != DI_OK) return false;
// 获取设备
result = dikeyboard->Acquire();
if (result != DI_OK) return false;
return true;
}
//响应键盘输入
void key_update(){
LRESULT result = dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)(&keys));
if (result != DI_OK) return;
if (keys[DIK_A] & 0x80){
X--;
}
else if (keys[DIK_S] & 0x80){
Y++;
}
else if (keys[DIK_D] & 0x80){
X++;
}
else if (keys[DIK_W] & 0x80){
Y--;
}
}
3. Initialize the mouse
After understanding the mechanism of initializing the keyboard, initializing the mouse seems to be very simple. Before reading the mouse input, most of them just pass in a logo that is different from the keyboard. If they are different, I will mark them with [different].
ZeroMemory(keys, sizeof(keys));
// 初始化DirectInput
HRESULT result = DirectInput8Create(
GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(void **)&dinput,
NULL
);
if (result != DI_OK) return false;
// 创建DirectInput的mouse对象
result = dinput->CreateDevice(GUID_SysMouse[异], &dimouse, NULL);
if (result != D3D_OK) return false;
// 设置数据格式
result = dimouse->SetDataFormat(&c_dfDIMouse[异]);
if (result != DI_OK) return false;
// 设置协作级别
result = dimouse->SetCooperativeLevel(window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
if (result != DI_OK) return false;
// 获取设备
result = dimouse->Acquire();
if (result != DI_OK) return false;
3.1 Get mouse input
It also uses the standard acquisition function GetDeviceState, but the acquired data has changed, it is:
DIMOUSESTATE mouse_state;
You can also use DIMOUSESTATE2, which gets more keys
The get function is as follows:
result = dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state);
It's worth noting here that in the DIMOUSESTATE structure:
typedef struct _DIMOUSESTATE {
LONG lX;
LONG lY;
LONG lZ;
BYTE rgbButtons[4];
}
lX , lY , lZ are only relative movement coordinates relative to the previous frame of the mouse. In rgbButtons ,
rgbButtons[0] is the left mouse click,
rgbButtons[1] is the left mouse click, and
rgbButtons[2] is the mouse wheel down
The code for judging to get the input is as follows:
if(mouse_state.rgbButtons[0] & 0x80)
{
//do samething
}