Implementare il feedback aptico nelle app Windows

Questo articolo illustra come aggiungere feedback aptico all'app Windows usando l'API InputHapticsManager, inclusi esempi di codice per modelli di interazione comuni.

Per indicazioni sulla progettazione su quando e perché usare gli aptici, vedere Linee guida per la progettazione aptici.

Dispositivi supportati

Gli aptici sono supportati su dispositivi di input come mouse, touchpad e penne. La disponibilità varia in base al modello e al produttore. Verificare sempre il supporto in fase di esecuzione prima di chiamare le API aptici (vedere Controllare il supporto di seguito).

Requirements

Requisito dettagli
Namespace Windows.Devices.Haptics
Sistema operativo minimo Windows 11, SDK 10.0.28000.1721 (marzo 2026)
Allinea/Collide/Passo/Crescere forme d'onda SDK 10.0.28000.1839 (aprile 2026)
Contratto dell'API UniversalApiContract versione 19.0

Per usare le versioni precedenti del sistema operativo, usare ApiInformation.IsTypePresent per proteggere tutte le chiamate (vedere il codice seguente).

Verificare la disponibilità del supporto

Verificare sempre che l'API sia disponibile e che sia presente un dispositivo aptico prima dell'uso. L'API non è presente nelle versioni precedenti del sistema operativo e non tutti i dispositivi di input supportano gli aptici.

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

Attiva una forma d'onda

Chiamare InputHapticsManager.GetForCurrentThread() nel thread dell'interfaccia utente per ottenere un'istanza del gestore associata al focus di input del thread corrente. Il rilevamento e il routing dei dispositivi vengono gestiti automaticamente: non è necessario enumerare manualmente i dispositivi.

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

Chiama GetForCurrentThread() dal thread dell'interfaccia utente (o dal thread che ha il focus di input). Chiamarlo da un thread in background non indirizzerà il feedback al dispositivo corretto.

Interrompi riproduzione

Chiama TryStopFeedback quando termina un trascinamento o un'interazione per interrompere qualsiasi riproduzione aptica in corso.

using Windows.Devices.Haptics;

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

Esempi di implementazione

Allineamento degli oggetti

Le guide di allineamento sono comuni negli strumenti di progettazione, negli editor di presentazioni e nelle app di creazione di diagrammi. Il feedback aptico aggiunge un secondo canale in modo che gli utenti possano sentire quando gli oggetti si bloccano sul posto, riducendo la necessità di eseguire lo zoom avanti per confermare visivamente l'allineamento.

Quando attivare: Usa la comparsa della guida di allineamento come segnale. Quando la logica di ancoraggio visualizza una guida, attiva il feedback aptico. Se non viene visualizzata alcuna guida, non sparare. Ciò mantiene gli eventi aptici strettamente associati al feedback visibile del sistema.

Evitare duplicati: Una forma può essere allineata contemporaneamente a più guide (ad esempio, bordo sinistro e bordo superiore). Considera questo come una singola interazione: tieni traccia delle guide attive e attiva solo quando viene visualizzata una nuova guida.

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

Il feedback aptico migliora le interazioni con il cursore ancorando il feedback a posizioni chiave. Associare sempre il feedback ai marcatori visibili che l'utente può comprendere: segni di graduazione, valori denominati o limiti di intervallo.

Quando attivare: Attiva il feedback aptico quando il pollice supera ogni tacca. Evitare un feedback continuo tra un ticchettio e l’altro, poiché può risultare fastidioso.

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

Affinamento dell'esperienza: Scalare l'intensità aptica in base alla posizione del dispositivo di scorrimento per aiutare gli utenti a percepire dove si trovano all'interno dell'intervallo. Usare TrySendHapticWaveformForPlayCount, che accetta un valore di intensità esplicito da 0.0 a 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;
}

Interazioni di trascinamento e rilevamento dell'intenzione

Durante un trascinamento, un oggetto può attraversare molti limiti di allineamento, ovvero il centro pagine, le guide e altri oggetti. L'attivazione del feedback aptico a ogni superamento di una soglia può risultare eccessiva per gli utenti, soprattutto durante i movimenti rapidi, quando stanno semplicemente riposizionandosi anziché cercare la massima precisione.

Usare il rilevamento dell’intenzione per attivare il feedback solo quando l’utente sta cercando intenzionalmente di allinearsi, non quando vi passa semplicemente attraverso.

Approccio 1: Filtro velocità

Disattiva il feedback aptico quando il cursore si sposta rapidamente, riservando il feedback ai movimenti più lenti e deliberati.

  • Stabilizza il segnale. Evitare di usare delta di cursori non elaborati, che possono essere rumorosi tra tipi di input, impostazioni DPI e configurazioni di visualizzazione. Normalizzare e regolare il segnale.
  • Scegliere attentamente una soglia. Verificare su dispositivi diversi, tipi di input, scale di visualizzazione e configurazioni con più schermi.

Approccio 2: Debounce del timer

Quando un oggetto entra in una zona trigger, avviare un breve timer (50 ms è un punto di partenza ragionevole). Se l'oggetto rimane nella zona quando il timer scade, consideralo intenzionale e attiva il feedback aptico. Se l'oggetto si sposta prima dell'attivazione del timer, eliminare il feedback.

  • Più semplice da implementare e tende a produrre un comportamento più stabile rispetto al filtro della velocità.
  • Un ritardo di 50 ms è sufficientemente lungo da distinguere l'allineamento intenzionale da un passaggio rapido, mentre rimane al di sotto della soglia di latenza evidente.
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();
}

Scelta tra i due

Filtro velocità Debounce timer
Funzionamento Reattivo: misura lo spostamento in tempo reale Predittivo: attende brevemente di confermare la finalità
Sentire Può sentirsi più immediato Leggermente ritardato, ma più coerente
Ottimizzazione dello sforzo Superiore: richiede un'attenta calibrazione Minore: un singolo valore di ritardo è in genere sufficiente
Consigliato per App che richiedono feedback altamente reattivo La maggior parte delle app; buon punto di partenza predefinito