使用Windows.Media.Devices.FocusControl控制HoloLens 2焦点时ArgumentException报错
HoloLens 2 手动控制焦点触发 ArgumentException 的解决方法
问题现象
在HoloLens 2上使用Windows.Media.Devices.FocusControl手动控制焦点时,调用FocusControl.Configure(FocusSettings)或FocusControl.SetValueAsync(UInt32)会抛出ArgumentException: Value does not fall within the expected range错误。已确认输入值在设备返回的支持范围(最小值170、最大值10000)内,且未使用FocusControl时拍照功能正常。
核心原因
- 共享模式限制:初始化
MediaCapture时使用SharedReadOnly模式,该模式仅允许读取相机参数,无法修改焦点等控制项。 - 配置顺序错误:未正确启用FocusControl的手动模式,或步骤顺序颠倒导致配置未生效。
- 焦点值未对齐Step:即使值在Min/Max范围内,未按设备支持的Step值对齐也会触发错误。
解决方案
1. 切换MediaCapture至独占控制模式
将MediaCaptureInitializationSettings的SharingMode改为ExclusiveControl,获取相机的独占控制权以修改参数:
var settings = new MediaCaptureInitializationSettings { SharingMode = MediaCaptureSharingMode.ExclusiveControl };
2. 按正确顺序配置并启用FocusControl
必须遵循「配置手动模式 → 启用 → 锁定 → 设置值」的顺序:
- 创建
FocusSettings并设置Mode = FocusMode.Manual,同时开启Enabled = true - 调用
focusControl.Configure应用配置 - 调用
LockAsync锁定焦点控制,避免其他操作干扰 - 设置焦点值后记得解锁
3. 对齐焦点值至设备支持的Step
使用设备返回的Step值对输入焦点值进行对齐,确保值为Min + N * Step(N为整数):
private uint AlignFocusValue(FocusControl focusControl, uint inputValue) { uint min = focusControl.Min; uint max = focusControl.Max; uint step = focusControl.Step; inputValue = Math.Clamp(inputValue, min, max); uint offset = inputValue - min; uint alignedOffset = (offset / step) * step; return min + alignedOffset; }
修正后的完整代码
async private void CaptureImageByMediaCapture() { MediaCapture mediaCapture = new MediaCapture(); var settings = new MediaCaptureInitializationSettings { SharingMode = MediaCaptureSharingMode.ExclusiveControl }; await mediaCapture.InitializeAsync(settings); var focusControl = mediaCapture.VideoDeviceController.FocusControl; if (focusControl.Supported) { Debug.Log($"焦点范围:Min={focusControl.Min}, Max={focusControl.Max}, Step={focusControl.Step}"); // 配置并启用手动调焦 var focusSettings = new FocusSettings { Mode = FocusMode.Manual, Enabled = true }; focusControl.Configure(focusSettings); // 锁定焦点控制 await focusControl.LockAsync(); // 对齐焦点值并设置 uint targetFocus = AlignFocusValue(focusControl, focusvalue); await focusControl.SetValueAsync(targetFocus); Debug.Log($"已成功设置焦点值:{targetFocus}"); // 执行拍照逻辑... // 操作完成后解锁 await focusControl.UnlockAsync(); } else { Debug.Log("当前相机不支持手动焦点控制"); } } // 对齐焦点值到设备支持的步进值 private uint AlignFocusValue(FocusControl focusControl, uint inputValue) { uint min = focusControl.Min; uint max = focusControl.Max; uint step = focusControl.Step; inputValue = Math.Clamp(inputValue, min, max); uint offset = inputValue - min; uint alignedOffset = (offset / step) * step; return min + alignedOffset; }
额外注意事项
- 独占模式会阻止其他应用使用相机,操作完成后建议调用
mediaCapture.Dispose()释放资源 - 若存在多个相机,可添加辅助方法筛选出支持手动调焦的设备ID
内容的提问来源于stack exchange,提问作者Titin Zu
相关产品推荐
相关产品推荐

