Wewnątrz Windows 7: Możliwości wielodotykowe w Windows 7

Yochay Kiriaty

Ten artykuł omawia:

                Modele programowania wielodotykowego

                Gesty

                Surowe komunikaty dotykowe

Ten artykuł wykorzystuje następujące technologie:
Windows 7

Ten artykuł jest oparty na wstępnej wersji systemu Windows 7. Szczegóły mogą ulec zmianie.

http://i.msdn.microsoft.com/Global/Images/clear.gif  Spis treści

Wprowadzenie do wielodotyku w Windows 7
Modele programowania platformy wielodotyku w Windows 7
Praca z gestami
Praca z surowymi komunikatami dotykowymi Windows
Podsumowanie

Jest to trzeci artykuł w serii artykułów dotyczących Windows 7. Seria ta skupia się na nowych cechach użytkowych, które programiści mogą wykorzystać, przy tworzeniu swoich aplikacji dla Windows 7. Część 1 omówiła biblioteki. Część 2 omówiła interfejsy API paska zadań. Część 3 omawia możliwości wielodotykowe w Windows 7 Należy teraz pobrać wersję Windows 7 Release Candidate, aby móc maksymalnie skorzystać z tego artykułu.

Wprowadzenie do wielodotyku w Windows 7

W Windows 7 wzbogaciliśmy interfejs Windows o możliwości dotykowe, czyniąc dotyk jednym z ważnych sposobów interakcji z komputerem obok myszy i klawiatury. W ostatnich latach byliśmy świadkami pojawienia się szerokiego zakresu urządzeń wielodotykowych, które generują niezwykle pozytywny odbiór wśród użytkowników. Dlatego całkiem naturalne dla systemu Windows staje się wprowadzenie obsługi takich urządzeń wielodotykowych w Windows 7 jako podstawowej możliwości.

Dzięki platformie wielodotykowej w Windows 7 mamy swobodę bezpośredniej interakcji ze swoim komputerem. Na przykład jesteśmy w stanie sięgać i powoli przeglądać zdjęcia bezpośrednio z Eksploratora Windows lub szybko je przerzucać. Ważne jest, aby zrozumieć, że nie utworzyliśmy specjalnej powłoki wielodotykowej w Windows 7. Nie ma specjalnego Eksploratora Windows, który jest dostępny tylko na urządzeniach z funkcją wielodotyku. Najprostszy przykład stanowią listy skoków paska zadań Windows 7. Gdy użyjemy myszy do kliknięcia prawym przyciskiem dowolnej ikony w pasku zdań, zobaczymy odpowiadającą jej listę skoków. Na przykład kliknięcie prawym przyciskiem myszy ikony Windows Live Messenger wyświetli listę skoków programu Live Messenger. Ale jak można kliknąć prawym przyciskiem myszy korzystając z wielodotyku? Trzeba po prostu dotknąć ikonę Live Messenger i przeciągnąć palcem w górę, jak pokazano na Rysunku 1.

fig01.gif

Rysunek 1 Korzystanie z wielodotyku na przykładzie listy skoków programu Live Messenger

Wykonanie tego gestu przeciągania wyświetli listę skoków programu Live Messenger. Jak widać na Rysunku 2, lista skoków wywołana dotknięciem wyświetla taką samą zawartość, jak standardowa lista skoków wywołana kliknięciem prawym przyciskiem myszy. Obrazek po prawej stronie pokazuje listę skoków programu Live Messenger wywołaną poprzez dotyk. Odstępy pomiędzy elementami na liście wywołanej wielodotykiem są większe niż odstępy pomiędzy elementami na lewym obrazku, który przedstawia domyślną listę skoków wywołaną kliknięciem prawym przyciskiem myszy.

fig01.gif

Rysunek 2 Standardowy i wywołany wielodotykiem widok listy skoków

Program Windows Live Messenger jest tylko jednym z przykładów, gdzie Windows 7 nie tworzy nowego interfejsu użytkownika specyficznego dla scenariuszy wykorzystujących dotyk, ale dopasowuje go do istniejącej infrastruktury. Pasek zadań jest tylko jednym z przykładów wielu elementów zoptymalizowanych dla wielodotyku, które są dostarczane z systemem Windows 7, jak XPS Viewer, Windows Photo Viewer oraz IE8.

