Я хочу воспроизвести процедуру калибровки из приложения C# WPF. В Интернете есть похожие приложения, например DIView:
и DXTweak:
Однако процедура утомительна, так как вас просят выбрать минимальное, среднее и максимальное значение для каждой оси.
У меня есть собственная плата джойстика, которая распознается Windows как игровой контроллер. Я могу читать его значения с помощью DirectInput или любых других библиотек. При использовании одного из этих двух приложений для калибровки джойстика я действительно могу получить результаты, когда опрашиваю значения с помощью DirectInput. Определенно есть способ сделать это с помощью кода.
Моей целью было бы разработать приложение для одновременной калибровки нескольких осей. Я считал, что DirectInput может справиться с такого рода задачами или что реестры Windows где-то их хранят. К сожалению, после нескольких часов поиска в Google результатов не хватило (пожалуйста, докажите, что я ошибаюсь!).
Обновлено:
В API DirectInput есть функции DeviceProperties.GetCalibrationPoints и DeviceProperties.SetCalibrationPoints, но я понятия не имею, как их использовать.
Вот документация.
Я пробовал получить точки калибровки следующим образом: MyDevice.GetCalibrationPoints(ParameterHow.ByUsage, MyDevice.DeviceInformation.Usage);, но я думаю, что делаю это неправильно, потому что получаю исключение -2147024894 (ERROR_FILE_NOT_FOUND).





Я нашел частичное решение, и мне оно не очень понравилось.
Следующий код 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 не подействовал ...
Хорошо, вот что я нашел с помощью реестров. Это немного долго, но у меня это работает.
Используя 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 байтах, затем 4 средних байта для значения середина калибровки и 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);