我需要使用 IDirectInputDevice8 界面对直接输入设备进行阻止和非阻止 调用进行轮询。
在linux中进行阻止,我们使用选择 ex:
while( ::select(_jdev+1, &set, NULL, NULL, &tv) > 0)
{
if( ::read( _jdev, &js, sizeof( js_event ) ) != sizeof( js_event ) )
{
perror( "Joystick : read error" );
return;
}
_handleEvent( js );
}
如何使用 idirectinputdevice8 界面执行相同的操作: https://msdn.microsoft.com/en-us/library/windows/desktop/ee417816(v=vs.85).aspx
即使我设置 IDirectInputDevice8 :: SetEventNotification(),我仍然必须每次调用poll()来获取新数据,这是不可行的解决方案,因为它会导致cpu旋转。
我怎样才能做到这一点?
***目前,我可以从操纵杆设备中查找,迭代,连接和获取数据。我只是没有实施阻止调用。
...这是我的实验/测试代码...请忽略语法错误
#include <windows.h>
#include <dinput.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include "joystick.h"
LPDIRECTINPUT8 di;
HRESULT hr;
LPDIRECTINPUTDEVICE8 joystick;
DIDEVCAPS capabilities;
BOOL CALLBACK
enumCallback(const DIDEVICEINSTANCE* instance, VOID* context)
{
HRESULT hr;
hr = di->CreateDevice(instance->guidInstance, &joystick, NULL);
if (FAILED(hr)) {
return DIENUM_CONTINUE;
}
return DIENUM_STOP;
}
int JoyStickProp()
{
if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick2))) {
return hr;
}
if (FAILED(hr = joystick->SetCooperativeLevel(NULL, DISCL_EXCLUSIVE |
DISCL_FOREGROUND))) {
return hr;
}
capabilities.dwSize = sizeof(DIDEVCAPS);
if (FAILED(hr = joystick->GetCapabilities(&capabilities))) {
return hr;
}
}
HRESULT JoyStickPoll(DIJOYSTATE2 *js)
{
HRESULT hr;
if (joystick == NULL) {
return S_OK;
}
// Poll the device to read the current state
hr = joystick->Poll();
if (FAILED(hr)) {
hr = joystick->Acquire();
while (hr == DIERR_INPUTLOST) {
hr = joystick->Acquire();
}
if ((hr == DIERR_INVALIDPARAM) || (hr == DIERR_NOTINITIALIZED)) {
return E_FAIL;
}
// If another application has control of this device, return successfully.
// We'll just have to wait our turn to use the joystick.
if (hr == DIERR_OTHERAPPHASPRIO) {
return S_OK;
}
}
// Get the input's device state
if (FAILED(hr = joystick->GetDeviceState(sizeof(DIJOYSTATE2), js))) {
return hr; // The device should have been acquired during the Poll()
}
return S_OK;
}
int main()
{
// Create a DirectInput device
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (VOID**)&di, NULL))) {
return hr;
}
// Look for the first simple joystick we can find.
if (FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback,
NULL, DIEDFL_ATTACHEDONLY))) {
return hr;
}
// Make sure we got a joystick
if (joystick == NULL) {
printf("Joystick not found.\n");
return E_FAIL;
}
JoyStickProp();
DIJOYSTATE2 diState;
HANDLE ghWriteEvent;
// Create joystick event stuff here
ghWriteEvent = CreateEvent(
NULL, // default security attributes
FALSE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
//makesure we can read fromt the joystick before waiting for an event
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
JoyStickPoll(&diState);
printf("x axis %d", diState.lX);
printf("y axis %d", diState.lY);
joystick->SetEventNotification(ghWriteEvent);
while (TRUE) {
DWORD dwResult = WaitForSingleObject(
ghWriteEvent, // event handle
INFINITE);
switch (dwResult) {
case WAIT_OBJECT_0:
// Event 1 has been set. If the event was created as
// autoreset, it has also been reset.
int x = 0;
//ProcessInputEvent1();
break;
}
}
}
答案 0 :(得分:1)
IDirectInputDevice8::SetEventNotification()
的MSDN文档为您提供了相关的代码段。
您需要致电CreateEvent()
并将返回的HANDLE
作为参数提供给SetEventNotification()
。当状态发生变化时,将向您发出事件信号。您可以等待该事件,然后在收到通知后,您将使用IDirectInputDevice8::GetDeviceState()
获取新的状态数据。
所有标准Wait Functions适用于等待发出信号的事件。以下代码段使用MsgWaitForMultipleObjects()
:
while (TRUE) {
dwResult = MsgWaitForMultipleObjects(2, ah, FALSE, INFINITE, QS_ALLINPUT);
switch (dwResult) {
case WAIT_OBJECT_0:
// Event 1 has been set. If the event was created as
// autoreset, it has also been reset.
ProcessInputEvent1();
break;
IDirectInputDevice8::Poll()
方法用于不生成事件通知的设备。您应该轮询它们,因为它们无法以您希望的方式运行。
一些操纵杆和其他游戏设备,或其上的特定物体,do not generate hardware interrupts and do not return any data or signal any events until you call the
IDirectInputDevice8::Poll
method。
只有当您需要通知设备时,才会进行投票。上面的链接解释了如何确定是否有必要进行轮询。