이 문서에서는 일반적인 상호 작용 패턴에 대한 코드 예제를 포함하여 InputHapticsManager API를 사용하여 Windows 앱에 촉각 피드백을 추가하는 방법을 설명합니다.
촉각을 사용하는 시기와 이유에 대한 디자인 지침은 Haptics 디자인 지침을 참조하세요.
지원되는 디바이스
촉각은 마우스, 터치 패드 및 펜과 같은 입력 장치에서 지원됩니다. 가용성은 모델 및 제조업체에 따라 다릅니다. 촉각 API를 호출하기 전에 항상 런타임에 지원을 확인합니다(아래 지원 확인 참조).
Requirements
| 요구 사항 | 세부 정보 |
|---|---|
| Namespace | Windows.Devices.Haptics |
| 최소 OS | Windows 11, SDK 10.0.28000.1721(2026년 3월) |
| 정렬 / 충돌 / 단계 / 파형 증가 | SDK 10.0.28000.1839 (2026년 4월) |
| API 계약 |
UniversalApiContract 버전 19.0 |
이전 OS 버전을 ApiInformation.IsTypePresent 대상으로 지정하려면 모든 호출을 보호합니다(아래 코드 참조).
지원 확인
항상 API를 사용할 수 있고 사용하기 전에 촉각 디바이스가 있는지 확인합니다. API는 이전 OS 버전에 존재하지 않으며, 모든 입력 디바이스가 촉각을 지원하는 것은 아닙니다.
using Windows.Devices.Haptics;
using Windows.Foundation.Metadata;
// Guard against older OS versions where the API is absent.
bool apiPresent = ApiInformation.IsTypePresent("Windows.Devices.Haptics.InputHapticsManager");
// Check that a supported haptic device is connected.
bool supported = apiPresent && InputHapticsManager.IsSupported();
파형을 트리거합니다
UI 스레드를 호출 InputHapticsManager.GetForCurrentThread() 하여 현재 스레드의 입력 포커스로 범위가 지정된 관리자 인스턴스를 가져옵니다. 디바이스 검색 및 라우팅은 자동으로 처리되므로 디바이스를 직접 열거할 필요가 없습니다.
using Windows.Devices.Haptics;
if (supported)
{
var mgr = InputHapticsManager.GetForCurrentThread();
// The second parameter is a fallback waveform used if the first is
// unsupported. Passing 0 lets the system choose a device-appropriate
// fallback. TrySendHapticWaveform returns false if neither waveform is
// supported; this is a non-fatal condition.
bool sent = mgr.TrySendHapticWaveform(
KnownSimpleHapticsControllerWaveforms.Align,
0);
}
Important
UI 스레드(또는 입력 포커스를 소유하는 스레드)에서 호출 GetForCurrentThread() 합니다. 백그라운드 스레드에서 호출해도 피드백을 올바른 디바이스로 라우팅하지 않습니다.
재생 중지
끌기 또는 상호 작용이 종료되면 호출 TryStopFeedback 하여 진행 중인 촉각 재생을 중지합니다.
using Windows.Devices.Haptics;
if (supported)
{
InputHapticsManager
.GetForCurrentThread()
.TryStopFeedback();
}
구현 예제
객체 정렬
맞춤 가이드는 디자인 도구, 프레젠테이션 편집기 및 다이어그램 앱에서 일반적입니다. 촉각 피드백은 개체가 제자리에 들어갈 때 사용자가 느낄 수 있도록 두 번째 채널을 추가하므로 맞춤을 시각적으로 확인하기 위해 확대할 필요가 줄어듭니다.
발사 시점: 정렬 가이드가 나타나는 것을 신호로 사용합니다. 스냅 로직이 가이드를 표시하면 햅틱 피드백을 발생시킵니다. 가이드가 표시되지 않으면 작동시키지 마세요. 이렇게 하면 촉각 이벤트가 표시되는 시스템 피드백과 긴밀하게 결합됩니다.
중복을 방지합니다. 셰이프는 여러 안내선에 동시에 정렬할 수 있습니다(예: 왼쪽 가장자리 및 위쪽 가장자리). 이를 단일 상호작용으로 처리하세요. 활성 가이드를 추적하고 새 가이드가 나타날 때만 실행되도록 하세요.
using Windows.Devices.Haptics;
private readonly HashSet<int> _activeGuides = new();
// Call this after computing which alignment guides are currently visible.
void OnGuidesUpdated(IEnumerable<int> currentGuideIds)
{
var currentGuides = currentGuideIds.ToHashSet();
bool hasNewGuide = currentGuides.Except(_activeGuides).Any();
// Update the tracked set in place (field is readonly).
_activeGuides.Clear();
_activeGuides.UnionWith(currentGuides);
if (hasNewGuide && supported)
{
InputHapticsManager.GetForCurrentThread()
.TrySendHapticWaveform(
KnownSimpleHapticsControllerWaveforms.Align,
0);
}
}
Sliders
촉각은 의미 있는 위치에 피드백을 고정하여 슬라이더 상호 작용을 향상시킵니다. 사용자가 이해할 수 있는 표시 표식(눈금 표시, 명명된 값 또는 범위 경계)에 항상 피드백을 연결합니다.
실행 시점: 엄지가 각 눈금을 지날 때마다 햅틱을 실행합니다. 틱 사이의 지속적인 피드백은 산만하게 느껴질 수 있으므로 피하세요.
using Windows.Devices.Haptics;
double _previousValue;
const double TickInterval = 25.0;
void OnSliderValueChanged(double newValue)
{
int previousTick = (int)(_previousValue / TickInterval);
int currentTick = (int)(newValue / TickInterval);
if (currentTick != previousTick && supported)
{
InputHapticsManager.GetForCurrentThread()
.TrySendHapticWaveform(
KnownSimpleHapticsControllerWaveforms.Step,
0);
}
_previousValue = newValue;
}
환경 구체화: 사용자가 범위 내에 있는 위치를 감지할 수 있도록 슬라이더 위치에 따라 촉각 강도 크기를 조정합니다.
TrySendHapticWaveformForPlayCount부터 0.0까지의 명시적 강도 값을 허용하는 1.0를 사용하세요.
void OnSliderValueChangedWithIntensity(double newValue, double maxValue)
{
int previousTick = (int)(_previousValue / TickInterval);
int currentTick = (int)(newValue / TickInterval);
if (currentTick != previousTick && supported)
{
double intensity = newValue / maxValue; // Scale 0.0–1.0
InputHapticsManager.GetForCurrentThread()
.TrySendHapticWaveformForPlayCount(
KnownSimpleHapticsControllerWaveforms.Step,
0, // fallback waveform
intensity,
1, // playCount
TimeSpan.Zero);
}
_previousValue = newValue;
}
드래그 상호작용 및 의도 감지
드래그하는 동안 개체는 페이지 중심, 안내선, 다른 개체 등 여러 정렬 기준선을 지날 수 있습니다. 경계를 지날 때마다 햅틱 피드백을 발생시키면, 특히 사용자가 정확하게 맞추려는 것이 아니라 빠르게 위치를 다시 잡는 중일 때 부담을 줄 수 있습니다.
의도 감지를 사용하여 사용자가 단순히 지나가는 경우가 아니라 의도적으로 정렬하려고 할 때만 피드백이 실행되도록 하세요.
접근 방식 1: 속도 필터
커서가 빠르게 이동할 때 촉각을 억제하여 더 느리고 신중한 움직임을 위해 피드백을 예약합니다.
- 신호를 안정화합니다. 입력 형식, DPI 설정 및 표시 구성에서 시끄럽을 수 있는 원시 커서 델타를 사용하지 마십시오. 신호를 정규화하고 부드럽게 만듭니다.
- 임계값을 신중하게 선택합니다. 여러 디바이스, 입력 유형, 디스플레이 배율 및 다중 디스플레이 설정에서 유효성을 검사합니다.
접근 방식 2: 타이머 디버그
개체가 트리거 영역에 들어가면 짧은 타이머를 시작합니다(50ms는 적절한 시작점임). 타이머가 완료될 때 객체가 영역 내에 계속 남아 있으면 의도적인 것으로 간주하고 햅틱 피드백을 실행합니다. 타이머가 작동하기 전에 개체가 이동하면 피드백을 표시하지 않습니다.
- 구현이 더 간단하고 속도 필터링보다 더 안정적인 동작을 생성하는 경향이 있습니다.
- 50ms 지연은 의도적인 맞춤을 빠른 패스와 구별할 수 있을 만큼 길지만, 눈에 띄는 대기 시간의 임계값 아래로 유지됩니다.
using System;
using Microsoft.UI.Xaml;
using Windows.Devices.Haptics;
private DispatcherTimer? _alignTimer;
void OnObjectEnteredAlignmentZone()
{
_alignTimer?.Stop();
_alignTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(50) };
_alignTimer.Tick += (_, _) =>
{
_alignTimer.Stop();
if (supported)
{
InputHapticsManager.GetForCurrentThread()
.TrySendHapticWaveform(
KnownSimpleHapticsControllerWaveforms.Align,
0);
}
};
_alignTimer.Start();
}
void OnObjectLeftAlignmentZone()
{
_alignTimer?.Stop();
}
둘 중에서 선택
| 속도 필터 | 타이머 디버그 | |
|---|---|---|
| 작동 방식 | 반응성 - 실시간으로 이동을 측정합니다. | 예측 - 의도를 확인하기 위해 잠시 기다립니다. |
| 느낌 | 더 즉각적일 수 있습니다. | 약간 지연되었지만 일관성이 더 높습니다. |
| 튜닝 작업 | 더 높음—세심한 보정이 필요함 | 낮음 - 단일 지연 값은 일반적으로 충분합니다. |
| 권장 대상 | 응답성이 뛰어난 피드백이 필요한 앱 | 대부분의 앱; 좋은 기본 시작점 |
관련된 문서
- 촉각 디자인 지침
- InputHapticsManager API 참조
- KnownSimpleHapticsControllerWaveforms
- 촉각 디자인 및 구현 (microsoft.design)
- 입력 안내서
- 터치 조작
Windows developer