Implémenter des commentaires haptiques dans les applications Windows

Cet article explique comment ajouter des commentaires haptiques à votre application Windows à l’aide de l’API InputHapticsManager, y compris des exemples de code pour les modèles d’interaction courants.

Pour obtenir des conseils sur le moment et la raison d’utiliser des haptiques, consultez les instructions de conception haptics.

Appareils pris en charge

Les haptics sont pris en charge sur les appareils d’entrée tels que les souris, les pavés tactiles et les stylos. La disponibilité varie selon le modèle et le fabricant. Vérifiez toujours la prise en charge au moment de l’exécution avant d’appeler les API haptics (voir Vérifier la prise en charge ci-dessous).

Requirements

Requirement Détails
Namespace Windows.Devices.Haptics
Système d’exploitation minimal Windows 11, SDK 10.0.28000.1721 (mars 2026)
Aligner / Faire se chevaucher / Déplacer par pas / Agrandir les formes d’onde SDK 10.0.28000.1839 (avril 2026)
Contrat d’API UniversalApiContract version 19.0

Pour cibler les versions antérieures du système d’exploitation, utilisez cette fonctionnalité ApiInformation.IsTypePresent pour protéger tous les appels (voir le code ci-dessous).

Rechercher le support technique

Vérifiez toujours que l’API est disponible et qu’un appareil haptique est présent avant l’utilisation. L’API n’est pas présente sur les versions antérieures du système d’exploitation, et tous les appareils d’entrée ne prennent pas en charge les haptics.

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

Déclencher une forme d’onde

Appelez InputHapticsManager.GetForCurrentThread() sur le thread d’interface utilisateur pour obtenir une instance de gestionnaire associée au focus d’entrée du thread actuel. La détection et le routage des appareils sont gérés automatiquement : vous n’avez pas besoin d’énumérer vous-même les appareils.

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

Appelez GetForCurrentThread() depuis le thread d’interface utilisateur (ou le thread qui a le focus d’entrée). L’appeler depuis un thread en arrière-plan n’acheminera pas le retour vers le bon appareil.

Arrêter la lecture

Appelez TryStopFeedback lorsqu’un glisser-déplacer ou une interaction se termine pour arrêter toute lecture haptique en cours.

using Windows.Devices.Haptics;

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

Exemples d’implémentation

Alignement de l’objet

Les repères d’alignement sont courants dans les outils de conception, les éditeurs de présentation et les applications de diagramme. Les commentaires haptiques ajoutent un deuxième canal pour que les utilisateurs puissent se sentir quand les objets s’alignent sur place, ce qui réduit la nécessité de zoomer pour confirmer visuellement l’alignement.

Quand déclencher : Utilisez l’apparence du repère d’alignement comme déclencheur. Lorsque votre logique d’alignement affiche un repère, déclenchez le haptique. Si aucun repère n’apparaît, ne déclenchez pas. Cela maintient les événements haptiques étroitement liés au retour visuel du système.

Évitez les doublons : Une forme peut s’aligner simultanément sur plusieurs repères (par exemple, bord gauche et bord supérieur). Traitez cela comme une interaction unique : suivez les repères actifs et ne déclenchez que lorsqu’un nouveau repère apparaît.

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

Les haptics améliorent les interactions de curseur en ancrent les commentaires à des positions significatives. Associez toujours les commentaires aux marqueurs visibles que l’utilisateur peut comprendre : graduations, valeurs nommées ou limites de plage.

Quand déclencher : Déclenchez les retours haptiques lorsque le pouce passe sur chaque graduation. Évitez les commentaires continus entre les cycles, ce qui peut se sentir distrait.

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

Améliorer l’expérience : Ajustez l’intensité haptique en fonction de la position du curseur pour aider les utilisateurs à percevoir ils se situent dans la plage de valeurs. Utilisez TrySendHapticWaveformForPlayCount, qui accepte une valeur d’intensité explicite de 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;
}

Interactions de glisser-déposer et détection de l’intention

Pendant un glissement, un objet peut traverser de nombreuses limites d’alignement : centre de pages, repères, autres objets. Le déclenchement de haptiques à chaque passage peut surcharger les utilisateurs, en particulier pendant les mouvements rapides lorsqu’ils se repositionnent plutôt que d’essayer d’être précis.

Utilisez la détection d’intention pour déclencher des commentaires uniquement lorsque l’utilisateur tente d’aligner délibérément, pas seulement en passant.

Approche 1 : Filtre de vitesse

Supprimez les haptiques lorsque le curseur se déplace rapidement, en réservant des commentaires pour un mouvement plus lent et plus délibéré.

  • Stabilisez le signal. Évitez d’utiliser des deltas de curseur bruts, qui peuvent être bruyants entre les types d’entrée, les paramètres DPI et les configurations d’affichage. Normalisez et lissez le signal.
  • Choisissez soigneusement un seuil. Validez sur différents appareils, types d’entrée, échelles d’affichage et configurations multi-affichage.

Approche 2 : temporisation d'antirebond

Lorsqu’un objet entre dans une zone de déclencheur, démarrez un minuteur court (50 ms est un point de départ raisonnable). Si l’objet reste dans la zone lorsque le minuteur se termine, traitez-le comme intentionnel et déclenchez le haptique. Si l’objet se déplace avant le déclenchement du minuteur, supprimez les commentaires.

  • Plus simple à implémenter et tend à produire un comportement plus stable que le filtrage de vitesse.
  • Un délai de 50 ms est suffisamment long pour distinguer l’alignement délibéré d’une passe rapide, tout en restant sous le seuil de latence notable.
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();
}

Choix entre les deux

Filtre de vitesse Minuteur anti-rebond
Fonctionnement Réactif : mesure le mouvement en temps réel Prédictif : attend brièvement de confirmer l’intention
Sentir Peut sembler plus immédiat Légèrement retardé, mais plus cohérent
Effort de réglage Plus élevé : nécessite un étalonnage prudent Inférieur : une valeur de délai unique est généralement suffisante
Recommandé pour Applications nécessitant des commentaires hautement réactifs La plupart des applications ; bon point de départ par défaut