在Windows 10上使用DirectInput与XBOX One手柄并保持窗口焦点

4
我正在尝试使用DirectInput来捕获XBOX One控制器的输入信号,将其与C# WinForms应用程序相关联。我的问题是:当窗体获得焦点时,它可以很好地捕获输入信号。当窗口失去焦点时,我没有得到任何反馈。在Windows 7上,这不是一个问题。 我已经尝试在Windows 10上使用其他控制器:PS4、Logitech、方向盘等等...一切都符合预期:当窗口失去焦点时,我仍然可以得到反馈。只有XBOX One控制器在Windows 10上出现了问题。
我认为可能与这行代码有关:
dev.SetCooperativeLevel(_ctlParent, CooperativeLevel.Background | CooperativeLevel.Nonexclusive);

但即使我去掉这行代码,一切仍然表现得相同。

似乎XBOX One手柄忽略了“CooperativeLevel.Background”标志,并添加了“CooperativeLevel.Foreground”标志。这里有更多关于这些标志的信息

是否有其他熟悉此问题并找到解决方法的人?


你知道SharpDX是否使用遗留的DirectInput、XINPUT或Windows.Gaming.Input吗? - Chuck Walbourn
我非常确定它是DirectInput的包装器。我调用的API几乎与调用1对1匹配(我将其从使用DirectInput的C++程序移植过来)。 - Andy
1
好的,首先要说的是,你应该使用XINPUT或“Windows.Gaming.Input”来支持Xbox 360 / Xbox One游戏手柄,只有在使用旧版HID控制器时才回退到DirectInput。这些控制器的DirectInput支持主要用于旧游戏,因此在使用该仿真时会有一些怪癖。 - Chuck Walbourn
@ChuckWalbourn,谢谢您--我将去研究一下,看看这是否适用于我们的解决方案。感谢您抽出时间来帮助。 - Andy
嘿@ChuckWalbourn,这对我有用!如果您就XINPUT问题提供答案,我会接受它。命名空间“Windows.Gaming.Input”适用于UWP应用程序,但我找到了一个.NET包装器(https://github.com/speps/XInputDotNet)。再次感谢您的所有帮助。 - Andy
2个回答

5
我一直在探索有关XBox One控制器的内容,每个API在处理XBox One和XBox360控制器时都有自己的限制。
以下是我所学到的内容摘要: Windows.Gaming.Input ref 在Windows 10上可以使用无限数量的控制器。(直到最近,我认为限制是8,但我已经测试了9个XBox 360/XBox One控制器,因此DirectXTK中的MAX_PLAYER_NUMBER=8并没有根据Windows 10的实际限制设置。ref
限制:
  • 控制器无法在后台访问...
    (虽然不确定。我自己没有让控制器在后台工作,文档中说这是UWP应用的限制。ref)
  • 仅适用于UWP设备(例如Windows 10、XBox One、Windows平板电脑等)
  • Gamepad类仅支持Xbox One认证或Xbox 360兼容游戏手柄(ref),其他游戏手柄可以通过RawGameController类访问(ref)。

XInput ref

这是一个用于访问四个XInput兼容控制器(例如XBox 360或XBox One控制器)的API。

  • XInput控制器可以在后台访问。

限制:

  • 最多支持4个控制器。
  • 仅支持XInput兼容设备。
  • 无法激活XBox One控制器扳机上额外的两个振动马达。(使用Windows.Gaming.Input来实现。)

DirectInput ref

这些API中最古老的一个。
可以连接无限数量的控制器(?)

限制:

  • XBox One控制器不能在后台访问。(是Bug还是特性?)
  • XBox 360和XBox One控制器在同一轴上有扳机,没有指南针按钮和震动。
  • Windows Store应用程序无法使用DirectInput。ref
  • 微软不再推荐使用DirectInput。ref

原始输入 ref

控制器数量不限(缺乏参考。已测试9个控制器)。

  • XBox One和其他控制器可以在后台访问。
    (使用此源代码进行尝试:ref)

限制:

  • XBox 360和XBox One的控制器在同一轴上有扳机,没有指南针按钮,可能没有震动。(使用此源代码测试ref

如果有人曾经成功在非UWP/Windows Store应用程序中使用Windows.Gaming.Input访问后台控制器,请在评论中告诉我。 - supersmo
编写了一个使用WinRT API在运行时加载的本地Windows应用程序(使用LoadLibrary和GetProcAddress),并使用Windows.Gaming.Input类。似乎在窗口没有焦点时震动效果正常,没有问题。 - DJm00n
@DJm00n,你有没有在开源代码库中的工作示例代码可以参考?我有一个使用案例,需要在后台访问,这将非常有用。 - supersmo
根据我的了解,Windows.gaming.input仅在有窗口且该窗口处于焦点状态时才会运行。有关详细信息以及我的测试存储库链接,请参见https://stackoverflow.com/questions/57042069/xbox-360-wireless-controller-is-not-working-via-c-winrt-and-windows-gaming-inp。 - DJm00n
1
谢谢DJm00N!我也认为控制器无法通过Windows.Gaming.Input在后台访问,但是你之前的帖子给了我一些希望。感谢你澄清了这个困惑。 - supersmo

1
Xbox 360通用手柄驱动程序和Xbox One手柄驱动程序都模拟“HID”,以便与旧游戏使用的遗留DirectInput API兼容,但模拟往往会出现一些问题,比如这个问题。
最好的解决方案可能是仅针对旧版HID控制器使用DirectInput,并针对这些控制器使用XINPUT。对于Windows 10 DirectX 12 / UWP应用程序,您也可以直接使用“Windows.Gaming.Input”。
请参见XINPUT and Windows 8DirectX Tool Kit: Now with GamePads

有点跑题,但我会回答。每次只能有一个窗口接收来自游戏手柄的xinput/direct-input输入消息,对吧? - KeyC0de
嗨,Chuck。在UWP文档中提到了以下声明:“Windows应用程序必须具有焦点才能从Xbox One控制器接收输入。”。 这表明Xbox One控制器在某种意义上是“特殊的”,即使使用最新的可用API,它仍然以这种不理想的方式运作,因此我很困惑你将其称为遗留API仿真的怪癖。 这个控制器的驱动程序堆栈是否只是有缺陷的?很难将其视为任何一种功能... - Neilski
"Windows.Gaming.Input" 是用于 UWP 游戏手柄输入的 API,只有当应用程序处于焦点状态时才接受输入。实际上,XInput 不支持 UWP。 "xinput_uap.lib" 只是一个围绕 Windows.Gaming.Input 的 XINPUT API 包装器。 - Chuck Walbourn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接