download.microsoft.comdownload.microsoft.com/documents/france/msdn/2011/visual... · web viewles...

46
Utiliser les services Bing dans une application Win32 Article par Eric Vernié Microsoft France Division Plate-forme & Ecosystème SOMMAIRE Utiliser les services Bing dans une application Win32.........................1 Introduction................................................................2 Pré requis..................................................................2 Architecture de l’application...............................................2 Décomposition du code source.............................................. 4 Définition d’un Agent.......................................................5 L’agent Microsoft BING......................................................7 Création du proxy Bing.................................................... 8 Utilisation de WWSAPI.................................................... 10 Implémentation de l’agent Bing........................................... 12 L’agent HTTP...............................................................14 Utilisation de WinINet................................................... 14 Implémentation de l’Agent HTTP........................................... 15 L’agent WIC................................................................16 Utilisation de WIC pour décoder des données brutes et en créer un bitmap Direct2D................................................................. 17 Implémentation de l’agent WIC............................................ 18 L’agent Display............................................................19 Création du contexte de rendu Direct2D...................................19

Upload: others

Post on 28-Mar-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Utiliser les services Bing dans une application Win32

Article par Eric Vernié Microsoft France Division Plate-forme & Ecosystème

SOMMAIRE

Utiliser les services Bing dans une application Win32.....................................................................................................1

Introduction................................................................................................................................................................2

Pré requis....................................................................................................................................................................2

Architecture de l’application.......................................................................................................................................2

Décomposition du code source...............................................................................................................................4

Définition d’un Agent..................................................................................................................................................5

L’agent Microsoft BING...............................................................................................................................................7

Création du proxy Bing............................................................................................................................................8

Utilisation de WWSAPI..........................................................................................................................................10

Implémentation de l’agent Bing............................................................................................................................12

L’agent HTTP.............................................................................................................................................................14

Utilisation de WinINet...........................................................................................................................................14

Implémentation de l’Agent HTTP..........................................................................................................................15

L’agent WIC...............................................................................................................................................................16

Utilisation de WIC pour décoder des données brutes et en créer un bitmap Direct2D.........................................17

Implémentation de l’agent WIC............................................................................................................................18

L’agent Display..........................................................................................................................................................19

Création du contexte de rendu Direct2D...............................................................................................................19

Implémentation de l’agent Display........................................................................................................................21

L’agent Store.............................................................................................................................................................22

Implémentation de l’agent Store...........................................................................................................................22

Exécution du pipeline................................................................................................................................................23

Page 2: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Saisie d’un mot clé et l’afficher avec DirectWrite......................................................................................................27

Utilisation de DirectWrite......................................................................................................................................27

Animation des vignettes............................................................................................................................................28

Utilisation de Windows Animation........................................................................................................................29

Test de la solution.....................................................................................................................................................33

Conclusion.................................................................................................................................................................36

Introduction Dans cet article, nous allons développer une application Windows Win32 en C++, qui utilisera les services de Bing pour rechercher des images et les afficher. L’idée n’est pas des plus originale j’en conviens, mais elle nous permettra

de vous montrer la manière de développer une interface réactive, qui ne se bloque pas lorsqu’une demande distante à un service Web est en cours. En un mot comment faire simplement de l’asynchronisme en C++.

Pour notre démonstration, nous aborderons les technologies suivantes :

- Les API du moteur de recherche de Microsoft Bing, et la manière de solliciter ses services avec les API Windows Web Services (WWSAPI). Sujet que nous avons traité en détail dans l’article. Consommer les services de Microsoft Translator, et sur lequel nous ne reviendrons pas en détail.

- WiniNet, pour télécharger les données réelles des images.- Les librairies Parallèle et Agent fournies avec Visual Studio 2010, qui nous permettront d’exécuter nos

demandes en mode asynchrone.- Windows Imaging Component (WIC), Direct2D et DirectWrite pour la création et le rendu des images à

l’écran, ainsi que pour la sauvegarde des images sur disques.- Windows Animation, pour ajouter un effet d’animation à nos images.

Pré requisPour réaliser les exemples de cet article il vous faut :

Visual Studio 2010 Kit de développement Windows 7 Créer une clé Microsoft Bing

Architecture de l’applicationL’idée simple de cette application est de requêter les services Bings, pour obtenir des images et les afficher à l’écran. L’enchainement de plusieurs étapes est alors nécessaire.

1) Récupérer les adresses électroniques (URL) des images.2) Télécharger les données brutes des images.3) Transformer les données brutes obtenues en bitmap.4) Afficher les bitmaps à l’écran.5) Stocker les bitmaps.6) Animer les bitmaps à l’écran.7) Sauvegarder les bitmaps sur disque.

Page 3: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Comme nous pouvons le constater, nous sommes dans un scénario de type pipeline, ou chaque étape doit se faire les unes après les autres. Néanmoins, comme dans notre cahier des charges, nous voulons, une application réactive qui ne se bloque pas, nous ne souhaitons pas attendre qu’une étape soit finie, pour passer à l’étape suivante.

Pour effectuer les différentes étapes en mode asynchrone et pour éviter de bloquer l’interface, un thread sera le producteur, alors qu’un autre thread sera le consommateur. Nous mettrons alors en place le pattern Producteur-Consommateur.Nous pourrions utiliser les threads et les primitives de synchronisation de base de Windows pour mettre en place ce pattern, mais comme c’est sujet à trop d’erreurs et que nous ne sommes jamais à l’abri d’une perte de montée en charge lors de l’augmentation du nombre de processeurs, il est préférable d’utiliser des librairies qui sont prévues à cet effet. Dans notre exemple, nous utiliserons la librairie Agent Asynchrone, livrée avec Visual Studio 2010, que nous aborderons un peu plus loin.Pour implémenter ce pipeline, nous allons utiliser la notion d’agent. Chaque agent étant en charge d’une seule tâche.

1. L’agent Bing est en charge de retrouver les adresses électroniques des images et de les transmettre à l’agent suivant dans le pipeline.

2. L’agent HTTP reçoit une adresse électronique d’une image et commence à télécharger les données brutes. Comme le téléchargement des images peut prendre du temps (assujettie à la latence d’internet), dès qu’il en télécharge une, il passe la main, à l’agent suivant dans le pipeline, avant de télécharger l’image suivante. Une fois que toutes les images sont téléchargées, il en informe l’agent suivant.

3. L’agent WIC reçoit les données brutes d’une image sous forme d’un tableau d'octets. A partir de ce tableau d’octets il en crée un bitmap Direct2D puis l’envoie à l’agent suivant. Une fois tous les bitmaps créés, il en informe l’agent suivant.

4. L’agent Display reçoit un bitmap Direct2D, et l’affiche à l’écran, puis le passe à l’agent suivant. Une fois tous les bitmaps affichés, il en informe l’agent suivant.

5. L’agent Store a simplement pour but de sauvegarder les bitmaps Direct2D dans un container, et d’envoyer ce container au dernier agent du pipeline.

6. La dernière étape de notre pipeline, n’est pas à proprement parler un agent, mais il en utilise les mécanismes. Il reçoit le container de bitmaps Direct2D, et en informe la procédure de la fenêtre Windows, pour qu’elle puisse mettre en place le mécanisme d’animation des images.

Architecture grossière de l’application

Page 4: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Décomposition du code source La solution livrée avec cet article se décompose de la manière suivante :

Un répertoire Application :Contient le fichier AfficherImageBing.cpp, qui inclut le point d’entrée (_tWinMain) de l’application, ainsi que la boucle des messages Windows.

Un répertoire IHMQui contient : La classe FenetrePrincipale. Classe qui a juste pour rôle d’instancier une fenêtre enfant. Nous pourrions tout à fait nous en passer dans notre exemple, mais elle pourra servir à d’autre fin plus tard.La classe FenetreEnfant. Classe qui va instancier tous les autres modules de l’application. Tous les traitements se font à partir de cette fenêtre. Saisie des mots clés de la recherche, recherche, traitement, stockage et animation des images.La classe DPEDirectD2D1helper. Classe qui contient tout le code d’accès à Direct2D et à DirectWriteLa classe DPEAnimationHelper. Classe qui contient le code d’accès aux animations Windows

Un répertoire HelperQui contient la classe DPEXmlLiteHelper, qui permet de lire la configuration de l’application à partir d’un fichier XML.

Un répertoire ProxyWebQui contient le fichier ProxyClientBing.c, qui contient le code comme son nom l’indique du proxy du service Web Bing.

Page 5: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Un répertoire Agent.Contenant tous nous agents.Avant de poursuivre il est important de faire un point sur ce qu’est et à quoi sert un agent.

Définition d’un AgentEn programmation parallèle, l’un des problèmes récurrent et non déterministe qui survient, est le partage d’états entre différentes threads. Ce partage d’états s’il n’est pas bien maitrisé, engendre systématiquement des problèmes de concurrences d’accès. C’est-à-dire qu’une variable, peu à tout moment être dans un état incohérent, et donc générée soit des résultats erronés soit dans le pire des cas, une instabilité de l’application.

Développer avec les agents, va permettre d’outre passer ce problème. En effet, une donnée ou un état seront isolés d’un agent par rapport à l’autre par l’intermédiaire d’un message qui sera véhiculé entre chaque agent.Un agent envoi (send) le message contenant les informations, l’agent suivant reçois (receive) le message le traite, et envoi un autre message de même nature à l’agent suivant dans le pipeline et ainsi de suite. Comme illustré sur la figure suivante.

Page 6: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

La méthode receive bloque le thread entrant, tant que le message n’est pas reçu. Il n’y a donc pas besoin de mettre en place des mécanismes complexe de synchronisation type Event par exemple, pour que le message soit transmis correctement d’agent en agent. On peut alors se focaliser sur le fonctionnel de l’agent, plutôt que sur de la plomberie multithreads toujours sujette à erreur.

Les agents permettent de développer des applications parallèles dites à gros grain, et sont basés sur des templates. Pour implémenter un agent il faut procéder comme suit :

