次の方法で共有


ペンの操作とハプティクス (触覚) のフィードバック

Windows では、ユーザーが自然で直接的な方法でデバイスと対話し、デジタル インクを使用した豊富な書き込みと描画エクスペリエンスを通じて創造性を表現できるデジタル ペンが長い間サポートされています。

Windows 11 では、デジタル ペンエクスペリエンスをさらに自然で説得力のあるものにする新しい機能が導入されています。"触覚フィードバック" をサポートするペンを使用すると、ユーザーは実際にアプリのユーザー インターフェイス (UI) と触覚的にペンが対話することを感じることができます。

この新機能を参照すると、開発者 API と関連ドキュメント全体で "触覚" が使用され、"触覚" は Windows 設定でフィードバックの基本設定を設定するためにユーザーに提示されるフレンドリ名です。

Windows 11 でサポートされている触覚フィードバック エクスペリエンスには、 手描き入力フィードバック対話フィードバックが含まれます。

  • 手描き入力フィードバックは、ペンが画面に接触している間の連続振動によって、さまざまな種類の書き込みまたは描画ツール (ペン、マーカー、鉛筆、蛍光ペンなど) の操作性をシミュレートします。 既定では、 Windows Ink Platform では、すべての描画ツールに対する触覚フィードバックがサポートされています (このトピックでは、Windows Ink でサポートされている以外のカスタム 手描き入力ソリューションを提供する方法について説明します)。
  • 一方、対話フィードバックは、ボタンをポイントまたはクリックする、アクションの完了に応答する、ユーザーの注意を引くなどの主要なユーザー アクションに基づく直接的なフィードバックです。

通常、触覚フィードバックを完全にサポートするには、次の 5 つの手順が必要です。

  • ペン入力を検出します。
  • 現在のペンとデバイスが触覚フィードバックをサポートしているかどうかを判断し、サポートする触覚フィードバック機能を確認します。
  • 送信する触覚フィードバック信号を決定します。
  • 触覚フィードバックを送信します。
  • 触覚フィードバックを停止する

ペン入力を検出する

ペン入力を検出して分離するには、まず PointerEntered イベントに 登録してから、 PointerDeviceTypeペンであるかどうかを確認する必要があります。

次のコードは、PointerEntered イベント内のポインター デバイスの種類を確認する方法を示しています。 この例では、入力がペンからでない場合は、単にイベント ハンドラーから返されます。 それ以外の場合は、ペンの機能を確認し、触覚フィードバックを構成します。


private void InputObserver_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    ...
    
    // If the current Pointer device is not a pen, exit.
    if (e.Pointer.PointerDeviceType != PointerDeviceType.Pen) 
    {
       return;
    }
    
    ...    
}

触覚フィードバックのサポートを決定する

すべてのペンとデジタイザーが触覚フィードバックをサポートしているわけではありません。また、このトピックで説明するすべての触覚フィードバック機能が必ずしもサポートされるとは限りません。 そのため、アクティブペンでサポートされている機能をプログラムで確認することが重要です。

前の例の続きで、アクティブペンが触覚フィードバックをサポートしているかどうかを確認する方法を示します。

最初に、現在の PointerId から PenDevice オブジェクトを取得しようとします。 PenDevice を取得できない場合は、単にイベント ハンドラーから戻ります。

PenDevice が取得された場合は、SimpleHapticsController プロパティがサポートされているかどうかをテストします。 そうでない場合は、もう一度イベント ハンドラーから戻ります。

// Attempt to retrieve the PenDevice from the current PointerId.
penDevice = PenDevice.GetFromPointerId(e.Pointer.PointerId);

// If a PenDevice cannot be retrieved based on the PointerId, it does not support 
// advanced pen features, such as haptic feedback. 
if (penDevice == null)
{
    return;
}

// Check to see if the current PenDevice supports haptic feedback by seeing if it 
// has a SimpleHapticsController.
hapticsController = penDevice.SimpleHapticsController;
if (hapticsController == null)
{
    return;
}

前の例で取得した SimpleHapticsController は、後続の例で触覚機能のクエリを実行し、触覚フィードバックを送信/停止するために使用されます。

Windows App SDK Preview 1.0でアプリを構築している場合は、PenDevice インタロップ (PenDeviceInterop.FromPointerPoint(PointerPoint)) を使用して、システムの PenDeviceにアクセスできます。

private void InputObserver_PointerEntered(PointerInputObserver sender, PointerEventArgs args)
{
    var penDevice = PenDeviceInterop.PenDeviceFromPointerPoint(args.CurrentPoint);
}

次のセクションでは、触覚ペンでサポートする必要があるフィードバック機能と、オプションのフィードバック機能について説明します。 通常、必要な触覚フィードバックの種類は、省略可能な機能の代わりにフォールバックとして使用できます。

インク波形

ペンが画面に接触している間、インク波形が連続して再生され、さまざまな書き込みツールや描画ツールの感覚をシミュレートしようとします。

