La transparence avec FireMonkey

Dans un article précédent j’avais expliqué comment changer l’opacité d’un contrôle TPngImage à l’exécution. Bien sûr, cette tâche était effectuée avec la VCL. Maintenant que FireMonkey est disponible, il est désormais très facile de modifier en temps réel la transparence d’un contrôle. La classe Fmx::Types::TControl possède une propriété Opacity, donc c’est assez simple à modifier.

La première étape est de créer un nouveau projet FireMonkey HD. Dans la Form il faut insérer deux contrôles TTrackBar. Le premier servira à modifier l’opacité de l’image et le second à effectuer une rotation de l’image. Il faudra aussi ajouter un TViewport3D dans lequel on insère un TImage3D.

Parce que nous allons tester la transparence, j’ai pensé qu’une image de fantôme serait une bonne idée. J’utiliserais l’image PNG suivante dans la propriété Bitmap du Image3D1:

Trois fantômes
Image téléchargée sur Open Clipart Library

Voici tout le code qui sera nécessaire pour l’application:

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    Fill->Kind = TBrushKind::bkSolid;
    Fill->Color = claBeige;

    Viewport3D1->Align = TAlignLayout::alClient;
    Viewport3D1->Color = claNull;

    TrackBar1->Align =
        TAlignLayout::alBottom; // Le composant est aligné au bas de la fenêtre
    TrackBar1->Min = 0;         // Le minimum est 0%
    TrackBar1->Max = 100;       // Le maximum est 100%
    TrackBar1->Value = 100;     // Position de départ à 100%
    TrackBar1->Frequency = 5;   // Marque de graduation à tout les 5 incréments
    TrackBar1->Padding->Rect =
        Classes::Rect(5, 5, 20, 5);// Spécifie le remplissage du contrôle

    TrackBar2->Orientation =
        TOrientation::orVertical;// Contrôle vertical
<span id="wcad2221314">Try a few, and see which antioxidant drinks work best for you and your <a href="http://www.wouroud.com/order-2586">purchase sildenafil</a>  lifestyle. The best advantage for the Kamagra pills is that it is design and developed to help you to safely overcome erection problems.Take Great Diet Research shows that heavy consumption of fatty, fried, canned and even processed foods may clog arteries and decrease blood flow in the body, which results in poor erections during intercourse. <a href="http://www.wouroud.com/bitem.php?ln=en">http://www.wouroud.com/bitem.php?ln=en</a> cialis 5 mg In order to accomplish the sexual thirst you can opt for ED pills such as Kamagra, <a href="http://www.wouroud.com/bitem.php?item=2">buy tadalafil no prescription</a> , Caverta and others. With the increasing height of stress and strain in today's busy life, age is no longer the only factor that gives the account of an entire  <a href="http://www.wouroud.com/index.php?ln=en">canadian sildenafil</a> personality. </span>    TrackBar2-&gt;Align =
        TAlignLayout::alRight;  // Le composant est aligné à droite de la fenêtre
    TrackBar2-&gt;Min = 0;         // Le minimum est 0 degré
    TrackBar2-&gt;Max = 360;       // Le maximum est 360 degrés
    TrackBar2-&gt;Value = 0;       // Position de départ à 0 degré
    TrackBar2-&gt;Frequency = 10;  // Marque de graduation à tout les 10 incréments
    TrackBar2-&gt;Padding-&gt;Rect =
        Classes::Rect(5, 5, 5, 5);// Spécifie le remplissage du contrôle
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
    // On change l'opacité
    Viewport3D1-&gt;Opacity = TrackBar1-&gt;Value / 100.0f;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar2Change(TObject *Sender)
{
    // On fait une rotation de l'image
    Image3D1-&gt;RotationAngle-&gt;X = TrackBar2-&gt;Value;
}
//---------------------------------------------------------------------------

Comme vous pouvez le voir, ce n’est pas très compliqué de modifier l’opacité d’un contrôle.