1) Il faut inclure l’entête agent.h et utiliser l’espace de nom Concurrency#include <agents.h>using namespace ::Concurrency;

2) Dériver sa classe de la classe agentclass MonAgent : public agent

3) Ensuite dans le constructeur, il faut définir un point d’entrée pour envoyer le message avec la méthode send() et un point d’entrée pour recevoir le message avec la méthode receive().explicit MonAgent(ITarget<RawData>& messageEnvoye,ISource<RawData>& messageRecu);

4) Puis il faut implémenter la méthode run(). Méthode qui sera appelée directement par la plate-forme agent lorsque l’agent démarreravoid MonAgent::run(){ do { //Le thread bloque ici en attente d'un message _data=receive(_messageRecu) //Télécharger les données TraitementDesDonnees(_data) ; //Envoi du message à l’agent suivant dans le pipeline send(_messageEnvoye,_data); } while(_data.Sentinel == FALSE)done();}Dans notre exemple, l’agent ne sait pas combien de messages il va recevoir. Il entre donc dans une boucle, qui s’arrêtera lorsqu’une variable (ex Sentinel) est à TRUE, indiquant que l’agent précédant dans le pipeline a envoyé toutes les données et a fini son travail.Une fois que toutes les données ont été reçues, l’agent met fin à son travail à l’aide de la méthode done().On notera ici l’implémentation simple et rapide du pattern Producteur/Consommateur.

5) Enfin pour démarrer l’agent et attendre qu’il ait finiunbounded_buffer <RawData> msgTargetResponse;unbounded_buffer <RawData> msgDowloadBitmap;MonAgent monagent(msgDowloadBitmap, msgTargetResponse)monagent.start ();agent::wait (&monagent);

unbounded_buffer<> est une classe qui représente une structure de message asynchrone capable de stocker un nombre illimité de messages. Cette classe conserve les messages dans une file d’attente en mode FIFO, garantissant que celui qui le recevra, les recevra tous et dans le bonne ordre.

Vous noterez également dans notre exemple, que la classe unbounded_buffer prend comme paramètre le type RawData. C’est une structure que nous avons définie, et qui nous permettra de transmettre un état d’agent en agent. Chaque agent remplissant un champ de la structure qui lui est assigné.struct RawData{HRESULT hr; //Contient un numéro de l'erreur sous forme de HRESULTBYTE* BufferVignette; //Pointeur sur le tableau de bytes des vignettesBYTE* BufferImageComplete; //Pointeur sur le tableau de bytes de l'image complètestruct ImageResult *ImageBingResult; //Pointeur sur le résultat de la rechercheID2D1Bitmap *D2D1Thumbnail; //Pointeur Direct2D sur une vignetteID2D1Bitmap *D2D1ImageComplete; //Pointeur Direct2D sur l'image complèteWCHAR Agent[25]; //Contient une chaine de caractère du nom de l'agentWCHAR Message[1024];//Message de debugD2D1_RECT_F CurRect;//Contient la position de la vignette à l'écran

Page 7: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

BOOL Sentinel;//Variable qui détermine si toutes les images ont été transmisesBOOL EncoursArret;//Est-ce que l'arrêt est demandéBOOL Sauvegarder; //Est-ce que la sauvegarde du bitmap sous forme de fichier a été fait}user_rawdata;Le champ ImageBingResult, sera rempli par l’agent Bing et utilisé par l’agent HTTP.Les champs BufferVignette et BufferImageComplete, seront remplis par l’agent HTTP et utilisés par l’agent WICLes champs D2D1Thumnail et D2D1ImageComplete, seront remplis par l’agent WIC et utilisés par l’agent Display, et ainsi de suite.

Voici en gros les étapes pour construire et démarrer un agent, et tous nos agents dans la suite de cet article reprendront cette structure.

Pour de plus amples informations sur la librairie agent http://msdn.microsoft.com/fr-fr/library/dd492627.aspx

Maintenant que nous connaissons la structure des agents, commençons donc par notre 1er Agent.

L’agent Microsoft BINGL’agent Bing a pour rôle de retrouver les adresses électroniques des images et les fournir à l’agent suivant dans le pipeline. Avant d’aller plus loin, faisons un rappel sur les API de Bing.Le moteur de recherche sur internet Microsoft Bing , vous permet de faire de la recherche sur le Web, les Images, la vidéo, les news j’en passe et des meilleurs. Comme illustré sur la figure suivante :

Avec les API Bing Version 2, vous pourrez ajouter ces fonctionnalités de recherches à votre application.Plusieurs protocoles sont disponibles pour accéder au service, JSON, XML et SOAP, c’est ce dernier que nous utiliserons.Pour utiliser le protocole SOAP, dans notre application, il nous faut obtenir la structure du service en lui-même. Cette structure contient la définition même du service, les noms et signature de méthodes, les types de retour, etc.La définition du service est définie dans un fichier au format WSDL (Web Service Description Language) et obtenue à l’adresse http://api.bing.net/search.wsdl?AppID=APPIDLe paramètre APPID est un global unique identifier que vous devez créer pour votre application à l’adresse suivante : http://www.bing.com/developers/createapp.aspx pour de plus amples détails sur la manière d’obtenir cet

APPID voir l’article Consommer les services Microsoft Translator via les nouvelles API WWSAPI de Windows 7 dans une application Win32

Pour manipuler les services Microsoft Bing, il faut dans un premier temps définir la source de la recherche, à l’aide de la structure SearchRequest.Cette structure devra être définie entre autre avec :

Le numéro d’identification de l’application, l’APPID Le texte de la requête Le ou les types de sources que l’on souhaite obtenir. Différents SourceType sont possibles, tels que,

la vidéo, les images, le web, les news, la publicité, la traduction, et autres que je vous laisse découvrir à cette adresse http://msdn.microsoft.com/en-us/library/dd251056.aspx

Et d’autres options, telle que Adult qui définit la restriction de la recherche à du contenu visible ou non.

Une fois la requête exécutée, la réponse est lisible dans la structure SearchResponse. Cette structure possède comme membre d’autres structures :

Qui contiendront les données en fonction du ou des SourceType choisies. Nous y retrouverons les structures WebResponse, ImageResponse, VideoResponse, TranslationResponse, etc.

Page 8: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Chaque structure ayant ses propres membres qui ne sont pas toujours les mêmes en fonction du SourceType.

Une structure de type Error, qui contiendra les éventuelles erreurs survenues lors de l’appel.

Pour télécharger le SDK de Bing http://www.bing.com/developers/appids.aspx

Création du proxy Bing La création du proxy Bing ce fait en deux étapes :

Tout d’abord, nous utilisons l’utilitaire svcutil.exe ; disponible avec le SDK de Windows 7 ; en lui passant l’adresse de la description du Service Microsoft Bingsvcutil /t:metadata http://api.bing.net/search.wsdl?AppID=<VOTRE APPID> L‘outil crée en local le fichier de description du service Microsoft Bingschemas.microsoft.com.LiveSearch.2008.03.Search.wsdlCe fichier au format XML, contient toute la description du service, comme illustré sur la figure suivante.Extrait du fichier WSDL

La seconde étape consiste à créer à partir du fichier WSDL le code source, ainsi que les fichiers d’entêtes du proxy client que nous utiliserons dans la section suivante. Pour cela on utilise l’outil WSUTIL de la manière suivante :wsutil.exe *.wsdl

wsutil, est en charge de transformer la description au format wsdl en un format natif langage C. Les deux fichiers suivants sont alors crées. schemas.microsoft.com.LiveSearch.2008.03.Search.wsdl.hschemas.microsoft.com.LiveSearch.2008.03.Search.wsdl.c

Remarque : Vous trouverez les outils svcutil et wsutil dans le répertoire C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin.Le fichier .H contient toutes les définitions des méthodes, structures et énumération que nous utiliserons. Par exemple, les structures SearchRequest et SearchResponse sont définies ainsi :

Page 9: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

typedef struct SearchRequest { WCHAR* Version; WCHAR* Market; WCHAR* UILanguage; WCHAR* Query; WCHAR* AppId; enum AdultOption Adult; double Latitude; double Longitude; double Radius; unsigned int OptionsCount; __field_ecount_opt(OptionsCount)enum SearchOption* Options; unsigned int SourcesCount; __field_ecount(SourcesCount)enum SourceType* Sources; struct WebRequest* Web; struct ImageRequest* Image; struct PhonebookRequest* Phonebook; struct VideoRequest* Video; struct NewsRequest* News; struct MobileWebRequest* MobileWeb; struct TranslationRequest* Translation;} SearchRequest;

typedef struct SearchResponse { WCHAR* Version; struct Query* Query; struct SpellResponse* Spell; struct WebResponse* Web; struct ImageResponse* Image; struct RelatedSearchResponse* RelatedSearch; struct PhonebookResponse* Phonebook; struct VideoResponse* Video; struct InstantAnswerResponse* InstantAnswer; struct NewsResponse* News; struct MobileWebResponse* MobileWeb; struct TranslationResponse* Translation; unsigned int ErrorsCount; __field_ecount_opt(ErrorsCount)struct Error* Errors;} SearchResponse;

Le fichier .C contient l’implémentation des méthodes, telle que la méthode Search.

HRESULT WINAPI LiveSearchPortBinding_Search( __in WS_SERVICE_PROXY* _serviceProxy, __in SearchRequest* parameters0, __out SearchResponse** parameters, __in WS_HEAP* _heap, __in_ecount_opt(_callPropertyCount) const WS_CALL_PROPERTY* _callProperties, __in const ULONG _callPropertyCount, __in_opt const WS_ASYNC_CONTEXT* _asyncContext, __in_opt WS_ERROR* _error){ void* _argList[2]; _argList[0] = &parameters0; _argList[1] = &parameters; return WsCall(_serviceProxy, (WS_OPERATION_DESCRIPTION*)&schemas_microsoft_com_LiveSearch_2008_03_Search_wsdlLocalDefinitions.contracts.LiveSearchPortBinding.LiveSearchPortBinding_Search.LiveSearchPortBinding_Search, (const void **)&_argList, _heap, _callProperties, _callPropertyCount, _asyncContext, _error);}

Page 10: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Utilisation de WWSAPIJe ne vais pas rentrer une nouvelle fois dans les détails des API WWSAPI, vous les retrouverez dans l’article Consommer les services Microsoft Translator via les nouvelles API WWSAPI de Windows 7 dans une application Win32. Néanmoins, voici les étapes à suivre.

1. Il faut inclure l’entête de WWSAPI#include <WebServices.h>

2. Se lier à la librairie WebServices.lib

3. Ensuite dans le code, il faut initialiser et ouvrir un proxy, à l’aide des méthodes LiveSearchPortBinding_CreateServiceProxy et WsOpenServiceProxy

HRESULT DPEBingAgent::InitialiserProxyWeb (){

HRESULT hr;hr=WsCreateError (NULL,0,&_wsError);if (FAILED(hr)) return hr;//SIZE_T_MAX évite le message d'erreur dépassement du quotahr=WsCreateHeap (SIZE_T_MAX,0,NULL,0,&_wsHeap,_wsError);

if (FAILED(hr)){

LibererRessourcesServiceWeb();return hr;

}WS_HTTP_BINDING_TEMPLATE templateValue={};hr=LiveSearchPortBinding_CreateServiceProxy (

&templateValue, NULL,0, &_wsServiceProxy, _wsError);

if (FAILED(hr)){

LibererRessourcesServiceWeb();return hr;

}

WS_ENDPOINT_ADDRESS address={};WS_STRING Url=WS_STRING_VALUE(L"http://api.search.live.net:80/soap.asmx");address.url=Url;hr=WsOpenServiceProxy (_wsServiceProxy ,&address,NULL,_wsError);if (FAILED(hr)){

LibererRessourcesServiceWeb();return hr;

}//Initialise la clé pour le Service Microsoft Bingwcscpy_s (_APPID,_countof(_APPID),L"[Votre APPID]");return hr;

}4. Initialiser la structure SearchRequest

SearchRequest *_request;SourceType _type[1]void DPEBingAgent::InitialiserServiceWeb(){_request=new SearchRequest();_request->AppId =_APPID;_request->Image =new ImageRequest ();_request->Adult =AdultOptionStrict;_type[0]=SourceTypeImage;_request->Sources =_type;_request->SourcesCount=1; }Ici nous initialisons un SourceType de type Image.

5. S’il y a initialisation de ressources, il faut également libérer les ressources, avec les API WWSAPI associéesvoid DPEBingAgent::LibererRessourcesServiceWeb (){

Page 11: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

if (_wsError!=nullptr){

WsFreeError (_wsError);}if (_wsHeap!=nullptr)

WsFreeHeap (_wsHeap);if (_wsServiceProxy !=nullptr){

WsCloseServiceProxy (_wsServiceProxy,nullptr,_wsError);WsFreeServiceProxy (_wsServiceProxy);

}if (_request!=nullptr)

delete _request;

}

6. Ensuite, il faut effectuer la recherche en utilisant la méthode LiveSearchPortBinding_Search HRESULT DPEBingAgent::RechercherImage(WCHAR *requete,

int nombreVignettes, int offset)

{HRESULT hr;

//Ici on complète la requête avec le texte à rechercher//et le nombre de vignettes à retrouver_request->Query =requete;_request->Image->Count =nombreVignettes;//l'offset correspond au décalage du nombre de vignettes déjà retrouvées.// Ex. 1er demande de 15 Vignettes=1er Page => offset=0// 2ieme demande de 15 Vignettes=2de Page => offset=15// 3ieme demande de 15 Vignettes=3ieme Page => offset=30// etc.._request->Image->Offset=offset; //Initialisation de la classe SearchRespons_response=new SearchResponse();

//Exécute en mode synchrone la recherche//ici ce n'est pas la peine d'utiliser le mode asynchrone//du service Web défini par WS_ASYNC_CONTEXT et WS_ASYNC_CALLBACK//car c'est la structure de type agent qui nous la fournit de base.hr=LiveSearchPortBinding_Search (_wsServiceProxy,

_request,&_response ,_wsHeap,NULL,0,NULL,_wsError);

return hr; }

Page 12: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Implémentation de l’agent Bing1. L’agent bing est le premier du pipeline, il prendra comme paramètre dans son constructeur :

Un point d’entrée pour envoyer un message :ITarget<RawData>& messageEnvoyeUn point d’entrée pour recevoir un éventuel message d’arrêt : ISource<BOOL>& stopUne structure : WebServiceConfig, struct WebServiceConfiguration{

WCHAR Requete[1024];int NombreVignettes;int NumeroPage;int TotalPages;int TotalVignettes;BOOL NouvelleRequete;BOOL Sauvegarder;

};qui contiendra, entre autre, le texte de la requête, le nombre de vignettes à télécharger et le numéro de page à utiliser.class DPEBingAgent_API DPEBingAgent : public DPEBaseAgent{public :explicit DPEBingAgent(ITarget<RawData>& messageEnvoye,

ISource<BOOL>& stop,WebServiceConfiguration config);

protected:void run();

//Code omis pour plus de clarté}Le constructeur s’implémente de la manière suivante : DPEBingAgent::DPEBingAgent(ITarget<RawData> &messageEnvoye,

ISource<BOOL>& stop,WebServiceConfiguration config)

:_messageEnvoye(messageEnvoye),_stop(stop),_config(config),_wsError(nullptr),_wsHeap(nullptr),_wsServiceProxy(nullptr)

{

InitialiserProxyWeb();InitialiserServiceWeb();

}

Vous noterez que notre agent Bing dérive de DPEBaseAgent qui est en fait une classe qui dérive elle-même de la classe agent, et qui propose des services supplémentaires que nous réutiliserons dans tous nos agents. Je ne rentrerai pas dans le détail de ses services, mais vous trouverez avec cet article, le code complet de l’application.

2. Enfin on implémente la méthode run() de la classe agentvoid DPEBingAgent::run(){

HRESULT hr;//Au démarrage de l'agent//Initialise la structure RawData (_data)_data.Sentinel=FALSE;//Permet de définir s’il y a encore des données à télécharger

//Code omis pour plus de clarté

//Télécharge une page de NombreVignettes//en n'oubliant pas de passer le bon offset si l'utilisateur//veut une autre page offset=numePage-1*NombreVignetteshr=this->RechercherImage (_config.Requete,

Page 13: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

_config.NombreVignettes,(_config.NumeroPage-1) *_config.NombreVignettes);

//Code omis pour plus de clartéint count=_request->Image->Count;//Envoi vignette par vignette à l'agent suivant dans le pipelinefor(int i=0; i<count ;i++){

//Code omis pour plus de clarté

//Si on arrive à la fin if ((i+1)==count){

_data.Sentinel =TRUE;}//Copier la réponse dans la structure RawData _dataCopierReponse(i);//Envoyer le message à l'agent suivant dans le pipelineBOOL bresult=asend(_messageEnvoye,_data);

}done();}