Modele programowania platformy wielodotyku w Windows 7

Aby zapewnić pełne rozwiązania dotykowe dla wszelkiego rodzaju aplikacji, platforma dotykowa Windows dostarcza różne poziomy obsługi. Istnieje kilka scenariuszy, poprzez które możemy ulepszać aplikacje wykorzystując funkcje platformy dotykowej Windows Touch. Zanim przyjmiemy określone podejście, powinniśmy rozważyć, co dokładnie chcemy zrobić z naszą aplikacją.

Wsparcie dla starszych aplikacji Załóżmy, że mamy już istniejącą aplikację z dużą bazą instalacji. Można by się zapytać, jakie możliwości dotykowe będą mieli użytkownicy podczas uruchamiania tej aplikacji pod kontrolą systemu Windows 7 na komputerze wyposażonym w funkcje wielodotykowe. Dobra wiadomość jest taka, że platforma wielodotyku Windows 7 zapewnia bezpośrednio i za darmo wsparcie dla aplikacji, które mają świadomość interfejsów dotykowych, a nie były projektowane do obsługi wielodotyku. W szczególności zapewnia od razu obsługę kilku podstawowych gestów. Innymi słowy można oczekiwać, że kilka podstawowych gestów będzie działać zgodnie z oczekiwaniami w naszej aplikacji. Do podstawowych gestów należą przesuwanie jednym lub dwoma palcami, powiększanie dwoma palcami i gesty pstrykania, które zostały wprowadzone w czasach Windows Vista.

Dodawanie podstawowej obsługi wielodotyku Tutaj skupiamy się na dodawaniu bezpośredniej obsługi gestów i innych zachowań oraz na zmianach interfejsu użytkownika tak, aby aplikacje były bardziej przyjazne dla obsługi przez dotyk.

Jednym z przykładów, z którym już zapoznaliśmy się na początku tego artykułu, są zoptymalizowane pod kątem korzystania z dotyku listy skoków paska zadań. Korzystając z metody getMessageExtraInfo pasek zadań może śledzić źródło komunikatu wejściowego i określić, czy jest to komunikat dotykowy, a następnie odpowiednio zareagować.

Ponadto możemy korzystać z gestów, aby wzbogacić naszą aplikację i zapewnić lepszą obsługę wielodotyku. Aplikacje, które bezpośrednio odpowiadają na gesty, mają pełną kontrolę nad tym, jak zachowują się, gdy użytkownik korzysta z urządzenia dotykowego. Na przykład system Windows 7 jest dostarczany z programem Windows Photo Viewer. Aplikacja Photo Viewer otrzymuje konkretne informacje o położeniu, z którego rozpoczął się gest powiększania. To znaczy gest powiększania zawiera informacje o punkcie środkowym – określonych współrzędnych X i Y – gestu powiększania, a następnie Photo Viewer może skupić się wokół środka tego gestu. Aplikacja Windows Photo Viewer wykorzystuje też gesty przesuwania i obrotu, aby zapewniać bardzo dobre środowisko do przeglądania zdjęć przy stosunkowo niewielkim wysiłku.

Korzystając z gestów można też zmienić domyślne zachowanie przy przesuwaniu. Na przykład domyślne przewijanie dotykowe zaprojektowano do pracy z oknami tekstowymi, które są głównie przewijane w pionie, jak strony WWW lub dokumenty; przeciąganie w poziomie raczej zaznacza tekst, a nie przewija go. W większości aplikacji działa to dobrze. Co jednak, jeśli nasza aplikacja w istocie wymaga obsługi przewijania w poziomie? Poza tym w przypadku niektórych aplikacji domyślne przewijanie może wydawać się toporne, działając zbyt szybko lub zbyt wolno. Dzięki obsłudze gestów możemy zmienić domyślne zachowanie przesuwania i zoptymalizować je do potrzeb naszej aplikacji.

