I. Introduction

Delphi 2009 avait frappé fort en proposant de nombreuses nouveautés techniques (Unicode, génériques, méthodes anonymes, etc...).
Cette année, l'équipe de CodeGear a décidé d'améliorer un ensemble de petits points, un peu à la manière d'un tisserand (Weaver en anglais, le nom de code de Delphi 2010) qui assemblerait les petites mailles pour former la belle robe.
Deux axes majeurs peuvent se tracer : le souhait de répondre aux attentes de ses utilisateurs (représenté par de nombreux ajouts dans l'EDI, corrections de bugs, etc...) et la préparation vers l'avenir (comme le framework de Gesturing, le mot clé delayed, etc..).
Un bémol cependant car la compatibilité 64 bits (projet Commodore) ainsi que le cross-platform (projet X) n'ont pas pu être intégrés à cette version.
Voici l'EDI tel qu'il apparaît en standard :

Image non disponible
Bureau standard

Beaucoup d'utilisateurs ont toujours été frileux d'abandonner leur Delphi 7, notamment à cause de l'interface. Delphi 2010 se veut être la version de la réconciliation puisque l'utilisateur peut personnaliser l'EDI pour qu'il ressemble un maximum à ce qui se faisait sous Delphi 7 comme le montre ce bureau remanié par mes soins :

Image non disponible
Bureau "façon D7"

II. Nouveautés dans l'EDI

Nous allons maintenant présenter les différentes nouveautés de l'EDI.

II-A. IDE Insight

La plus importante des nouveautés, l'IDE Insight est la fonctionnalité qui répond à la problématique : "j'ai le nom d'un truc mais je ne sais plus où c'est".
En clair, appuyez sur F6 et rentrez le nom (même partiellement) et Delphi se charge de retrouver tout ce qui pourrait correspondre.
De nombreuses informations présentes dans l'EDI sont analysées ce qui comprend : les actions menus, les fichiers projets, les composants sur la palette, les modèles de code et même les options de l'EDI ou du projet.

Image non disponible
L'IDE Insight

II-B. Formateur de code

Jusqu'à présent, le formatage de code a toujours été assuré par un plugin externe. Aujourd'hui c'est terminé, l'EDI se dote enfin d'un formateur de code en standard, complètement personnalisable. Un petit coup de CTRL+ALT+F et votre code est formaté.

II-C. Recherche intégrée

La recherche à l'intérieur d'un fichier est maintenant intégrée à la fenêtre d'édition de code comme le montre la capture ci-dessous :

Image non disponible
Fonction de recherche intégrée à l'éditeur de code

Bien sûr la recherche multi-fichiers est toujours disponible, il faut maintenant utiliser le raccourcit CTRL+SHIFT+F.

II-D. Palette des composants

Une des grandes différences entre Delphi 7 et les versions supérieures fut de faire passer la palette des composants horizontale vers une fenêtre indépendante "verticale". Ce changement d'interface ayant même été un critère pour ne pas passer à une version plus évoluée de Delphi pour certains utilisateurs. Avec Delphi 2010, la palette horizontale fait son grand retour en plus du système "vertical" afin de contenter tout le monde.
Absente par défaut, il suffit de faire un clic droit sur la barre principale de l'EDI et de cocher "Composants" pour faire apparaître la fameuse barre horizontale.

II-E. Explorateur de classes pour C++ Builder

L'explorateur de classes de C++ Builder a été complètement réécrit pour correspondre aux attentes des utilisateurs.
La fenêtre présente la liste complète de toutes les classes avec possibilité de les grouper de différentes façon et même de créer et sauvegarder vos propres groupes.
En cliquant sur un élément vous avez la possibilité d'aller voir sa définition ou bien les endroits où il est utilisé.
Enfin le clic droit vous permet d'effectuer différentes actions dont l'ajout de champs, méthodes et propriétés à votre classe.

III. Débogueur

Cette section va vous présenter les nouveautés apportées au débogueur.

III-A. Déboguer les threads

L'une des nouveautés phare concernant le débogueur est sa capacité à maintenant déboguer plus efficacement les threads.
En effet comme le montre la capture ci-dessous, il est maintenant possible de rattacher un point d'arrêt à un thread particulier.

Image non disponible
Associer un point d'arrêt à un thread

La liste des threads disponibles évolue au fur et à mesure que le programme instancie et termine des threads.
Attention cependant, par défaut sera affiché l'id du thread qui, par nature, changera d'une instanciation à l'autre. Néanmoins vous pouvez associer un nom de débogage à un thread au moyen de la nouvelle méthode NameThreadForDebugging. Il est bien sûr hautement conseillé de le faire.
En effet le lien entre un point d'arrêt et un thread est matérialisé par une simple chaîne (id ou nom de débogage) qui est conservée dans le paramétrage du point d'arrêt d'une exécution à l'autre. De fait, si votre thread porte le même nom de débogage, le point d'arrêt se "souvient" de ne s'arrêter que pour ce thread en particulier à chaque exécution.
Il est également possible de visualiser l'ensemble des threads de l'application et surtout de pouvoir les figer et les libérer à volonté si vous ne voulez voir l'exécution que de quelques threads en particulier.

Image non disponible
Visualiser et agir sur les threads

L'appel à NameThreadForDebugging peut se faire à n'importe quel moment, vous pouvez même l'appelez de l'extérieur du thread.
Néanmoins gardez en mémoire que tant que la méthode ne sera pas appelée vous ne pourrez voir que l'id du thread au niveau du débogueur. Le mieux étant donc de l'appeler au niveau du constructeur ou bien de la méthode Execute du thread.

III-B. Visualiseurs

Le débogueur se dote de visualiseurs qui lui permettent d'afficher l'élément inspecté de manière plus efficace.
Pour le moment il n'existe que deux visualiseurs : pour les TStrings et les TDateTime.

Image non disponible
Image non disponible
Image non disponible

Il est possible de rajouter des visualiseurs personnalisés à l'EDI via les API Open Tools.

IV. RTTI

Le système de RTTI a été complètement révisé et apporte son lot de nouveautés comme les attributs. Voyons cela plus en détails.

IV-A. Extensions des possibilités

Une nouvelle unité, RTTI.pas, a fait son apparition et contient toutes les fonctionnalités liées au RTTI. Rassurez-vous TypInfo.pas est toujours là et ses routines n'ont pas bougé de place car le nouveau système utilise désormais comme point d'entrée un record : le TRttiContext.
Le nombre de choses couvertes par les RTTI a sensiblement augmenté mais surtout il n'est plus obligatoire que les éléments soient déclarés en publié.
Via le TRttiContext on peut maintenant avoir accès à toutes les propriétés, champs, méthodes mais aussi les classes parentes et même les packages où est définie la classe.
Le nouveau système apporte aussi beaucoup de possibilités de recherche par nom des différents éléments plutôt que de faire les parcours nous-même.

IV-B. Les attributs

Un attribut est conceptuellement une sorte d'annotation que le développeur ajoute au niveau de la déclaration d'une classe, d'une méthode ou d'une propriété.
On peut ensuite y accéder au moment de l'exécution via le nouveau système de RTTI.
Voici comment procéder.

IV-B-1. Déclaration d'un attribut

Un attribut est une classe qui doit hériter de la classe de base TCustomAttribute et doit se terminer par 'Attribute'. Par exemple :

 
Sélectionnez

TFieldAliasAttribute = class(TCustomAttribute)
private
 FAliasName: String;
public
 Constructor Create( const AAliasName: String );

 property AliasName: String read FAliasName;
end;

Ses propriétés ne peuvent être que des types simples, pas d'objet ou de record.

IV-B-2. Affectation d'un attribut

Un attribut s'ajoute au niveau d'une classe, d'une méthode ou d'une propriété de la manière suivante (ici pour une propriété) :

 
Sélectionnez

TEntity = class(TObject)
private
 FID: Integer;
 FEntCode: String;
published
 [TFieldAlias('ID')]
 property ID: Integer read FID write FID;
 
 [TFieldAlias('CODE')]
 property EntCode: String read FEntCode write FEntCode;
end;				

Notez que le nom de l'attribut ici doit correspondre au nom de la classe que vous avez déclaré sans le 'Attribute'.
Notez enfin que les paramètres attendus sont ceux du ou des constructeurs de la classe d'attribut.

IV-B-3. Récupération des attributs via RTTI

Voici un exemple complet permettant de récupérer les "AliasName" de n'importe quel objet :

 
Sélectionnez

procedure ShowAliasesNames(AEnt: TObject);
var
 Context: TRttiContext;
 Rtti: TRttiType; 
 Props: TArray<TRttiProperty>;
 Prop: TRttiProperty;
 PropAttrs: TArray<TCustomAttribute>;
 PropAttr: TCustomAttribute;
begin
  Context := TRttiContext.Create;
  try
    Rtti := Context.GetType(AEnt.ClassInfo);
    Props := Rtti.GetProperties;
    for Prop in Props do
    begin
      PropAttrs := Prop.GetAttributes;
      for PropAttr in PropAttrs do
       if PropAttr is TFieldAliasAttribute then
        ShowMessageFmt('Nom de la propriété : %s, nom de l''alias : %s', [Prop.Name, TFieldAliasAttribute(PropAttr).AliasName]);
    end;
  finally
    Context.Free;  
  end;
end;

V. Le nouveau framework de Gesturing

Le Gesturing (mouvement en français) traité ici est en rapport avec la reconnaissance et la réaction aux mouvements de l'utilisateur, que ce soit à la souris ou sur un écran tactile.
Ainsi, en plus du clic et de la molette, l'utilisateur a maintenant la possibilité de donner des ordres à l'application en effectuant certains mouvements précis.

V-A. Le composant TGestureManager

Le TGestureManager est le composant non-visuel sur lequel repose toute la mise en place du Gesturing.
Vu que la réponse à un mouvement doit passer par l'intermédiaire d'un TAction, vous aurez besoin de déposer également un TActionList sur votre fiche.
Par défaut vous avez accès aux 34 mouvements pré-enregistrés standards (glissement droit ou gauche, carré, cercle, triangle, chevron, etc...) mais vous pourrez également définir vos propres mouvements par l'intermédiaire du TGestureManager. Nous aborderons ce point dans la suite de l'article.

V-B. La propriété Touch

Une nouvelle propriété a fait son apparition au niveau de TControl : Touch, c'est grâce à elle que vous allez pouvoir configurer les contrôles pour qu'ils puissent répondre aux mouvements de l'utilisateur.
La première des choses à faire est donc de renseigner le TGestureManager au niveau de la sous-propriété GestureManager, ensuite pour chaque mouvement à prendre en charge affectez un TAction qui répondra lorsque l'utilisateur reproduira le mouvement. Les actions sont accessibles via la sous-propriété Gestures.
Touch définit également d'autres sous-propriétés de configuration qui n'auront de sens que si le programme tourne sur un matériel vraiment tactile plutôt qu'un PC standard.

V-C. Exemple d'implémentation

Imaginons une application simple affichant une image, lorsque l'utilisateur fait un mouvement vers la droite ou vers la gauche alors l'image suivante ou précédente s'affichera.
Nous déposons donc un TGestureManager, un TActionList, un TImageList contenant les différentes images et un TImage pour l'affichage.

Ne mettez pas le TImage en align client. Nous allons uniquement configurer le Gesturing sur le TImage afin de montrer que seul ce composant réagit aux mouvements utilisateurs, et non l'ensemble de l'application.

Après avoir assigné le TGestureManager à la propriété Touch du TImage, nous ajoutons une action pour les mouvements standards left et right

Image non disponible
Les propriétés à renseigner pour activer le Gesturing

Côté code nous avons simplement les choses suivantes :

 
Sélectionnez
				
// utilitaire pour dessiner l'image courante sur le TImage
procedure TForm1.DrawImage(const Index: Integer);
begin
  ImageList1.Draw(image1.Canvas, 0, 0, Index);
  Image1.Refresh;
end;

// initialisations
procedure TForm1.FormCreate(Sender: TObject);
begin
  FIndexCourant := 0;
  DrawImage(FIndexCourant);
end;

// l'utilisateur fais un mouvement gauche, passer à l'image précédente dans le TImageList
procedure TForm1.SwingLeftExecute(Sender: TObject);
begin
  if FIndexCourant > 0 then
  begin
    Dec(FIndexCourant);
    DrawImage(FIndexCourant);
  end;
end;

// l'utilisateur fais un mouvement droit, passer à l'image suivante dans le TImageList
procedure TForm1.SwingRightExecute(Sender: TObject);
begin
  if (FIndexCourant + 1) < ImageList1.Count then
  begin
    Inc(FIndexCourant);
    DrawImage(FIndexCourant);
  end;
end;

Compilez et exécutez. Positionnez la souris sur le TImage, faites un clic droit, restez appuyé et déplacez un peu la souris horizontalement vers la droite puis relâchez. L'image devrait passer à la suivante.
Répétez le mouvement, mais cette fois-ci vers la gauche. C'est l'image précédente qui devrait s'afficher.

V-D. Mouvements personnalisés

Le TGestureManager vous permet également de concevoir vos propres évènements personnalisés. Pour cela double-cliquez sur le composant pour activer l'expert vous permettant d'ajouter des mouvements.
La création d'un mouvement se fait assez aisément. Cliquez sur "enregistrer un mouvement" puis dessinez le mouvement que devra suivre l'utilisateur à la souris.

Image non disponible
Ecran de création d'un nouveau mouvement

Attention à ne pas créer de mouvement qui ressemblerait de trop près à un déjà existant. En effet si deux mouvements sont trop proches, le système aura du mal à distinguer qui est qui lorsque l'utilisateur fera son mouvement et risque de rediriger vers le mauvais gestionnaire de mouvement ou aucun.
Lorsque vous avez fini d'enregistrer votre mouvement, l'expert vous indiquera le cas échéant les conflits qu'il détecte et le pourcentage de similitude.

Pour utiliser votre nouveau mouvement il suffit de procéder comme avant, la seule différence est qu'au niveau de la sous-propriété Gestures il faut chercher votre mouvement sous "Custom" et non sous "Standard".

Image non disponible

VI. Base de données

Dans cette section nous allons voir tout ce qui a été amélioré concernant les bases de données.

VI-A. Mise à jour de dbExpress

Les pilotes de dbExpress ont été mis à jour pour inclure de nouveaux SGBD. Sont maintenant supportés :

  • Firebird 1.5 et 2.1
  • InterBase 2009
  • Microsoft SQL Server 2008
  • MySQL 5.1
  • Oracle 11g
  • Tous les autres SGBD précédemment supportés

VI-B. MIDAS.dll

Le code source de MIDAS (en C++) a été rendu publique dans cette version. Vous pouvez le trouver dans {$BDS}\source\db\midas.

VI-C. DataSnap

DataSnap, pour ceux qui l'ignorent, est un framework de composants permettant la communication n-tiers entre une base de données et un ou plusieurs applicatifs, pas forcement en Delphi.
Avec D2009, DataSnap avait opéré un gros changement en délaissant son architecture COM au profit d'une implémentation basé sur TCP/IP avec Indy.
Avec D2010, DataSnap permet maintenant de choisir comme protocole de transport HTTP et HTTPS. Le serveur supporte aussi l'architecture REST et peut retourner des flux JSON.
De plus l'on peut maintenant ajouter des filtres au niveau des flux de données échangés afin de compresser ou crypter les données par exemple.
Les CallBacks entre clients et serveurs sont dorénavant possibles également.

Comme dit précédemment, DataSnap permet de renvoyer des flux JSON. Tous les outils de sérialisation/dé-sérialisation de ce format se trouvent dans l'unité DBXJSON.pas si par hasard vous en aviez besoin.

VII. Les autres nouveautés du langage

Ici nous verrons tout ce que Delphi 2010 apporte comme autre nouveauté au langage.

VII-A. Support des images étendu

En plus des formats jusqu'à présent supportés viennent maintenant s'ajouter le TIFF ainsi que le WICWindows Imaging Component. De plus la transparence alpha pour les PNG et les BMP est également supportée.
Pour ce qui est des WIC, une nouvelle unité WinCodec.pas a fait son apparition pour sa gestion.

WIC est implanté dans Windows à partir de XP SP3, Vista et plus récent. Pour les autres systèmes vous devez prévoir son installation depuis le site de microsoft (gratuitement).

VII-B. Nouvelle directive delayed

Avec le mot clé external il est possible de lier l'exécutable avec des routines d'une DLL. Ces liaisons sont effectuées avant le démarrage du programme en lui-même cependant si la DLL ou la routine en question n'existe pas sur le système alors l'application crashe inévitablement et ce avant même que le développeur ait la main pour agir.
C'est pour rendre la gestion des liaisons plus souple que la directive delayed est maintenant disponible. Une routine déclarée avec cette directive n'est maintenant liée qu'au moment de son appel.
De fait le développeur peut maintenant prendre des précautions avant de lancer l'appel comme par exemple :

 
Sélectionnez

if OSVersion=WINDOWS_7 then
  CloseTouchInputHandle
else
  MyInternalSimplerClose;

On pourra noter que le nouveau framework de Gesturing tire profit de cette nouvelle directive. Ainsi, sous Windows 7, le framework utilise les API de Gesturing propre à ce Système d'Exploitation (SE) tandis que sous les autres SE le framework utilise le moteur développé par CodeGear.

VII-C. Localisation

Tous les descendants de TWinControl traitent à présent le message WM_INPUTLANGCHANGE qui notifie l'application que l'utilisateur vient de changer la langue du bureau.
De fait le composant qui intercepte ce message renvoi à tous les autres un message CM_INPUTLANGCHANGE que vous pouvez implémenter dans votre composant pour qu'il réagisse au changement de langue.

 
Sélectionnez

procedure CMInputLangChange(var Message: TMessage); message CM_INPUTLANGCHANGE;		

Le paramètre LParam du message contient le Language Identifier que l'utilisateur vient de choisir.
Vous pouvez récupérer l'identifiant de langue primaire et secondaire via les routines PRIMARYLANGID et SUBLANGID. Les constantes correspondantes de langue primaire (LANG_XXX) et secondaire (SUBLANG_XXX) sont déclarées dans windows.pas.
Pour plus d'informations sur les Language Identifier vous pouvez consulter cet article sur la MSDN. Pour consulter la liste des constantes de langues, regardez cet article.
Notez enfin que l'unité SysUtils se dote d'une nouvelle classe TLanguages qui permet de récupérer une chaîne de caractère représentant la langue mais attention elle fonctionne avec des Locale Identifier ce qui est différent des Language Identifier. Consultez cet article pour plus de détails sur la différence entre les deux.

 
Sélectionnez
	
procedure TForm1.CMInputLangChange(var Message: TMessage);
var
 LangId, ASubLangID: Word;
begin
  LangId := PRIMARYLANGID(Message.LParam);
  ASubLangID := SUBLANGID(Message.LParam);

  ShowMessageFmt('%d_%d', [LangId, ASubLangID]);

  ShowMessage(Languages.NameFromLocaleID[MAKELCID(Message.LParam, SORT_DEFAULT)]);
end;

VII-D. TTouchKeyboard

Le TTouchKeyboard est un composant qui joue le rôle de clavier virtuel. L'appui sur une touche renvoie la touche vers le composant actif sans que ce dernier ne perde le focus.

Image non disponible

Notez que le clavier change suivant que vous changez la langue du système. Il est également possible de configurer le composant pour qu'il n'affiche que le pavé numérique.

Image non disponible

Bien sûr on pourrait s'interroger sur l'intérêt d'un clavier virtuel dans une application. Déployé sur un PC normal aucun mais si vous l'imaginez déployé sur un mobile, un Tablet PC ou même une borne tactile l'intérêt d'un tel clavier devient tout de suite évident.
Ceci, comme le framework de Gesture est bien sûr là pour poser les bases de l'avenir.

VII-E. Transtyper une interface vers sa classe d'implémentation

Les opérateurs is et as sont maintenant possible pour transtyper une interface vers la classe qui l'implémente. Par exemple :

 
Sélectionnez

type
  IMonInteface = interface
    procedure Toto;
  end;
  
  TMaClasse = class(TInterfacedObject, IMonInteface)
    procedure Toto;
    procedure Titi;
  end;
  
procedure FaisQuelqueChose(AMonInterface: IMonInteface);
begin
  if AMonInterface is TMaClasse then
    TMaClasse(AMonInterface).Titi;
end;

VII-F. Autres nouvelles unités et traductions de header

Ici nous verrons brièvement les nouvelles unités présentes dans Delphi 2010 ainsi que les traductions de header incluses.

  • Direct2D.pas : contient le TDirect2DCanvas qui implémente les Microsoft Direct2D API. Malheureusement cette implémentation ne fonctionne que sous Windows 7, là où ces API existent.
  • DirectX : Les derniers headers ont été inclus dans les unités Direct3D.pas, D3DX9.pas et D2D1.pas
  • Manipulations.pas : Traduction des headers pour les technologies de manipulation et inertie de Windows Touch.
  • IOUtils.pas : définit les classes utilitaires TDirectory, TPath et TFile

VIII. Informations et téléchargements

Si vous souhaitez télécharger le version architecte entièrement fonctionnelle pendant 30 jours, vous pouvez vous rendre sur le site de téléchargement de CodeGear :
Télécharger la trial de delphi 2010
Bien que la page de téléchargement soit en Anglais, Delphi 2010 Trial est bien en Français.

En complément d'information, vous pouvez consulter la fiche technique en Anglais de Delphi 2010 :
CodeGear Delphi 2010 Fiche Technique

Comparez les caractéristiques des différentes versions Architecte, Entreprise et Professionnelle afin de mieux guider votre choix sur la version qui vous convient :
CodeGear Delphi 2010 matrice des fonctionnalités

Retrouvez toutes les vidéos et les billets blogs parlant du nouveau Delphi 2010.

IX. Remerciements

Je tenais à remercier Ero-sennin, Laurent Dardenne, Franck Soriano, Evarisnea, Pedro et Nono40 pour leur relecture et leurs conseils avisés.