特徴 説明 必須/省略可能
InkContinous 波形 物理的なボール ポイント ペンを使用して、手描き入力の感覚をシミュレートします。 これは、インク波形が触覚ペンでサポートされていない場合の既定のフォールバックです。 必須
ブラシ連続波形 ユーザーが手描き入力ツールとしてブラシを選択したときの連続触覚信号。 オプション
一続きのノミマーカ波形 ユーザーがインク ツールとしてチゼル マーカー/蛍光ペンを選択したときの連続触覚信号。 オプション
イレイザーコンティニュアス波形 ユーザーが消しゴムを手描き入力ツールとして選択したときの連続触覚信号。 オプション
ギャラクシー連続波形
(HID のドキュメントと実装ガイドでは、この波形を SparkleContinuousと参照します)
多色ブラシなどの特殊なインク ツール用の連続触覚信号。 オプション
マーカー連続波形 ユーザーが手書きツールとしてマーカーを選択したときの連続触覚信号。 オプション
ペンシル連続波形 ユーザーが手描き入力ツールとして鉛筆を選択したときの連続触覚信号。 オプション

相互作用波形

相互作用波形は、通常は短く (次の表に示す例外があります)、必要に応じて生成された直接フィードバック波形を使用して、ボタンをポイントまたはクリックする、アクションの完了に応答する、ユーザーの注意を引くなどの主要なアクションを確認します。

特徴 説明 必須/省略可能
クリック波形 短い「クリック」フィードバック。 これは、アプリによって選択された相互作用波形が触覚ペンでサポートされていない場合の既定のフォールバックです。 必須
エラー波形 アクションが失敗したか、エラーが発生したことをユーザーに警告する強いシグナル。 オプション
ホバー波形 ユーザーが対話型 UI 要素の上にマウス ポインターを置き始めたことを示します。 オプション
波形を押す ユーザーが増分アクションで対話型 UI 要素を押すタイミングを示します (リリースを参照)。 オプション
リリース波形 ユーザーが増分アクションで対話型 UI 要素を解放するタイミングを示します (「押す」を参照)。 オプション
成功波形 アクションが成功したことをユーザーに警告する強いシグナル。 オプション
バズ連続波形 連続的な振動感覚。 オプション
連続ランブル波形 連続する振動感。 オプション

触覚フィードバックのカスタマイズ

一部の触覚ペンでは、次のカスタマイズをサポートできます。

特徴 説明 必須/省略可能
強度 触覚信号の強度を設定します。 オプション
再生回数 指定した回数だけ触覚信号を繰り返します。 オプション
再生の一時停止間隔 触覚信号を繰り返し再生する間隔を設定します。 オプション
再生時間 触覚信号が再生される時間間隔を設定します。 オプション

カスタム設定のサポートを確認する

強度、再生回数、再生一時停止間隔、再生時間のサポートを確認するには、 SimpleHapticsController の次のプロパティを使用します。

インクの触覚フィードバックを送信および停止

SimpleHapticsController オブジェクトの SendHapticFeedback メソッドを使用して、インク波形をユーザーのペンに渡します。 このメソッドは、カスタマイズされた強度値を持つ波形または両方の波形を渡すことをサポートします ( 「触覚フィードバックのカスタマイズ」を参照)。

SendHapticFeedback を呼び出し、 インク波形を 渡して、ペンの先端が画面上の任意の場所にタッチするとすぐにその波形の再生を開始するようにペンを構成します。 波形は、ペンが持ち上げられるか、StopFeedback が呼び出されるまで、どちらかが先に発生するまで再生を続けます。 これは、触覚を再生する要素の、PointerEntered イベント ハンドラーで行うことをお勧めします。 たとえば、カスタム の手描き入力実装を使用するアプリは、その手書き入力キャンバスの PointerEntered メソッドでこれを行います。

目的のインク波形を取得するには、SimpleHapticsControllerSupportedFeedback コレクションを反復処理し、アクティブなペンでサポートされていることを確認する必要があります。

サポートされていない場合は、サポートされていることが保証されているため、何も再生しないか、 InkContinuous 波形にフォールバックするかを選択できます。

次の例では、BrushContinuous 波形を送信しようとします (ただし、 BrushContinuous がサポートされていない場合は InkContinuous にフォールバックします)。

SimpleHapticsControllerFeedback currentWaveform;

// Attempt to set the currentWaveform to BrushContinuous.
foreach (var waveform in hapticsController.SupportedFeedback)
{
    if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.BrushContinuous)
    {
        currentWaveform = waveform;
    }
} 

// If currentWaveform is null, it was not in the SupportedFeedback collection, so instead set 
// the waveform to InkContinuous.
if (currentWaveform == null)
{
    foreach (var waveform in hapticsController.SupportedFeedback)
    {
        if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.InkContinuous)
        {
            currentWaveform = waveform;
        }
    }
}

// Send the currentWaveform 
hapticsController.SendHapticFeedback(currentWaveform);

関連付けられたポインターが触覚フィードバックに登録した要素を終了したときにも、触覚フィードバックを停止することが重要です。 それ以外の場合、波形はアクティブなペンでの再生を試み続けます。

