Freigeben über


Verbessern des Single-Finger Verschiebungsvorgangs

Wenn Sie eine Anwendung erstellen, die auf Windows Touch ausgerichtet ist, bietet sie automatisch grundlegende Unterstützung für das Verschieben. Sie können jedoch die WM_GESTURE-Nachricht verwenden, um erweiterte Unterstützung für das Schwenken mit einem Finger bereitzustellen.

Übersicht

Führen Sie die folgenden Schritte aus, wie in den folgenden Abschnitten dieses Themas erläutert, um die Einfingerverschiebung zu verbessern:

  • Erstellen Sie eine Anwendung mit Bildlaufleisten und deaktivierten Flicken.
  • Unterstützung für Gestenverschiebungsmeldungen hinzufügen.
  • Aktivieren Sie die Unzustellbarkeit.

Erstellen einer Anwendung mit Bildlaufleisten und deaktivierten Flicks

Bevor Sie beginnen, müssen Sie eine Anwendung mit Bildlaufleisten erstellen. Im Abschnitt Legacy Support for Panning with Scrollbars (Legacy Support for Panning with Scrollbars) wird dieser Vorgang erläutert. Wenn Sie mit dem Beispielinhalt beginnen möchten, wechseln Sie zu diesem Abschnitt, und erstellen Sie eine Anwendung mit Bildlaufleisten, und deaktivieren Sie dann Flicks. Wenn Sie bereits über eine Anwendung mit funktionierenden Bildlaufleisten verfügen, deaktivieren Sie Flicks wie in diesem Abschnitt beschrieben.

Hinzufügen benutzerdefinierter Schwenkunterstützung für Gestenverschiebungsnachrichten

Um Gestenverschiebungsmeldungen zu unterstützen, müssen Sie sie in der WndProc-Methode behandeln. Die Gestenmeldungen werden verwendet, um horizontale und vertikale Deltas für schwenkbare Nachrichten zu bestimmen. Die Deltas werden verwendet, um das Bildlaufleistenobjekt zu aktualisieren, wodurch die Benutzeroberfläche aktualisiert wird.

Aktualisieren Sie zunächst die Windows-Versionseinstellungen in der Datei targetver.h, um Windows Touch zu aktivieren. Der folgende Code zeigt die verschiedenen Windows-Versionseinstellungen, die diese in targetver.h ersetzen sollen.

#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

Fügen Sie als Nächstes die Datei UXTheme.h zu Ihrem Projekt hinzu, und fügen Sie die Bibliothek uxtheme.lib zu den zusätzlichen Abhängigkeiten Ihres Projekts hinzu.

#include <uxtheme.h>

Fügen Sie als Nächstes die folgenden Variablen am Anfang der WndProc-Funktion hinzu. Diese werden in Berechnungen für die Verschiebung verwendet.

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

Fügen Sie als Nächstes den Handler für die WM_GESTURE-Nachricht hinzu, damit die Bildlaufleisten mit Deltas aktualisiert werden, die auf Verschiebungsgesten basieren. Dadurch erhalten Sie eine viel feiner abgestimmte Steuerung des Schwenkens.

Der folgende Code ruft die GESTUREINFO-Struktur aus dem lParam ab, speichert die letzte y-Koordinate aus der Struktur und bestimmt die Änderung der Position zum Aktualisieren des Bildlaufleistenobjekts. Der folgende Code sollte in Ihrer WndProc-Switch-Anweisung platziert werden.

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

Wenn Sie nun die Schwenkbewegung in Ihrem Fenster ausführen, sehen Sie, dass der Text mit Inertia scrollt. An diesem Punkt können Sie den Text so ändern, dass er mehr Zeilen enthält, damit Sie das Verschieben großer Textabschnitte untersuchen können.

Begrenzungsfeedback in WndProc

Begrenzungsfeedback ist eine Art visuelles Feedback, das Benutzern gegeben wird, wenn sie das Ende eines schwenkbaren Bereichs erreichen. Sie wird von der Anwendung ausgelöst, wenn eine Grenze erreicht wird. In der vorherigen Beispielimplementierung der WM_GESTURE Nachricht wird die Endbedingung (si.nPos == si.yPos) aus dem WM_GESTURE Fall verwendet, um zu testen, ob Sie das Ende einer schwenkbaren Region erreicht haben. Die folgenden Variablen werden verwendet, um Werte nachzuverfolgen und Fehler zu testen.

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

Die Groß-/Kleinschreibung der Schwenkgeste wird aktualisiert, um Begrenzungsfeedback auszulösen. Der folgende Code veranschaulicht den GID_PAN Fall aus dem WM_GESTURE Nachrichtenhandler.

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

Jetzt sollte das Fenster Ihrer Anwendung Begrenzungsfeedback haben, wenn ein Benutzer am unteren Rand des Bildlaufleistenbereichs vorbei schwenkt.

Windows-Touchgesten

BeginPanningFeedback

EndPanningFeedback

UpdatePanningFeedback