Single-Fingerパンエクスペリエンスの改善

Windows Touch を対象とするアプリケーションをビルドすると、基本的なパンのサポートが自動的に提供されます。 ただし、WM_GESTURE メッセージを使用して、 1 本指でのパンのサポートを強化できます。

概要

1 本指でのパンエクスペリエンスを向上させるには、このトピックの後続のセクションで説明されているように、次の手順を使用します。

  • スクロール バーとフリックを無効にしたアプリケーションを作成します。
  • ジェスチャ パン メッセージのサポートを追加します。
  • バウンスを有効にします。

スクロール バーとフリックを無効にしてアプリケーションを作成する

開始する前に、スクロール バーを含むアプリケーションを作成する必要があります。 「 スクロール バーを使用したパンのレガシ サポート」セクションで、 このプロセスについて説明します。 サンプル コンテンツから始める場合は、そのセクションに移動し、スクロール バーを含むアプリケーションを作成し、フリックを無効にします。 スクロール バーが機能するアプリケーションが既にある場合は、そのセクションで説明されているようにフリックを無効にします。

ジェスチャ パン メッセージのカスタム パンサポートを追加する

ジェスチャ パン メッセージをサポートするには、 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 タッチ ジェスチャ

BeginPanningFeedback

EndPanningFeedback

UpdatePanningFeedback