Środowisko zoptymalizowane dla wielodotyku Najlepszym scenariuszem jest, gdy aplikacje są od podstaw zaprojektowane do obsługi wielodotyku. Te aplikacje opierają się na komunikacie dotykowym WM_TOUCH. Ten komunikat zapewnia aplikacji surowe dane dotyczące dotyku i możemy przetwarzać te komunikaty oraz obsługiwać wiele punktów dotykowych. Większość gestów, o których wspominaliśmy wcześniej, stanowią gesty dwupalcowe, natomiast w komunikatach WM_TOUCH możemy otrzymywać tyle równoczesnych punktów dotyku, ile obsługuje dany sprzęt czuły na dotyk.

Platforma wielodotyku Windows 7 zapewnia również procesory manipulacji i bezwładności pomagające nam w interpretowaniu komunikatów dotykowych. Manipulację można traktować jako czarną skrzynkę, która otrzymuje na wejściu dotykany obiekt i wszystkie powiązane z nim komunikaty dotykowe. Wynikiem jest dwuwymiarowa macierz przekształcenia afinicznego reprezentująca transformację, która dokonała się jako wynik ruchu palców. Na przykład, gdybyśmy pisali aplikację do edycji fotografii, moglibyśmy złapać dwa zdjęcia jednocześnie używając dowolnej liczby palców, aby obracać, zmieniać rozmiary i przesuwać zdjęcia, a proces manipulacji zapewnia zmiany, które trzeba odzwierciedlić na tych obiektach.

Bezwładność zapewnia aplikacjom bardzo podstawowy model fizyczny i zapewnia nam łatwy sposób kontynuacji łagodnego przejścia dla obiektu nawet po podniesieniu palców znad urządzenia czułego na dotyk w celu utworzenia prostego wrażenia wygaszenia ruchu, zamiast nagłego zatrzymania obiektu w miejscu.

Praca z gestami

Za każdym razem, gdy użytkownik dotyka obsługiwane w Windows 7 urządzenie czułe na dotyk, platforma wielodotyku Windows 7 domyślnie wysyła komunikaty gestów WM_GESTURE do naszej aplikacji. To zachowanie dostępne jest automatycznie i trzeba je specjalnie wyłączyć, jeśli nie chcemy otrzymywać takich komunikatów.

Gesty są traktowane jako informacje wejściowe pochodzące od dotyku jednym lub dwoma palcami, które są tłumaczone na jakiś rodzaj wstępnie zdefiniowanego działania (gest) wykonywanego przez użytkownika. Po wykryciu gestu (system operacyjny wykonuje tu całą pracę za nas) system operacyjny prześle komunikat gestu do naszej aplikacji. Ten komunikat zawiera wszystkie informacje potrzebne do odszyfrowania gestu i zastosowania go. Windows 7 obsługuje następujące gesty:

                 Powiększanie

                 Przesuwanie pojedynczym palcem i dwoma palcami

                 Obrót

                 Stuknięcie dwoma palcami

                 Naciśnięcie i stuknięcie

Obsługa komunikatów WM_Gesture Aby pracować z gestami, musimy obsługiwać komunikaty WM_GESTURE, które są przesyłane do naszej aplikacji. Jeśli jesteśmy programistami Win32, możemy sprawdzać komunikaty WM_GESTURE w funkcji WndProc naszej aplikacji.

WM_GESTURE jest ogólnym komunikatem używanym dla wszystkich gestów. Dlatego, aby określić, który gest musimy obsłużyć, najpierw musimy zdekodować komunikat gestu. Informacje na temat gestów można znaleźć w parametrze lParam i trzeba skorzystać z funkcji specjalnej GetGestureInfo, aby odszyfrować komunikat gestu, jak pokazano w poniższym fragmencie kodu.

Kopiuj kod

GESTUREINFO gi;
ZeroMemory(&gi, sizeof(GESTUREINFO));
gi.cbSize = sizeof(gi);
BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);

Po uzyskaniu struktury GESTUREINFO możemy sprawdzić element dwID, aby zidentyfikować, który gest został wykonany. Struktura GESTUREINFO zawiera kilka innych ważnych elementów:

**                cbSize** – rozmiar struktury w bajtach

**                ptsLocation** – Struktura POINTS zawierająca współrzędne skojarzone z gestem. Te współrzędne są zawsze podawane względem początku ekranu.