La méthode run(), appel la méthode RechercherImages(), qui retourne si tout va bien le nombre d’images dans une structure de type SearchResponse Le nombre de réponses, nous servira comme nombre d’itérations de notre boucle. A chaque itération, nous copions (CopierReponse()) une réponse dans la structure RawData, que nous envoyons asend() au prochain agent dans le pipeline.

Note : La méthode asend() diffère de la méthode send(), dans le sens où elle envoie le message en mode asynchrone, c’est-à-dire qu’elle n’attend pas l’éventuelle réponse de l’agent suivant dans le pipeline.

La méthode CopierReponse(), récupère les adresses électroniques des images à partir de la structure SearchResponse, et les copies dans les structures ImageResult, et Thumbnail typedef struct ImageResult { WCHAR* Title; WCHAR* MediaUrl; WCHAR* Url; WCHAR* DisplayUrl; unsigned int Width; unsigned int Height; unsigned int FileSize; WCHAR* ContentType; struct Thumbnail* Thumbnail;} ImageResult;

typedef struct Thumbnail { WCHAR* Url; WCHAR* ContentType; unsigned int Width; unsigned int Height; unsigned int FileSize; unsigned int RunTime;} Thumbnail;Comme vous pouvez le constater, ces deux structures contiendront les informations nécessaires, Url, Taille, largeur et hauteur des images etc., qui seront utilisées par les agents suivants dans le pipeline. A la dernière itération, nous informons (_data.Sentinel=TRUE) l’agent suivant, que le nombre de réponses total a été atteint. Enfin on signale que l’agent a terminé son travail avec la méthode done().

Note : Le commentaire //Code omis pour plus de clarté, correspond au code de gestion d’erreur, qui permet si une erreur survient, de diffuser l’erreur d’agent en agent, et surtout d’arrêter l’exécution du pipeline.

Page 14: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

L’agent HTTP

L’agent HTTP, a pour rôle, de télécharger en fonction d’une adresse électronique fournie par l’agent BING, les données brutes d’une image, et les envoyer à l’agent suivant dans le pipeline.

Pour pouvoir télécharger des images provenant du résultat du service Bing, nous avons à notre disposition dans Windows 7, deux APIS, l’API WinINet http ://msdn.microsoft.com/en-us/library/aa385483(v=VS.85).aspx et WinHTTP http ://msdn.microsoft.com/en-us/library/aa384273(v=VS.85).aspx

Dans notre exemple, nous utiliserons l’API WinINET, car notre application n’est pas destinée à tourner sur un serveur. Par contre, il sera préférable d’utiliser l’API WinHTTP, si vous souhaitez développer un service, ou faire tourner du code sur un serveur.

Utilisation de WinINet1. Tout d’abord il faut inclure l’entête WinInet.h

#include <WinInet.h>2. Se lier à la librairie Wininet.lib3. Ensuite il faut ouvrir une session internet avec l’API InternetOpen()

