101
102
Lexemple le plus simple concerne les listes de raccourcis de la barre des tches Windows 7, examines aux chapitres 1, Bienvenue dans Windows 7 et 2, Intgration de la barre des tches Windows 7 : fonctionnalits de base . Dans Windows 7, lorsque vous effectuez un clic avec le bouton droit de la souris sur toute icne pingle la barre des tches, vous voyez sa liste de raccourcis correspondante. Par exemple, en effectuant un clic droit sur licne de barre des tches de Microsoft Office Word 2007 vous voyez la liste de raccourcis de lapplication Office. Comment toutefois effectuez un clic droit laide du multi-tactile ? Mme sil existe un geste clic droit disponible dans Windows 7 (appuyez et tapoter), vous pouvez galement toucher licne Word (signale par le numro 1 dans lillustration suivante) et faire glisser votre doigt (illustr par la flche se dplaant vers le numro 2 dans lillustration suivante), en supposant que la barre des tches se trouve son emplacement par dfaut en bas de lcran.
Effectuer ce geste de glisser affiche la liste de raccourcis de Word. Comme le montre limage suivante, la liste de raccourcis ouverte tactilement ( droite) affiche le mme contenu que la liste de raccourcis standard affiche laide dun clic droit de souris ( gauche), mais dune faon lgrement diffrente.
103
Lespacement entre les lments de la liste de raccourcis multi-tactile est plus important que celui entre les lments de la liste de raccourcis standard. La raison de cette diffrence dapparence est simple : la barre des tches est optimise pour le multi-tactile. De ce fait, ses lments sont affichs de faon faciliter une slection manuelle, en proposant une surface de touche plus importante et diminuant le risque de toucher le mauvais lment avec votre doigt. Augmenter la surface dun lment qui doit tre touch est une pratique classique lors de la programmation dune application capacits tactiles, et cette approche est exploite dans tout Windows 7. La barre des tches nest quun exemple de la faon dont Windows 7 ne cre pas un nouvel ensemble dinterfaces utilisateur uniquement pour les scnarios tactiles, mais fond la nouvelle fonctionnalit dans linfrastructure existante. Aero Peek, le dispositif Windows 7 qui affiche des miniatures des applications ouvertes, a galement recours cette approche. Il permet demployer un geste tactile deux doigts plutt quun survol de souris, prenant en charge cette fonctionnalit en affichant des points tactiles plus importants pour rarranger les fentres sur votre cran. Une fois encore, la barre des tches nest quun exemple des nombreux ressentis optimiss multi-tactiles qui accompagnent Windows 7. Parmi les autres figurent la visionneuse XPS, Windows Photo Viewer et Internet Explorer 8.
104
Un autre aspect important du dispositif multi-tactile de Windows 7 est le concept Aucun toucher ignor . Le systme ne vous laissera pas toucher lcran et avoir limpression que rien ne sest pass ou que le toucher na pas t peru. Le systme gnre une raction chaque toucher, soit un vacillement dicne pour des gestes de toucher lger ou, si vous placez votre doigt au mme endroit quelques secondes, lapparition dun cercle rond signalant la disponibilit dun menu contextuel de clic droit. Autre concept tactile, celui de frontire. Les frontires servent aux gestes de balayage de lutilisateur pour crer un effet de rebond de la fentre lorsque lutilisateur atteind le haut ou le bas dune zone dfilante.
105
panoramique dun ou de deux doigts, un zoom deux doigts et les gestes d'effleurement apparus lpoque de Windows Vista. Il existe une vaste palette dapplications existantes non conscientes du toucher, comme Microsoft Office Word 2007 ou Adobe PDF Reader. Elles se comportent toutefois dune faon surprenante comme attendu avec les gestes panoramiques un ou deux doigts et les gestes de zoom. Tirant profit de la plate-forme multi-tactile de Windows 7, elles offrent une prise en charge tactile immdiate.
106
rotation pour offrir un excellent ressenti dexamen des images avec relativement peu defforts. Les gestes permettent doutrepasser le comportement de dfilement (panoramique) par dfaut. Par exemple, le dfilement tactile par dfaut est conu pour travailler dans des fentres de texte qui se droulent de faon primaire verticalement, comme avec des pages Web ou des documents, tandis quun dplacement horizontal slectionne du texte sans dplacer la page. Cest parfait dans la plupart des applications. Mais si votre application doit pouvoir prendre en charge un dfilement horizontal ? De mme, dans certaines applications le dfilement par dfaut peut paratre saccad, trop rapide ou trop lent. La prise en charge des gestes permet doutrepasser le comportement de dfilement par dfaut et de loptimiser selon les besoins de votre application.
107
dtecter et de rpondre de multiples touchers simultans. Le multi-tactile est dfini comme au moins deux touchers simultans. Nous nous intressons galement au monotactile car il existe quelques gestes un doigt (toucher unique) concerns par lAPI multitactile. La fonctionnalit multi-tactile de Windows 7 est fournie par un nouvel ensemble de messages Windows ddis. Examinons comment sont gnrs ces messages et ce que vous devez faire pour consommer des messages multi-tactiles et travailler avec ceux-ci.
WISPTIS
Application 5
Figure 5-1 Flux de donnes dun dispositif tactile vers linfrastructure multi-tactile Windows 7 et votre application
108
En rponse lentre de lutilisateur (point 1 du diagramme), le matriel tactile gnre un flux de donnes propritaire communiqu au pilote (point 2 du diagramme). Le pilote transforme le flux de donnes propritaire en constructions tactiles compatibles Windows 7 transmises au processus WISPTIS (Windows Ink Services Platform Table Input Subsystem) de la plate-forme Tablet (point 3 du diagramme). Le processus WISPTIS Tablet gnre alors des messages Windows envoys lapplication (point 4). Lapplication peut alors choisir de grer ou dignorer ces messages. En supposant quelle gre le message tactile, elle actualise son affichage. Le processus WISPTIS Tablet est le cur de la plate-forme multi-tactile Windows 7, recevant en entre les donnes du pilote et gnrant en rponse les messages Windows. Il peut gnrer soit des messages dentre tactiles bruts (raw touch) sous forme de messages WM_TOUCH ou des messages de gestes sous la forme de messages WM_GESTURE. Cela signifie que le WISPTIS Tablet traite lentre du pilote et reconnat si lutilisateur effectue des gestes spcifiques : zoom, panoramique ou rotation. Le WISPTIS Tablet est le moteur de reconnaissance de geste de Microsoft.
Remarque Souvenez-vous que les applications reoivent par dfaut des messages de gestes multi-tactiles. Cela signifie que WISPTIS Tablet envoie des messages de gestes lapplication lorsquil dtecte un geste, sauf si vous spcifiez de ne recevoir que des messages tactiles bruts (comme dcrit au Chapitre 6, Touchez-moi : programmation multi-tactile avance ). Les messages tactiles bruts (WM_TOUCH) et les messages de gestes (WM_GESTURE) sont mutuellement exclusifs : une application ne peut recevoir les deux simultanment.
Des fonctions dAPI ddies encapsulent les dtails de la cration et de la consommation des messages WM_GESTURE. La raison en tient ce que les informations associes ce message pourraient changer lavenir, sans casser les applications qui consomment dj le message, et quil vaut mieux toujours employer lAPI. Il existe plusieurs moyens de grer les messages tactiles envoys votre application. Si vous employez Win32, vous pouvez vrifier le message WM_GESTURE dans la fonction WndProc de votre application. Les dveloppeurs WPF nont pas se proccuper de la gestion de tels messages Windows de bas niveau puisque le .NET Framework sen charge leur place. Nous examinerons le modle de programmation multi-tactile WPF dans les prochains chapitres et le modle de programmation natif dans ce chapitre et le suivant. Avant toutefois de commencer nous intresser aux nouvelles API, repenchons-nous sur le modle Bien , la prise en charge multi-tactile par dfaut attendue de Windows 7 pour les applications hrites.
109
Une autre partie de larchitecture qui doit tre mentionne dans ce survol est que WISPTIS Tablet gnre des messages WM_GESTURE envoys par dfaut la fentre de votre application. En tant que dveloppeur, vous pouvez dcider des messages grer et de ceux ignorer. Vous employez souvent une construction switch-case pour grer diffremment chaque message. Si vous ne voulez pas grer un message spcifique, il est hautement recommand de le renvoyer Windows pour tre certain que le message sera gr par le processus de gestion par dfaut de Windows. Si vous choisissez dignorer les messages WM_GESTURE, ces messages franchiront votre construction switch-case WndProc et seront renvoys au systme dexploitation comme comportement par dfaut en appelant DefWindowProc. En Win32, il est hautement recommand dappeler DefWindowsProc pour les messages WM que votre application ne gre pas. WISPTIS Tablet intervient alors nouveau en consommant ces messages et en revoyant des messages Windows alternatifs votre application (voir Figure 5-2).
110
WISPTIS
.... ....
default: DefWindowProc(..) 2
Par exemple, avec un panoramique un doigt, la plate-forme doit dterminer si vous effectuez un dfilement (gnralement un geste vertical) ou slectionnez du texte (gnralement un geste horizontal). La plate-forme vrifie si votre doigt accomplit un geste dans les limites de ce qui est dfini comme zone dfilante. Une zone dfilante est tout contrle utilisateur qui affiche un contenu avec une barre de dfilement prenant en charge les messages Windows de dfilement vertical ou horizontal, WM_VSCROLL et WM_HSCROLL. Tous les contrles utilisateur par dfaut qui prennent en charge la fonctionnalit de barre de dfilement, dans MFC (Microsoft Foundation Classes), Win32 et .NET WinForm prennent galement en charge mes messages Windows pr-mentionns et prennent donc en charge les panoramiques un doigt. Les panoramiques deux doigts sont galement pris en charge dans les applications hrites. Avec les panoramiques deux doigts toutefois, vous ne pouvez effectuer que des gestes de dfilement et de slection de texte. En supposant que votre contrle utilisateur prenne en charge le dfilement, la plate-forme vrifie alors dans quelle direction lutilisateur a effectu le geste de dfilement. Un panoramique vertical dans une zone dfilante aboutit un message de dfilement vertical, WM_VSCROLL, tandis quun panoramique horizontal gnre gnralement un message WM_HSCROLL. La prise en charge multi-tactile de Windows 7 pour les applications hrites comprend galement le geste dagrandissement ou zoom. Le geste de zoom est gnralement dcrit comme un mouvement de pince effectu sur deux points tactiles. Tout geste de zoom non gr par votre application retourne vers le systme, comme mentionn plus tt, et est renvoy lapplication comme message Windows de CTRL+molette de souris.
111
112
WM_GESTURE est le message gnrique employ pour tous les gestes. De ce fait, pour dterminer quel geste vous devez grer, vous devez dabord dcoder le message de geste. Les informations sur le geste se trouvent dans le paramtre lParam et vous devez employer une fonction spciale, GetGestureInfo, pour dcoder le message de geste. Cette fonction reoit un pointeur vers une structure GESTUREINFO et lParam. En cas de russite, la fonction remplit la structure dinformations de geste avec toutes les informations sur le geste :
GESTUREINFO gi; ZeroMemory(&gi, sizeof(GESTUREINFO)); gi.cbSize = sizeof(gi); BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);
Vous pouvez voir ici que vous prparez la structure GESTUREINFO, gi, en la remplissant de zros sauf pour la taille, puis transmettez son pointeur la fonction pour la peupler des informations du message de geste. Aprs avoir obtenu une structure GESTUREINFO, vous pouvez vrifier dwID, un des membres de la structure, pour identifier le geste accompli. dwID nest toutefois quun des membres de la structure, qui comprend plusieurs autres membres importants :
dwFlags dwID
Lidentifiant de la commande du geste. Ce membre indique le type de La taille de la structure, exprime en octets. Doit tre fix avant lappel de
geste. fonction. Une structure POINTS qui contient les coordonnes associes au geste. Ces coordonnes sont toujours relatives lorigine de lcran. Ce sont des identifiants internes de la structure, qui ne doivent tre ni employs ni grs.
cbSize
ptsLocation
Un entier non sign sur 64 bits qui contient les arguments de gestes qui tiennent en huit octets. Il sagit des informations supplmentaires uniques pour chaque type de geste. La taille, en octets, dautres ullArguments qui accompagnent ce geste.
cbExtraArgs
Vous pouvez maintenant complter la clause switch-case pour grer tous les gestes Windows 7, comme le montre le fragment de code suivant :
void CMTTestDlg::DecodeGesture(WPARAM wParam, LPARAM lParam) { // crer une structure pour peupler et rcuprer les informations supplmentaires de message GESTUREINFO gi;
113
Remarque Dans le fragment de code prcdent, vous pouvez voir comment chaque geste est gr sparment : le drapeau dwID indique le type de geste. Remarquez galement que nous appelons la fin de la fonction la fonction CloseGestureInfoHandle, qui ferme les ressources associes au handle dinformation de geste. Si vous grez le message WM_GESTURE, il vous revient de fermer le handle laide de cette fonction. Omettre de le faire peut provoquer une fuite de mmoire. Remarque Dans du code de production, vous devez vrifier la valeur de renvoi des fonctions pour vrifier quelles ont bien fonctionn. Par simplification, nos fragments de code sont dpourvus de ces vrifications.
En examinant soigneusement le SDK Windows 7, vous dcouvrirez que le membre dwID peut galement possder des valeurs indiquant quand un geste a dbut (GID_BEGIN), ce qui est fondamentalement le moment o lutilisateur a plac ses doigts sur lcran. Le SDK dfinit galement le drapeau GID_END, qui indique la fin dun geste. Les gestes sont exclusifs, ce qui signifie que vous ne pouvez effectuer simultanment un zoom et une rotation laide de gestes. Votre application peut recevoir un moment donn un geste de zoom ou un geste de rotation, mais pas les deux. Les gestes peuvent toutefois tre composs, parce que lutilisateur peut effectuer plusieurs gestes pendant un long pisode tactile. GID_BEGIN et GID_END sont les marqueurs de dbut et de fin de telles squences de gestes. Pour obtenir une rotation et un zoom simultanment, vous devez grer les v-
114
nements tactiles bruts et employer le processus de manipulation, comme dcrit dans le prochain chapitre. La plupart des applications devraient ignorer les messages GID_BEGIN et GID_END et les transmettre DefWindowProc. Ces messages sont employs par le gestionnaire de gestes par dfaut. Le systme dexploitation ne peut procurer aucune prise en charge tactile aux applications hrites sans voir ces messages. Ces membres dwFlags contiennent les informations ncessaires la gestion du dbut ou de la fin dun geste particulier. Vous pouvez maintenant voir que ces messages de gestion des messages ne sont pas si difficiles. La gestion des messages de geste possde un processus bien dfini qui comprend la configuration (que nous aillons dcrire plus loin dans ce chapitre), le dcodage du message de gestes et la gestion de chaque geste spcifique en fonction des besoins de votre application. Vous allez maintenant dcouvrir quelles informations propres comprend chaque geste et comment les grer.
Vous pouvez voir dans lillustration deux points tactiles, marqus 1 et 2. Par dfaut, le geste pan prend en charge les panoramiques un et deux doigts. Vous verrez comment configurer les gestes pan et dautres gestes plus loin dans ce chapitre. Regardez maintenant le code que vous devez mettre en uvre dans votre switch GID_ PAN pour obtenir cet effet de dplacement. Notre application est simple : elle naffiche quun unique rectangle. Nous ne montrerons que les parties du code ncessaires la gestion des messages de geste. Comme cela appartient un exemple plus important crit en C++, nous ne dcrions pas en dtail un quelconque des autres lments, comme le trac du rectangle. La structure dinformations du geste comprend le membre dwFlags, qui sert dterminer ltat du geste et peut possder une quelconque des valeurs suivantes :
115
Nous employons le drapeau GF_BEGIN pour enregistrer les coordonnes initiales du point touch comme variable qui sera rfrence dans les tapes suivantes. Les informations du geste comprennent un membre ptsLocation qui renferme les coordonnes X et Y du point touch. Ensuite, pour chaque message panoramique, nous extrairons les nouvelles coordonnes du point touch. laide de la position initiale prcdemment enregistre et des nouvelles coordonnes, nous pouvons calculer la nouvelle position et appliquer lopration de dplacement lobjet. Celui-ci est enfin redessin sa nouvelle position. Lextrait de code suivant montre la totalit de la structure switch pour GID_PAN :
case GID_PAN: switch(gi.dwFlags) { case GF_BEGIN: _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptFirst); break; default: // Lecture du second point du geste. Cest un point mdian // entre les doigts la nouvelle position _ptSecond.x = gi.ptsLocation.x; _ptSecond.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptSecond); // Application de lopration de dplacement de lobjet ProcessMove(_ptSecond.x-_ptFirst.x,_ptSecond.y-_ptFirst.y); InvalidateRect(hWnd,NULL,TRUE); // Le second point doit tre copi sur le premier pour prparer // la prochaine tape du geste. _ptFirst = _ptSecond; break; } break;
Vous pouvez voir ici que si le drapeau GF_BEGIN est fix, nous employons _ptFirst, une simple structure POINT, pour enregistrer les coordonnes initiales du premier point touch partir des informations de geste de ptsLocation. Nous appelons la fonction ScreenToClient pour convertir les coordonnes cran dun point donn de la fentre de notre application, puisque les coordonnes des informations de geste sont toujours relatives lorigine de lcran.
116
Le message panoramique suivant est gr par le case par dfaut. Nous enregistrons cette fois les coordonnes dans la variable _ptSecond et calculons nouveau les coordonnes relativement la fentre de lapplication. Nous soustrayons ensuite le premier point du second pour dterminer le nouvel emplacement et appelons ProcessMove (une fonction utilitaire) pour actualiser les nouvelles coordonnes du rectangle. Nous appelons InvalidateRect pour redessiner la totalit de la fentre et afficher le rectangle aux nouvelles coordonnes. Enfin, nous enregistrons le dernier point touch dans _ptFirst fin de rfrencement pour le prochain message de geste. Lors de lemploi dun geste panoramique deux doigts, les coordonnes du point touch dans la structure des informations de geste, ptsLocation, reprsentent la position actuelle constitue par le centre du geste. Largument ullArgument indique la distance entre les deux points touchs. Le geste panoramique Windows 7 prend galement en charge linertie. Linertie sert crer un effet en continu au mouvement gnr par le geste. Lorsque vous retirez vos doigts de la surface tactile, le systme calcule la trajectoire daprs la vitesse et langle du dplacement et continue envoyer des messages WM_GESTURE de type GID_PAN avec le drapeau GF_INERTIA fix, tout en rduisant progressivement la vitesse du dplacement jusqu larrt complet. Les messages drapeau inertie comprennent toujours des coordonnes actualises, mais, dans chaque message, le delta avec les coordonnes prcdentes diminue jusqu devenir nul. Vous pouvez tablir une distinction entre des gestes panoramiques normaux ou dinertie pour ventuellement dfinir un comportement spcial pour linertie.
117
1 1
2
Regardez maintenant le code que vous devez mettre en uvre dans votre structure switch pour GID_ZOOM pour obtenir leffet dsir. Comme avec lexemple de geste prcdent, nous ne nous concentrerons que sur les parties du code ncessaires la gestion des messages de geste. Comme auparavant, nous employons GF_BEGIN pour stocker les paramtres qui se rvleront utiles lors de larrive du prochain message de geste. Une fois encore, nous enregistrons ptsLocation dans _ptFirst. Pour un geste zoom, ptsLocation indique le centre du zoom. Comme prcdemment, nous appelons la fonction ScreenToClient pour convertir les coordonnes cran dun point donn sur laffichage de la fentre de notre application. Outre lemplacement du centre du geste zoom, nous enregistrons galement la distance entre les deux points touchs, situe dans la structure ullArgument GestureInfo. Cette distance nous permettra par la suite de calculer le rapport dagrandissement. Le prochain message de zoom est gr par le case par dfaut. Nous enregistrons nouveau les coordonnes dans la variable _ptSecond et appelons la fonction ScreenToClient. Nous calculons ensuite le point central du zoom et le ratio de zoom. Enfin, nous actualisons la fentre pour reflter le point central du zoom et le rapport dagrandissement du rectangle. Voici un petit fragment de code illustrant cette dmarche :
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: // Lecture du second point du geste. Cest le point mdian entre les doigts. _ptSecond.x = gi.ptsLocation.x; _ptSecond.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptSecond);
118
Vous pouvez voir ici quoutre enregistrer lemplacement du geste zoom dans le switch GF_BEGIN, nous extrayons galement la distance entre les deux points touchs de gi.ullArgument laide de la macro LODWORD. ullArgument est long de 8 octets et les informations supplmentaires sur le geste sont stockes dans les quatre premiers octets. Le message zoom suivant est gr par le case par dfaut. Nous enregistrons nouveau lemplacement du geste et calculons partir des deux ensembles de points touchs le point central du zoom et le stockons dans ptZoomCenter. Nous devons ensuite calculer le rapport de zoom. Cela est effectu en calculant le rapport entre la nouvelle et lancienne distance. Nous appelons ensuite la fonction utilitaire ProcessZoom, qui actualise les coordonnes pour reflter le rapport dagrandissement et le point central. Cela fait, nous appelons InvalidateRect pour forcer la fentre redessiner le rectangle. Enfin, nous enregistrons le dernier point touch dans _ptFirst et la dernire distance entre les deux points touchs dans _dwArguments fin de rfrence dans le prochain message zoom. La principale diffrence entre la prise en charge par dfaut hrite du geste zoom et celle qui vient dtre dcrite est la connaissance du centre du geste de zoom. Dans la prise en charge hrite, le systme dexploitation effectue toujours le zoom sur le centre du contrle ou lemplacement actuel du curseur. Toutefois, en employant le geste zoom pour grer la modification de taille par vous-mme vous pouvez employer la connaissance du centre du geste zoom pour agrandir ou diminuer partir de ce point, procurant lutilisateur un ressenti plus riche et plus prcis.
119
principales de la fourniture de la prise en charge hrite pour ces gestes. La section prcdente montrait comment personnaliser la gestion de ces gestes. Cette section sintresse au geste de rotation, qui aprs les gestes zoom et panoramique est probablement le geste le plus employ dans les applications qui affichent du contenu laide de surfaces, comme dans des applications daffichage et de modification dimages ou de cartographie. Imaginez quune vraie photo soit place plat sur votre bureau. Cest une photographe de paysage, qui est affiche lenvers. Pour la remettre lendroit, vous devez placer votre main (ou uniquement deux doigts) sur la photo et dplacer votre main de faon circulaire pour mettre la photo dans la position souhaite. Cest exactement le mme geste que vous pouvez accomplir dans Windows 7. Le geste de rotation est effectu en crant deux points de touche sur un objet et en dplaant ces points de faon circulaire, comme montr dans la figure suivante. Les numros 1 et 2 reprsentent les deux points de touche et les flches reprsentent la direction du mouvement partir de ces points. Comme dans les exemples prcdents, nous examinerons chaque point de codage ncessaire pour faire pivoter le rectangle.
La valeur GID_ROTATE sert identifier le geste de rotation. Comme avec les gestionnaires de geste prcdents, nous recourons au drapeau GF_BEGIN pour enregistrer ltat initial du geste. Nous stockons ici 0 (zro) dans _dwArguments, qui servira de variable pour lange de rotation. Dans le case par dfaut, nous enregistrons encore lemplacement du geste. Le membre ptsLocation reprsente le centre entre les deux points touchs et peut tre considr comme le centre de rotation. Comme avec tout message de geste, le membre ullArguments contient les informations supplmentaires du geste. Dans un geste de rotation, cest langle de rotation cumul. Celui-ci est relatif langle initial entre les deux premiers points touchs, considr comme angle zro pour le geste de rotation actuel. Cest pourquoi il est superflu denregistrer langle initial dans le case GF_BEGIN : nous considrons que cet angle est gal zro degrs. Cela est logique puisque nous voulons capturer
120
le mouvement de lutilisateur et la projection relativement la position de lobjet sur lcran plutt quemployer des positions angles fixes, ce qui imposerait de nombreux calculs dans ltat initial.
case GID_ROTATE: switch(gi.dwFlags) { case GF_BEGIN: _dwArguments = 0; break; default: _ptFirst.x = gi.ptsLocation.x; _ptFirst.y = gi.ptsLocation.y; ScreenToClient(hWnd,&_ptFirst); // Le gestionnaire de geste renvoie langle de rotation cumul. Nous devons // toutefois transmettre chaque delta angulaire la fonction responsable // du traitement du geste de rotation. ProcessRotate( GID_ROTATE_ANGLE_FROM_ARGUMENT(LODWORD(gi.ullArguments)) - GID_ROTATE_ANGLE_FROM_ARGUMENT(_dwArguments), _ptFirst.x,_ptFirst.y ); InvalidateRect(hWnd,NULL,TRUE); _dwArguments = LODWORD(gi.ullArguments); break; } break;
Vous pouvez voir ici que, comme avec tous les gestes, nous enregistrons lemplacement du geste et convertissons le point pour reflter les coordonnes relativement notre fentre. Nous extrayons ensuite langle de rotation de largument ullArgument laide de la macro LODWORD. Langle est reprsent en radians et nous employons la macro GID_ROTATE_ANGLE_FROM_ARGUMENT pour le convertir en degrs. Comme mentionn prcdemment, le gestionnaire du geste de rotation renvoie langle de rotation cumul, mais nous devons employer la diffrence entre les deux angles pour crer le mouvement de rotation. Nous transmettons ensuite le delta angulaire et le centre de la rotation la fonction utilitaire ProcessRotate qui actualise les coordonnes X et Y de lobjet pour reflter le mouvement de rotation. Nous invalidons la fentre pour redessiner le rectangle. Enfin, nous enregistrons langle cumul actuel dans _dwArguments pour pouvoir effectuer la soustraction entre les angles larrive du nouveau message de geste de rotation. Comme avec le geste zoom, ptsLocation contient le centre de rotation, ce qui vous permet de contrler finement le mode de rotation de lobjet. Plutt que de le faire pivoter autour du point central de lobjet, vous le faites autour du point spcifique de rotation pour mieux respecter le geste de lutilisateur et procurer un meilleur ressenti utilisateur.
121
La valeur GID_TWOFINGERTAP sert identifier un geste de tapotement deux doigts. Comme avec les gestionnaires de geste prcdents, ullArguments contient les informations complmentaires sur le geste. Dans le cas du geste tapotement deux doigts, ullArguments contient la distance entre les deux doigts et pstLocation indique le centre du tapotement deux doigts. Dans lextrait de code suivant, il est superflu denregistrer ou demployer la distance entre les deux points touchs ou le centre du geste. Nous allons dfinir un drapeau et un minuteur qui expire au bout de 200 millisecondes et rinitialiserons le drapeau moins quun autre message de geste de tapotement deux doigts survienne avant lexpiration du minuteur. Si le second message de geste survient avant le dlai de 200 millisecondes, nous appelons la fonction ProcessTwoFingerTap qui dessine un X sur le rectangle. Le code ressemble ceci :
case GID_TWOFINGERTAP: if( _intFlag == 0) { _ bWaitForSecondFingerTap = 1;
122
Vous pouvez voir que nous ne grons ici quun cas dcole du message, sans inspecter les drapeaux de message du message GF_BEGIN comme pour le geste prcdent. Nous excutons simplement la logique contenue dans le switch case de GID_TWOFINGERTAP. Vous pourriez envisager de simplement supprimer le drapeau et le minuteur du code prcdent et grer un unique tapotement deux doigts, ce qui ne troublerait pas lutilisateur en tentant dtablir une distinction entre un panoramique un doigt et un tapotement deux doigts alors quil ny a pas de tapotement simple. Dans ce cas, un tapotement un doigt pourrait tre lquivalent dun clic de souris et, si ncessaire, un tapotement deux doigts tre considr comme l'quivalent dun double clic.
Nous employons la valeur GID_PRESS_AND_TAP pour identifier ce geste. Comme avec les gestionnaires de geste prcdents, ullArguments contient les informations complmentaires sur le geste. Dans le cas du geste appui et tapotement, ullArguments contient la distance entre les deux doigts et pstLocation indique la position touche par le premier doigt. Vous pouvez exploiter cette information pour personnaliser la reprsentation graphique du premier point touch ou tout autre effet de mise en vidence. Pour notre dmonstration simple, nous ne stockons aucune information pour ce gestionnaire de geste, ni nexploitons le drapeau GF_BEGIN. Nous allons simplement grer la fonction
123
ProcessPressAndTap pour colorer alatoirement les bordures du rectangle, comme le montre lextrait de code suivant :
case GID_PRESSANDTAP: ProcessPressAndTap(); InvalidateRect(hWnd,NULL,TRUE); break;
Lidentifiant du type de configuration pour lequel les messages sont activs ou dsactiv. Ce peut tre nimporte lequel des messages de geste GID_ (zoom, panoramique, rotation, tapotement deux doigts ou appui et tapotement). Indique les messages activer en relation avec le geste dfini dans dwID Indique les messages dsactiver en relation avec le geste dfini dans
dwWant dwBlocks
dwID
Vous pouvez employer le fragment de code suivant pour activer tous les gestes laide du drapeau spcial GC_AllGESTURES :
GESTURECONFIG gc = {0,GC_ALLGESTURES,0}; SetGestureConfig(hWnd, 0, 1, &gc, sizeof(GESTURECONFIG));
Si vous voulez disposer dun contrle plus fin sur les gestes pour lesquels vous voulez recevoir les messages, vous pouvez employer la structure de configuration de geste et spcifier les messages de geste recevoir et ceux bloquer. Par exemple, le code suivant montre comment dsactiver tous les gestes :
GESTURECONFIG gc[] = {{ GID_ZOOM, 0, GC_ZOOM }, { GID_ROTATE, 0, GC_ROTATE}, { GID_PAN, 0, GC_PAN}, { GID_TWOFINGERTAP, 0, GC_TWOFINGERTAP}, { GID_PRESSANDTAP, 0 , GC_PRESSANDTAP} }; UINT uiGcs = 5; bResult = SetGestureConfig(hWnd, 0, uiGcs, gc, sizeof(GESTURECONFIG));
124
Ce code dfinit cinq structures de configuration de geste diffrentes, une pour chaque geste. Comme vous pouvez le voir, le premier paramtre de chaque structure est le message de geste GID_. Dans chaque structure, le deuxime paramtre est fix zro, indiquant que nous avons choisi de ne grer aucun message. Il en va de mme du dernier paramtre, indiquant que nous vouons bloquer le message de geste spcifique. Le bon moment o appeler SetGestureConfig est lors de lexcution du gestionnaire WM_GESTURENOTIFY. WM_GESTURENOTIFY est un message envoy lapplication juste avant que le systme dexploitation ne commence envoyer des messages WM_GESTURE la fentre de votre application. Fondamentalement, le systme dexploitation vous dit : Hello, je ne vais pas tarder vous envoyer des messages de geste . Ce message est en ralit envoy alors que lutilisateur a dj plac ses doigts sur le dispositif tactile et a commenc effectuer un certain geste. Cest le parfait endroit o dfinir la liste des gestes que va prendre en charge votre application. En peuplant les bonnes structures GESTURECONFIG pour dfinir les gestes que vous voulez grer et en appelant la fonction SetGestureConfig, vous pouvez slectionner les gestes que vous voulez grer dans votre application.
La plupart de ces valeurs sexpliquent delles-mmes. GC_PAN sert autoriser tous les gestes. Le drapeau qui mrite un peu dexplication complmentaire est GC_PAN_ WITH_GUTTER. Une gouttire (gutter) dfinit les frontires de la zone droulante dans laquelle fonctionne votre geste panoramique. La frontire de gouttire limite le mouvement perpendiculaire la direction primaire, quil sagisse dun balayage vertical ou horizontal. Lorsquun certain seuil est atteint, la squence actuelle des gestes panoramiques est arrte. Si bien que dans le cas dun panoramique vertical, le mouvement na pas besoin dtre en parfaite ligne droite : une certaine diagonale est autorise. Vous pouvez dvier denviron 30 degrs partir de la perpendiculaire principale sans que le mouve-
GC_PAN_WITH_INERTIA
125
ment tactile ne soit plus considr comme geste panoramique, comme le montre la Figure 5-3 : les frontires de gouttire gauche et droite dfinissent comme un entonnoir, au sein duquel fonctionne encore le geste panoramique. Aprs avoir dfini le premier point de toucher (numro 1), vous pouvez effectuer le geste panoramique nimporte o lintrieur de la zone dfinie par lentonnoir. Si, pendant le geste, vous sortez de lentonnoir (point numro 3), le geste panoramique est arrt et le systme dexploitation cesse de vous envoyer des messages panoramiques WM_GESTURE.
Figure 5-3
En dsactivant les gouttires, vous permettez au geste panoramique de passer en mode free-style, ce qui autorise le systme dexploitation envoyer des messages panoramiques pour chaque geste panoramique effectu sur la zone balayable, sans considration de panoramique vertical ou horizontal. Cela peut provoquer un bon ressenti lors du dplacement dobjets comme des images ou lors du parcours dune carte. Imaginez une application de cartographie dans laquelle vous vouliez procurer un ressenti de dplacement 2D complet. Le fragment de code suivant montre comment vous pouvez configurer la plate-forme multi-tactile Windows 7 pour autoriser des gestes de zoom, de rotation et panoramiques verticaux et horizontaux avec les gouttires dsactives. Cest une configuration utile pour une application de cartographie dans laquelle vous voulez autoriser lutilisateur se dplacer, zoomer et faire pivoter le point de vue de la carte.
DWORD dwPanWant = GC_PAN | GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; DWORD dwPanBlock = GC_PAN_WITH_GUTTER; GESTURECONFIG gc[] = {{ GID_ZOOM, GC_ZOOM, 0 }, { GID_ROTATE, GC_ROTATE, 0}, { GID_PAN, dwPanWant , dwPanBlock} }; UINT uiGcs = 3; SetGestureConfig(hWnd, 0, uiGcs, gc, sizeof(GESTURECONFIG));
126
Un bon exemple de cette fonctionnalit est lapplication Photo Viewer qui accompagne Windows 7. Elle prend dj en charge zoom et rotation laide de la souris. Ces fonctionnalits sont dsormais appuyes par la prise en charge des gestes multi-tactiles avec relativement peu defforts.
Rsum
Ce chapitre prsentait le monde merveilleux du multi-tactile Windows 7. Nous avons commenc par dfinir les diffrents modles de programmation et dcrit les capacits de la plate-forme. Nous avons ensuite examin les couches de mise en uvre internes du multi-tactile et dtaill les rles des diffrents composants. Nous avons ensuite plong dans la prise en charge fournie pour les gestes. Comme vous lavez vu, ceux-ci permettent daccomplir bien des choses. Mme la prise en charge immdiate fondamentale propose par Windows 7 aux applications hrites procure aux utilisateurs finaux limpression que lapplication rpond au toucher. Vous avez galement vu comme il est facile dajouter des gestionnaires de geste spcifiques votre application et proposer un ressenti utilisateur multi-tactile solide et excitant. Nous avons parcouru les tapes ncessaires la gestion des gestes partir du premier message reu laide des drapeaux de dbut, ainsi qu effectuer le nettoyage une fois le dernier message reu. Nous avons enfin vu comment configurer des comportements spcifiques pour les gestes, essentiellement pour les panoramiques. Dans le prochain chapitre, nous passerons lexamen dtaill du modle de programmation multi-tactile Windows 7 Meilleur , qui dcrit comment grer des vnements de toucher brut et comment crer vos propres gestionnaires de geste. Pour les dveloppeurs de code gr, le Chapitre 6, Touchez-moi : programmation multi-tactile avance , procure un aperu du modle de programmation multi-tactile WPF de Windows 7. Enfin, le Chapitre 8, Emploi de Windows 7 Touch avec Silverlight , aborde brivement comment Silverlight 3 peut sexcuter en dehors du navigateur sur une machine Windows 7 et proposer un ressenti multi-tactile.