极简主义DirectX开发第一弹:DirectInput手柄操作

 

目的:简化开发学习过程,以最小代码清晰展示某功能的实现。
手柄设备和键盘鼠标是不同的,因为手柄不是必须的输入设备,因此系统没有事先定义好GUID供用户调用,并且手柄设备差异很大,因此只能用轮询来获得手柄设备的ID.
本文为新手解释了如何初始化DirectInput设备为手柄,高手请忽略。
 
整体思路是这样的,首先创建DirectInput对象,之后用这个对象来轮询设备,从而获得可用的设备ID,之后通过这个ID来创建设备:
#include "stdafx.h"
#include <dinput.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "DXGuid.lib")//unresolved external symbol for guid


#define JOYSTICK_BUTTON_STATE(x) ((joy_state.rgbButtons[x] &0x80) ? TRUE : FALSE)
#define MY_BUFSIZE 1024

//This is the callback function that takes the 2nd arguement pretty useful for handling DI in a class
BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext)
{																		//Name of general usb pad device "  USB  Joystick  ", but don't forget the white spaces
	if (0 == wcscmp(pdidInstance->tszProductName, L"  USB  Joystick  "))//You can also create the device within the callback and pass the device address
	{																	//Thus, you don't have to enum the device by the name 
		GUID* t;
		t = (GUID*)pContext;//Retrieving the GUID thru the 2nd param
		*t = pdidInstance->guidInstance;//Now t takes over the pGuid, so the address of GUID in calling func is t.		//if(SUCCEEDED(pContext -> CreateDevice(pdidInstance->guidInstance, &lpJoystick, NULL)))...and then pass the lpJoystick thru pContext again
		return DIENUM_STOP;
	}
	return DIENUM_CONTINUE;
}

LRESULT InitDI(LPDIRECTINPUT8* lpdi, LPDIRECTINPUTDEVICE8* lpdev)
{
	GUID id;
	auto result = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)lpdi, NULL);

	(*lpdi)->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, &id, DIEDFL_ATTACHEDONLY);//id can be retrieved by the 3rd param
	(*lpdi)->CreateDevice(id, lpdev, NULL);//The * mark is very tricky that it gets the content of the pointer. 
        (*lpdev)->SetDataFormat(&c_dfDIJoystick);//All the secret is here if it is necessary to avoid globals or statics.
	HWND hwndFound;         
	wchar_t pszOldWindowTitle[MY_BUFSIZE]; 
	GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
	hwndFound = FindWindow(NULL, pszOldWindowTitle);//locate hwnd in a console app
	(*lpdev)->SetCooperativeLevel(hwndFound, DISCL_BACKGROUND | DISCL_EXCLUSIVE);
	if (FAILED((*lpdev)->Acquire()))
	{
		MessageBox(hwndFound, L"Cannot acquire joystic!", L"Error", MB_ICONERROR); 
		return E_FAIL;
	}
	return S_OK;
}


int main()
{
	LPDIRECTINPUT8 lpDI = nullptr;
	LPDIRECTINPUTDEVICE8 lpjsDev = nullptr;
	InitDI(&lpDI, &lpjsDev);
	DIJOYSTATE      joy_state;
	bool f = true;
	lpjsDev->Poll();
	while (f)
	{
		lpjsDev->GetDeviceState(sizeof(DIJOYSTATE), &joy_state);
		if (JOYSTICK_BUTTON_STATE(0))
		{
			cout << "This is to test if the joystick device is etablished." << endl;
		}
		if (JOYSTICK_BUTTON_STATE(8))
			f = false;
	}
	lpjsDev->Unacquire();
	lpjsDev->Release();
	lpDI->Release();
	return 0;
}  
由于与回调函数内通讯比较困难,微软特意留了一个 pContext可以从 EnumDevices的第三个参数取回东西,因此在封装到类时,可以通过这个参数传递GUID或者DirectInput对象,避免使用全局变量或者初始化静态变量(回调函数需要在类中声明为静态,内部不能使用类成员)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值