HINTERNET _hSession_hSession=InternetOpen(L"WinInet agent V 0.5 (EV)",

INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);4. Avec le handle _hSession obtenue, on ouvre une adresse électronique à l’aide de la méthode

InternetOpenUrl().HINTERNET hOpenUrl=0;hOpenUrl=InternetOpenUrl (_hSession,

Url.c_str (), NULL, 0, INTERNET_FLAG_EXISTING_CONNECT, NULL);

Ou le paramètre Url.c_str() contient l’adresse électronique de l’image à télécharger. Souvenez-vous cette adresse est fourni par l’agent Bing.

5. Ensuite, il faut lire les données brutes à l’aide de la méthode InternetReadFile()BOOL bResult=FALSE;DWORD lpdwNumberOfBytesRead=0bResult=InternetReadFile(hOpenUrl, pBuffer, dwNumberOfByteToRead, &lpdwNumberOfBytesRead);hOpenUrl, est un handle qui provient de l’ouverture de l’Url à l’étape 3pBuffer, est un tableau d’octets qui a été initialisé à la taille de l’image Bing, et que nous sauvegarderons dans notre structure RawData et que nous fournirons à l’agent suivant dans le pipelinedwNumberOfByteToRead, correspond au nombre d’octets à lire.lpdwNumberOfBytesRead, correspond au nombre d’octets effectivement lues

6. Enfin il faut libérer les deux handles _hSession et hOpenUrl que nous avons ouvert.InternetCloseHandle(hOpenUrl);InternetCloseHandle(_hSession);

Listing complet de la méthode de téléchargement des données brutes.HRESULT DPEHttpAgent::TelechargerDonneesBrutes(wstring Url,

BYTE* pBuffer, DWORD dwNumberOfByteToRead)

