【问题标题】:Calibrating a game controller from code从代码校准游戏控制器
【发布时间】:2018-07-18 14:16:09
【问题描述】:

我希望从 C# WPF 应用程序中重现校准过程。网上也有类似的应用,比如DIView

DXTweak:

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

我有自己的操纵杆板,Windows 将其识别为游戏控制器。我可以使用 DirectInput 或任何其他库读取它的值。当使用这两个应用程序之一来校准我的操纵杆时,当我使用 DirectInput 轮询值时,我实际上可以得到结果。绝对有办法通过代码做到这一点。

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

编辑:

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

这是documentation

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

【问题讨论】:

    标签: c# .net wpf window


    【解决方案1】:

    好的,这就是我使用注册表找到的内容。这有点长,但我得到了它的工作。

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

    通过选择所需的设备,您最终会得到以下路径: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'

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

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

    • 数组长度为12,前4个字节存放校准的min值,后4个为middle校准值,以及 ma​​x 的最后 4 个值。

    • 要读取每个部分的实际值,您需要将每个部分的第二个字节乘以 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);
    

    【讨论】:

      【解决方案2】:

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

      以下代码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函数没有效果...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        • 1970-01-01
        • 2012-05-09
        • 1970-01-01
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多