**                dwFlags** – stan gestu taki jak początek, bezwładność i koniec

**                ullArguments** – 64-bitowa liczba całkowita bez znaku, która zawiera argumenty dla gestów, które mieszczą się w ośmiu bajtach. Jest to informacja dodatkowa, która jest unikalna dla każdego typu gestów.

Mając tę wiedzę możemy teraz przejść dalej i napisać kompletną metodę switch-case, która obsłuży wszystkie gesty, jak pokazano na Rysunku 3.

http://i.msdn.microsoft.com/Global/Images/clear.gif  Rysunek 3 Metoda Switch-Case

Kopiuj kod

void CMTTestDlg::DecodeGesture(WPARAM wParam, LPARAM lParam)
{
    GESTUREINFO gi;
    ZeroMemory(&gi, sizeof(GESTUREINFO));
    GetGestureInfo((HGESTUREINFO)lParam, &gi);
    switch (gi.dwID){
        case GID_ZOOM:
            // Tutaj kod do obsługi powiększania
            break;
        case GID_PAN:
            break;
        case GID_ROTATE:
            break;
        case GID_TWOFINGERTAP:
            break;
        case GID_PRESSANDTAP:
            break;
        default:
            // Natrafiliśmy na nieznany gest
            break;
    CloseGestureInfoHandle((HGESTUREINFO)lParam);
}

Należy zwrócić uwagę, że na końcu tej funkcji wywołujemy funkcję CloseGestureInfoHandle, która zamyka zasoby skojarzone z procedurą obsługi informacji o geście. Jeśli obsługujemy komunikat WM_GESTURE, to naszym obowiązkiem jest zamknięcie tego uchwytu przy pomocy tej funkcji. Pominięcie tego może spowodować wyciek pamięci.

Obsługa komunikatów gestów ma ustalony przebieg, który obejmuje konfigurację, dekodowanie komunikatu gestu i obsługę określonych gestów zgodnie z potrzebami naszej aplikacji. Jak widać na poprzednim kodzie, nie jest to trudne.

Przyjrzyjmy się teraz dokładnie gestom powiększania, co da nam pojęcie, jak mogą wyglądać wszystkie inne gesty.

Korzystanie z gestu powiększania do skalowania obiektu

Gest powiększania jest zwykle rozpoznawany przez użytkowników, jako ruch „szczypiący” pomiędzy dwoma punktami dotyku, gdzie zbliża się palce do siebie, aby pomniejszyć obiekt, a odsuwa się palce od siebie, aby powiększyć obiekt. Gest powiększania pozwala nam skalować rozmiary naszych obiektów. Rysunek 4 ilustruje, jak działa gest powiększania.

fig01.gif

Rysunek 4 Gest powiększania

Teraz zobaczmy, jaki kod musimy zaimplementować w gałęzi GID_ZOOM instrukcji switch, aby osiągnąć żądany efekt powiększania.

Struktura z informacjami o geście zawiera element dwFlags, który jest używany do określania stanu gestu i może zawierać dowolną spośród następujących wartości:

**                GF_BEGIN** – wskazuje, że gest się rozpoczyna, otrzymywane w pierwszym komunikacie WM_Gesture

**                GF_INERTIA** – wskazuje, że gest wywołał bezwładność

**                GF_END** – wskazuje, że gest się zakończył

                Gałąź default instrukcji switch – wskazuje pozostałe komunikaty gestu i zwykle określa zmianę w stosunku do poprzedniego komunikatu

Wykorzystamy flagę GF_BEGIN do zapisania współrzędnych początkowych punktu dotyku w zmiennych, do odwoływania się w kolejnych krokach. Zapisujemy ptsLocation w zmiennej _ptFirst. Dla gestu powiększania ptsLocation określa środek powiększenia.

Następny komunikat powiększania, który nadejdzie, zostanie obsłużony przez przypadek domyślny (default). Zapisujemy współrzędne w zmiennej _ptSecond. Następnie obliczamy punkt środkowy powiększania, stopień powiększenia, a na koniec aktualizujemy prostokąt (nasz obiekt graficzny), aby odzwierciedlić punkt środkowy powiększenia i wskaźnik powiększenia. Rysunek 5 pokazuje te argumenty.

http://i.msdn.microsoft.com/Global/Images/clear.gif Rysunek 5 Gałąź GID_ZOOM instrukcji switch

Kopiuj kod

case GID_ZOOM:
switch(gi.dwFlags)
{
case GF_BEGIN:
    _dwArguments = LODWORD(gi.ullArguments);
    _ptFirst.x = gi.ptsLocation.x;
    _ptFirst.y = gi.ptsLocation.y;
    ScreenToClient(hWnd,&_ptFirst);
    break;
default:
    // Tutaj odczytujemy drugi punkt gestu. Jest to punkt środkowy pomiędzy palcami.
    _ptSecond.x = gi.ptsLocation.x;
    _ptSecond.y = gi.ptsLocation.y;
    ScreenToClient(hWnd,&_ptSecond);
    // Musimy obliczyć punkt środkowy powiększania
    ptZoomCenter.x = (_ptFirst.x + _ptSecond.x)/2;
    ptZoomCenter.y = (_ptFirst.y + _ptSecond.y)/2;
    // Stopień powiększenia jest stosunkiem pomiędzy nową i starą odległością.
    k = (double)(LODWORD(gi.ullArguments))/(double)(_dwArguments);
    // Teraz możemy przetworzyć powiększanie/pomniejszanie obiektu
    ProcessZoom(k,ptZoomCenter.x,ptZoomCenter.y);
    InvalidateRect(hWnd,NULL,TRUE);
    // Teraz musimy zapisać nowe informacje jako informacje początkowe dla następnego kroku
    _ptFirst = _ptSecond;
    _dwArguments = LODWORD(gi.ullArguments);
    break;
}
break;

W procedurze obsługi przypadku domyślnego zapisujemy lokalizację gestu i tworzymy dwa zestawy punktów (reprezentujące bieżący i poprzedni punkt dotyku), obliczamy położenie punktu środkowego powiększania i zapisujemy je w ptZoomCenter. Obliczamy też stopień powiększenia wyliczając stosunek pomiędzy oboma punktami. Wywołanie funkcji pomocniczej ProcessZoom aktualizuje nowe współrzędne w celu odzwierciedlenia współczynnika i punktu środkowego powiększenia.

Obsługa pozostałych gestów domyślnych Windows 7 jest bardzo podobna do obsługi gestu powiększania opisanej powyżej. Wszystkie gesty mają podobny przebieg, a jedynie implementacja logiki wewnętrznej różni się dla poszczególnych gestów. Następnie przeglądniemy model optymalny i zagłębimy się w interfejs API, który pozwala nam odbierać i obsługiwać surowe zdarzenia dotykowe.

Praca z surowymi komunikatami dotykowymi Windows

Aby zacząć otrzymywać surowe komunikaty dotykowe WM_TOUCH, musimy najpierw poprosić system operacyjny o rozpoczęcie przesyłania komunikatów dotykowych do naszej aplikacji i zatrzymanie przesyłania domyślnych komunikatów gestów. W tym celu musimy wywołać funkcję RegisterTouchWindow(HWND hWnd, ULONG uFlags). Wywołanie tej funkcji rejestruje pojedynczy element hWnd (zwykle okno) jako obsługujący dotyk.

Tak jak w przypadku gestów obsługujemy komunikaty WM_TOUCH w funkcji WndProc naszej aplikacji. Pojedynczy komunikat WM_TOUCH może zawierać kilka różnych komunikatów dla punktów dotyku, które trzeba rozpakować do tablicy struktur dotykowych danych wejściowych. Standardowo chcemy rozpakować komunikat WM_TOUCH do tablicy struktur TOUCHINPUT, gdzie każda struktura w tej tablicy reprezentuje dane z pojedynczego punktu dotyku. Aby odpakować te dane, musimy wywołać funkcję GetTouchInputInfo(HTOUCHINPUT hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize) i przekazać jej parametr lParam komunikatu WM_TOUCH oraz nowo utworzoną tablicę punktów dotyku, jak pokazano na Rysunku 6.

http://i.msdn.microsoft.com/Global/Images/clear.gif Rysunek 6 Rozpakowywanie komunikatu WM_TOUCH

Kopiuj kod

case WM_TOUCH:
{
    unsigned int numInputs = (unsigned int) wParam;
    TOUCHINPUT* ti = new TOUCHINPUT[numInputs];
    if(GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT)))
    {
        // Obsłuż każdy punkt styku
        for(unsigned int i=0; i< numInputs; ++i)
        {
           /* obsłuż ti[i]  */
        }
    }
    CloseTouchInputHandle((HTOUCHINPUT)lParam);
    delete [] ti;
}
break;
default:
    return DefWindowProc(hWnd, message, wParam, lParam);