{

HRESULT hr=S_OK;BOOL bResult=FALSE;DWORD lpdwNumberOfBytesRead=0;HINTERNET hOpenUrl=0;if (_hSession){

hOpenUrl=InternetOpenUrl (_hSession, Url.c_str (), NULL, 0, INTERNET_FLAG_EXISTING_CONNECT, NULL);

Page 15: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

if (hOpenUrl){

ZeroMemory (pBuffer,dwNumberOfByteToRead);bResult=InternetReadFile(hOpenUrl,

pBuffer, dwNumberOfByteToRead, &lpdwNumberOfBytesRead);

if (bResult==FALSE){

_data.hr=E_FAIL;wcscpy(_data.Message,L"Impossible de lire les données du

fichier"); }

}else{

_data.hr=E_FAIL;wcscpy(_data.Message,L"Impossible d'accéder à l'URL");

}

}else{

_data.hr=E_FAIL;wcscpy(_data.Message,L"Impossible d'ouvrir l'agent WinInet agent V 0.5

(EV)"); }if (hOpenUrl)

InternetCloseHandle(hOpenUrl);return hr;

}

Implémentation de l’Agent HTTP1. L’agent HTTP est le second agent du pipeline, il recevra un message de l’agent Bing contenant les adresses

électroniques à télécharger et enverra un message à l’agent suivant dans le pipeline contenant les données brutes de l’image. Son constructeur prendra alors comme paramètres :Un point d’entrée pour envoyer un message : ITarget<RawData>& messageEnvoyeUn point d’entrée pour recevoir le message de l’agent Bing : ISource<RawData>& messageRecu ;Un point d’entrée pour recevoir un éventuel message d’arrêt : ISource<BOOL>& stopUne variable booléen telechargerImageComplete indiquant si il faut télécharger la vignette ou l’image complète :

class DPEHttpAgent:public DPEBaseAgent{public:

explicit DPEHttpAgent(ITarget<RawData>& messageEnvoye, ISource<RawData>&messageRecu, ISource<BOOL>& stop, BOOL telechargerImageComplete);

protected:void run();

//Code omis pour plus de clarté}

Le constructeur s’implémente de la manière suivante : DPEHttpAgent::DPEHttpAgent(ITarget<RawData>& messageEnvoye,

ISource<RawData>& messageRecu, ISource<BOOL>& stop, BOOL telechargerImageComplete)

:_messageEnvoye(messageEnvoye),

Page 16: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

_messageRecu(messageRecu), _stop(stop),_telechargerImageComplete(telechargerImageComplete), _hSession(0)

{

_hSession=InternetOpen(L"WinInet agent V 0.5 (EV)",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);

}

2. Enfin on implémente la méthode run()void DPEHttpAgent::run(){

//Code omis pour plus de clartédo{

//L’agent bloque ici en attente d'un message_data=receive(_messageRecu);//Code omis pour plus de clartéUINT fileSize;wstring url;//Est-ce que je dois télécharger l'image complète ? if

(_telechargerImageComplete){

url.append (_data.ImageBingResult->MediaUrl); fileSize=_data.ImageBingResult->FileSize;_data.BufferImageComplete=(BYTE*)malloc(fileSize);_data.hr=TelechargerDonneesBrutes(url,

_data.BufferImageComplete,fileSize);

}else{

url.append (_data.ImageBingResult->Thumbnail->Url);fileSize=_data.ImageBingResult->Thumbnail->FileSize ;

//Télécharger la vignette_data.BufferVignette=(BYTE*)malloc(fileSize);_data.hr =TelechargerDonneesBrutes (url,_data.BufferVignette, fileSize);

}//Code omis pour plus de clarté//Envoyer le message à l'agent suivant dans le pipelineasend(_messageEnvoye,_data); }

while(_data.Sentinel ==FALSE);done();

}

Vous noterez ici, que la méthode run() rentre dans une boucle qui se finira lorsque la variable Sentinel de notre message sera à TRUE. C’est l’agent précédant dans le pipeline en l’occurrence l’agent BING, qui en avertira notre agent HTTP. A l’initialisation de la boucle, l’agent HTTP, attend de recevoir (_data=receive()) un message. Tant que le message n’est pas envoyé par l’agent BING, la méthode receive() bloque l’appel. Dès qu’un message est reçu, l’agent HTTP, va télécharger en fonction d’une adresse électronique fourni par l’agent BING, les données brutes de l’image. Données brutes qu’il sauvegarde dans la structure RawData et l’envoi immédiatement à l’agent suivant dans le pipeline. Enfin l’agent signale qu’il a fini son travail, à l’aide de la méthode done().

L’agent WICL’agent WIC, a pour rôle de transformer les données brutes fournies par l’agent HTTP, en bitmap Direct2D. Il utilise la technologie Windows Imaging Component (WIC) pour le faire.WIC étant une plateforme extensible (permettant de développer son propre codec), qui offre un jeu d’interfaces

Page 17: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

standard permettant de décoder ou d’encoder des images et ceci quelques soit le format (TIFF, JPEG, PNG, GIF, BMP etc.).

Pour de plus amples informations sur Windows Imaging Component, reportez-vous à la documentation MSDN : http://msdn.microsoft.com/fr-fr/library/ee719902(v=VS.85).aspx

Utilisation de WIC pour décoder des données brutes et en créer un bitmap Direct2D1. Tout d’abord il faut inclure l’entête WIC

#include <wincodec.h>

2. Se lier à la librairie windowscodecs.lib

3. WIC est un composant COM, il est donc important d’initialiser COM avant de faire appel à ses API_data.hr=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

Même si vous avez déjà initialisé COM dans l’application, n’oubliez pas ici que nous utiliserons WIC dans un agent qui s’exécute dans un autre thread. Il donc important d’initialiser COM pour le thread courant.

4. Pour manipuler WIC, il faut commencer par créer une fabrique symbolisée par l’interface IWICImagingFactoryIWICImagingFactory *_pWicFactory;_data.hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,

IID_PPV_ARGS(&_pWicFactory) );

5. Comme nous voulons créer un bitmap à partir d’un tableau d'octets, nous allons passer par un flux de données symbolisé par l’interface IWICStream.IWICStream *_pStream;hr=_pWicFactory->CreateStream(&_pStream);

Ensuite nous initialisons le flux avec les données brutes de l’imagehr = _pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(_data.BufferVignette ),

_data.ImageBingResult->Thumbnail->FileSize);

6. Ensuite nous créons un décodeur, à partir du flux de données IWICStream que nous venons d’initialiser.IWICBitmapDecoder *_pDecoder ;hr = _pWicFactory->CreateDecoderFromStream( _pStream, NULL, WICDecodeMetadataCacheOnDemand , &_pDecoder );

7. A partir de ce décodeur, nous obtenons la 1ere frame de l’image qui nous servira pour la conversion de l’image.IWICBitmapFrameDecode *_pFrameSource ;hr = _pDecoder->GetFrame(0, &_pFrameSource);

La méthode GetFrame() retrouve la première frame de l’image, et en créée une source de type IWICBitmapFrameDecode qui dérive de IWICBitmapSource.

8. Pour convertir l’image il nous faut créer un convertisseur symbolisé par l’interface IWICFormatConverter, puis ensuite initialiser le convertisseur avec le bitmap source. Ce convertisseur nous permet ici de convertir l’image IWICBitmapFrameDecode en une image au format 32 bits. Pour de plus amples informations sur les formats gérés par WIC http://msdn.microsoft.com/fr-fr/library/ee719797(v=VS.85).aspx.IWICFormatConverter *_pConverter;hr = _pWicFactory->CreateFormatConverter(&_pConverter);

hr = _pConverter->Initialize( _pFrameSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeSolid,

Page 18: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

NULL, 0.f, WICBitmapPaletteTypeMedianCut );

9. Une fois le convertisseur initialisé, on le passe à la méthode Direct2D CreateBitmapFromWicBitmap qui crée le bitmap et le sauvegarde dans le champ D2D1Thumbnail de notre structure RawData qui sera transmis à l’agent suivant dans le pipeline. ID2D1RenderTarget *_pRender;hr = _pRender->CreateBitmapFromWicBitmap (_pConverter,nullptr,

&_data.D2D1Thumbnail);

Nous verrons au chapitre suivant comment créer l’objet Direct2D ID2D1RenderTarget qui nous permettra d’effectuer le rendu.

10. Enfin il faut libérer les ressources utilisées.void DPECreateD2D1BitmapAgent::LibererRessources (){

SafeRelease(&_pStream);SafeRelease(&_pDecoder);

SafeRelease(&_pFrameSource); SafeRelease(&_pConverter);}La méthode SafeRelease étant implémenter de la manière suivante :template<class Interface>inline voidSafeRelease(Interface **ppInterfaceToRelease){ if (*ppInterfaceToRelease != NULL) { (*ppInterfaceToRelease)->Release(); (*ppInterfaceToRelease) = NULL; }}

Implémentation de l’agent WIC

1. L’agent WIC reçoit un message de l’agent HTTP contenant les données brutes de l’image, et envoie un message contenant un bitmap Direct2D à l’agent suivant dans le pipeline. Son constructeur prendra alors comme paramètres :Un point d’entrée pour envoyer un message : ITarget<RawData>& messageEnvoyeUn point d’entrée pour recevoir le message de l’agent Bing : ISource<RawData>& messageRecu ;Une variable booléen imageComplete indiquant si l’on doit décoder la vignette ou l’image complète.Un pointeur sur le contexte de rendu Direct2DID2D1RenderTarget *render

class DPECreateD2D1BitmapAgent : public DPEBaseAgent{public:

explicit DPECreateD2D1BitmapAgent(ITarget<RawData>& messageEnvoye, ISource<RawData>& messageRecu, BOOL imageComplete, ID2D1RenderTarget *render);

~DPECreateD2D1BitmapAgent(void);protected :

void run();//Code omis pour plus de clarté

Page 19: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

}

2. La méthode run(), s’implémente de la manière suivante : void DPECreateD2D1BitmapAgent::run(){

_data.hr=InitialiserFabriqueImage ();//Code omis pour plus de clartédo{

//L'agent bloque ici en attente d'un message_data=receive(_messageRecu);//Code omis pour plus de clarté_data.hr=DecoderImage();//Code omis pour plus de clartéasend (_messageEnvoye,_data);

}while(_data.Sentinel ==FALSE);

done();}

La méthode run() rentre dans une boucle qui se finira lorsque la variable Sentinel du message RawData sera à TRUE. Une fois l’image décodée, le message est envoyé immédiatement à l’agent suivant. Enfin l’agent signale qu’il a fini avec la méthode done().

L’agent DisplayL’agent Display, a pour simple rôle d’afficher à l’écran les vignettes au format d’un bitmap direct2D. Affichage qui sert uniquement d’indicateur une espèce de sablier indiquant que le téléchargement est en cours. Le réel affichage sous forme de grille de vignettes, se fera toujours à l’aide de Direct2D mais en associations avec les animations Windows comme nous le verrons plus tard.

Direct2D est une API pour la création de graphiques 2D. Basée sur Direct3D 10, elle offre aux développeurs Win32, une API indépendante de la résolution, et qui utilise la puissance des cartes graphiques de nouvelle génération. Vous pouvez, avec Direct2D, améliorer vos applications GDI existantes, sans être obligé de les réécrire. En effet Direct2D a été conçu pour coopérer avec le GDI et d'autres technologies graphiques. Enfin, Direct2D vous permet d'écrire du contenu Direct2D sur une surface GDI.

Pour de plus amples informations sur Direct2D, reportez-vous à la documentation MSDN : http://msdn.microsoft.com/fr-fr/library/dd370990(v=VS.85).aspx

Dans notre exemple, l’agent Display (ainsi que l’agent WIC) ne font qu’utiliser le contexte de rendu Direct2D. Voici comment en créer un.

Création du contexte de rendu Direct2DPour créer un contexte de rendu Direct2D il faut :

1. Inclure le fichier d’entête D2D1.h#include <D2D1.h>

2. Se lier à la librairie D2D1.lib3. Créer une fabrique qui permettra de créer tous les objets Direct2D.

ID2D1Factory *_pfabriqueD2D1;D2D1CreateFactory (D2D1_FACTORY_TYPE_MULTI_THREADED,

&_pfabriqueD2D1);

4. Une fois que la fabrique est créée, nous allons nous en servir pour créer notre contexte de rendu.ID2D1HwndRenderTarget *_pcontexteRenduD2D1;

Page 20: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

RECT rc;GetClientRect(hWnd,&rc); D2D1_SIZE_U usize = D2D1::SizeU((rc.right - rc.left),(rc.bottom - rc.top));//Création du contexte de renduD2D1_RENDER_TARGET_PROPERTIES proprietesRendu=D2D1::RenderTargetProperties();D2D1_HWND_RENDER_TARGET_PROPERTIES proprietesHwndRendu=D2D1::HwndRenderTargetProperties (hWnd,usize);hr=_pfabriqueD2D1->CreateHwndRenderTarget (proprietesRendu,

proprietesHwndRendu, &_pcontexteRenduD2D1);

La méthode CreateHwndRenderTarget, prend comme paramètre une structure D2D1_RENDER_TARGET_PROPERTIES, qui est initialisée avec des valeurs par défaut, à l’aide de la méthode D2D1 ::RenderTargetProperties()Ces valeurs par défaut, permettent de fonctionner avec la plus part des matériels de rendu et est initialisée de la manière suivante :proprietesRendu.type =D2D1_RENDER_TARGET_TYPE_DEFAULT;proprietesRendu.dpiX =0.0f;proprietesRendu.dpiY =0.0f;proprietesRendu.pixelFormat.format =DXGI_FORMAT_UNKNOWN;proprietesRendu.pixelFormat.alphaMode=D2D1_ALPHA_MODE_UNKNOWN;proprietesRendu.usage=D2D1_RENDER_TARGET_USAGE_NONE;proprietesRendu.minLevel =D2D1_FEATURE_LEVEL_DEFAULT ;

Le champ type, correspond au type de rendu que vous souhaité, soit matériel, D2D1_RENDER_TARGET_TYPE_HARDWARE, soit logiciel D2D1_RENDER_TARGET_TYPE_SOFTWAREDans notre exemple la valeur par défaut, indique que Direct2D utilisera le rendu matériel si la carte graphique le supporte. Vous pouvez forcer la valeur du champ type à l’une ou l’autre des valeurs, et vérifier leurs effets sur l’utilisation de la CPU, comme illustré sur les figures suivantes

Utilisation de l’accélération Hardware Utilisation du CPU

On voit dans ces deux images que l’utilisation de la CPU est d’environ 5% lors de l’utilisation matériel (sous entendu c’est la carte graphique qui bosse) alors qu’elle est de 79% lors d’un rendu logiciel.

Les champs dpiX et dpiY, sont initialisés à zéro, indiquant que nous utilisons la taille de l’affichage par défaut. (à ne pas confondre avec la résolution de l’écran). Vous devez savoir que Windows 7 introduit la technologie Hight-DPI qui permet d’augmenter la lisibilité de lecture à l’écran. L’affichage d’un écran est de base de 96 DPI, mais avec cette technologie il est possible de monter à 120 ou à 144 DPI, comme illustré sur la figure suivante :

Page 21: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

125% correspondant à 120 DPI (96*125/100), 150% correspondant à 144 DPI (96*150/100)

Sur notre configuration les champs dpiX et dpiY prendront comme valeur par défaut 120.Le champ pixelFormat correspondant au format de l’image que nous voulons, la valeur est par défaut, car nous ne connaissons pas à l’avance le format des images qui seront téléchargées.Le champ usage, permet de définir, si le bitmap sera rendu localement et envoyé au client terminal service (D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING), mais il permet de définir également si le contexte de rendu peut être utilisé avec le GDI (D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE)Le champ minLevel, permet de déterminer le niveau de Direct3D. D2D1_FEATURE_LEVEL_9 = D3D10_FEATURE_LEVEL_9_1,D2D1_FEATURE_LEVEL_10 = D3D10_FEATURE_LEVEL_10_0

Remarque : Tout le code le code Direct2D est implémenté dans la classe DPEDirectD2D1Helper

Implémentation de l’agent Display1. L’agent Display reçoit un message de l’agent WIC contenant un bitmap Direct2D à afficher et envoie un

message contenant un bitmap Direct2D à l’agent suivant dans le pipeline.Son constructeur prendra alors comme paramètres :Un point d’entrée pour envoyer un message : ITarget<RawData>& messageEnvoyeUn point d’entrée pour recevoir le message de l’agent Bing : ISource<RawData>& messageRecu ;Un pointeur sur le contexte de rendu Direct2DID2D1RenderTarget *render

class DPEDisplayAgent : public DPEBaseAgent{public:

explicit DPEDisplayAgent(ITarget<RawData>& messageEnvoye, ISource<RawData>& messageRecu, ID2D1RenderTarget *pRender);

~DPEDisplayAgent(void);

protected : void run();

//Code omis pour plus de clarté}

2. La méthode run() s’implémente alors de la manière suivante :void DPEDisplayAgent::run(){

//Récupère la taille de la zone cliente sur laquelle//sera rendu les imagesD2D1_SIZE_F zoneClientSize= _pRender->GetSize (); do

Page 22: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

{//L'agent bloque ici en attente d'un message_data=receive(_messageRecu);//Code omis pour plus de clartéif (SUCCEEDED(_data.hr)){

//récupère la taille de l'imageD2D1_SIZE_F size =_data.D2D1Thumbnail->GetSize ();//Affiche les bitmaps en tasD2D1_POINT_2F upperLeftCorner =

D2D1::Point2F(zoneClientSize.width/2, zoneClientSize.height/4);

_pRender->BeginDraw ();_pRender->DrawBitmap (_data.D2D1Thumbnail,

D2D1::RectF ( upperLeftCorner.x, upperLeftCorner.y, (upperLeftCorner.x+size.width),

(upperLeftCorner.y + size.height)));_data.hr=_pRender->EndDraw (); //passe la main à un autre agent dans le pipe même si l'affichage ce passe mal//l'agent suivant en sera informéasend(_messageEnvoye,_data);

}//Code omis pour plus de clarté

}while(_data.Sentinel ==FALSE);done();

}

La méthode run() s’implémente de la même manière que les autres agents. Un message est reçu avec la bitmap Direct2D. Pour l’afficher à l’écran on débute par la méthode BeginDraw() du contexte de rendu. On dessine la bitmap via la méthode DrawBitmap() au milieu de l’écran.Puis on finit toujours par la méthode EndDraw(). Cette dernière méthode retourne un HRESULT, qui permet de vérifier si une erreur est survenue.L’affichage de tous les bitmaps, dans notre exemple, ce fait en tas, et nous sert de sablier nous indiquant qu’il y a un téléchargement encours.Une fois qu’un bitmap est affiché, l’agent Display, le passe à l’agent suivant dans le pipeline. Enfin l’agent signale qu’il a fini son travail.

L’agent StoreL’agent store à juste comme rôle de sauvegarder les vignettes dans un vecteur, qui servira par la suite dans notre application pour le module d’animation.

Implémentation de l’agent Store1. L’agent store reçoit de l’agent Display un bitmap qu’il doit sauvegarder dans un vecteur

Son constructeur prendra alors comme paramètres :Un point d’entrée pour envoyer un message. Vous noterez que le type envoyé sera un vecteur de RawData.ITarget<concurrent_vector<RawData>>& messageEnvoyeUn point d’entrée pour recevoir le message de l’agent Bing : ISource<RawData>& messageRecu ;

class DPEStoreAgent :public DPEBaseAgent

{public:

explicit DPEStoreAgent(ITarget<concurrent_vector<RawData>>& rawVector, ISource<RawData>& messageRecu);

Page 23: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

~DPEStoreAgent(void);protected :

void run();//Code omis pour plus de clarté}

2. La méthode run() s’implémente de la manière suivante : void DPEStoreAgent::run(){

//Instanciation du vecteurconcurrent_vector<RawData> vector;do{

this->_data=receive(_messageRecu);//Code omis pour plus de clartéif (SUCCEEDED(_data.hr)){

//Stocke la donnéevector.push_back (_data);

}}while(_data.Sentinel ==FALSE);//Une fois toutes les vignettes sauvegardées dans le vector//envoi le vecteur au prochain agent dans le pipelineasend(_messageEnvoye,vector);done();

}

