Haptische feedback implementeren in Windows-apps

In dit artikel wordt uitgelegd hoe u haptische feedback toevoegt aan uw Windows-app met behulp van de InputHapticsManager-API, inclusief codevoorbeelden voor veelvoorkomende interactiepatronen.

Zie Ontwerprichtlijnen voor haptiek voor richtlijnen over wanneer en waarom u haptiek gebruikt.

Ondersteunde apparaten

Haptics zijn beschikbaar op invoerapparaten zoals muizen, touchpads en pennen. De beschikbaarheid verschilt per model en fabrikant. Controleer altijd op ondersteuning tijdens runtime voordat haptics-API's worden aangeroepen (zie Controleren op ondersteuning hieronder).

Requirements

Voorwaarde Details
Namespace Windows.Devices.Haptics
Minimaal besturingssysteem Windows 11 SDK 10.0.28000.1721 (maart 2026)
Uitlijnen / Collide / Stap / Golfvormen vergroten SDK 10.0.28000.1839 (april 2026)
API-contract UniversalApiContract versie 19.0

Als u oudere versies van het besturingssysteem wilt ondersteunen, gebruikt u ApiInformation.IsTypePresent om alle aanroepen af te schermen (zie de onderstaande code).

Controleren op ondersteuning

Controleer altijd of de API beschikbaar is en of er een haptisch apparaat aanwezig is voordat u deze gebruikt. De API is niet aanwezig in oudere versies van het besturingssysteem en niet alle invoerapparaten ondersteunen haptiek.

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

Een golfvorm triggeren

Roep InputHapticsManager.GetForCurrentThread() aan op de UI-thread om een managerinstantie te verkrijgen die is gebonden aan de invoerfocus van de huidige thread. Apparaatdetectie en -routering worden automatisch verwerkt. U hoeft apparaten niet zelf op te sommen.

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

Aanroepen GetForCurrentThread() vanuit de UI-thread (of de thread die eigenaar is van de invoerfocus). Als u het vanuit een achtergrondthread aanroept, wordt feedback niet doorgestuurd naar het juiste apparaat.

Afspelen stoppen

Roep TryStopFeedback aan wanneer een sleepactie of interactie eindigt om eventuele actieve haptische weergave te beëindigen.

using Windows.Devices.Haptics;

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

Implementatievoorbeelden

Objectuitlijning

Uitlijningshulplijnen zijn gebruikelijk in ontwerphulpmiddelen, presentatie-editors en diagramming-apps. Haptische feedback voegt een tweede kanaal toe, zodat gebruikers zich kunnen voelen wanneer objecten worden uitgelijnd. Hierdoor hoeft u minder in te zoomen om de uitlijning visueel te bevestigen.

Wanneer activeren: Gebruik het verschijnen van de uitlijningshulplijn als trigger. Wanneer uw snaplogica een hulplijn toont, activeer dan de haptische feedback. Als er geen richtlijn verschijnt, vuur dan niet. Hierdoor blijven haptische gebeurtenissen nauw gekoppeld aan zichtbare systeemfeedback.

Vermijd duplicaten: Een vorm kan tegelijk op meerdere hulplijnen worden uitgelijnd (bijvoorbeeld op de linkerrand en de bovenrand). Behandel dit als één interactie: houd actieve hulplijnen bij en vuur alleen wanneer er een nieuwe gids wordt weergegeven.

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

Haptische feedback verbetert interacties met schuifregelaars door feedback te koppelen aan relevante posities. Koppel feedback altijd aan zichtbare markeringen die de gebruiker kan begrijpen: maatstreepjes, benoemde waarden of bereikgrenzen.

Wanneer activeren: Activeer haptische feedback telkens wanneer de duim een streepmarkering passeert. Vermijd voortdurende feedback tussen opeenvolgende tikken, omdat dit als storend kan aanvoelen.

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

De ervaring verfijnen: Schaal haptische intensiteit op basis van de schuifregelaarpositie om gebruikers te helpen bepalen waar ze zich binnen het bereik bevinden. Gebruik TrySendHapticWaveformForPlayCount, die een expliciete intensiteitswaarde tussen 0.0 en 1.0 accepteert.

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

Interacties en intentiedetectie slepen

Tijdens het slepen kan een object veel uitlijningsgrenzen passeren: het midden van de pagina, hulplijnen en andere objecten. Het activeren van haptische feedback bij elke kruising kan gebruikers overweldigen, vooral tijdens snelle bewegingen wanneer ze hun positie aanpassen in plaats van nauwkeurig te proberen te zijn.

Gebruik intentieherkenning om alleen feedback te geven wanneer de gebruiker bewust probeert uit te lijnen en niet er alleen langs beweegt.

Benadering 1: Snelheidsfilter

Onderdruk haptiek wanneer de cursor snel beweegt, zodat u feedback kunt reserveren voor tragere, bewustere bewegingen.

  • Het signaal stabiliseren. Vermijd het gebruik van onbewerkte cursor-delta's, die luidruchtig kunnen zijn voor invoertypen, DPI-instellingen en weergaveconfiguraties. Normaliseer en maak het signaal glad.
  • Kies zorgvuldig een drempelwaarde. Valideer op verschillende apparaten, invoertypen, weergaveschalen en installatie met meerdere beeldschermen.

Methode 2: Debouncing met een timer

Wanneer een object een triggerzone binnenkomt, start u een korte timer (50 ms is een redelijk uitgangspunt). Als het object in de zone blijft wanneer de timer afloopt, beschouw het dan als opzettelijk en activeer de haptische feedback. Als het object verder beweegt voordat de timer afgaat, onderdruk dan de feedback.

  • Eenvoudiger te implementeren en produceert doorgaans stabieler gedrag dan snelheidsfiltering.
  • Een vertraging van 50 ms is lang genoeg om opzettelijke uitlijning te onderscheiden van een snelle pas, terwijl deze onder de drempelwaarde van merkbare latentie blijft.
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();
}

Kiezen tussen de twee

Snelheidsfilter Timer debounce
Hoe werkt het? Reactief: meet beweging in realtime Voorspellend: wacht kort om de intentie te bevestigen
Voelen Kan zich directer voelen Enigszins vertraagd, maar consistenter
Afstemmingsinspanning Hoger: vereist zorgvuldige kalibratie Lager: een enkele vertragingswaarde is meestal voldoende
Aanbevolen voor Apps waarvoor zeer responsieve feedback is vereist De meeste apps; goed standaard startpunt