Поделиться через


Улучшение опыта прокрутки Single-Finger

Если вы создаете приложение, предназначенное для сенсорного интерфейса Windows, оно автоматически предоставляет базовую поддержку прокрутки. Однако вы можете использовать сообщение WM_GESTURE, чтобы обеспечить расширенную поддержку сдвига одним пальцем.

Обзор

Чтобы улучшить процесс прокрутки с одним пальцем, выполните следующие действия, как объяснено в последующих разделах этой статьи:

  • Создайте приложение с полосами прокрутки и с отключенными щелчками.
  • Добавьте поддержку сообщений панорамирования жестов.
  • Включите отскоки.

Создание приложения с полосами прокрутки и отключение flicks

Перед началом работы необходимо создать приложение с полосами прокрутки. В разделе Поддержка устаревших систем для сдвига с помощью полос прокрутки объясняется этот процесс. Если вы хотите начать с примера содержимого, перейдите в этот раздел и создайте приложение с полосами прокрутки, а затем отключите flicks. Если у вас уже есть приложение с работоспособными полосами прокрутки, отключите щелчки, как описано в этом разделе.

Добавление настраиваемой поддержки панорамирования для сообщений о жестах панорамирования

Для поддержки сообщений сдвига жестов их необходимо обрабатывать в методе WndProc. Сигналы жестов используются для определения горизонтальных и вертикальных разностей для сообщений панорамирования. Дельты используются для обновления объекта полосы прокрутки, который, в свою очередь, обновляет пользовательский интерфейс.

Сначала обновите параметры версии Windows в файле targetver.h, чтобы включить Windows Touch. В следующем коде показаны различные параметры версии Windows, которые должны заменить их в targetver.h.

#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, чтобы полосы прокрутки обновлялись с учетом изменений на основе жестов панорамирования. Это дает вам гораздо более детализированное управление поворотом.

Следующий код получает структуру GESTUREINFO из lParam, сохраняет последнюю координату 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 конечное условие (si.nPos == si.yPos) из случая WM_GESTURE используется для проверки того, что вы достигли конца прокручиваемой области. Следующие переменные используются для отслеживания значений и проверки ошибок.

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

Обновляется жест перемещения, чтобы активировать обратную связь о границах. Следующий код иллюстрирует случай GID_PAN из обработчика сообщений WM_GESTURE.

                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