Exécution du pipelineMaintenant que nous avons vu comment implémenter le pipeline, nous allons voir comment le démarrer.Tout d’abord, même si les agents du pipeline s’exécutent dans des threads différents que le thread qui a créé les fenêtres, il faut quand même en démarrer un nouveau pour éviter que l’interface graphique soit bloquée.Pour ce faire, nous allons utiliser la notion de tâche, que nous retrouvons avec la librairie Parallèle de Visual Studio 2010.Je ne vais pas rentrer dans les détails de cette librairie, vous retrouverez toutes les informations nécessaire dans l’aide de MSDN : http://msdn.microsoft.com/fr-fr/library/dd492418.aspxNéanmoins, sachez que cette libraire, au même titre que la librairie Agent, simplifiera grandement le développement d’application parallèle. En effet, il sera préférable d’utiliser ce type de bibliothèque, plutôt que d’utiliser les mécanismes bas niveau type thread et autres objets de synchronisation de Windows. Mais ceci est un autre débat. Pour ceux qui souhaiteraient aller plus loin avec l’offre parallèle de Microsoft, n’hésitez pas à visiter le blog http://blogs.msdn.com/b/devpara/

Pour démarrer une nouvelle tâche voici une des manières de procéder.1. Nous allons créer une méthode RechercherImagesAsync

void FenetreEnfant::RechercherImagesAsync(WebServiceConfiguration param)

qui prend comme paramètre la structure WebServiceConfiguration que nous passerons à l’agent BING.Cette structure contient le texte de la requête, le nombre de vignettes à télécharger, ainsi que le numéro de page à utiliser en autre.struct WebServiceConfiguration{

WCHAR Requete[1024];int NombreVignettes;int NumeroPage;int TotalPages;int TotalVignettes;BOOL NouvelleRequete;BOOL Sauvegarder;

};

Page 24: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Dans notre exemple, nous téléchargerons des images page par page , il est donc important de signifier à l’agent Bing qu’elle page nous voulons télécharger. (cf. étape 6 de la section utilisation de WWSAPI).

2. Ensuite, il faut inclure l’entête ppl.h et utiliser l’espace de nom Concurrency :#include <ppl.h>using namespace ::Concurrency;

3. Puis nous allons instancier et démarrer notre tâchetask_group *_tasks=nullptr;_tasks=new task_group();_tasks->run ([&]()

{RechercherImages (param);

});

L’objet task_group, possède la méthode run(), qui permet de démarrer une tâche. Comme vous pouvez le constater, nous lui passons en paramètre une syntaxe un peu particulière, sous forme d’expression lambda. Cette forme provient d’une nouveauté du langage C++0X, et supporter par le compilateur C++ de Visual Studio 2010. Mais avant d’aller plus loin et d’expliquer un peu les expressions lambda et leur utilité dans le langage C++, voyons ce que dit la documentation MSDN pour la méthode run().template<typename _Function>void run(const _Function& _Func);template<typename _Function>void run(task_handle<_Function>& _Task_handle);

Soit elle prend une fonction de type _Function définie dans l’entête TR1 <functional> ou _Func peut être une lambda expression.Soit elle prend un task_handle <_Function>, l’objet task_handle étant l’objet tâche défini dans l’entête <ppl.h>.Sans les expressions lambda, voici comment nous aurions écrit notre code : Nous aurions déclaré une fonction statique .WebServiceConfiguration _param; //Déclaré en globalvoid FenetreEnfant::MaFonctionExterne()

{RechercherImages (_param);

}

Puis déclaré un appel à cette fonction de la manière suivante en utilisant la signature à base de task_handle :

void FenetreEnfant::RechercherImagesAsync(WebServiceConfiguration param){//Sauvegarde des paramètres_param=param;task_handle<function<void (void)>> task(&FenetreEnfant::MaFonctionExterne);_tasks->run(task);_tasks->wait();}

Syntaxe beaucoup moins lisible si il en faut qu’avec notre simple expression lambda.

Comme en mathématique, nous pouvons simplifier l’expression, en utilisant la signature à base de fonction.function<void (void)> maFunc=&FenetreEnfant::MaFonctionExterne;_tasks->run(maFunc);

C++0X réintroduit le mot clé auto qui permet de déduire un type par rapport à une expression, ce mot clé va nous permettre de simplifier encore notre expression auto  maFunc=&FenetreEnfant:: MaFonctionExterne;_tasks->run(maFunc);

Page 25: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Jusque la tout fonctionne correctement, néanmoins, le code n’est pas des plus lisible, car nous avons une variable globale déclaré en externe ainsi qu’une méthode déclarée ailleurs dans le code source.C’est la ou intervient la lambda expression, afin de simplifier et améliorer la lisibilité du code.Je peux réécrire mon expression comme ceci.auto  maFunc=[&]()

{RechercherImages (param);

});_tasks->run(maFunc);

Pour arriver à la simplification ultime _tasks->run ([&]()

{RechercherImages (param);

});

C’est beau, court, concis et pratique et rend le code plus lisible. Ici plus besoin de déclarer des méthodes et des variables en globale. Pour débuter une expression lambda on commence toujours par les signes crochets []Si on souhaite capturer les paramètres par référence, on utilise le signe & (si on souhaite en faire une copie il faut les capturer par valeur en utilisant le signe =) Dans notre exemple le compilateur saura qu’il faut passer une référence à la variable paramEnsuite on déclare le corps de la fonction de la même manière qu’un corps de fonction avec des parenthèses () et des accolades {} suivie d’un point virgule ;.Etonnement, ce type de code compile avec le compilateur de VC ++ 2010.[](){}();[]{}();

Pour en savoir plus sur les expressions lambda : http://msdn.microsoft.com/fr-fr/library/dd293608.aspx

Maintenant, nous allons implémenter la méthode RechercheImage de la manière suivante.

1. La signature sera la même que la méthode RechercherImagesAsync: void FenetreEnfant::RechercherImages(WebServiceConfiguration Param)

2. Ensuite nous définissons les messages qui voyageront entre chaque agent. Rappelez-vous pour définir un message nous allons utiliser la classe de messagerie unbounded_buffer<> avec notre type RawData qui sera véhiculé d’agent en agent.//Message qui contiendra les réponses du Service Bingunbounded_buffer <RawData> msgReponseBing; //Message qui contiendra les images sous forme de //tableau de BYTES téléchargées par l'agent HTTPunbounded_buffer <RawData> msgTelechargeImages;//Message qui contiendra les bitmaps Direct2D à afficherunbounded_buffer <RawData> msgDisplayBitmap;//Message qui contiendra les bitmaps à stockerunbounded_buffer <RawData> msgStoreBitmap; //Message qui contiendra le container de toutes les Images sous forme d’un vecteurunbounded_buffer<concurrent_vector<RawData>> msgRawDataVecteur;

//Message qui nous serviront pour arrêter les //agents BING et http ces messages seront déclarer en globaleunbounded_buffer<BOOL> msgStopAgentBing;unbounded_buffer<BOOL> msgStopAgentHttp;

Page 26: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

3. Puis il faut instancier nos agents avec les bons messages et les bons paramètres//Pointeur sur Helper Direct2DDPEDirectD2D1helper *_pD2D1helper=nullptr;

