Compartir a través de


Detección y seguimiento de varios puntos táctiles

En los pasos siguientes se explica cómo realizar un seguimiento de varios puntos táctiles mediante Windows Touch.

  1. Cree una aplicación y habilite Windows Touch.
  2. Agregue un controlador para WM_TOUCH y puntos de seguimiento.
  3. Dibuje los puntos.

Una vez que la aplicación se esté ejecutando, se representarán círculos bajo cada toque. En la captura de pantalla siguiente se muestra el aspecto de la aplicación mientras se ejecuta.

captura de pantalla que muestra una aplicación que representa los puntos táctiles como círculos verdes y amarillos

Crear una aplicación y habilitar Windows Touch

Comience con una aplicación De Microsoft Win32 mediante el Asistente de Microsoft Visual Studio. Una vez completado el asistente, agregue compatibilidad con los mensajes de Windows Touch estableciendo la versión de Windows en targetver.h e incluyendo windows.h y windowsx.h en la aplicación. En el código siguiente se muestra cómo establecer la versión de Windows en targetver.h.

#ifndef WINVER                  // Specifies that the minimum required platform is Windows 7.
#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 7.
#define _WIN32_WINNT 0x0601     // Change this to the appropriate value to target other versions of Windows.
#endif     

#ifndef _WIN32_WINDOWS          // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE                       // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700        // Change this to the appropriate value to target other versions of IE.
#endif

En el código siguiente se muestra cómo se deben agregar las directivas include. Además, puede crear algunas variables globales que se usarán más adelante.

#include <windows.h>    // included for Windows Touch
#include <windowsx.h>   // included for point conversion

#define MAXPOINTS 10

// You will use this array to track touch points
int points[MAXPOINTS][2];

// You will use this array to switch the color / track ids
int idLookup[MAXPOINTS];


// You can make the touch points larger
// by changing this radius value
static int radius      = 50;

// There should be at least as many colors
// as there can be touch points so that you
// can have different colors for each point
COLORREF colors[] = { RGB(153,255,51), 
                      RGB(153,0,0), 
                      RGB(0,153,0), 
                      RGB(255,255,0), 
                      RGB(255,51,204), 
                      RGB(0,0,0),
                      RGB(0,153,0), 
                      RGB(153, 255, 255), 
                      RGB(153,153,255), 
                      RGB(0,51,153)
                    };

Agregar controlador para WM_TOUCH y puntos de seguimiento

En primer lugar, declare algunas variables que usa el controlador de WM_TOUCH en WndProc.

int wmId, wmEvent, i, x, y;

UINT cInputs;
PTOUCHINPUT pInputs;
POINT ptInput;   

Ahora, inicialice las variables usadas para almacenar puntos táctiles y registre la ventana para la entrada táctil desde el método InitInstance .

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd) {
      return FALSE;
   }

   // register the window for touch instead of gestures
   RegisterTouchWindow(hWnd, 0);  

   // the following code initializes the points
   for (int i=0; i< MAXPOINTS; i++){
     points[i][0] = -1;
     points[i][1] = -1;
     idLookup[i]  = -1;
   }  

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

A continuación, controle el WM_TOUCH mensaje del método WndProc . En el código siguiente se muestra una implementación del controlador para WM_TOUCH.

case WM_TOUCH:        
  cInputs = LOWORD(wParam);
  pInputs = new TOUCHINPUT[cInputs];
  if (pInputs){
    if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){
      for (int i=0; i < static_cast<INT>(cInputs); i++){
        TOUCHINPUT ti = pInputs[i];
        index = GetContactIndex(ti.dwID);
        if (ti.dwID != 0 && index < MAXPOINTS){                            
          // Do something with your touch input handle
          ptInput.x = TOUCH_COORD_TO_PIXEL(ti.x);
          ptInput.y = TOUCH_COORD_TO_PIXEL(ti.y);
          ScreenToClient(hWnd, &ptInput);
          
          if (ti.dwFlags & TOUCHEVENTF_UP){                      
            points[index][0] = -1;
            points[index][1] = -1;                
          }else{
            points[index][0] = ptInput.x;
            points[index][1] = ptInput.y;                
          }
        }
      }

      InvalidateRect(hWnd, NULL, FALSE);
    }
    // If you handled the message and don't want anything else done with it, you can close it
    CloseTouchInputHandle((HTOUCHINPUT)lParam);
    delete [] pInputs;
  }else{
    // Handle the error here 
  }  

Nota:

Para poder usar la función ScreenToClient , debe tener compatibilidad con valores altos de PPP en la aplicación. Para obtener más información sobre cómo admitir valores altos de PPP, consulte Valores altos de PPP.

