Article technique

Alcinoe avec Delphi 11.1 Alexandria prenant en charge

· Programmation Delphi

Alcinoe Component Library, développé par Zeus64, est une bibliothèque open source de composants visuels et non visuels pour Delphi.

Lecteur vidéo OpenGL complet, wrapper Delphi pour WebRTC, TEdit natif pour iOS/Android, contrôles FireMonkey améliorés, messagerie cloud Firebase, SDK Facebook pour Android/iOS, analyseur Json/Bson, wrapper ImageMagick, client MongoDB.

Alcinoe est compatible avec Delphi Rio 10.3.3 et Delphi Sydney 10.4.2.
https://github.com/Zeus64/alcinoe

Avec Delphi Alexandria 11.1, support du téléchargement de MOD (supprimé).

Alcinoe est maintenant entièrement compatible avec Delphi Athens 12.3..

Installer Alcinoe.
Si vous ne prévoyez pas d'utiliser de composants visuels Alcinoe au moment de la conception, vous n'avez rien à installer, ajoutez simplement {alcinoe_rootdir}\source au chemin de recherche de votre projet.

Si vous prévoyez d'utiliser des composants visuels au moment de la conception, vous devez installer le BPL. Lancez Delphi et allez dans composant > Installer les packages... > et choisissez le fichier BPL situé dans {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\sydney\Alcinoe_sydney.bpl (si vous utilisez Delphi Sydney, sinon choisissez le répertoire correspondant à votre version de Delphi). Vous devez toujours ajouter {alcinoe_rootdir}\source à votre chemin de recherche.

Alcinoe améliore également légèrement les codes sources Delphi originaux. Pour ce faire, vous devez vous rendre dans {alcinoe_rootdir}\embarcadero\sydney\10_4_2 et exécuter update.bat pour récupérer et corriger le code source Delphi original. Le fichier batch suppose que le code source original est situé dans "c:\Program Files (x86)\Embarcadero\Studio\21.0\source" et que vous avez GIT dans votre chemin. Une fois que le fichier batch a été exécuté, le code source Delphi devra inclure ce code source dans le chemin de recherche de votre projet.