Tutaj możemy zobaczyć, jak wypełniamy tablicę TOUCHPOINT ti danymi dla każdego punktu dotyku. Następnie przechodzimy przez tablicę punktów dotyku stosując naszą logikę do każdego punktu dotyku (komentarz obsłuż ti[i]). Na koniec musimy oczyścić uchwyt dotyku wywołując CloseTouchInputHandle(HTOUCHINPUT hTouchInput) przekazując parametr lParam z WinProc. Pominięcie tego będzie powodować wycieki pamięci.

Poprzedni kod reprezentuje pierwszy krok w obsłudze komunikatów WM_TOUCH. Pojedyncza struktura danych wejściowych dotyku TOUCHINPUT zawiera wszystkie potrzebne informacje dotyczące pojedynczego punktu dotyku, z którymi będziemy musieli pracować:

**                dwID** – jest identyfikatorem punktu dotyku, który odróżnia określone dane wejściowe dotyku od innych

**                dwFlags** – jest zbiorem flag bitowych, które określają stan punktu dotyku

                współrzędne X i Y punktu dotyku (lokalizacja każdego punktu dotyku)

**                dwTime** – okres czasu dla zdarzenia w milisekundach

**                dwMask** – zbiór flag bitowych określających, które pola opcjonalne w strukturze zawierają istotne wartości