一部のペンは、必要に応じて、ペンが画面の範囲を離れたときに触覚を停止できます。 ただし、すべてのペンでこれを行う必要はありません。そのため、ここで説明するように、アプリケーションでは常に触覚フィードバックを明示的に停止する必要があります。

要素に対する触覚フィードバックを停止するには、触覚信号を送信した PointerEntered ハンドラーを登録したのと同じ要素で PointerExited イベントに登録します。 その終了したイベント ハンドラーで、次に示すように StopFeedback を呼び出します。

hapticsController.StopFeedback();

対話フィードバックの送信と停止

対話フィードバックの送信は、手描き入力フィードバックの送信とよく似ています。

操作波形をユーザーのペンに渡すには、SimpleHapticsController オブジェクトの SendHapticFeedback メソッドを使用します。 このメソッドは、カスタマイズされた強度値を持つ波形または両方の波形を渡すことをサポートします ( 「触覚フィードバックのカスタマイズ」を参照)。

SendHapticFeedback を呼び出し、 インク波形を 渡して、(ペンの先端が画面にタッチしてフィードバックを入力する代わりに) アプリ内の相互作用に基づいてすぐにその波形の再生を開始するようにペンを構成します。

連続していない相互作用波形のいずれかを使用する場合、対応する StopFeedback 呼び出しを行う必要はありません。 あなたはまだ継続的な相互作用波形のために StopFeedback を呼び出す必要があります。

手描き入力波形が再生されているときに相互作用波形を送信すると、一時的に手描き入力波形が中断されます。 対話波形が停止すると、インキング波形が再開されます。

目的の相互作用波形を取得するには、SimpleHapticsControllerSupportedFeedback コレクションを反復処理し、アクティブなペンでサポートされていることを確認する必要があります。

サポートされていない場合は、サポートされていることが保証されているため、何も再生しないか、 クリック 波形にフォールバックするかを選択できます。

次の例では、エラー波形の送信を試みます (ただし、 エラー がサポートされていない場合は Click にフォールバックします)。

SimpleHapticsControllerFeedback currentWaveform;  

// Attempt to set the currentWaveform to BrushContinuous.
foreach (var waveform in hapticsController.SupportedFeedback)
{
    if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Error)
    {
        currentWaveform = waveform;
    }
} 

// If currentWaveform is null, it was not in the SupportedFeedback collection, so instead set 
// the waveform to Click.
if (currentWaveform == null)
{
    foreach (var waveform in hapticsController.SupportedFeedback)
    {
        if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
        {
            currentWaveform = waveform;
        }
    }
} 

// Send the currentWaveform.
hapticsController.SendHapticFeedback(currentWaveform); 

触覚フィードバックをカスタマイズする

触覚フィードバックをカスタマイズするには、3 つの方法があります。 1 つ目は Inking フィードバックと Interaction フィードバックの両方でサポートされ、2 番目と 3 番目はインタラクション フィードバックでのみサポートされます。

  1. システムの最大強度設定に対するフィードバックの強度を調整します。 これを行うには、まず、SimpleHapticsController が強度の設定をサポートしていることを確認し、次に、 の目的の値で Intensity を呼び出す必要があります。

    if (hapticsController.IsIntensitySupported) 
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
            {
                double intensity = 0.75;
                hapticsController.SendHapticFeedback(waveform, intensity);
            }
        }
    }
    
  2. 指定した回数だけ触覚信号を繰り返します。 これを行うには、まず SimpleHapticsController が強度の設定をサポートしていることを確認してから、必要なカウント値で SendHapticFeedbackForPlayCount を呼び出す必要があります。 強度と再生の一時停止間隔の両方を設定することもできます。

    SimpleHapticsController が強度または再生の一時停止間隔の設定をサポートしていない場合、指定された値は無視されます。

    if (hapticsController.IsPlayCountSupported && hapticsController.IsIntensitySupported && hapticsController.IsReplayPauseIntervalSupported)
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
            {
                double intensity = 0.75;
                int playCount = 3;
                System.TimeSpan pauseDuration = new System.TimeSpan(1000000);
                hapticsController.SendHapticFeedbackForPlayCount(currentWaveform, intensity, playCount, pauseDuration);
            }
        }
    }
    
  3. 触覚信号の継続時間を設定します。 これを行うには、まず SimpleHapticsController が再生時間の設定をサポートしていることを確認してから、必要な時間間隔値で SendHapticFeedbackForDuration を呼び出す必要があります。 強度を設定することもできます。

    SimpleHapticsController が強度の設定をサポートしていない場合、指定された値は無視されます。

    if (hapticsController.IsPlayDurationSupported && hapticsController.IsIntensitySupported)
    {
        foreach (var waveform in hapticsController.SupportedFeedback)
        {
            if (waveform.Waveform == KnownSimpleHapticsControllerWaveforms.RumbleContinuous)
            {
                double intensity = 0.75;
                System.TimeSpan playDuration = new System.TimeSpan(5000000);
                hapticsController.SendHapticFeedbackForDuration(currentWaveform, intensity, playDuration);
            }
        }
    }
    

例示

次の機能の動作例については、 Pen 触覚 サンプルを参照してください。