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


Устаревшая поддержка сдвига с помощью полос прокрутки

В этом разделе описывается поддержка сдвига с помощью полос прокрутки в приложениях windows.

В Windows 7 жесты сдвига создают сообщения WM_*SCROLL, чтобы включить поддержку сдвига прежних версий. Так как приложения могут поддерживать не все сообщения WM_*SCROLL, сдвиг может работать неправильно. В этом разделе описываются действия, которые необходимо предпринять для обеспечения того, чтобы устаревший интерфейс сдвига в приложениях работал так, как ожидает пользователь.

Общие сведения

В следующих разделах объясняется, как включить устаревший интерфейс сдвига.

  • Создайте приложение с полосами прокрутки.
  • Отключение flicks.
  • Настройка интерфейса сдвига.

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

Запустите новый проект Win32 с помощью мастера Microsoft Visual Studio. Убедитесь, что в качестве типа приложения задано приложение Windows. Не нужно включать поддержку активной библиотеки шаблонов (ATL). На следующем рисунке показано, как будет выглядеть проект после его запуска.

Снимок экрана: окно без полос прокрутки

Затем включите полосы прокрутки на изображении. Измените код создания окна в InitInstance , чтобы вызов функции CreateWindow создавал окно с полосами прокрутки. В следующем примере кода показано, как это сделать:

   hWnd = CreateWindow(
      szWindowClass, 
      szTitle, 
      WS_OVERLAPPEDWINDOW | WS_VSCROLL,  // style
      200,                               // x
      200,                               // y
      550,                               // width
      300,                               // height
      NULL,
      NULL,
      hInstance,
      NULL
    );  

После изменения кода создания окна приложение будет иметь полосу прокрутки. На следующем рисунке показано, как приложение может выглядеть на этом этапе.

Снимок экрана: окно с вертикальной полосой прокрутки без текста

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

    TEXTMETRIC tm;     
    SCROLLINFO si; 
     
    // These variables are required to display text. 
    static int xClient;     // width of client area 
    static int yClient;     // height of client area 
    static int xClientMax;  // maximum width of client area 
     
    static int xChar;       // horizontal scrolling unit 
    static int yChar;       // vertical scrolling unit 
    static int xUpper;      // average width of uppercase letters 
     
    static int xPos;        // current horizontal scrolling position 
    static int yPos;        // current vertical scrolling position 
     
    int i;                  // loop counter 
    int x, y;               // horizontal and vertical coordinates
     
    int FirstLine;          // first line in the invalidated area 
    int LastLine;           // last line in the invalidated area 
    HRESULT hr;
    int abcLength = 0;  // length of an abc[] item

    int lines = 0;

    // Create an array of lines to display. 
    static const int LINES=28;
    static LPCWSTR abc[] = { 
       L"anteater",  L"bear",      L"cougar", 
       L"dingo",     L"elephant",  L"falcon", 
       L"gazelle",   L"hyena",     L"iguana", 
       L"jackal",    L"kangaroo",  L"llama", 
       L"moose",     L"newt",      L"octopus", 
       L"penguin",   L"quail",     L"rat", 
       L"squid",     L"tortoise",  L"urus", 
       L"vole",      L"walrus",    L"xylophone", 
       L"yak",       L"zebra",
       L"This line contains words, but no character. Go figure.",
       L""
     };        

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

    case WM_CREATE : 
        // Get the handle to the client area's device context. 
        hdc = GetDC (hWnd); 
 
        // Extract font dimensions from the text metrics. 
        GetTextMetrics (hdc, &tm); 
        xChar = tm.tmAveCharWidth; 
        xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2; 
        yChar = tm.tmHeight + tm.tmExternalLeading; 
 
        // Free the device context. 
        ReleaseDC (hWnd, hdc); 
 
        // Set an arbitrary maximum width for client area. 
        // (xClientMax is the sum of the widths of 48 average 
        // lowercase letters and 12 uppercase letters.) 
        xClientMax = 48 * xChar + 12 * xUpper; 
 
        return 0;

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

    case WM_SIZE: 
 
        // Retrieve the dimensions of the client area. 
        yClient = HIWORD (lParam); 
        xClient = LOWORD (lParam); 
 
        // Set the vertical scrolling range and page size
        si.cbSize = sizeof(si); 
        si.fMask  = SIF_RANGE | SIF_PAGE; 
        si.nMin   = 0; 
        si.nMax   = LINES - 1; 
        si.nPage  = yClient / yChar; 
        SetScrollInfo(hWnd, SB_VERT, &si, TRUE); 
 
        // Set the horizontal scrolling range and page size. 
        si.cbSize = sizeof(si); 
        si.fMask  = SIF_RANGE | SIF_PAGE; 
        si.nMin   = 0; 
        si.nMax   = 2 + xClientMax / xChar; 
        si.nPage  = xClient / xChar; 
        SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);            
        return 0;

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

        case WM_VSCROLL:
         // Get all the vertical scroll bar information
         si.cbSize = sizeof (si);
         si.fMask  = SIF_ALL;
         GetScrollInfo (hWnd, SB_VERT, &si);
         // Save the position for comparison later on
         yPos = si.nPos;
         switch (LOWORD (wParam))
         {
         // user clicked the HOME keyboard key
         case SB_TOP:
             si.nPos = si.nMin;
             break;
              
         // user clicked the END keyboard key
         case SB_BOTTOM:
             si.nPos = si.nMax;
             break;
              
         // user clicked the top arrow
         case SB_LINEUP:
             si.nPos -= 1;
             break;
              
         // user clicked the bottom arrow
         case SB_LINEDOWN:
             si.nPos += 1;
             break;
              
         // user clicked the scroll bar shaft above the scroll box
         case SB_PAGEUP:
             si.nPos -= si.nPage;
             break;
              
         // user clicked the scroll bar shaft below the scroll box
         case SB_PAGEDOWN:
             si.nPos += si.nPage;
             break;
              
         // user dragged the scroll box
         case SB_THUMBTRACK:
             si.nPos = si.nTrackPos;
             break;

         // user positioned the scroll box
         // This message is the one used by Windows Touch
         case SB_THUMBPOSITION:
             si.nPos = HIWORD(wParam);
             break;
                            
         default:
              break; 
         }
         // Set the position and then retrieve it.  Due to adjustments
         //   by Windows it may not be the same as the value set.
         si.fMask = SIF_POS;
         SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
         GetScrollInfo (hWnd, SB_VERT, &si);
         // If the position has changed, scroll window and update it
         if (si.nPos != yPos)
         {                    
          ScrollWindow(hWnd, 0, yChar * (yPos - si.nPos), NULL, NULL);
          UpdateWindow (hWnd);
         }
         break;