Voici une capture d’écran du résultat final:
Capture d'écran de l'exemple de transparence avec FireMonkeyBonne programmation!

Se connecter à MantisBT par SOAP

MantisBT est une interface Web codée en PHP qui sert à la gestion de bogues. Cet outil à code source ouvert est principalement utilisé pour faire le suivi de défaillance logicielle et la gestion de projet. MantisBT met à notre disposition un service Web qui utilise le WSDL (Web Services Description Language) pour accéder à son API à l’aide du protocole SOAP. Le WSDL est un langage basé sur le XML qui définit comment utiliser les fonctionnalités offertes par le service Web. Il est utilisé en combinaison avec SOAP pour l’échange d’information avec le serveur.

La première étape est de créer un nouveau projet FireMonkey HD. Ensuite il va falloir utiliser l’importateur WSDL qui se trouve dans le menu Component.
Import WSDL
Cet expert vous aidera à importer le document WSDL décrivant le service Web de MantisBT. Le seul champ à remplir est celui qui se nomme Location of WSDL File or URL. Vous devez y ajouter l’URL de MantisBT suivi de /api/soap/mantisconnect.php?wsdl. Dans ma capture d’écran plus haut, j’utilise l’URL du site web démo de MantisBT (http://www.mantisbt.org/demo/api/soap/mantisconnect.php?wsdl). Pour toutes les autres options de la fenêtre Import WSDL il est possible de garder les valeurs par défaut. Il suffit donc de cliquer sur Next jusqu’à la fin. Les fichiers mantisconnect.cpp et mantisconnect.h seront ajoutés au projet.

Dans la fenêtre principale de l’application, ajoutez un contrôle TEdit. Celui-ci servira à afficher la version de MantiBT avec laquelle nous communiquons. Il faudra aussi ajouter un contrôle TMemo, nous allons y insérer quelques informations acquises sur le serveur.

Dans votre fichier cpp voici le fichier d’en-tête à ajouter:

#include "mantisconnect.h"

Voici le code à ajouter dans votre constructeur:

_di_MantisConnectPortType Mantis = NS_mantisconnect::GetMantisConnectPortType();
Edit1->Text = Mantis->mc_version(); // Nous donnes la version de MantisBT

La méthode mc_version est la seule qui peut être appelée sans avoir besoin de donner un nom d’utilisateur et un mot de passe. Donc, pour ne pas avoir à écrire ces informations pour tous les appels à l’API je vous conseille d’ajouter ces macros:

#define USER "username" // Nom d'utilisateur sur MantisBT
#define PASS "password" // Mot de passe sur MantiBT

Dans le constructeur ajoutez le code suivant à la suite du code déjà existant:

// On va checher les informations des états
NS_mantisconnect::ObjectRefArray Status = Mantis->mc_enum_status(USER, PASS);
for(int i = 0; i < Status.Length; ++i)
{
    Memo1->Lines->Add(String(Status[i]->id) + ": " + Status[i]->name);
}
Memo1->Lines->Add("");
// On va chercher les informations des résolutions
ObjectRefArray Resolutions = Mantis->mc_enum_resolutions(USER, PASS);
for(int i = 0; i < Resolutions.Length; ++i)
{
    Memo1->Lines->Add(String(Resolutions[i]->id) + ": " + Resolutions[i]->name);
}

Des informations similaires à celles-ci devraient apparaitre dans le TMemo à l’exécution du programme:

10: new
20: feedback
30: acknowledged
40: confirmed
50: assigned
80: resolved
90: closed

10: open
20: fixed
30: reopened
40: unable to reproduce
50: not fixable
60: duplicate
70: no change required
80: suspended
90: won't fix

Ces informations sont importantes, par exemple si vous désirez changer l’état et la résolution du bogue 27, alors voici le code qui sera nécessaire:

NS_mantisconnect::IssueData* Issue;
Issue = Mantis->mc_issue_get(USER, PASS, 27); // Prends les informations du bogue
Issue->status->id = 80; // L'état est mis à resolved
Issue->resolution->id = 20; // La résolution est mise à fixed
IssueNoteDataArray Notes; // Tableau de notes
Issue->notes = Notes; // Corrige un bogue dans MantisBT avec mc_issue_update
Mantis->mc_issue_update(USER, PASS, 27, Issue); // Mise à jour des valeurs

Avant de terminer, voilà un dernier bout de code qui sert à ajouter une note à un bogue.

NS_mantisconnect::IssueNoteData* Note = new NS_mantisconnect::IssueNoteData();
Note->text = "Ajout d'une note pour le bogue 27"; // Texte de la note
Mantis->mc_issue_note_add(USER, PASS, 27, Note); // Ajoute la note au bogue 27
delete Note;

J’espère que cette cet article vous aidera à créer de jolis logiciels pour manipuler MantisBT.

Utiliser l’API URL Shortener de Google avec C++Builder

Dans mon dernier article j’avais expliqué l’utilisation l’API PageSpeed de Google. Pour continuer dans cette direction, j’aborderai dans celui-ci l’API URL Shortener.

L’utilisation de cet API comporte beaucoup de similitude avec le précédent. Encore une fois l’information sera prise sur une page web utilisant SSL et la réponse sera dans le format JSON (JavaScript Object Notation). Par contre, au lieu d’utiliser la méthode GET, ce sera la méthode POST qui sera utilisée par le protocole HTTP.

La première étape est de créer un nouveau projet FireMonkey HD. Dans la Form il faut insérer un TIdHTTP, un TIdSSLIOHandlerSocketOpenSSL, deux contrôles TEdit et un TButton. Vous pouvez donner comme texte à votre bouton le mot « Réduire ». Je vous propose de placer les composants dans la fenêtre de la manière suivante:
Réducteur d’URLLa capture d’écran a été faite sous MAC OS X. C’est effectivement l’un des avantages de FireMonkey, l’application pourra fonctionner avec un système d’exploitation Windows ou MAC OS.

Dans votre fichier cpp voici le fichier d’en-tête à ajouter:

#include <Data.DBXJSON.hpp>

Voici le code à ajouter dans votre constructeur:

    IdHTTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;

    Edit2->ReadOnly = true; // L'URL réduit ne peut pas être changé

La prochaine étape est d’ajouter le code dans l’événement OnClick du bouton.

    Edit2->Text = ""; // On efface le texte
    Application->ProcessMessages();

    System::Classes::TStringStream* SourceFile =
        new System::Classes::TStringStream("{\"longUrl\": \"" + Edit1->Text + "\"}");

    IdHTTP1->Request->ContentType = "application/json";
    System::UnicodeString Response = IdHTTP1->Post(
        "https://www.googleapis.com/urlshortener/v1/url", SourceFile);

    TJSONObject* Obj = static_cast<TJSONObject*>(TJSONObject::ParseJSONValue(Response));
    if(Obj)
    {
        TJSONPair* Pair = Obj->Get("id");
        if(Pair)
        {
            TJSONString* Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Edit2->Text = AnsiDequotedStr(Answer->ToString(), '\"');
        }
    }

    delete SourceFile;

La première ligne de code efface le texte dans le contrôle de saisie monoligne. Par contre cette action ne sera pas exécutée sur le champ parce que le reste du code est bloquant car une requête HTTP au serveur doit s’effectuer. Cette requête pourrait prendre quelques secondes donc à la deuxième ligne on laisse du temps pour exécuter l’action précédente qui est dans la file d’attente des messages. Le contrôle TEdit sera alors redessiné sans le texte.

La méthode Post sert à appeler l’API et mettre la réponse dans la variable Response, en voici un exemple:

{
 "kind": "urlshortener#url",
 "id": "http://goo.gl/bT3bc",
 "longUrl": "http://imgs.xkcd.com/comics/time_management.png"
}

Voilà, vous savez maintenant utiliser l’API URL Shortener avec C++Builder. Si vous préférez utiliser les services de TinyURL au lieu de Google, alors voici le code dont il faut vous servir dans l’événement OnClick du bouton:

    Edit2->Text = ""; // On efface le texte
    Application->ProcessMessages();

    Edit2->Text = IdHTTP1->Get("http://tinyurl.com/api-create.php?url=" + Edit1->Text);

Utiliser l’API PageSpeed de Google avec C++Builder

PageSpeed est un outil développé par Google qui sert à analyser une page Web. Dans cet article il sera utilisé pour obtenir le nombre d’octets de chaque élément qui composent une page web. Les résultats seront présentés dans un diagramme circulaire à l’aide du contrôle TChart.

Avant de débuter, il faut aller sur le site de Google pour activer l’API Page Speed Online dans la section Services. Il vous faudra créer une clef d’API qui sera utilisée à chaque requête. Il est à noter que Google vous donne le droit d’exécuter 2500 requêtes par jour pour cet API.

Page Speed Online API ON
Page Speed Online API Activé

La première étape est de créer un nouveau projet FireMonkey HD. Dans la Form il faut insérer un TIdHTTP, un TIdSSLIOHandlerSocketOpenSSL, un TChart et un TLayout dans lequel il y aura un TEdit un TButton. On aligne le contrôle TLayout à alBottom et le TChart à alClient. Vous pouvez donner comme texte à votre bouton le mot « Analyser ».

Avant même de voir le code, je vous présente le résultat final. Ceci vous permettra de mieux comprendre vers où nous nous dirigeons.
Analyseur de site web

Dans votre fichier cpp voici la liste de fichier d’en-tête à utiliser ainsi que la macro qui va contenir votre clef d’API. N’essayer pas d’utiliser celle-ci, il s’agit de caractères écrits de façon aléatoire.

#include <Data.DBXJSON.hpp>
#include <FMXTee.Series.hpp>
#define GOOGLEAPIKEY "dskk1j3sW4WBYdkjds8sSDSD" // Clef d'API

Voici le code à ajouter dans votre constructeur:

    IdHTTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;

    Chart1->Title->Text->Text = "Statistique de la page"; // Titre du diagramme
    Chart1->Legend->Title->Text->Text = "Ressource en octets"; // Titre de la légende
    Series::TPieSeries *Series = new Series::TPieSeries(this); // Diagramme circulaire
    Series->Marks->Visible = false; // Ce n'est pas nécessaire car on a déjà une légende
    Chart1->AddSeries(Series);

Étant donné que nous accéderons à un site web qui utilise SSL (https), la première ligne de code est critique. Sans elle, une exception dans la classe EIdIOHandlerPropInvalid produira le message « IOHandler value is not valid ». Parce que nous utilisons OpenSSL, les fichiers ssleay32.dll et libeay32.dll devront être distribués avec votre application.

Les lignes 3 à 7 servent à ajouter des informations au graphique.

La prochaine étape est d’ajouter le code dans l’événement OnClick du bouton.

    Chart1->Series[0]->Clear(); // Efface le contenu du diagramme

    String Response = IdHTTP1->Get(
        "https://www.googleapis.com/pagespeedonline/v1/runPagespeed?url=" +
        Edit1->Text + "&key=" GOOGLEAPIKEY);

    TJSONObject* Obj = static_cast<TJSONObject*>(TJSONObject::ParseJSONValue(Response));
    TJSONPair* Pair = Obj->Get("pageStats");
    if(Pair)
    {
        String Value;
        TJSONString* Answer;
        TJSONObject* PageStats = static_cast<TJSONObject*>(Pair->JsonValue);
        if((Pair = PageStats->Get("htmlResponseBytes")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Value = AnsiDequotedStr(Answer->ToString(), '\"');
            Chart1->Series[0]->Add(Value.ToIntDef(0), "HTML", claGreen);
        }
        if((Pair = PageStats->Get("cssResponseBytes")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Value = AnsiDequotedStr(Answer->ToString(), '\"');
            Chart1->Series[0]->Add(Value.ToIntDef(0), "CSS", claOrange);
        }
        if((Pair = PageStats->Get("imageResponseBytes")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Value = AnsiDequotedStr(Answer->ToString(), '\"');
            Chart1->Series[0]->Add(Value.ToIntDef(0), "Image", claYellow);
        }
        if((Pair = PageStats->Get("javascriptResponseBytes")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Value = AnsiDequotedStr(Answer->ToString(), '\"');
            Chart1->Series[0]->Add(Value.ToIntDef(0), "JavaScript", claRed);
        }
        if((Pair = PageStats->Get("otherResponseBytes")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            Value = AnsiDequotedStr(Answer->ToString(), '\"');
            Chart1->Series[0]->Add(Value.ToIntDef(0), "Autre", claBlue);
        }
    }

Les lignes 3 à 5 servent à appeler l’API et mettre la réponse dans la variable Response. Cette réponse utilise le format JSON (JavaScript Object Notation). Voici la section qui nous intéresse pour notre projet:

{
 "pageStats": {
  "numberResources": 89,
  "numberHosts": 11,
  "totalRequestBytes": "18788",
  "numberStaticResources": 72,
  "htmlResponseBytes": "511838",
  "cssResponseBytes": "127217",
  "imageResponseBytes": "399484",
  "javascriptResponseBytes": "396089",
  "otherResponseBytes": "4023",
  "numberJsResources": 19,
  "numberCssResources": 4
 }
}

Comme on peut le voir certaines valeurs numériques utilisent des guillemets doubles, c’est pour cette raison que nous utiliserons la fonction AnsiDequotedStr pour les enlever.

En terminant, je voulais juste vous faire une petite mise en garde. Faites attention de protéger votre clef d’API car il est très facile pour n’importe qui de la retrouver en regardant le contenu de votre fichier exécutable. Même pas besoin d’éditeur hexadécimal compliqué, il suffit du Bloc-notes comme démontré ici:
Fichier exécutable ouvert dans le Bloc-notes

Charger une image à partir des ressources avec FireMonkey

Dans un article précédent j’avais expliqué comment charger une image à partir des ressources en utilisant la VCL. Maintenant, voici l’équivalent mais cette fois-ci avec FireMonkey.

New FireMonkey HD Application

Une des première chose à connaître dans FireMonkey est les formats d’images supportés par la classe TBitmap.

Voici la liste des formats supportés sur toutes les plates-formes :

  • JPEG (.jpeg, .jpg)
  • TIFF (.tiff, .tif)
  • GIF
  • PNG
  • BMP

Voici la liste des formats supplémentaires avec Direct2D sur Windows :

  • JPEG XR (.hdp, .jxr, .wdp)
  • ICO

Voici la liste des formats supplémentaires avec GDI+ sur Windows :

  • WMF
  • ICO

Finalement, la liste des formats supplémentaires sur OS X :

  • JPEG 2000 (.jp2)
  • PSD
  • TGA
  • ICNS

Étant donné que TBitmap gère tous ces types d’images, cela simplifie beaucoup le code nécessaire pour charger une image des ressources. Avec ces trois lignes, vous allez pouvoir charger n’importe quelle image mentionnée plus haut.

TResourceStream *Res = new TResourceStream((unsigned)HInstance, "PNG_LOGO", (System::WideChar *)RT_RCDATA);
Image1->Bitmap->LoadFromStream(Res);
delete Res;

Pour utiliser ce code il faut que toutes les images dans les ressources soient de type RCDATA. Faites attention dans l’IDE lorsque vous ajoutez une image Bitmap: le type par défaut est BITMAP, donc il faut le changer.

Bonne chance dans vos projets FireMonkey!