Trzeba zauważyć, że współrzędne X i Y są podane w setnych częściach piksela fizycznych współrzędnych ekranu (tzn. w centa-pikselach). Ta super dokładna rozdzielczość wspomaga wysoką dokładność i precyzję rozpoznawania pisma odręcznego dla innych aplikacji, które mogą wymagać takiej dokładnej rozdzielczości. W przypadku większości scenariuszy musimy pamiętać o podzieleniu współrzędnych X i Y punktu dotyku przez sto, aby przetłumaczyć współrzędne punktu dotyku na możliwe do wykorzystania współrzędne ekranowe przed rozpoczęciem stosowania tych współrzędnych.

Jak dotąd wiemy, jak obsługiwać komunikaty dotykowe i mamy wszystkie informacje potrzebne, aby przejść i dodać prawdziwą logikę do naszej procedury obsługi komunikatu WM_TOUCH opisanej powyżej. Wykorzystajmy tę wiedzę i zbudujmy wielodotykową aplikację malarską, znaną jako Scratch Pad.

Śledzenie identyfikatorów punktów dotyku Aby utworzyć aplikację Scratch Pad, musimy śledzić ruch każdego punktu dotyku i ścieżkę, którą tworzy, a następnie rysować linię wzdłuż tej ścieżki. Aby rozróżniać pomiędzy różnymi punktami dotyku i mieć pewność, że naprawdę obsługujemy każdy punkt dotyku prawidłowo, przypisujemy inny kolor do każdego punktu dotyku.

Po rozpakowaniu komunikatu dotyku do tablicy struktur dotykowych danych wejściowych ti musimy sprawdzić stan każdego punktu dotyku i zastosować różną logikę w zależności od stanu dotyku. W przykładzie Scratch Pad nowe punkty dotyku są identyfikowane przez stan dotknięcia TOUCHEVENTF_DOWN. Rejestrujemy nowy identyfikator punktu dotyku i przypisujemy mu kolor. Gdy punkt dotyku zostaje usunięty TOUCHEVENTF_UP, kończymy ostatnią kreskę i wyrejestrowujemy identyfikator punktu dotyku. Pomiędzy zdarzeniami rozpoczęcia i zakończenia dotyku najprawdopodobniej otrzymamy wiele komunikatów ruchu TOUCHEVENTF_MOVE. Dla każdego komunikatu ruchu dodajemy nowy punkt do istniejącej linii i malujemy nowy odcinek tej linii. Rysunek 7 pokazuje całą procedurę obsługi komunikatu WM_TOUCH, która jest wymagana, aby aplikacja Scratch Pad obsługiwała wielodotyk.

