Implementowanie opinii haptycznych w aplikacjach Windows

W tym artykule wyjaśniono, jak dodać opinie haptyczne do aplikacji Windows przy użyciu interfejsu API InputHapticsManager, w tym przykłady kodu dla typowych wzorców interakcji.

Aby uzyskać wskazówki dotyczące projektowania dotyczące tego, kiedy i dlaczego należy używać haptyki, zobacz Wskazówki dotyczące projektowania haptyki.

Obsługiwane urządzenia

Haptics są obsługiwane na urządzeniach wejściowych, takich jak myszy, touchpady i długopisy. Dostępność różni się w zależności od modelu i producenta. Zawsze sprawdzaj wsparcie w czasie działania przed wywołaniem interfejsów API funkcji haptycznych (zobacz poniżej sekcję Sprawdzanie wsparcia).

Requirements

Requirement Szczegóły
Namespace Windows.Devices.Haptics
Minimalna wersja systemu operacyjnego Windows 11, SDK 10.0.28000.1721 (marzec 2026)
Wyrównaj/ zderzaj się / Krok / Rozwijaj kształty fali Zestaw SDK 10.0.28000.1839 (kwiecień 2026 r.)
Kontrakt API UniversalApiContract wersja 19.0

Aby obsługiwać starsze wersje systemu operacyjnego, użyj ApiInformation.IsTypePresent, aby warunkowo zabezpieczyć wszystkie wywołania (zobacz poniższy kod).

Sprawdź obsługę

Przed użyciem zawsze sprawdź, czy interfejs API jest dostępny i czy urządzenie haptyczne jest obecne. Interfejs API nie jest obecny w starszych wersjach systemu operacyjnego, a nie wszystkie urządzenia wejściowe obsługują haptyki.

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();

Wyzwalanie kształtów fali

Wywołaj InputHapticsManager.GetForCurrentThread() w wątku interfejsu użytkownika, aby uzyskać instancję menedżera powiązaną z fokusem wejściowym bieżącego wątku. Wykrywanie i routing urządzeń są obsługiwane automatycznie — nie musisz wyliczać urządzeń samodzielnie.

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

Wywołaj GetForCurrentThread() z wątku interfejsu użytkownika (lub z wątku, który ma fokus danych wejściowych). Wywołanie tej funkcji z wątku w tle nie będzie przekierowywać informacji zwrotnej do właściwego urządzenia.

Zatrzymaj odtwarzanie

Wywołaj TryStopFeedback, gdy zakończy się przeciąganie lub interakcja, aby zatrzymać wszelkie trwające efekty haptyczne.

using Windows.Devices.Haptics;

if (supported)
{
    InputHapticsManager
        .GetForCurrentThread()
        .TryStopFeedback();
}

Przykład wdrożenia

Wyrównanie obiektu

Prowadnice wyrównania są powszechne w narzędziach projektowych, edytorach prezentacji i aplikacjach do tworzenia diagramów. Sprzężenie haptyczne dodaje drugi kanał, dzięki czemu użytkownicy mogą poczuć, kiedy obiekty wskakują na swoje miejsce — co zmniejsza konieczność powiększania, aby wzrokowo potwierdzić wyrównanie.

Kiedy należy uruchomić: Użyj wyglądu przewodnika wyrównania jako wyzwalacza. Gdy mechanizm przyciągania wyświetli prowadnicę, włącz reakcję haptyczną. Jeśli nie pojawi się wskaźnik, nie oddawaj strzału. Dzięki temu zdarzenia haptyczne są ściśle powiązane z widocznymi informacjami zwrotnymi systemu.

Unikaj duplikatów: Kształt może być wyrównany do wielu prowadnic jednocześnie (na przykład lewa krawędź i górna krawędź). Traktuj to jako jedną interakcję — śledź aktywne prowadnice i uruchamiaj je tylko wtedy, gdy pojawi się nowy przewodnik.

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

Haptyka poprawia interakcje z suwakiem, przypisując informacje zwrotne do istotnych położeń. Zawsze należy powiązać opinie z widocznymi znacznikami, które użytkownik może zrozumieć — znaczniki zaznaczenia, nazwane wartości lub granice zakresu.

Kiedy uruchamiać: Uruchamiaj haptyczne sprzężenie zwrotne, gdy kciuk mija każdy znacznik podziałki. Unikaj ciągłej informacji zwrotnej między tyknięciami, ponieważ może to rozpraszać.

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;
}

Udoskonalanie działania: Dostosuj intensywność haptyki w zależności od położenia suwaka, aby użytkownicy mogli wyczuć, w którym miejscu zakresu się znajdują. Użyj elementu TrySendHapticWaveformForPlayCount, który akceptuje jawną wartość intensywności z 0.0 do 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;
}

Interakcje przeciągania i wykrywanie intencji

Podczas przeciągania obiekt może przechodzić przez wiele linii wyrównania — środek strony, prowadnice i inne obiekty. Uruchamianie informacji haptycznej przy każdym przekroczeniu może przytłaczać użytkowników, zwłaszcza podczas szybkich ruchów, gdy zmieniają położenie, a nie próbują działać precyzyjnie.

Użyj wykrywania intencji, aby uruchamiać informację zwrotną tylko wtedy, gdy użytkownik próbuje świadomie wyrównać element, a nie tylko obok niego przechodzi.

Podejście 1. Filtr szybkości

Wyłącz reakcje haptyczne, gdy kursor porusza się szybko, pozostawiając je dla wolniejszych, bardziej celowych ruchów.

  • Stabilizuj sygnał. Unikaj używania nieprzetworzonych różnic kursorów, które mogą być hałaśliwe dla typów wejściowych, ustawień DPI i konfiguracji wyświetlania. Normalizuj i wygładź sygnał.
  • Starannie wybierz próg. Zweryfikuj różne urządzenia, typy danych wejściowych, skale wyświetlania i konfiguracje z wieloma wyświetlaczami.

Podejście 2. Odrzuć czasomierz

Gdy obiekt wchodzi w strefę wyzwalacza, uruchom krótki czasomierz (50 ms jest rozsądnym punktem początkowym). Jeśli obiekt nadal znajduje się w strefie, gdy licznik czasu dobiegnie końca, uznaj to za działanie zamierzone i uruchom sygnał haptyczny. Jeśli obiekt przemieści się, zanim upłynie czas timera, wstrzymaj informację zwrotną.

  • Prostsze do zaimplementowania i ma tendencję do tworzenia bardziej stabilnego zachowania niż filtrowanie szybkości.
  • Opóźnienie 50 ms jest wystarczająco długie, aby odróżnić celowe ustawienie od szybkiego przesunięcia, a jednocześnie pozostaje poniżej progu zauważalnej zwłoki.
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();
}

Wybieranie między nimi

Filtr prędkości Eliminacja drgań timera
Jak to działa Reaktywne — mierzy ruch w czasie rzeczywistym Predykcyjna — czeka krótko, aby potwierdzić intencję
Poczuj Może sprawiać wrażenie bardziej bezpośredniego Nieco opóźnione, ale bardziej spójne
Wysiłek związany ze strojeniem Wyższa — wymaga starannej kalibracji Niższa — pojedyncza wartość opóźnienia jest zwykle wystarczająca
Zalecane dla Aplikacje wymagające bardzo dynamicznej opinii Większość aplikacji; dobry domyślny punkt początkowy