共用方式為


改善Single-Finger移動流覽體驗

如果您建置以 Windows Touch 為目標的應用程式,它會自動提供基本的移動流覽支援。 不過,您可以使用 WM_GESTURE 訊息來提供單指移動流覽的增強支援。

概觀

若要改善單指移動流覽體驗,請使用下列步驟,如本主題後續各節所述:

  • 建立具有捲軸且已停用閃爍的應用程式。
  • 新增對手勢移動流覽訊息的支援。
  • 啟用退回。

建立具有捲軸且已停用閃爍的應用程式

開始之前,您必須建立具有捲軸的應用程式。 使用 捲軸進行移動流覽的舊版支援 一節將說明此程式。 如果您想要從範例內容開始,請移至該區段,並使用捲軸建立應用程式,然後停用閃爍。 如果您已經有具有運作中捲軸的應用程式,請停用該區段中所述的閃爍。

新增手勢移動流覽訊息的自訂移動流覽支援

若要支援手勢移動流覽訊息,您必須在 WndProc 方法中處理它們。 手勢訊息可用來判斷移動流覽訊息的水準和垂直差異。 差異可用來更新捲軸物件,以更新使用者介面。

首先,更新 targetver.h 檔案中的 Windows 版本設定,以啟用 Windows Touch。 下列程式碼顯示應該取代 targetver.h 中各種 Windows 版本設定。

#ifndef WINVER                  // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0601           // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0601     // Change this to the appropriate value to target other versions of Windows.
#endif

接下來,將 UXTheme.h 檔案新增至您的專案,並將 uxtheme.lib 程式庫新增至專案的其他相依性。

#include <uxtheme.h>

接下來,將下列變數新增至 WndProc 函式的頂端。 這些會用於移動流覽的計算中。

// The following are used for the custom panning handler      
BOOL bResult = FALSE;

static int scale = 8;   // altering the scale value will change how fast the page scrolls
static int lastY = 0;   // used for panning calculations (initial / previous vertical position)
static int lastX = 0;   // used for panning calculations (initial / previous horizontal position)
GESTUREINFO gi;  

接下來,新增 WM_GESTURE 訊息的處理常式,以便根據移動流覽手勢以差異更新捲軸。 這可讓您更精細地控制移動流覽。

下列程式碼會從lParam取得GESTUREINFO結構、從 結構儲存最後一個 Y 座標,並判斷位置變更以更新捲軸物件。 下列程式碼應該放在 WndProc switch 語句中。

    case WM_GESTURE:        
        // Get all the vertial scroll bar information
        si.cbSize = sizeof (si);
        si.fMask  = SIF_ALL;
        GetScrollInfo (hWnd, SB_VERT, &si);
        yPos = si.nPos;

        ZeroMemory(&gi, sizeof(GESTUREINFO));
        gi.cbSize = sizeof(GESTUREINFO);
        bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);

        if (bResult){
            // now interpret the gesture            
            switch (gi.dwID){
                case GID_BEGIN:
                   lastY = gi.ptsLocation.y;
                   CloseGestureInfoHandle((HGESTUREINFO)lParam);
                   break;                     
                // A CUSTOM PAN HANDLER
                // COMMENT THIS CASE OUT TO ENABLE DEFAULT HANDLER BEHAVIOR
                case GID_PAN:                                                  
                    
                    si.nPos -= (gi.ptsLocation.y - lastY) / scale;

                    si.fMask = SIF_POS;
                    SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
                    GetScrollInfo (hWnd, SB_VERT, &si);                                                        
                                               
                    yOverpan -= lastY - gi.ptsLocation.y;
                    lastY = gi.ptsLocation.y;
                     
                    if (gi.dwFlags & GF_BEGIN){
                        BeginPanningFeedback(hWnd);
                        yOverpan = 0;
                    } else if (gi.dwFlags & GF_END) {
                        EndPanningFeedback(hWnd, TRUE);
                        yOverpan = 0;
                    }
                           
                    if (si.nPos == si.nMin || si.nPos >= (si.nMax - si.nPage)){                    
                        // we reached the bottom / top, pan
                        UpdatePanningFeedback(hWnd, 0, yOverpan, gi.dwFlags & GF_INERTIA);
                    }
                    ScrollWindow(hWnd, 0, yChar * (yPos - si.nPos), NULL, NULL);
                    UpdateWindow (hWnd);                    
                                        
                    return DefWindowProc(hWnd, message, lParam, wParam);
                case GID_ZOOM:
                   // Add Zoom handler 
                   return DefWindowProc(hWnd, message, lParam, wParam);
                default:
                   // You have encountered an unknown gesture
                   return DefWindowProc(hWnd, message, lParam, wParam);
             }          
        }else{
            DWORD dwErr = GetLastError();
            if (dwErr > 0){
                // something is wrong 
                // 87 indicates that you are probably using a bad
                // value for the gi.cbSize
            }
        } 
        return DefWindowProc (hWnd, message, wParam, lParam);

現在,當您在視窗上執行移動流覽手勢時,您會看到具有慣性的文字捲動。 此時,您可能會想要將文字變更為有更多行,以便探索移動流覽大型文字區段。

WndProc 中的界限意見反應

界限意見反應是當使用者到達可移動流覽區域結束時,提供給使用者的視覺意見反應類型。 達到界限時,應用程式會觸發它。 在先前WM_GESTURE訊息的範例實作中,會使用WM_GESTURE案例中的結束條件 (si.nPos == si.yPos) 來測試您已到達可移動流覽區域的結尾。 下列變數可用來追蹤值和測試錯誤。

// The following are used for panning feedback (Window Bounce)
static int animCount = 0;
static DWORD dwErr   = 0;

static BOOL isOverpan  = FALSE;
static long xOverpan   = 0;
static long yOverpan   = 0;

移動流覽手勢案例會更新為觸發界限意見反應。 下列程式碼說明來自 WM_GESTURE 訊息處理常式 GID_PAN 案例。

                case GID_PAN:                                                  
                    
                    si.nPos -= (gi.ptsLocation.y - lastY) / scale;

                    si.fMask = SIF_POS;
                    SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
                    GetScrollInfo (hWnd, SB_VERT, &si);                                                        
                                               
                    yOverpan -= lastY - gi.ptsLocation.y;
                    lastY = gi.ptsLocation.y;
                     
                    if (gi.dwFlags & GF_BEGIN){
                        BeginPanningFeedback(hWnd);
                        yOverpan = 0;
                    } else if (gi.dwFlags & GF_END) {
                        EndPanningFeedback(hWnd, TRUE);
                        yOverpan = 0;
                    }
                           
                    if (si.nPos == si.nMin){                    
                        // we reached the top, pan upwards in y direction
                        UpdatePanningFeedback(hWnd, 0, yOverpan, gi.dwFlags & GF_INERTIA);
                    }else if (si.nPos >= (si.nMax - si.nPage)){
                        // we reached the bottom, pan downwards in y direction
                        UpdatePanningFeedback(hWnd, 0, yOverpan, gi.dwFlags & GF_INERTIA);
                    }
                    ScrollWindow(hWnd, 0, yChar * (yPos - si.nPos), NULL, NULL);
                    UpdateWindow (hWnd);                    
                                        
                    return DefWindowProc(hWnd, message, lParam, wParam);
  

現在,當使用者移動流覽超過捲軸區域底部時,應用程式視窗應該會有界限意見反應。

Windows Touch 手勢

BeginPanningFeedback

EndPanningFeedback

UpdatePanningFeedback