Pour finir, de plus en plus de bibliothèques utilisent les fonctionnalités de Java 1.8 (comme webRTC, exoplayer, etc.). Par conséquent, nous devons effectuer une "desucrage" (le "desucrage" vous permet d'utiliser ces fonctionnalités sur les appareils plus anciens en remplaçant les nouveaux bytecodes et les API de langage par des versions plus anciennes pendant le processus de construction). Avec d8.bat (remplacement de dx.bat), le "desucrage" est activé par défaut. Vous pouvez donc maintenant utiliser la plupart des dernières modifications du langage tout en ciblant les appareils plus anciens. En attendant qu'Embarcadero remplace dx.bat par D8.bat, nous devons faire de DX.bat un "proxy" pour D8.bat. Pour cela, remplacez simplement votre fichier DX.bat original (le mien est situé dans c:\SDKs\android\build-tools\30.0.3\d8.bat) par celui situé dans {alcinoe_rootdir}\tools\D8Proxy\dx.bat. Plus de détails ici : https://quality.embarcadero.com/browse/RSP-24155

Lecteur vidéo OpenGL complet pour FireMonkey.
ALVideoPlayer affiche une vidéo sur une TEXTURE. Ceci est très important car vous pouvez intégrer complètement la vidéo dans le formulaire Delphi et vous pouvez placer n'importe quel contrôle au-dessus de celle-ci, car elle prend en charge l'ordre Z. Les lecteurs vidéo Delphi officiels sont simplement des fenêtres de lecteur vidéo natives au-dessus du formulaire et ne prennent donc pas en charge l'ordre Z.

Sous Android, j'utilise ExoPlayer. ExoPlayer prend en charge des fonctionnalités telles que le streaming adaptatif dynamique via HTTP (DASH), HLS, SmoothStreaming et le chiffrement commun, qui ne sont pas pris en charge par MediaPlayer. Il est conçu pour être facile à personnaliser et à étendre. Sous iOS, j'utilise AVPlayer, qui prend également en charge HLS comme ExoPlayer.

Lecteur vidéo pour FireMonkey

Wrapper Delphi pour WebRTC.
WebRTC (Web Real-Time Communications) est une technologie qui permet aux applications et sites web de capturer et, éventuellement, de diffuser des médias audio et/ou vidéo, ainsi que d'échanger des données arbitraires entre les navigateurs et les applications mobiles, sans nécessiter d'intermédiaire. L'ensemble des normes qui composent WebRTC permet de partager des données et de réaliser des conférences en mode peer-to-peer, sans que l'utilisateur ait besoin d'installer des plugins ou d'autres logiciels tiers.

Le composant TALWebRTC facilite l'ajout de chat vidéo et audio dans vos applications, ce qui ouvre un tout nouveau monde d'interactivité.

Wrapper Delphi pour WebRTC.

Contrôles natifs iOS/Android TEdit et TMemo pour FireMonkey.
L'objectif est de combiner les contrôles FireMonkey avec les contrôles natifs de la plateforme lorsque la mise en œuvre de certaines fonctionnalités sur ces contrôles devient très difficile (comme les navigateurs web, les champs de texte, les zones de texte, les sélecteurs de date, etc.). Cependant, il ne s'agit pas de créer plusieurs formulaires distincts pour différentes plateformes, comme le propose par exemple http://www.turbococoa.com/ (mais cette option est également une bonne alternative, c'est à vous de décider).

Dans Delphi (berlin), il existe déjà des contrôles de plateforme iOS qui ont été bien implémentés, mais très peu de contrôles de plateforme Android, et c'est pourquoi j'ai commencé à créer des contrôles natifs Android/iOS tels que TEdit/TMemo. Ces contrôles fonctionnent principalement comme des fenêtres placées au-dessus du formulaire (donc, bien sûr, pas de gestion de l'ordre Z avec les contrôles FireMonkey).

Dessin

Dessin

Contrôles FireMonkey avec mise à jour rapide/double tampon et rendu natif.
Rectangle
Cercle
Texte (Peut également afficher du texte HTML sur iOS/Android/Windows/macOS)
Glyphe
etc.
TALRectangle

TALRectangle

Le fait
Le rendu des contrôles FireMonkey peut parfois être lent, ou, pour le dire autrement, pas suffisamment rapide pour un défilement fluide. Par exemple, si vous regardez simplement un TRectangle basique avec des coins arrondis, la procédure de rendu peut prendre environ 3 ms ! Donc, si vous avez environ 20 TRectangles visibles à l'écran, cela vous coûtera environ 60 ms pour redessiner toute l'écran (et normalement vous n'avez pas que des TRectangle, vous avez aussi TLabel, TCheckbox, etc.). Après, c'est simple : il faut 100 ms pour redessiner l'écran, donc vous ne pouvez afficher qu'environ 10 images par seconde (en réalité, vous en aurez beaucoup moins), et le défilement ne peut donc pas être fluide 🙁

La solution
Je ne voulais pas reconstruire les contrôles FireMonkey, c'est un travail beaucoup trop important pour moi, et au lieu de cela, j'ai essayé de trouver une solution intermédiaire. C'est ce que j'ai trouvé en ajoutant une propriété "double buffering" aux contrôles FireMonkey. Au lieu de redessiner et redessiner (et redessiner) les contrôles pour chaque pixel de mouvement de la barre de défilement, je dessine d'abord le contrôle sur un "buffer" que je stocke directement dans la mémoire de la GPU (via TTexture), et lorsque le système me demande de redessiner les contrôles, au lieu de rappeler l'algorithme de rendu, je redessine simplement le buffer TTexture.

Les résultats
Comme je l'ai dit précédemment, il faut 3 ms pour dessiner un simple TRectangle avec des coins arrondis. Avec ma propriété de double buffering, cela ne prend maintenant que 0,1 ms ! Le défilement est donc beaucoup plus fluide !

OpenGL draw => Remplacé par le rendu natif iOS/Android.
La plupart des formes de base (comme TRectangle, TCircle, etc.) utilisent OpenGL pour le rendu, ce qui n'est pas très efficace. Par exemple, pour dessiner un cercle avec OpenGL, vous dessinez en réalité 50 triangles. Cela se traduit souvent par une qualité médiocre : https://quality.embarcadero.com/browse/RSP-15206. Pour les rectangles arrondis, c'est encore pire, car vous devez d'abord calculer le chemin, puis le dessiner (beaucoup plus lent que TCircle).

Un autre problème est que tous ces rendus dépendent de Form.quality. Si vous définissez form.quality sur highquality, tout ce que vous faites sur la zone de dessin sera échantillonné, comme le dessin d'une image, ce qui peut être problématique car l'image sera anti-crénelée. Si vous définissez form.quality sur highperformance, le rendu sera très grossier (sans anti-crénelage).

Pour résoudre ce problème, j'utilise les API NATIVES ANDROID/IOS pour créer le tampon de mon contrôle. De cette façon, nous aurons un rendu de haute qualité, mais aussi une grande vitesse, sans dépendre de form.quality.

TALCircle

Amélioration des contrôles FireMonkey.
ScrollBox
TabControl
RangeTrackBar
RangeTrackBar

Lecteur vidéo pour FireMonkey

Animation de chute de confettis
ALConfetti est une bibliothèque Delphi simple pour créer une animation de chute de confettis configurable et performante.

confettis

Messagerie cloud Firebase
Une méthode multiplateforme pour utiliser Firebase Cloud Messaging (FCM) afin de recevoir des notifications push. Avec FCM, vous pouvez informer une application cliente que de nouveaux e-mails ou d'autres données sont disponibles pour la synchronisation. Vous pouvez envoyer des messages de notification pour encourager la réactivation et la fidélisation des utilisateurs. Pour des cas d'utilisation tels que la messagerie instantanée, un message peut transférer une charge utile allant jusqu'à 4 Ko à une application cliente.

Connexion via SDK VKontakte/Facebook pour Android/iOS.
Le SDK VKontakte/Facebook pour Android permet aux utilisateurs de se connecter à votre application via la connexion VKontakte/Facebook. Lorsque les utilisateurs se connectent à votre application via VKontakte/Facebook, ils peuvent accorder des autorisations à votre application afin que vous puissiez récupérer des informations ou effectuer des actions sur VKontakte/Facebook en leur nom.

Filtres d'éditeur de photos pour Android/iOS.
Avec TALColorAdjustEffect, des filtres photo magnifiques avec une amélioration automatique en un seul clic, rendez vos photos belles et expressives en quelques minutes !

Lecteur vidéo pour FireMonkey.

Analyseur JSON.
TALJsonDocument est un analyseur/rédacteur Delphi pour le format de données JSON / BSON. Il prend en charge les analyseurs DOM et SAX (notez qu'un meilleur nom pourrait être SAJ pour Simple API for JSON au lieu de SAX pour Simple API for XML, mais comme le concept de SAX est bien connu, je conserve ce nom), prend en charge le format BSON et utilise une syntaxe similaire à TALXMLDocument / TXMLDocument. TALJsonDocument peut également exporter des données Json / Bson dans TALStringList.

Lorsqu'il s'agit d'analyser du contenu (textuel), deux directions sont généralement envisagées. Dans le monde JSON, vous devez généralement choisir entre :

Un analyseur DOM, qui crée une structure arborescente en mémoire d'objets qui correspond au contenu JSON ;
Un analyseur SAX, qui lit le contenu JSON, puis déclenche des événements prédéfinis pour chaque élément du contenu JSON.
En fait, les analyseurs DOM utilisent en interne un analyseur SAX pour lire le contenu JSON. Par conséquent, en raison de la surcharge de création d'objets et de l'initialisation de leurs propriétés, les analyseurs DOM sont généralement trois à cinq fois plus lents que les analyseurs SAX (et utilisent beaucoup plus de mémoire pour stocker tous les nœuds). Cependant, les analyseurs DOM sont beaucoup plus puissants pour la manipulation des données : dès qu'ils sont mappés dans des objets natifs, le code peut accéder à n'importe quel nœud sans délai, tandis qu'un accès basé sur SAX doit relire l'intégralité du contenu JSON.

La plupart des analyseurs JSON disponibles dans Delphi utilisent une approche similaire à DOM. Par exemple, l'unité DBXJSON incluse depuis Delphi 2010 ou la bibliothèque SuperObject créent une instance de classe qui correspond à chaque nœud JSON. Pour obtenir les meilleures performances, TALJsonDocument implémente à la fois un analyseur DOM et un analyseur SAX.

TALJsonDocument peut également prendre en charge les commentaires dans le code source JSON, ce qui est une extension des spécifications JSON.

La syntaxe de TALJsonDocument est très similaire à celle de TALXMLDocument / TXMLDocument.

TALJsonDocument est disponible en 2 variantes : TALJsonDocument, qui est basé sur ansiString (donc UTF-8), et TALJsonDocumentU, qui est basé sur une chaîne Unicode (donc UTF-16).

Exemple :

{
_id: 1, // commentaires
name: { first: “John”, last: “Backus” },
birth: new Date('1999-10-21T21:04:54.234Z'),
contribs: [ “Fortran”, “ALGOL”, “Backus-Naur Form”, “FP” ],
awards: [
{ award: “National Medal of Science”,
year: 1975,
by: “National Science Foundation” },
{ award: "Turing Award",
year: 1977,
by: "ACM" }
],
spouse: "",
address: {},
phones: []
}
Pour accéder aux nœuds du document :

MyJsonDoc.loadFromJson(AJsonStr, False);
MyJsonDoc.ParseOptions := [poAllowComments]; // pour autoriser les commentaires dans le code source JSON.
MyJsonDoc.childnodes['_id'].int32;
MyJsonDoc.childnodes['name'].childnodes['first'].text;
MyJsonDoc.childnodes['name'].childnodes['last'].text;
MyJsonDoc.childnodes['birth'].datetime;
for i := 0 to MyJsonDoc.childnodes['contribs'].ChildNodes.count – 1 do
MyJsonDoc.childnodes['contribs'].childnodes[i].text;
for i := 0 to MyJsonDoc.childnodes['awards'].ChildNodes.count – 1 do begin
MyJsonDoc.childnodes['awards'].childnodes[i].childnodes['award'].text;
MyJsonDoc.childnodes['awards'].childnodes[i].childnodes['year'].text;
MyJsonDoc.childnodes['awards'].childnodes[i].childnodes['by'].text;
fin;
Ou, si vous n'êtes pas sûr de l'existence des nœuds avant d'y accéder, ou si vous ne voulez pas vérifier leur existence, vous pouvez également faire ceci :

MyJsonDoc.GetChildNodeValueInt32(' _id', 0{valeur par défaut si le nœud n'existe pas});
MyJsonDoc.GetChildNodeValueText(['name', 'first'], ""{valeur par défaut si le nœud n'existe pas});
MyJsonDoc.GetChildNodeValueDateTime('birth', Now{valeur par défaut si le nœud n'existe pas});
Pour créer les nœuds de document :

MyJsonDoc.addchild('_id').int32 := 1;
with MyJsonDoc.addchild('name', ntObject) do begin
addchild('first').text := 'John';
addchild('last').text := 'Backus';
fin;
MyJsonDoc.addchild('birth').dateTime := Now;
with MyJsonDoc.addchild('contribs', ntArray) do begin
addchild.text := ‘Fortran’;
addchild.text := ‘ALGOL’;
addchild.text := ‘Backus-Naur Form’;
addchild.text := ‘FP’;
fin;
with MyJsonDoc.addchild(‘awards’, ntArray) do begin
with addchild(ntObject) do begin
addchild(‘award’).text := ‘National Medal of Science’;
addchild('year').int32 := 1975;
addchild('by').text := 'National Science Foundation';
fin;
with addchild(ntObject) do begin
addchild('award').text := 'Turing Award';
addchild('year').int32 := 1977;
addchild('by').text := 'ACM';
fin;
fin;
MyJsonDoc.addChild('spouse');
MyJsonDoc.addChild('address', ntObject);
MyJsonDoc.addChild('phones', ntArray);
Vous pouvez également créer/mettre à jour des nœuds de cette manière :

MyJsonDoc.SetChildNodeValueInt32('_id', 0);
MyJsonDoc.SetChildNodeValueText(['name', 'first'], 'John');
MyJsonDoc.SetChildNodeValueDateTime('birth', Now);
Pour charger et enregistrer depuis BSON :

MyJsonDoc.LoadFromFile(aBSONFileName, False{saxMode}, True{BSON});
MyJsonDoc.SaveToFile(aBSONFileName, False{saxMode}, True{BSON});
Pour analyser un document JSON en mode SAX :

MyJsonDoc.onParseText := procedure (Sender: TObject;
const Path: AnsiString;
const name: AnsiString;
const Args: array of const;
NodeSubType: TALJSONNodeSubType) -> NodeSubType: TALJSONNodeSubType)
begin
case NodeSubType of -> cas NodeSubType de
nstFloat: Writeln(Path + ‘=’ + ALFloatToStr(Args[0].VExtended^, ALDefaultFormatSettings)); -> nstFloat: Writeln(Path + ‘=’ + ALFloatToStr(Args[0].VExtended^, ALDefaultFormatSettings));
nstText: Writeln(Path + ‘=’ + ansiString(Args[0].VAnsiString)); -> nstText: Writeln(Path + ‘=’ + ansiString(Args[0].VAnsiString));
nstObjectID: Writeln(Path + ‘=’ + ‘ObjectId(“‘+ALBinToHex(ansiString(Args[0].VAnsiString))+'”)’); -> nstObjectID: Writeln(Path + ‘=’ + ‘ObjectId(“‘+ALBinToHex(ansiString(Args[0].VAnsiString))+'”)’);
nstBoolean: Writeln(Path + ‘=’ + ALBoolToStr(Args[0].VBoolean,’true’,’false’)); -> nstBoolean: Writeln(Path + ‘=’ + ALBoolToStr(Args[0].VBoolean,'true','false'));
nstDateTime: Writeln(Path + ‘=’ + ALFormatDateTime(”’ISODate(“”yyyy”-”mm”-”dd”T”hh”:”nn”:”ss”.”zzz”Z”)”’, Args[0].VExtended^, ALDefaultFormatSettings)); -> nstDateTime: Writeln(Path + ‘=’ + ALFormatDateTime(”’ISODate(“”yyyy”-”mm”-”dd”T”hh”:”nn”:”ss”.”zzz”Z”)”’, Args[0].VExtended^, ALDefaultFormatSettings));
nstNull: Writeln(Path + ‘=’ + ‘null’);
nstRegEx: Writeln(Path + ‘=’ + ansiString(Args[0].VAnsiString));
nstBinary: Writeln(Path + ‘=’ + ‘BinData(‘+inttostr(Args[1].VInteger)+’, “‘+ansiString(ALBase64EncodeStringNoCRLF(ansiString(Args[0].VAnsiString)))+'”)’);
nstJavascript: Writeln(Path + ‘=’ + ansiString(Args[0].VAnsiString));
nstInt32: Writeln(Path + ‘=’ + ‘NumberInt(‘+inttostr(Args[0].VInteger)+’)’);
nstTimestamp: Writeln(Path + ‘=’ + ‘Timestamp(‘+inttostr(int64(cardinal(Args[0].VInteger)))+’, ‘+inttostr(int64(cardinal(Args[1].VInteger)))+’)’);
nstInt64: Writeln(Path + ‘=’ + ‘NumberLong(‘+inttostr(Args[0].VInt64^)+’)’);
fin;
fin;
MyJsonDoc.LoadFromJSON(AJsonStr, true{saxMode});
Wrapper Delphi pour ImageMagick.
Utilisez ImageMagick® pour créer, modifier, composer ou convertir des images bitmap. Il peut lire et écrire des images dans une variété de formats (plus de 200), notamment PNG, JPEG, GIF, HEIC, TIFF, DPX, EXR, WebP, Postscript, PDF et SVG. Utilisez ImageMagick pour redimensionner, retourner, inverser, faire pivoter, déformer, incliner et transformer des images, ajuster les couleurs des images, appliquer divers effets spéciaux ou dessiner du texte, des lignes, des polygones, des ellipses et des courbes de Bézier.

Exemple :

var aWand: PMagickWand;
begin

//Créer la bibliothèque ImageMagick.
alCreateImageMagickLibrary({alcinoe_rootdir} + ‘\lib\dll\imagemagick\win32\imagemagick’, min(2, System.CPUCount){aThreadLimit});
try

//créer le pointeur wand
aWand := ALImageMagickLib.NewMagickWand;
try

//charger l'image
if ALImageMagickLib.MagickReadImage(aWand, pansiChar(aInputFilename)) <> MagickTrue then RaiseLastMagickWandError(aWand);

//définir la qualité de compression
Si ALImageMagickLib.MagickSetImageCompressionQuality(aWand, 80) n'est pas égal à MagickTrue, alors RaiseLastMagickWandError(aWand);

//ajuster automatiquement la qualité de l'image
Si ALImageMagickLib.MagickAutoOrientImage(aWand) n'est pas égal à MagickTrue, alors RaiseLastMagickWandError(aWand);

//Redimensionner l'image en utilisant le filtre Lanczos
Si ALImageMagickLib.MagickResizeImage(aWand, 640, 480, LanczosFilter) n'est pas égal à MagickTrue, alors RaiseLastMagickWandError(aWand);

//enregistrer l'image
ALImageMagickLib.MagickWriteImage(aWand, pansiChar(aOutputFilename));

finally
ALImageMagickLib.DestroyMagickWand(aWand);
fin;

finally
alFreeImageMagickLibrary;
fin;

fin;

Client MongoDB
Client Delphi pour la base de données MongoDB. Un pilote Delphi (avec pool de connexions) pour accéder à un serveur mongoDB. Un pool de connexions est un cache de connexions de base de données maintenu afin que les connexions puissent être réutilisées lorsque de futures requêtes à la base de données sont nécessaires. Dans un pool de connexions, après qu'une connexion a été créée, elle est placée dans le pool et réutilisée afin qu'une nouvelle connexion n'ait pas à être établie. Si toutes les connexions sont utilisées, une nouvelle connexion est établie et ajoutée au pool. Le pool de connexions réduit également le temps qu'un utilisateur doit attendre pour établir une connexion à la base de données.

Exemple :

aJSONDoc := TALJSONDocument.create;
aMongoDBClient := TAlMongoDBClient.create;
try
aMongoDBClient.Connect("", 0);
aMongoDBClient.SelectData('test.exemple',
'{fieldA:123}', // la requête
‘{fieldA:1, fieldB:1}’, // les champs à renvoyer
aJSONDoc.node);
aMongoDBClient.disconnect;
for i := 0 to aJSONDoc.node.childnodes.count – 1 do
with aJSONDoc.node.childnodes[i] do
writeln(aJSONDoc.node.childnodes[i].nodename + ‘=’ + aJSONDoc.node.childnodes[i].text)
finally
aMongoDBClient.free;
aJSONDoc.free;
fin;
Exemple avec pool de connexions :

aMongoDBConnectionPoolClient := TAlMongoDBConnectionPoolClient.create(aDBHost, aDBPort);
try

::Thread1::
aMongoDBConnectionPoolClient.SelectData('test.example',
'{fieldA:123}', // la requête
‘{fieldA:1, fieldB:1}’, // les champs à renvoyer
aLocalVarJSONDOC.node);

::Thread2::
aMongoDBConnectionPoolClient.SelectData('test.example',
'{fieldA:999}', // la requête
‘{fieldA:1, fieldB:1}’, // les champs à renvoyer
aLocalVarJSONDOC.node);

finally
aMongoDBClient.free;
fin;
Exemple de surveillance des journaux :

aMongoDBTailMonitoringThread := TAlMongoDBTailMonitoringThread.Create(
aDBHost,
aDBPort,
‘test.cappedCollectionExemple’
‘{}’, // la requête
‘{fieldA:1, fieldB:1}’, // les champs à renvoyer

Procédure (Sender: TObject; JSONRowData: TALJSONNode)
begin
writeln('Nouvel élément ajouté dans cappedCollectionExemple: ' + JSONRowData.childnodes['fieldA'].text);
end,

procédure (Sender: TObject; Error: Exception)
begin
writeln(Error.message);
end);
….
aMongoDBTailMonitoringThread.free;
Client WebSocket
Client WebSocket pour Delphi, implémenté sur WinHTTP. WebSocket est un protocole de communication qui permet d'ouvrir une session de communication interactive bidirectionnelle entre le navigateur de l'utilisateur et un serveur. Cela vous permet d'envoyer des messages à un serveur et de recevoir des réponses basées sur des événements sans avoir à interroger le serveur pour une réponse.

Fast TStringList
TALStringList fonctionne de la même manière que TStringList de Delphi, sauf qu'il permet de rechercher un nom=valeur en utilisant un algorithme de tri rapide lorsque la liste est triée. De plus, TALStringList utilise un algorithme indépendant de la locale (basé sur la valeur ordinale 8 bits de chaque caractère) au lieu de AnsiCompareText et AnsiCompareStr utilisés par le TStringList de Delphi. Par conséquent, le tri dans TALStringList est jusqu'à 10 fois plus rapide que dans TStringList de Delphi. De plus, TALStringList n'est pas un TStringList Unicode, mais une liste de chaînes 100 % ANSI.

TALNVStringList (NV pour NameValue) est identique à TALStringList (utilise également un algorithme de tri rapide), sauf qu'ici, l'optimisation est axée sur les listes de noms/valeurs plutôt que sur les listes de chaînes.

TALHashedStringList TALHashedStringList est identique à TALStringList, sauf qu'il utilise une table de hachage interne au lieu d'un algorithme de tri rapide. En utilisant TALHashedStringList au lieu de TALStringList, vous pouvez améliorer les performances lorsque la liste contient un grand nombre de chaînes (sinon, si votre liste ne contient pas beaucoup de chaînes, les performances sont inférieures à celles de TALStringList en raison du coût du calcul du hachage).

Exécutable PHP
ALPHPRunnerEngine est un composant simple mais utile pour utiliser facilement PHP (n'importe quelle version) comme langage de script dans les applications Delphi. ALPHPRunnerEngine permet d'exécuter les scripts PHP au sein du programme Delphi sans serveur Web. ALPHPRunnerEngine utilise l'interface CGI/FastCGI de PHP (php-cgi.exe) pour communiquer avec le moteur PHP.

Client Memcached
Client Delphi pour la base de données memcached.

Qu'est-ce que Memcached ? Système de cache d'objets mémoire distribué, open source et haute performance, de nature générique, mais destiné à accélérer les applications web dynamiques en réduisant la charge de la base de données.

Memcached est un magasin de clés-valeurs en mémoire pour de petits morceaux de données arbitraires (chaînes de caractères, objets) provenant des résultats des appels de base de données, des appels d'API ou du rendu de pages.

Memcached est simple mais puissant. Sa conception simple favorise un déploiement rapide, une facilité de développement et résout de nombreux problèmes liés aux caches de données volumineuses.

Composant GSM
Le composant TAlGSMComm implémente l'envoi de messages texte SMS via l'interface en mode texte définie dans la spécification technique GSM 07.05, version 5.1.0, datée de décembre 1996. Il existe plusieurs variations de cette spécification, utilisées dans les modèles Nokia, Siemens, Ericsson, etc. Nous avons testé le Nokia 6230 en interne, mais les modèles Nokia 7190, 8890, 6210 et 9110 devraient également fonctionner. Les téléphones d'autres fabricants fonctionneront également, à condition qu'ils implémentent l'interface en mode texte. Environ 1/4 des téléphones actuels peuvent être connectés à un PC (par IR ou câble série), environ 1/3 de ceux-ci sont uniquement en mode texte, 1/3 sont uniquement en mode PDU et les autres 1/3 prennent en charge à la fois le mode texte et le mode PDU. Certains téléphones (comme le Nokia 5190) prennent en charge les SMS, mais ils utilisent un protocole propriétaire, que TALGSMComm ne prend pas en charge.

Pour tester votre téléphone, connectez-le à votre PC via le câble série ou le périphérique IR (consultez la documentation de votre téléphone pour plus de détails sur la façon de vous connecter). Entrez "AT" dans une fenêtre de terminal pour vérifier que la connexion est établie (vous devriez recevoir "OK" du téléphone), puis entrez "AT+CMGF=?". La réponse doit contenir un "1", indiquant qu'il prend en charge le mode texte. Si ces deux tests réussissent, alors votre téléphone répond aux exigences de base.

Client SQLite3
Interrogez la base de données SQLite3 et obtenez le résultat au format XML ou au format JSON/BSON.

Et bien plus encore.
Exécuteur CGI
Client HTTP (WinInet/WinHTTP)
Client MySQL
Client NNTP
Client POP3
Client SMTP
Analyseur XML

WIN64
Malheureusement, dans win64, nous avons perdu toute l'héritage de FastCode (qui était principalement basé sur l'assembleur). Cela signifie que la plupart des fonctions seront 2 à 10 fois plus lentes. Vous pouvez essayer de lancer /demo/ALStringBenchMark/ dans win64 et Win32 pour voir la différence de vitesse.