通过代码校准游戏控制器

时间:2018-07-18 14:16:10

标签: c# .net wpf window

我希望从C#WPF应用程序复制校准过程。互联网上有类似的应用程序,例如DIView

DIView calibration procedure

DXTweak

DXTweak calibration procedure

但是,此过程很繁琐,因为要求您为每个轴选择最小值,中间值和最大值。

我有自己的游戏杆板,Windows认为它是游戏控制器。我可以使用DirectInput或任何其他库读取其值。当使用这两个应用程序之一来校准操纵杆时,当我使用DirectInput轮询值时,实际上可以得到结果。肯定有一种方法可以通过代码完成。

我的目标是开发一个可同时校准多个轴的应用程序。我相信DirectInput可以处理此类任务,或者Windows注册表将它们存储在某个地方。可悲的是,在Google上搜索了几个小时后,结果还不够(请证明我错了!)。

编辑:

DirectInput API中有DeviceProperties.GetCalibrationPointsDeviceProperties.SetCalibrationPoints函数,但是我不知道如何使用它们。

这里是documentation

我尝试获取像这样的校准点:MyDevice.GetCalibrationPoints(ParameterHow.ByUsage, MyDevice.DeviceInformation.Usage);,但我想我做错了,因为遇到了-2147024894 (ERROR_FILE_NOT_FOUND)异常。

2 个答案:

答案 0 :(得分:1)

好的,这就是我在注册表中找到的内容。它有点长,但我可以正常工作。

使用regedit,您可以使用以下路径找到DirectInput设备的列表:Computer\HKEY_CURRENT_USER\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput

DirectInput registry

通过选择所需的设备,最终最终得到以下路径:Computer\HKEY_CURRENT_USER\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\YOUR_DEVICE_HERE\Calibration\0\Type\Axes。如果您在该注册表中看不到其他任何内容,则表明您的轴尚未进行校准。

使用C#,您可以使用以下函数并通过将其转换为字节数组来读取注册表中每个轴的校准值:

Byte[] Axis = Registry.GetValue(registry + '0', "Calibration", "EMPTY") as Byte[];

您可以更改每个轴的'0'

如果注册表不存在,请确保处理异常,这意味着您的路径无效或之前从未校准过所需的Axis(因此使用默认值)。

在使用结果数组时,我还注意到了一些不同之处,这些值以一种奇怪的方式存储:

  • 数组的长度为12,校准的 min 值存储在前4个字节中,然后4个中间的存储值用于中间校准值,最后4个为 max

  • 要读取每个部分的实际值,您需要将每个部分的第二个字节乘以256,然后将其添加到第一个字节: int min = 256 * Axis[1] + Axis[0];

最后,如果您想编写自己的校准值,则只需使用以下功能Registry.SetValue(regPath + '0', "Calibration", ByteArray);

不要忘记为每个轴更改'0',并在数组中使用相同的格式:

ByteArray[0] = (byte)(min % 256);
ByteArray[1] = (byte)(min / 256);
ByteArray[4] = (byte)(middle % 256);
ByteArray[5] = (byte)(middle / 256);
ByteArray[8] = (byte)(max % 256);
ByteArray[9] = (byte)(max / 256);

答案 1 :(得分:0)

我找到了部分解决方案,但我对此并不满意。

以下代码CalibrationPoint[] points = mDevice.Properties.GetCalibrationPoints(ParameterHow.ByOffset, 0);将为您提供2个CalibrationPoints对象的数组,它们对应于控制器的第一轴。如果同时显示这两个点,则外观如下:

(0) ScalingValue: 0 RawData: 0 (1) ScalingValue: 10000 RawData: 4095

困扰我的是参数。我知道ByOffset参数会为您的值数组中的值提供带偏移的位置(例如常规数组),但是我不得不以 4 而不是1的增量进行迭代得到每个轴。我找不到替代方法,例如使用sizeof(CalibrationPoint),但我知道何时停止使用设备可用的轴数进行迭代。

最后,您可以通过更改RawData值来使用这两点,并将它们作为参数传递到SetCallibrationPoints函数中以校准控制器。

编辑:

关于最后一部分,我错了,调用SetCalibrationPoint函数没有效果...