http://i.msdn.microsoft.com/Global/Images/clear.gif Rysunek 7 Procedura obsługi komunikatu WM_TOUCH

Kopiuj kod

case WM_TOUCH:
{
    unsigned int numInputs = (unsigned int) wParam;
    TOUCHINPUT* ti = new TOUCHINPUT[numInputs];
    if(GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT)))
    {
        // Dla każdego styku wyślij ten komunikat do odpowiedniej procedury obsługi komunikatu.
        for(unsigned int i=0; i< numInputs; ++i)
        {
            if(ti[i].dwFlags & TOUCHEVENTF_DOWN)
            {
               OnTouchDownHandler(hWnd, ti[i]);
            }
            else if(ti[i].dwFlags & TOUCHEVENTF_MOVE)
            {
               OnTouchMoveHandler(hWnd, ti[i]);
            }
            else if(ti[i].dwFlags & TOUCHEVENTF_UP)
            {
               OnTouchUpHandler(hWnd, ti[i]);
            }
        }
    }
    CloseTouchInputHandle((HTOUCHINPUT)lParam);
    delete [] ti;
}
break;

Kluczem do śledzenia poszczególnych punktów dotyku jest wykorzystanie identyfikatora dwID, który pozostaje taki sam przez czas trwania określonego dotknięcia. W funkcji pomocniczej OnTouchDownHandler przypisujemy ten identyfikator do obiektu CStroke, który jest po prostu tablicą punktów reprezentujących linię. Ta linia jest ścieżką, po której prowadzony jest palec po powierzchni urządzenia czułego na dotyk. Nie omówimy całego kodu przykładowego, który obsługuje tę aplikację i faktycznie rysuje linie na ekranie. Właściwie wszystko, co musimy zrobić, aby obsługiwać wielodotyk, można znaleźć w poprzednim kodzie przykładowym.

Wynik działania aplikacji Scratch Pad można zobaczyć na Rysunku 8.

fig01.gif

Rysunek 8 Wynik działania aplikacji Scratch Pad

Podsumowanie

Platforma wielodotyku Windows 7 jest platformą programistyczną o bardzo dużych możliwościach. Od implementacji domyślnej obsługi gestów do bardziej zaawansowanych surowych komunikatów dotykowych daje nam to mnóstwo możliwości przy stosunkowo prostej implementacji.

Platforma ta obejmuje również procesory manipulacji i bezwładności. Manipulacje są pod wieloma względami podobne do gestów , ale mają znacznie większe możliwości. Manipulacje są używane do upraszczania operacji transformacji na dowolnej liczbie obiektów. Można jednocześnie wykonywać kombinacje określonych gestów składowych takich jak obrót, powiększanie i skalowanie na określonym obiekcie. Procesor manipulacji zwraca dwuwymiarową „macierz transformacji”, która reprezentuje transformacje współrzędnych X i Y, zmianę skali i obrót, które odnoszą się do danego obiektu w czasie jako wynik wykonanego ruchu punktów dotyku. Gdy pobrany zostanie ostatni punkt dotyku, możemy zechcieć zastosować proste zasady fizyczne wobec obiektu, aby płynnie wyhamował zamiast nagłego zatrzymania się w miejscu. Do obsługi tego płynnego ruchu platforma wielodotyku Windows 7 zapewnia interfejs API dla bezwładności.

Te interfejsy API będą tematem naszego następnego artykułu MSDN.

Yochay Kiriaty pracuje jako Technical Evangelist w firmie Microsoft skupiając się na Windows 7. Ma ponad dekadę doświadczenia w tworzeniu oprogramowania. Przygotowywał i prowadził akademickie kursy informatyczne i jest aktywnym współautorem The Windows Blog .