Détection et suivi de plusieurs points tactiles
Les étapes suivantes expliquent comment suivre plusieurs points de contact à l’aide de Windows Touch.
- Créez une application et activez Windows Touch.
- Ajoutez un gestionnaire pour les points de WM_TOUCH et de suivi.
- Dessinez les points.
Une fois que votre application est en cours d’exécution, elle affiche les cercles sous chaque contact. La capture d’écran suivante montre à quoi votre application peut ressembler lors de l’exécution.
Créer une application et activer Windows Touch
Commencez par une application Microsoft Win32 à l’aide de l’Assistant Microsoft Visual Studio. Une fois l’Assistant terminé, ajoutez la prise en charge des messages Windows Touch en définissant la version de Windows dans targetver.h et en incluant windows.h et windowsx.h dans votre application. Le code suivant montre comment définir la version de Windows dans 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
Le code suivant montre comment vos directives include doivent être ajoutées. Vous pouvez également créer des variables globales qui seront utilisées ultérieurement.
#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)
};
Ajouter un gestionnaire pour les points de WM_TOUCH et de suivi
Tout d’abord, déclarez certaines variables utilisées par le gestionnaire WM_TOUCH dans WndProc.
int wmId, wmEvent, i, x, y;
UINT cInputs;
PTOUCHINPUT pInputs;
POINT ptInput;
À présent, initialisez les variables utilisées pour stocker les points tactiles et inscrivez la fenêtre pour l’entrée tactile à partir de la méthode 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;
}
Ensuite, gérez le message WM_TOUCH à partir de la méthode WndProc . Le code suivant montre une implémentation du gestionnaire pour 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
}
Notes
Pour utiliser la fonction ScreenToClient , vous devez disposer d’une prise en charge élevée des PPP dans votre application. Pour plus d’informations sur la prise en charge d’un DPI élevé, consultez DPI élevé.
À présent, lorsqu’un utilisateur touche l’écran, les positions qu’il touche sont stockées dans le tableau de points. Le membre dwID de la structure TOUCHINPUT stocke un identificateur qui dépend du matériel.
Pour résoudre le problème lié au fait que le membre dwID dépend du matériel, le gestionnaire de cas WM_TOUCH utilise une fonction, GetContactIndex, qui mappe le membre dwID de la structure TOUCHINPUT à un point qui est dessiné à l’écran. Le code suivant montre une implémentation de cette fonction.
// 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;
}
Important
Windows 11 et versions ultérieures
Par défaut, certaines interactions tactiles à trois et quatre doigts ne fonctionnent plus dans les applications Windows.
Par défaut, les interactions tactiles à trois et quatre doigts sont désormais consommées par le système pour des opérations telles que le changement ou la réduction des fenêtres et la modification des bureaux virtuels. Comme ces interactions sont désormais gérées au niveau du système, les fonctionnalités de votre application peuvent être affectées par cette modification.
Pour prendre en charge les interactions à trois ou quatre doigts au sein d’une application, un nouveau paramètre utilisateur a été introduit qui spécifie si le système gère ou non ces interactions :
> Appareils Bluetooth & Tactiles > « Mouvements tactiles à trois et quatre doigts »
Lorsqu’il est défini sur « Activé » (par défaut), le système gère les interactions à trois et quatre doigts (les applications ne peuvent pas les prendre en charge).
Lorsqu’elles sont définies sur « Off », les interactions à trois et quatre doigts peuvent être prises en charge par les applications (elles ne seront pas gérées par le système).
Si votre application doit prendre en charge ces interactions, nous vous recommandons d’informer les utilisateurs de ce paramètre et de fournir un lien qui lance l’application Paramètres vers la page appropriée (ms-settings:devices-touch). Pour plus d’informations, consultez La méthode Launcher.LaunchUriAsync.
Dessiner les points
Déclarez les variables suivantes pour la routine de dessin.
// 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;
Le memDC de contexte d’affichage de la mémoire est utilisé pour stocker un contexte graphique temporaire qui est échangé avec le contexte d’affichage rendu, hdc, afin d’éliminer le scintillement. Implémentez la routine de dessin, qui prend les points que vous avez stockés et dessine un cercle aux points. Le code suivant montre comment implémenter le gestionnaire 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;
Lorsque vous exécutez votre application, elle doit maintenant ressembler à l’illustration au début de cette section.
Pour le plaisir, vous pouvez dessiner des lignes supplémentaires autour des points de contact. La capture d’écran suivante montre à quoi l’application peut ressembler avec quelques lignes supplémentaires dessinées autour des cercles.