DPEBingAgent  agentBing(msgReponseBing,msgStopAgentBing,Param);DPEHttpAgent  agentHttp(msgTelechargeImages, msgReponseBing,msgStopAgentHttp,FALSE);//Récupère le contexte de rendu pour le fournir à l'agent WICID2D1HwndRenderTarget *pRender=_pD2D1helper->GetContexteRendu ();DPEWICAgent agentWIC(msgDisplayBitmap, msgTelechargeImages,FALSE,pRender);DPEDisplayAgent agentDisplay(msgStoreBitmap,msgDisplayBitmap,pRender);DPEStoreAgent agentStore(msgRawDataVecteur,msgStoreBitmap);

Vous noterez que le contexte de rendu est fourni par la méthode GetContextRendu(), implémenter dans la classe DPEDirectD2D1helper.

4. On démarre les agents.//démarrer les agentsagentBing.start ();agentHttp.start ();agentWIC.start ();agentDisplay.start ();agentStore.start ();

Ici le démarrage se fait dans l’ordre des agents, mais en faite cela n’a pas d’importance dans notre pipeline, car tous les agents seront en attente sur la méthode receive() d’une 1er réponse de l’agent BING.

5. Ensuite il faut attendre que tous les agents finissent leur travail (méthode done()).//Attente des agentsagent::wait(&agentBing);agent::wait (&agentHttp);agent::wait(&agentWIC);agent::wait(&agentDisplay);agent::wait(&agentStore);

6. Vous aurez remarqué, qu’aucun agent n’est démarré, pour réceptionner le vecteur de RawData envoyé par l’agent Store. Peut importe, car nous pouvons utiliser la méthode receive() dans notre méthode sans passer par la structure d’un agent. //contiendra le résultat de la recherche et de la //transformation en Bitmap concurrent_vector<RawData>  *_pconcurVector=nullptr;_pconcurVector=new concurrent_vector<RawData>();

//le code bloque ici, tant qu'il n'a pas reçu le vecteur d'images*_pconcurVector=receive(msgRawDataVecteur);

Remarque : Puisque le thread est bloqué sur la méthode receive(), il est superflue d’attendre que tous les agents finissent leur travail. L’étape 5 ici n’est pas nécessaire et est juste là à titre indicatif.

7. Une fois que nous avons reçu notre vecteur de RawData, on en informe la procédure de la fenêtre à l’aide de l’API PostMessage()PostMessage (_hwndEnfant,WM_COMMAND,WM_INIT_VIGNETTES,0);

Remarque : Nous utilisons la méthode PostMessage et non pas SendMessage, car notre pipeline s’exécute dans un thread différent que celui de l’IHM. Avec la méthode PostMessage, cela permet de poster un message dans la file des messages associée au thread qui à crée la fenêtre. En d’autres termes, nous synchronisons le thread de notre pipeline, avec le thread de l’IHM, et ceci parce qu’avec Windows nous ne pouvons pas accéder à un objet crée dans le thread principal à partir d’un autre thread.

Page 27: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Vous noterez que l’on passe le message WM_COMMAND et la commande utilisateur WM_INIT_VIGNETTE, pour initialiser les vignettes, afin que la plate-forme d’animation de Windows (que nous verrons à la section suivante Animation des vignettes.) puisse les animer.

Pour en finir avec notre pipeline et pour illustrer mes propos, vous apercevrez dans les figures suivantes (prise d’une photo à un instant T), que l’agent BING est en cours d’exécution, que l’agent HTPP est en attente d’un message. L’agent WIC quand à lui est train de décoder une image avant de l’envoyer à l’agent Display qui est en attente, alors que l’agent Store est en train de stocker une image que l’agent Display lui a envoyé.Notre pipeline travail ici sur 3 itérations en parallèle.

Saisie d’un mot clé et l’afficher avec DirectWriteDirectWrite est une nouvelle API DirectX, qui permet aux applications de supporter un rendu texte de haute qualité. Elle supporte les fonctionnalités suivantes :

Indépendante du périphérique, DirectWrite améliore la lisibilité des documents (Text Layout) Rendu des textes, en High-Quality, subpixel, et ClearType®, qui peuvent utiliser des techniques telles que le

GDI, Direct2D, ou un rendu spécifique à l'application. Un jeu d'API conforme à Unicode Accélération Matériel du texte, lorsque DirectWrite est utilisé avec Direct2D Formatage de texte multiple Support de typographie avancée de type OpenType® Compatible avec le GDI

Utilisation de DirectWritePour utiliser les APIs DirectWrite, il faut procéder comme suit :

1. Il faut inclure l’entête dwrite.h#include <dwrite.h>

2. Se lier à la librairie dwrite.lib3. Créer une fabrique DirectWrite

IDWriteFactory *_pfabriqueDWrite;

Page 28: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

hr=DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,__uuidof(IDWriteFactory),reinterpret_cast<IUnknown**>(&_pfabriqueDWrite));

4. Créer un format de texteIDWriteTextFormat *format;_pfabriqueDWrite->CreateTextFormat (L"Arial", NULL,

   DWRITE_FONT_WEIGHT_REGULAR,    DWRITE_FONT_STYLE_NORMAL,   DWRITE_FONT_STRETCH_NORMAL,   20.0f,   L"fr-fr",&format);

5. Utiliser un contexte de rendu Direct2D et sa méthode DrawText, pour écrire du texte à l’écran.void DPEDirectD2D1helper::EcrireMotCle(LPCWSTR texte){

//Code omis pour plus de clartésize_t length=wcslen (texte);//Code omis pour plus de clartéFLOAT fontSize=_ptextFormat->GetFontSize ();D2D1_SIZE_F sizeRendu= _pcontexteRenduD2D1->GetSize (); _pcontexteRenduD2D1->BeginDraw ();

D2D1_RECT_F layoutRect1 = D2D1::RectF(0,sizeRendu.height/4 ,sizeRendu.width,fontSize+sizeRendu.height/4);

_pcontexteRenduD2D1->FillRectangle (layoutRect1,_pBackgroundBrush);_pcontexteRenduD2D1->DrawTextW (texte,static_cast<UINT>(length),

_ptextFormat, layoutRect1, _pbrosseBlanche);

_pcontexteRenduD2D1->EndDraw();

}

Le code DirectWrite se trouve dans le fichier DPEDirect2D1Helper.cpp6. Vous noterez que la méthode EcrireMotCle() prend un pointeur sur un WCHAR, pointeur qui provient de la

méthode OnWMChar de la fenêtre enfant, et que je ne détaillerai pas ici.HRESULT FenetreEnfant::OnWMChar(WPARAM wChar)

Animation des vignettesLe gestionnaire d'Animation de Windows (Windows Animation) permet une animation riche des éléments d'interface utilisateur. Il est conçu pour simplifier le processus d'ajout d'animation à l'interface utilisateur d'une application et pour permettre aux développeurs de mettre en œuvre des animations qui sont fluides, naturelles et interactives.

La plate-forme d’animation de Windows 7, gère la planification et l’exécution des animations, et fournit également une bibliothèque de fonctions mathématiques utiles pour spécifier le comportement d'un élément d'interface utilisateur au fil du temps. Elle permet également aux développeurs de mettre en œuvre des fonctions personnalisées qui fournissent des comportements supplémentaires.

Il est à noter que, ce n’est pas elle qui est en charge du rendu, mais qu’elle peut être utilisée avec n'importe quelle plate-forme graphiques, y compris Direct2D, Direct3D ou GDI +.

Les deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément visuel à animer et (2) la description de la façon dont cette caractéristique change au fil du temps. Une application peut animer une grande variété de caractéristiques telles que la position, la couleur, taille, rotation, contraste et opacité.

Dans Windows Animation, une variable d'animation représente la caractéristique à animer. Une transition décrit l'évolution de la valeur de cette variable d'animation lorsqu’une animation se produit. Par exemple, un élément

Page 29: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

visuel pourrait avoir une variable d'animation qui spécifie son opacité, et une action de l'utilisateur pourrait générer une transition qui prend cette opacité d'une valeur de 50 à 100, ce qui représente une animation de semi-transparent entièrement opaque. Un storyboard est un ensemble de transitions appliquée à une ou plusieurs variables d'animation au fil du temps.

La plate-forme d’animation de Windows est composée :

D’un gestionnaire d’animation, qui permet de créer des variables, des storyboards et de planifier les animations.

Des variables à animer qui représente un des aspects d’un élément visuel à animer. Dans notre exemple nous animerons les coordonnées des images.

Un système de timer, qui assure que les animations utiliseront une cadence de rafraichissement fluide et consistante, tout en réduisant l’utilisation de ressources systèmes lors du rendu lorsque le système est fortement en charge.

Diagramme lorsque l’application interagit directement avec la plate-forme d’animation.

Pour de plus amples information sur Windows Animation http://msdn.microsoft.com/fr-fr/library/dd371981(v=VS.85).aspx

Utilisation de Windows AnimationDans notre exemple, ce que nous voulons, c’est créer un effet d’animation à la fin d’exécution de notre pipeline, et lorsque la fenêtre se repeint (WM_PAINT). L’animation sera planifiée à partir d’un storyBoard et utilisera des effets de transitions type parabolique et des effets d’accélération et de décélération.

Pour mettre en place une animation voici les différentes tâches à accomplir.

1. Tout d’abord il faut inclure l’entête UIAnimation.h#include <UIAnimation.h>

Page 30: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

2. Une animation débute toujours par la création du gestionnaire d’animation ainsi qu’un certain nombre d’autres objets comme le timer, la librairie de transitions et un gestionnaire qui reçoit l’état du gestionnaire d’animation.

// Création du gestionnaire d'AnimationIUIAnimationManager *_pAnimationManager;    HRESULT hr = CoCreateInstance(        CLSID_UIAnimationManager,        NULL,        CLSCTX_INPROC_SERVER,        IID_PPV_ARGS(&_pAnimationManager));// Création du Timer d'animationIUIAnimationTimer *_pAnimationTimer;

hr = CoCreateInstance(            CLSID_UIAnimationTimer,            NULL,            CLSCTX_INPROC_SERVER,            IID_PPV_ARGS(&_pAnimationTimer));

