共用方式為


筆互動和觸覺回饋

Windows 長期以來一直支援數位畫筆,讓使用者以自然、直接的方式與其裝置互動,並使用數位筆跡豐富的寫作和繪圖體驗來表達他們的創造力。

使用 Windows 11 時,引進了一項新功能,讓數位畫筆體驗更加自然且引人注目:使用支援「觸覺回饋」的畫筆時,用戶實際上可以透過與應用程式的使用者介面(UI) 以觸覺方式互動他們的手寫筆。

備註

討論這項新功能時,「haptic 觸覺」這一詞會在整個開發人員 API 和相關文件中使用,而「tactile 簡單觸覺」則是向用戶顯示的易理解名稱,可在 Windows 設定中設定觸覺反饋喜好。

Windows 11 中支持的觸覺意見反應體驗包括 手寫筆跡意見反應互動意見反應

  • 書寫回饋透過筆與螢幕接觸時產生的持續振動,模擬各種書寫或繪圖工具(如原子筆、標記筆、鉛筆、螢光筆等)的手感。 預設情況下,Windows Ink 平台 支援所有繪圖工具的觸覺回饋(本文涵蓋如何提供超出 Windows Ink 支援的解決方案之自定義筆跡解決方案)。
  • 另一方面,互動意見反應是根據重要用戶動作的直接意見反應,例如將滑鼠懸停或點擊按鈕、回應動作的完成,或引起使用者的注意。

一般而言,需要五個步驟才能完全支持觸覺回饋:

  • 偵測手寫筆輸入。
  • 判斷目前的畫筆和裝置是否支援觸覺回饋,如果是的話,它支援什麼觸覺回饋功能。
  • 決定要傳送的觸覺回饋訊號。
  • 傳送觸覺反饋。
  • 停止觸覺回饋

偵測手寫筆輸入

若要偵測並隔離手寫筆輸入,您必須先註冊 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 Interop(PenDeviceInterop.FromPointerPoint)來存取系統 PenDevice

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

下列各節說明觸覺筆必須支持的意見反應功能,以及選擇性的回饋功能。 必要的觸覺回饋類型通常可用來作為後援,而不是選擇性功能。

墨跡波形

墨水波形會在筆與螢幕接觸時持續呈現,並嘗試模擬各種書寫或繪圖工具的手感。

特徵 / 功能 說明 必要/ 選擇性
InkContinous 波形 模擬實體原子筆書寫的感覺。 這是當觸覺筆不支援墨迹波形時的預設備用方案。 為必填項目
連續畫刷波形 當用戶選取筆刷作為筆跡工具時,會有連續的觸覺訊號。 可選
ChiselMarkerContinuous 波形 當使用者選取平頭記號筆/螢光筆作為書寫工具時,會提供連續的觸覺反饋。 可選
EraserContinuous 波形 當用戶選取橡皮擦作為筆跡工具時,將會有連續觸覺訊號。 可選
GalaxyContinuous 連續波形
HID 檔和實作指南將此波形稱為 SparkleContinuous
特殊墨水工具的連續觸覺訊號,例如多色畫刷。 可選
MarkerContinuous 波形 當用戶選取標記作為墨跡工具時,將會持續提供觸覺反饋。 可選
鉛筆連續波形 當用戶選取鉛筆作為筆跡工具時,會有連續的觸覺訊號。 可選

互動波形

互動波形通常很短(下表中指出的例外情況),是按需生成的直接反饋波形,用於確認重要操作,如懸停或點擊按鈕、響應操作完成,或吸引使用者的注意。

特徵 / 功能 說明 必要/ 選擇性
點擊波形 簡短的「點擊」反饋。 這是當觸覺筆不支援應用程式選取的互動波形時的預設備援。 為必填項目
誤差波 發出強訊號,提醒用戶動作失敗,或發生錯誤。 可選
悬浮波形 表示使用者已開始將滑鼠停留在互動式UI元素上。 可選
按波形圖 指出使用者何時在累加動作中按下互動式 UI 元素(請參閱 Release)。 可選
釋放波形 指出使用者何時在累加動作中釋放互動式 UI 元素(請參閱 Press)。 可選
成功波形 強訊號,提醒用戶動作成功。 可選
BuzzContinuous 波形 連續嗡嗡作響的感覺。 可選
隆隆連續波形 連續的隆隆感。 可選

觸覺反饋自定義設定

某些觸覺筆可以支援下列自訂功能。

特徵 / 功能 說明 必要/ 選擇性
強度 設定觸覺訊號的強度。 可選
播放計數 重複觸覺訊號的指定次數。 可選
重播暫停間隔 設定每次重複播放觸覺訊號之間的時間。 可選
播放持續時間 設定觸覺訊號播放的時間間隔。 可選

檢查是否支援自訂設定

若要檢查強度、播放計數、重新執行暫停間隔和播放持續時間支援,請使用 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 集合,確保作用中的手寫筆支援它。

如果不支援,您可以選擇完全不播放任何聲音,或切換回 點擊 波形,因為這保證受到支援。

在下列範例中,我們嘗試傳送 Error 波形(但如果不支援 Error,將退回到 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); 

自定義觸覺反饋

有三種方式可以自定義觸覺回饋。 第一個是由手寫和互動反饋所支援,而第二個和第三個則只有互動反饋支援。

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

範例

如需下列功能的工作範例,請參閱 畫筆觸覺範例