Suporte herdado para movimento panorâmico com barras de rolagem

Esta seção descreve o suporte para o movimento panorâmico usando barras de rolagem em aplicativos baseados no Windows.

No Windows 7, gestos de movimento panorâmico geram mensagens WM_*SCROLL para habilitar o suporte herdado para movimento panorâmico. Como seus aplicativos podem não dar suporte a todas as mensagens WM_*SCROLL, o movimento panorâmico pode não funcionar corretamente. Este tópico descreve as etapas que você deve seguir para garantir que a experiência de movimento panorâmico herdado nos aplicativos funcione conforme os usuários esperam.

Visão geral

As seções a seguir explicam como habilitar a experiência de movimento panorâmico herdado:

  • Crie um aplicativo com barras de rolagem.
  • Desabilitar movimentos.
  • Personalize a experiência de movimento panorâmico.

Criar um aplicativo com barras de rolagem

Inicie um novo projeto Win32 usando o assistente do Microsoft Visual Studio. Verifique se o tipo de aplicativo está definido como o aplicativo do Windows. Você não precisa habilitar o suporte para a ATL (Biblioteca de Modelos Ativos). A imagem a seguir mostra como será a aparência do projeto depois que você o tiver iniciado.

captura de tela mostrando uma janela sem barras de rolagem

Em seguida, habilite as barras de rolagem na imagem. Altere o código de criação da janela em InitInstance para que a chamada de função CreateWindow crie uma janela com barras de rolagem. O código a seguir mostra como fazer isso.

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

Depois de alterar o código de criação da janela, seu aplicativo terá uma barra de rolagem. A imagem a seguir mostra como o aplicativo pode ser exibido neste ponto.

captura de tela mostrando uma janela com uma barra de rolagem vertical, mas sem texto

Depois de alterar o código de criação da janela, adicione um objeto de barra de rolagem ao aplicativo e um texto a ser rolado. Coloque o código a seguir na parte superior do método 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""
     };        

Em seguida, implemente a lógica do aplicativo para configurar os cálculos de texto para métricas de texto. O código a seguir deve substituir o caso de WM_CREATE existente na função 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;

Em seguida, implemente a lógica do aplicativo para recálculo do bloco de texto quando a janela for redimensionada. O código a seguir deve ser colocado na opção de mensagem no 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;

Em seguida, implemente a lógica do aplicativo para mensagens de rolagem vertical. O código a seguir deve ser colocado na opção de mensagem no 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;

Em seguida, atualize o código para redesenhar a janela. O código a seguir deve substituir o caso de WM_PAINT padrão no 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;

Agora, quando você cria e executa o aplicativo, ele deve ter o texto clichê e uma barra de rolagem vertical. A imagem a seguir mostra a aparência do aplicativo.

captura de tela mostrando uma janela com uma barra de rolagem vertical e texto

Desabilitar Movimentos

Para melhorar a experiência de movimento panorâmico em seu aplicativo, você deve desativar os movimentos. Para fazer isso, defina as propriedades da janela no valor hWnd quando ele for inicializado. Os valores usados para movimentos são armazenados no cabeçalho tpcshrd.h, que também deve ser incluído. O código a seguir deve ser colocado em suas diretivas include e na função InitInstance depois de criar o hWnd.

Observação

Isso é útil para aplicativos que exigem comentários imediatos sobre um evento touch ou pen down em vez de testar um limite de tempo ou distância.

 

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

Personalizar a Experiência de Movimento Panorâmico

Talvez você queira uma experiência de movimento panorâmico diferente das ofertas do Windows 7 por padrão. Para melhorar a experiência de movimento panorâmico, você deve adicionar o manipulador para a mensagem WM_GESTURE . Para obter mais informações, consulte Aprimorando a experiência de panning do Single-Finger.

Gestos de Toque do Windows