Затем обновите код, чтобы перерисовать окно. Следующий код должен заменить вариант WM_PAINT по умолчанию в WndProc.

    case WM_PAINT:
         // Prepare the window for painting
         hdc = BeginPaint (hWnd, &ps);
         // Get vertical scroll bar position
         si.cbSize = sizeof (si);
         si.fMask  = SIF_POS;
         GetScrollInfo (hWnd, SB_VERT, &si);
         yPos = si.nPos;
         // Get horizontal scroll bar position
         GetScrollInfo (hWnd, SB_HORZ, &si);
         xPos = si.nPos;
         // Find painting limits
         FirstLine = max (0, yPos + ps.rcPaint.top / yChar);
         LastLine = min (LINES - 1, yPos + ps.rcPaint.bottom / yChar);
         
         
         
         for (i = FirstLine; i <= LastLine; i++)         
         {
              x = xChar * (1 - xPos);
              y = yChar * (i - yPos);
              
              // Note that "55" in the following depends on the 
              // maximum size of an abc[] item.
              //
              abcLength = wcslen(abc[i]);
              hr = S_OK;
              if ((FAILED(hr)))
              {
                 MessageBox(hWnd, L"err", L"err", NULL);
              }else{
                  TextOut(hdc, x, y, abc[i], abcLength);
              }
              
         }
         // Indicate that painting is finished
         EndPaint (hWnd, &ps);
         return 0;

Теперь при сборке и запуске приложения в нем должен быть стандартный текст и вертикальная полоса прокрутки. На следующем рисунке показано, как может выглядеть приложение.

Снимок экрана: окно с вертикальной полосой прокрутки и текстом

Отключение Flicks

Чтобы улучшить процесс сдвига в приложении, следует отключить жесты. Для этого задайте свойства окна для значения hWnd при его инициализации. Значения, используемые для щелчков, хранятся в заголовке tpcshrd.h, который также должен быть включен. Следующий код следует поместить в директивы include и в функцию InitInstance после создания hWnd.

Примечание

Это полезно для приложений, которым требуется немедленная обратная связь о событии касания или нажатия пера вместо проверки порогового значения времени или расстояния.

 

#include <tpcshrd.h>
[...]
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
[...]
  
   const DWORD_PTR dwHwndTabletProperty = 
    TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture
    TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves)
    TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle)
    TABLET_DISABLE_FLICKS; // disables pen flicks (back, forward, drag down, drag up)
   
   SetProp(hWnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, reinterpret_cast<HANDLE>(dwHwndTabletProperty));

Настройка интерфейса сдвига

По умолчанию может потребоваться другой режим сдвига, отличный от возможностей Windows 7. Чтобы улучшить процесс сдвига, необходимо добавить обработчик для сообщения WM_GESTURE . Дополнительные сведения см. в разделе Улучшение Single-Finger сдвига.

Сенсорные жесты Windows