// Création de la librairie de TransitionIUIAnimationTransitionLibrary *_pTransitionLibraryhr = CoCreateInstance(      CLSID_UIAnimationTransitionLibrary,      NULL,      CLSCTX_INPROC_SERVER,      IID_PPV_ARGS(&_pTransitionLibrary));

//Permet de recevoir l'état du gestionnaire d'animationIUIAnimationManagerEventHandler *pManagerEventHandler;hr = CManagerEventHandler::CreateInstance(hWnd,&pManagerEventHandler);//Fournit le gestionnaire d'état au gestionnaire d'animationhr = _pAnimationManager->SetManagerEventHandler(pManagerEventHandler);

Nous créons un objet IUIAnimationTimer , car nous en aurons besoins pour planifier un storyboard et mettre à jour le gestionnaire d’animation.Nous créons un objet IUIAnimationTransitionLibrary, qui nous permettra d’affecter une transition à un StoryBoard. Plusieurs types de transition sont disponibles, telles que des transitions cubique, linéaire, parabolique, d’accélération et de décélération, etc. Pour de plus amples informations sur les storyBoard et les transitions, reportez vous à l’aide MSDN : http://msdn.microsoft.com/fr-fr/library/dd756779(v=VS.85).aspxPuis nous créons un objet de type IUIAnimationManagerEventHandler, qui aura en charge de recevoir l’état du gestionnaire d’animation. Toute la mécanique COM d’implémentation de ce gestionnaire est contenu dans les fichiers ManagerEventHandler.h et UIAnimationHelper.h, provenant des exemples du SDK Windows 7.

3. Ensuite il faut créer les variables à animer.IUIAnimationVariable *_pAnimationVariableX;IUIAnimationVariable *_pAnimationVariableY; HRESULT CThumbnail::Initialize(    ID2D1Bitmap *pBitmap,    IUIAnimationManager *pAnimationManager,    DOUBLE x,    DOUBLE y)){// Code omis pour plus de clarté

// création des variables d'animations pour les coordonnées X et YHRESULT hr = pAnimationManager->CreateAnimationVariable(x,&_pAnimationVariableX);

Page 31: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

hr = pAnimationManager->CreateAnimationVariable(y,&_pAnimationVariableY) ; // Code omis pour plus de clarté }

Nous utilisons le gestionnaire d’animation pour créer les variables d’animation en fonction des positions x et y d’une vignette à l’écran. Vous retrouverez le code complet dans la classe CThumnnail fourni avec cet article et qui est issue également d’un exemple du SDK Windows 7.

4. Ensuite il faut créer un storyboard// Création du storyboard pour la transition de toutes les vignettes    IUIAnimationStoryboard *pStoryboard;    HRESULT hr = _pAnimationManager->CreateStoryboard(        &pStoryboard        );

5. Puis il faut ajouter les transitions au storyboard.HRESULT CLayoutManager::AddThumbnailTransitions(    IUIAnimationStoryboard *pStoryboard,    IUIAnimationVariable *pVariablePrimary,    DOUBLE valuePrimary,    IUIAnimationVariable *pVariableSecondary,    DOUBLE valueSecondary    )

{// Code omis pour plus de clartéIUIAnimationTransition *pTransitionPrimary;    HRESULT hr = _pTransitionLibrary->CreateParabolicTransitionFromAcceleration(        valuePrimary,        0.0,        ACCELERATION,        &pTransitionPrimary);

 hr = pStoryboard->AddTransition(        pVariablePrimary,        pTransitionPrimary);

// Code omis pour plus de clartéUI_ANIMATION_KEYFRAME keyframeEnd;hr = pStoryboard->AddKeyframeAfterTransition(pTransitionPrimary,

            &keyframeEnd);// Code omis pour plus de clartéIUIAnimationTransition *pTransitionSecondary;hr = _pTransitionLibrary->CreateAccelerateDecelerateTransition(1.0,

                valueSecondary,ACCELERATION_RATIO,DECELERATION_RATIO,                    &pTransitionSecondary );

// Code omis pour plus de clartéhr = pStoryboard->AddTransitionBetweenKeyframes(                        pVariableSecondary,                        pTransitionSecondary,                        UI_ANIMATION_KEYFRAME_STORYBOARD_START,                        keyframeEnd);// Code omis pour plus de clarté}

Vous noterez que nous utilisons la notion de KeyFrame, qui permet de spécifier le début et la fin d’une transition. Notez également que nous passons en paramètre de la fonction les variables IUIAnimationVariable, variables qui determinent la position x et y d’une vignette, afin de les utiliser dans les transitions.

6. Ensuite il faut planifier le storyboard. // Récupère le temps courant est planifie le storyboardUI_ANIMATION_SECONDS timeNow;hr = _pAnimationTimer->GetTime(&timeNow);hr = pStoryboard->Schedule(timeNow);                }

Page 32: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Le code complet des étapes 4 à 6 se trouve dans le fichier LayoutManager.cpp, issue lui aussi du SDK de Windows 7.

7. Une fois que le storyboard est planifié, cela déclenche une modification de l’état du gestionnaire d’animation qui le notifie au gestionnaire d’état IUIAnimationManagerEventHandler (que nous avons crée à l’étape 2) en appelant sa méthode OnManagerStatusChanged

IFACEMETHODIMP OnManagerStatusChanged(UI_ANIMATION_MANAGER_STATUS newStatus,UI_ANIMATION_MANAGER_STATUS previousStatus)    {        HRESULT hr = S_OK;         if (newStatus == UI_ANIMATION_MANAGER_BUSY)        {            //Repeindre la fenêtre

BOOL bResult = InvalidateRect(_hWnd, NULL, FALSE);

}

Comme le gestionnaire d’animation est occupé à ce moment précis, cela déclenche l’appel à l’API Windows InvalidateRect(), indiquant à la fenêtre de se redessiner.Le code de cette méthode se trouve dans le fichier ManagerEventHandler.h

8. Le faite d’invalider la zone cliente de la fenêtre enfant, déclenche le message Windows WM_PAINT, dans lequel nous indiquons qu’il faut dessiner les vignettes.

9. Avant de dessiner les vignettes, nous devons mettre à jour l’état du gestionnaire d’animation.UI_ANIMATION_SECONDS secondsNow;hr = _pAnimationTimer->GetTime(&secondsNow);hr = _pAnimationManager->Update(secondsNow);

10. Puis lire les variables d’animations, afin de retrouver les nouvelles coordonnées de la vignette.DOUBLE x = 0;HRESULT hr = _pAnimationVariableX->GetValue(&x);DOUBLE y = 0;hr = _pAnimationVariableY->GetValue(&y);

11. Une fois les nouvelles coordonnées obtenues, nous pouvons dessiner la vignette. Nous utiliserons ici notre contexte Direct2D.

ID2D1Bitmap *_pBitmap;D2D1_SIZE_F size = _pBitmap->GetSize();D2D1_RECT_F rc = D2D1::Rect<FLOAT>(                static_cast<FLOAT>(x - 0.5 * size.width),                static_cast<FLOAT>(y - 0.5 * size.height),                static_cast<FLOAT>(x + 0.5 * size.width),                static_cast<FLOAT>(y + 0.5 * size.height)                 );pRender->BeginDraw();

pRender->DrawBitmap(_pBitmap,rc,OPACITY); pRender->EndDraw();

Le code des étapes 9 à 11 se trouve dans le fichier DPEAnimationHelper.cpp ainsi que dans le fichier thumbnail.cpp.

Page 33: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Test de la solution.Enfin nous arrivons au bout de nos peines, il temps maintenant d’exécuter l’application AfficherImageBing.exe.Une fenêtre sur fond noir s’affiche, WOUAW !!

Tapez un mot clé, par exemple Windows 7

Puis la touche <Entrez>

Page 34: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Les images commencent à se charger. Vous remarquerez que leur affichage se fait au mileu de l’écran, c’est ce que nous avions prévu dans l’agent Display.

Une fois que toutes les images sont téléchargées, décodées, et stockées, l’animation commence.

Page 35: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

En retaillant la fenêtre, vous devriez voir des effets de mouvement d’images paraboliques.

Vous pouvez également naviguer dans les pages d’images à l’aide des touches flèche gauche et flèche droite. En appuyant sur la flèche droite s’il n’y a pas de page dans le cache, l’application en télécharge une nouvelle.

Si vous souhaitez modifier le nombre de vignette par page, ouvrez le fichier AfficherImageBing.config et modifiez la valeur de la clé NombreVignettes

<?xml version="1.0" encoding="utf-8"?><configuration>  <appSettings>    <add key ="NombreVignettes" value ="50"/>  </appSettings></configuration>

Page 36: download.microsoft.comdownload.microsoft.com/documents/France/MSDN/2011/Visual... · Web viewLes deux unités fondamentales d'une animation sont (1) la caractéristique d'un élément

Il est également possible de sauvegarder une image complète dans le répertoire courant de l’application, en cliquant sur le bouton droit de la souris au niveau d’une image.

ConclusionDans cet article nous avons vu, comment :développer une application Win32 en C++ avec une interface réactive qui ne se bloque pas lorsqu’un téléchargement est en cours, et comment utiliser les technologies suivantes :

Les librairies agent et parallèle de Visual Studio 2010 en lieu et place des threads. Les services de Microsoft Bing avec les API Windows Web Service API afin de télécharger les adresses

électroniques des images. L’API WinInet pour télécharger les données brutes des images. Windows Imaging Component pour décoder les images et en créer des bitmaps Direct2D Direct2D et DirectWrite pour afficher les images et du texte à l’écran en s’appuyant sur l’accélération

matériel. Et la plate-forme d’animation de Windows, pour un rendu fluide des images à l’écran avec des effets de

transitions.

Maintenant que vous avez le code source, rien ne vous empêche d’améliorer l’application, en ajoutant par exemple un module qui permettrait d’afficher sous forme de diaporama, cette fois-ci, non plus les vignettes, mais les images complète.

Eric Vernié

Article Powered by Windows Seven and Windows Live