Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Önemli
Microsoft Game Development Kit (GDK)aracılığıyla PC ve Xbox'ta desteklenen yeni nesil giriş API'sinin ayrıntıları için bkz. GameInput API.
Bu belgede XInput ve DirectInput denetleyici girişi uygulamaları ve hem XInput cihazları hem de eski DirectInput cihazları nasıl desteklenmektedir.
Windows Mağazası uygulamaları directInput desteklemez.
Genel bakış
XInput, uygulamaların XUSB denetleyicilerinden giriş almasını sağlar. API'ler DirectX SDK'sı aracılığıyla, sürücü ise Windows Update aracılığıyla kullanılabilir.
DirectInputyerine XInput kullanmanın çeşitli avantajları vardır:
- XInput kullanımı daha kolaydır ve DirectInput daha az kurulum gerektirir
- Hem Xbox hem de Windows programlaması aynı çekirdek API kümelerini kullanarak programlamanın platformlar arası çeviriyi çok daha kolay hale getirebilmesini sağlar
- Yüklü büyük bir denetleyici tabanı olacaktır
- XInput cihazı yalnızca XInput API'lerini kullanırken titreşim işlevselliğine sahip olur
DirectInput ile XUSB denetleyicilerini kullanma
XUSB denetleyicileri, DirectInputüzerinde düzgün numaralandırılır ve DirectInputAPIs ile kullanılabilir. Ancak, XInput tarafından sağlanan bazı işlevler DirectInput uygulamasında eksik olacaktır:
- Sol ve sağ tetikleyici düğmeleri bağımsız olarak değil tek bir düğme olarak çalışır
- Titreşim efektleri kullanılamayacak
- Kulaklık cihazları için sorgulama kullanılamayacak
DirectInput sol ve sağ tetikleyicilerin birleşimi tasarım gereğidir. Oyunlar her zaman, cihazla kullanıcı etkileşimi olmadığında DirectInput cihaz eksenlerinin ortalandığını varsayar. Ancak daha yeni denetleyiciler, tetikleyiciler tutulmadığında en düşük değeri kaydedecek şekilde tasarlanmıştır. Bu nedenle eski oyunlar kullanıcı etkileşimi olduğunu varsayar.
Çözüm tetikleyicileri birleştirmek, tetikleyicilerden birini pozitif yönde, diğerini negatif yönde ayarlamaktı, bu nedenle hiçbir kullanıcı etkileşiminin ortada olan "denetimin" DirectInput göstermemesi.
Tetikleyici değerlerini ayrı olarak test etmek için XInput kullanmanız gerekir.
XInput ve DirectInput Yan Yana
Yalnızca XInput'u destekleyerek, oyununuz eski DirectInput cihazlarıyla çalışmaz. XInput bu cihazları tanımaz.
Oyununuzun eski DirectInput cihazları desteklemesini istiyorsanız DirectInput ve XInput'u yan yana kullanabilirsiniz. DirectInput cihazlarınızı numaralandırırken, tüm DirectInput cihazları doğru numaralandırılır. Tüm XInput cihazları hem XInput hem de DirectInput cihazları olarak görünür, ancak DirectInput aracılığıyla işlenmemelidir. DirectInput cihazlarınızdan hangilerinin eski cihazlar olduğunu ve hangilerinin XInput cihazları olduğunu belirlemeniz ve bunları DirectInput cihazlarının numaralandırmasından kaldırmanız gerekir.
Bunu yapmak için bu kodu DirectInput numaralandırma geri aramanıza ekleyin:
#include <wbemidl.h>
#include <oleauto.h>
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } }
#endif
//-----------------------------------------------------------------------------
// Enum each PNP device using WMI and check each device ID to see if it contains
// "IG_" (ex. "VID_0000&PID_0000&IG_00"). If it does, then it's an XInput device
// Unfortunately this information cannot be found by just using DirectInput
//-----------------------------------------------------------------------------
BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
{
IWbemLocator* pIWbemLocator = nullptr;
IEnumWbemClassObject* pEnumDevices = nullptr;
IWbemClassObject* pDevices[20] = {};
IWbemServices* pIWbemServices = nullptr;
BSTR bstrNamespace = nullptr;
BSTR bstrDeviceID = nullptr;
BSTR bstrClassName = nullptr;
bool bIsXinputDevice = false;
// CoInit if needed
HRESULT hr = CoInitialize(nullptr);
bool bCleanupCOM = SUCCEEDED(hr);
// So we can call VariantClear() later, even if we never had a successful IWbemClassObject::Get().
VARIANT var = {};
VariantInit(&var);
// Create WMI
hr = CoCreateInstance(__uuidof(WbemLocator),
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWbemLocator),
(LPVOID*)&pIWbemLocator);
if (FAILED(hr) || pIWbemLocator == nullptr)
goto LCleanup;
bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == nullptr) goto LCleanup;
bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == nullptr) goto LCleanup;
bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == nullptr) goto LCleanup;
// Connect to WMI
hr = pIWbemLocator->ConnectServer(bstrNamespace, nullptr, nullptr, 0L,
0L, nullptr, nullptr, &pIWbemServices);
if (FAILED(hr) || pIWbemServices == nullptr)
goto LCleanup;
// Switch security level to IMPERSONATE.
hr = CoSetProxyBlanket(pIWbemServices,
RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr, EOAC_NONE);
if ( FAILED(hr) )
goto LCleanup;
hr = pIWbemServices->CreateInstanceEnum(bstrClassName, 0, nullptr, &pEnumDevices);
if (FAILED(hr) || pEnumDevices == nullptr)
goto LCleanup;
// Loop over all devices
for (;;)
{
ULONG uReturned = 0;
hr = pEnumDevices->Next(10000, _countof(pDevices), pDevices, &uReturned);
if (FAILED(hr))
goto LCleanup;
if (uReturned == 0)
break;
for (size_t iDevice = 0; iDevice < uReturned; ++iDevice)
{
// For each device, get its device ID
hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, nullptr, nullptr);
if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != nullptr)
{
// Check if the device ID contains "IG_". If it does, then it's an XInput device
// This information cannot be found from DirectInput
if (wcsstr(var.bstrVal, L"IG_"))
{
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0;
WCHAR* strVid = wcsstr(var.bstrVal, L"VID_");
if (strVid && swscanf_s(strVid, L"VID_%4X", &dwVid) != 1)
dwVid = 0;
WCHAR* strPid = wcsstr(var.bstrVal, L"PID_");
if (strPid && swscanf_s(strPid, L"PID_%4X", &dwPid) != 1)
dwPid = 0;
// Compare the VID/PID to the DInput device
DWORD dwVidPid = MAKELONG(dwVid, dwPid);
if (dwVidPid == pGuidProductFromDirectInput->Data1)
{
bIsXinputDevice = true;
goto LCleanup;
}
}
}
VariantClear(&var);
SAFE_RELEASE(pDevices[iDevice]);
}
}
LCleanup:
VariantClear(&var);
if(bstrNamespace)
SysFreeString(bstrNamespace);
if(bstrDeviceID)
SysFreeString(bstrDeviceID);
if(bstrClassName)
SysFreeString(bstrClassName);
for (size_t iDevice = 0; iDevice < _countof(pDevices); ++iDevice)
SAFE_RELEASE(pDevices[iDevice]);
SAFE_RELEASE(pEnumDevices);
SAFE_RELEASE(pIWbemLocator);
SAFE_RELEASE(pIWbemServices);
if(bCleanupCOM)
CoUninitialize();
return bIsXinputDevice;
}
//-----------------------------------------------------------------------------
// Name: EnumJoysticksCallback()
// Desc: Called once for each enumerated joystick. If we find one, create a
// device interface on it so we can play with it.
//-----------------------------------------------------------------------------
BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
VOID* pContext )
{
if( IsXInputDevice( &pdidInstance->guidProduct ) )
return DIENUM_CONTINUE;
// Device is verified not XInput, so add it to the list of DInput devices
return DIENUM_CONTINUE;
}
Bu kodun biraz geliştirilmiş bir sürümü eski DirectInput Oyun Çubuğu örneğindedir.
İlgili konular
XInput Kullanmaya Başlama