Ahora, cuando un usuario toca la pantalla, las posiciones que toca se almacenarán en la matriz de puntos. El miembro dwID de la estructura TOUCHINPUT almacena un identificador que dependerá del hardware.

Para solucionar el problema del miembro dwID que depende del hardware, el controlador de mayúsculas y minúsculas WM_TOUCH usa una función , GetContactIndex, que asigna el miembro dwID de la estructura TOUCHINPUT a un punto dibujado en la pantalla. El código siguiente muestra una implementación de esta función.

// This function is used to return an index given an ID
int GetContactIndex(int dwID){
  for (int i=0; i < MAXPOINTS; i++){
    if (idLookup[i] == -1){
      idLookup[i] = dwID;
      return i;
    }else{
      if (idLookup[i] == dwID){
        return i;
      }
    }
  }
  // Out of contacts
  return -1;
}

Importante

Windows 11 y versiones más recientes

Algunas interacciones táctiles de tres y cuatro dedos ya no funcionarán en las aplicaciones de Windows de forma predeterminada.

De forma predeterminada, el sistema usa interacciones táctiles de tres y cuatro dedos para operaciones como cambiar o minimizar ventanas y cambiar escritorios virtuales. Dado que estas interacciones ahora se controlan en el nivel de sistema, la funcionalidad de la aplicación podría verse afectada por este cambio.

Para admitir interacciones de tres o cuatro dedos dentro de una aplicación, se ha introducido una nueva configuración de usuario que especifica si el sistema controla o no estas interacciones:

Dispositivos > Bluetooth & Touch > "Gestos táctiles de tres y cuatro dedos"

Cuando se establece en "Activado" (valor predeterminado), el sistema controlará las interacciones de tres y cuatro dedos (las aplicaciones no podrán admitirlas).

Cuando se establece en "Desactivado", las interacciones de tres y cuatro dedos se pueden admitir en las aplicaciones (el sistema no las controlará).

Si la aplicación debe admitir estas interacciones, se recomienda informar a los usuarios de esta configuración y proporcionar un vínculo que inicie la aplicación Configuración en la página correspondiente (ms-settings:devices-touch). Para obtener más información, vea Launcher.LaunchUriAsync (Método).

Dibujar los puntos

Declare las siguientes variables para la rutina de dibujo.

    // For double buffering
    static HDC memDC       = 0;
    static HBITMAP hMemBmp = 0;
    HBITMAP hOldBmp        = 0;
   
    // For drawing / fills
    PAINTSTRUCT ps;
    HDC hdc;
    HBRUSH hBrush;
    
    // For tracking dwId to points
    int index;

El contexto de visualización de memoria memDC se usa para almacenar un contexto de gráficos temporales que se intercambia con el contexto de visualización representado, hdc, para eliminar el parpadeo. Implemente la rutina de dibujo, que toma los puntos que ha almacenado y dibuja un círculo en los puntos. En el código siguiente se muestra cómo se puede implementar el controlador de WM_PAINT .

  case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);    
    RECT client;
    GetClientRect(hWnd, &client);        
  
    // start double buffering
    if (!memDC){
      memDC = CreateCompatibleDC(hdc);
    }
    hMemBmp = CreateCompatibleBitmap(hdc, client.right, client.bottom);
    hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);          

    hBrush = CreateSolidBrush(RGB(255, 255, 255));
    FillRect(memDC, &client, hBrush);
    DeleteObject(hBrush);

    //Draw Touched Points                
    for (i=0; i < MAXPOINTS; i++){
      hBrush = CreateSolidBrush(colors[i]);        
      SelectObject( memDC, hBrush);           

      x = points[i][0];
      y = points[i][1];
      if  (x >0 && y>0){              
        Ellipse(memDC, x - radius, y - radius, x+ radius, y + radius);
      }

      DeleteObject(hBrush);
    }
  
    BitBlt(hdc, 0,0, client.right, client.bottom, memDC, 0,0, SRCCOPY);      
    EndPaint(hWnd, &ps);

    SelectObject(memDC, hOldBmp);
    DeleteObject(hMemBmp);

    break;

Al ejecutar la aplicación, ahora debería tener un aspecto similar a la ilustración al principio de esta sección.

Para divertirse, puedes dibujar algunas líneas adicionales alrededor de los puntos táctiles. En la captura de pantalla siguiente se muestra cómo la aplicación podría verse con algunas líneas adicionales dibujadas alrededor de los círculos.

captura de pantalla que muestra una aplicación que representa puntos táctiles como círculos con líneas a través de los centros e intersección de los bordes de los puntos táctiles

Entrada táctil de Windows