Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W poniższych krokach wyjaśniono, jak śledzić wiele punktów dotykowych przy użyciu funkcji Windows Touch.
- Utwórz aplikację i włącz funkcję Windows Touch.
- Dodaj procedurę obsługi dla WM_TOUCH i punktów śledzenia.
- Rysuj punkty.
Po uruchomieniu aplikacji będzie ona renderować okręgi pod każdym dotknięciem. Na poniższym zrzucie ekranu pokazano, jak aplikacja może wyglądać podczas działania.
Tworzenie aplikacji i włączanie funkcji Windows Touch
Zacznij od aplikacji Microsoft Win32, używając kreatora Microsoft Visual Studio. Po zakończeniu pracy kreatora dodaj obsługę wiadomości Windows Touch, ustawiając wersję systemu Windows w pliku targetver.h, uwzględniając windows.h i windowsx.h w aplikacji. Poniższy kod pokazuje, jak ustawić wersję systemu Windows w pliku 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
Poniższy kod pokazuje, jak powinny zostać dodane dyrektywy include. Ponadto możesz utworzyć pewne zmienne globalne, które będą używane później.
#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)
};
Dodawanie programu obsługi dla WM_TOUCH i punktów śledzenia
Najpierw zadeklaruj kilka zmiennych używanych przez procedurę obsługi WM_TOUCH w WndProc.
int wmId, wmEvent, i, x, y;
UINT cInputs;
PTOUCHINPUT pInputs;
POINT ptInput;
Teraz zainicjuj zmienne używane do przechowywania punktów dotykowych i zarejestruj okno w celu odbierania danych dotykowych z metody 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;
}
Następnie obsłuż komunikat WM_TOUCH z metody WndProc . Poniższy kod przedstawia implementację procedury obsługi dla 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;
// Remove the old contact index to make it available for the new incremented dwID.
// On some touch devices, the dwID value is continuously incremented.
RemoveContactIndex(index);
}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
}
Notatka
Aby można było użyć funkcji ScreenToClient, musisz mieć wysoką obsługę DPI w aplikacji. Aby uzyskać więcej informacji na temat obsługi wysokiej rozdzielczości DPI, zobacz high DPI.
Teraz, gdy użytkownik dotyka ekranu, pozycje, które dotyka, będą przechowywane w tablicy punktów. Struktura członka dwID dla TOUCHINPUT przechowuje identyfikator, który będzie zależny od sprzętu.
Aby rozwiązać problem elementu członkowskiego dwID zależnego od sprzętu, program obsługi przypadków WM_TOUCH używa funkcji, GetContactIndex, która mapuje element dwID elementu członkowskiego TOUCHINPUT do punktu narysowanego na ekranie. Poniższy kod przedstawia implementację tej funkcji.
// 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] == dwID) {
return i;
}
}
for (int i = 0; i < MAXPOINTS; i++) {
if (idLookup[i] == -1) {
idLookup[i] = dwID;
return i;
}
}
// Out of contacts
return -1;
}
// Mark the specified index as initialized for new use
BOOL RemoveContactIndex(int index) {
if (index >= 0 && index < MAXPOINTS) {
idLookup[index] = -1;
return true;
}
return false;
}
Ważny
Windows 11 i nowszych
Niektóre trzy-i cztery interakcje dotykowe nie będą już działać w aplikacjach systemu Windows domyślnie.
Domyślnie trzy-i czteropalcze interakcje dotykowe są teraz używane przez system na potrzeby operacji, takich jak przełączanie lub minimalizowanie okien i zmienianie pulpitów wirtualnych. Ponieważ te interakcje są teraz obsługiwane na poziomie systemu, ta zmiana może mieć wpływ na funkcjonalność aplikacji.
Aby obsługiwać interakcje z trzema lub czterema palcami w aplikacji, wprowadzono nowe ustawienie użytkownika określające, czy system obsługuje te interakcje:
urządzenia & Bluetooth > Touch > "Gesty dotykowe trzema i czterema palcami"
Po ustawieniu wartości "Włączone" (wartość domyślna) system będzie obsługiwał wszystkie interakcje z trzema i czterema palcami (aplikacje nie będą mogły ich obsługiwać).
Po ustawieniu opcji "Wyłączone" interakcje z trzema i czterema palcami mogą być obsługiwane przez aplikacje (nie będą obsługiwane przez system).
Jeśli aplikacja musi obsługiwać te interakcje, zalecamy informowanie użytkowników o tym ustawieniu i podanie linku, który uruchamia ustawienia systemu Windows do odpowiedniej strony (ms-settings:devices-touch). Aby uzyskać więcej informacji, zobacz Launcher.LaunchUriAsync Method.
Narysuj punkty
Zadeklaruj następujące zmienne dla procedury rysunku.
// 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;
Kontekst pamięci wyświetlania memDC służy do przechowywania tymczasowego kontekstu graficznego, który jest zamieniany z renderowanym kontekstem wyświetlania hdc, aby zapobiec migotaniu. Zaimplementuj procedurę rysowania, która pobiera przechowywane punkty i rysuje okrąg na punktach. Poniższy kod pokazuje, jak można zaimplementować procedurę obsługi 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;
Po uruchomieniu aplikacji powinna ona teraz wyglądać podobnie do ilustracji na początku tej sekcji.
Dla zabawy możesz narysować kilka dodatkowych linii wokół punktów dotykowych. Na poniższym zrzucie ekranu pokazano, jak aplikacja może wyglądać z kilkoma dodatkowymi liniami narysowanymi wokół okręgów.