_______     ________    __          ________    __    __    __
   |       \   |        |  |  |        |        |  |  |  |  |  |  |
   |   __   |  |   _____|  |  |        |   __   |  |  |__|  |  |  |
   |  |  |  |  |  |___     |  |        |  |__|  |  |        |  |  |
   |  |__|  |  |   ___|_   |  |_____   |   _____|  |   __   |  |  |
   |        |  |        |  |        |  |  |        |  |  |  |  |  |
   |_______/   |________|  |________|  |__|        |__|  |__|  |__|
                  Cours sur le delphi, langage objet



                        delphi.txt  02/06/2024
                            ultimecool.com

Sommaire


  Introduction
  CHAPITRE 1 - Notions élémentaires
     1.1. Variables
     1.2. Types de données simples
     1.3. Type de données tableau et enregistrement
     1.4. Directives de compilation
     1.5. Structure d'un programme
     1.6. Structures de controle
     1.7. passage de paramètres par réference
     1.8. passage d'une fonction en paramètre et fonctions locales
     1.9. Surdéfinition des fonctions
    1.10. Les pointeurs
    1.11. Traduction des notions de classes et objets
    1.12. gestion des saisies et des erreurs
    1.13. exceptions
    1.14. Déclarations externes
    1.15. Liaison de fichiers objet
    1.16. Importation des fonctions de bibliothèques
    1.17. Déploiement d'une application Delphi

  CHAPITRE 2 - Free pascal
    1.18. Conversion d'un source Delphi en source Lazarus et mode objfpc
    1.19. Conteneurs (listes, dictionnaires) utilisant des génériques
    1.20. Clonage
    1.21. Nombre variable d'arguments

  CHAPITRE 2 - Fiches, Composants et ressources.
     2.1. Utilisation des fiches
     2.2. Boites de dialogue integrées
     2.3. Création Dynamique d'un composant
     2.4. Parcours de chaque composants
     2.5. Fiches MDI
     2.6. Utilisation des Frames
     2.7. Intégration de fichiers dans l'executable

  CHAPITRE 3 - Programmation Webservices avec ADO et Intraweb
     3.1. Gestion des processus
     3.2. ADO (ActiveX Data Objects)
     3.3. Procedures stockées sql serveur, MSDE, Interbase:
     3.4. Principe d'Intraweb
     3.5. WebServices
     3.6. Objets COM
     3.7. ActiveX

  CHAPITRE 4 - Composant et Propriétés
     4.1. Propriété canvas et Bitmap
     4.2. Procedures val et str
     4.3. composants memo MainMenu OpenDialog SaveDialog MessageDlg ...

  CHAPITRE 5 - Gestion des donnees et du temps
     5.1. Gestion des dossiers
     5.2. Gestion des fichiers
     5.3. Parcours d'un dossier
     5.4. Gestion des dates et des heures

Introduction

Ce petit document a été écrit dans le but de retrouver à coup sur et rapidement, toute information concernant la programmation Delphi, sous environnement Linux (avec Kylix) ou Windows. Il a été écrit avec un editeur en mode texte, pour etre imprimable sous forme de fiches miniatures, lors de mes debut dans ce langage. Ce document suppose que vous avez déjà quelques notions de programmation. Si ce n'est pas le cas, vous pouvez consulter le site "www.delphibasics.co.uk" pour les passage incompris. Dans tous les cas, ce document peut s'avérer très utile, car il condense toutes les informations.

Basic: Ce langage est assez facile à utiliser, mais il génère des applications limitées en taille, assez peu performantes et lentes.

Pascal: Ce langage est bien structure, d'une difficulté moyenne, il donne des applications rapides.

C, C++: Ce langage laisse une grande liberté au programmeur, il est assez difficile à utiliser, il donne des applications performantes et rapides.

Visual Basic: Facile à utiliser, ce langage génère des exécutables assez lents. (même avec une amélioration de vitesse sur la dernière version).

Delphi: Ce langage offre beaucoup de possibilités, les exécutables sont très rapides. Il est utilisé par les professionnels. Delphi 5, 7 2006 pour Windows XP, XE3 pour Windows 8 et 10. Sa déclinaison Kylix 3 destinée à Linux a été abandoné par Borland.

C++ Builder: Semblable à Delphi, la syntaxe diffère, mais les possibilités sont voisines.

Lazarus Lazarus est le RAD/EDI qui s'approche le plus possible de Delphi. Free Pascal Compilateur sous licence GPL fonctionnant sous Linux, Windows, OS2 Mac OSX, BSD, iOS, Android, etc. Il est conçu pour interpréter et compiler le Pascal Objet de Delphi. A la différence de Java dont le slogan est: « write once run anywhere » celui de Lazarus et Free Pascal est: write once compile anywhere »

CHAPITRE 1 - Notions élémentaires

Ce chapitre regroupe toutes les notions de base du Pascal, de son compilateur, et de l'environnement de programmation.

1.1. Variables

Delphi n'est pas sensible au majuscules et aux minuscules.

  • déclaration : var a : string; var i,j : integer;
  • affectation : a := 'tete a toto'; i := 15+17*3;
  • lecture : ShowMessage(a);
  • operations : iv := 7 < (16/2); iv := 2*5;
  • operandes : + - / * < > <= >= <> = And Or Xor Not
  • commentaires : {} //

1.2. Types de données simples

Définifion de constantes (facilite la maintenance): Const NULL = 0; CONST USER1 = 0; // groupe de constantes CRLF = #13+#10; // #13d + #10d -> 0D0Ah

Création d'un type utilisateur: Déclaration: Type Str80 = string[80]; Var S1 : string[80]; Var S2 : Str80;

Création d'un type énumeration (ne peut contenir que les valeurs specifiées): Type TSuit = (Lu, Ma, Me); // Lu->0, Ma->1, Me->2 Type TNiveaux = (Ja, Fe=10, Ma); // Ja->0, Fe->10, Ma->11 Type TUpper = 'A'..'Z'; // A->0, B->1,...Z->25 Une constante est créer à chacune des énumerations (var a : TSuit; a := Lu).

Création d'un type set (permet de définir un masque de 255 indicateurs): Une variable du type set Type TNums = set of Byte; // 0->255 <=> '0'..'255' peut englober chacune des Var nums : TNums; valeurs attribuées par le Begin programmeur. Il peut en nums := [20..50]; // 20 -> 50 rajouter ou en supprimer Include(nums, 12); // 12, 20 -> 50 avec Include et Exclude. Exclude(nums, 35); // 12, 20 -> 34, 36 -> 50 Chaque valeur du masque if 35 In nums then ShowMessage('Impossible'); peut être vérifiée par In End;


Déclaration de variable:
Var    //                             --- Type de donnée logique ---
   Log1 : Boolean;     //                     'True' & 'False'
                       //             --- Type de donnée Entière ---
   Int1 : Byte;        //                          0 a 255
   Int2 : ShortInt;    //                       -127 a 127
   Int3 : Word;        //                          0 a 65,535
   Int4 : SmallInt;    //                    -32,768 a 32,767
   Int5 : LongWord;    //                          0 a 4,294,967,295
   Int6 : Cardinal;    //                          0 a 4,294,967,295
   Int7 : LongInt;     //             -2,147,483,648 a 2,147,483,647
   Int8 : Integer;     //             -2,147,483,648 a 2,147,483,647
   Int9 : Int64;       // -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807
                       //             --- Type de donnée décimale ---
   Dec1 : Single;      //  7  chifres significatifs, exposant   -38 a +38
   Dec2 : Currency;    // 50+ chiffres significatifs, dont 4 décimales max
   Dec3 : Double;      // 15  chifres significatifs, exposant  -308 a +308
   Dec4 : Real;        // +/- 2.9´10-39 à 1.7´10+38
   Dec4 : Extended;    // 19  chifres significatifs, exposant -4932 a +4932
                       //             --- Type de donnée texte ---
   Str1 : Char;        //       Occupe 1 caractère, alphabet ASCII
   Str2 : WideChar;    //       Occupe 1 caractère, alphabet International
   Str3 : AnsiChar;    //       Occupe 1 caractère, alphabet ASCII ANSI
   Str4 : ShortString; //       Chaine de 255 Char's maxi Ord(s[0])<=>Length(s)
   Str5 : String;      //       Chaine de x Char's maxi (String[x])
   Str6 : AnsiString;  //       Chaine de x AnsiChar's (AnsiString[x])
   Str7 : WideString;  //       Chaine de x WideChar 's (WideString[x])
 

1.3. Type de données tableau et enregistrement

Il est possible de créer des tableaux de variable dans chacuns de ces types.


Var Tab1dim : array[5..8] of Integer;         // 1 tableau de 4 élements
Var Tab2dim : array[1..100,1..12] of real;    //100 tableaux de 12 élements
const Days  : array[1..7] of string = ('Lu','Ma','Me','Je','Ve','Sa','Di');
 

Ces tableaux peuvent être bornée ou non. Il est possible de définir la longueur d'un tableau par "SetLength".


  byteArray  : Array of Byte;                    SetLength(multiArray, 3);
  multiArray : Array of Array of string;         SetLength(multiArray[0], 1);

  charArray : TCharArray; // func(var nom_var : TCharArray);
  openArray : Array [0..2] of char; // func(nom_var : Array of char);
  func(['H','e','l','l','o']); // (const nom_var : Array of const);
 

Le type enregistrement correspond aux type structure du langage c. Il est également possible de créer des tableaux avec ces structures.


// déclaration:                 // tableau d'enregistrements:
Type TPersonne = record         Type TTabPersonnes = array[1..50] of TPersonne;
  Nom : string[25];             Var TabPersonnes : TTabPersonnes;
  Prenom : string[25];
  Age : ShortInt;               TabPersonnes[3].Nom := 'DUBOIS';
End; { n'alloue rien }          TabPersonnes[3].Prenom := 'Cathy';
                                TabPersonnes[3].Age := 18;
// création:
Var Personne:TPersonne;
{ alloue ou moins 51 oct }      TabPersonnes[1] := TabPersonnes[3];

// assignation:                 // correspond a:
Personne.Nom := 'DUPOND';       TabPersonnes[1].Nom := TabPersonnes[3].Nom;
Personne.Prenom := 'Albert';    TabPersonnes[1].Prenom :=TabPersonnes[3].Prenom;
Personne.Age := 35;             TabPersonnes[1].Age := TabPersonnes[3].Age;
 

1.4. Directives de compilation

Chaque directive de compilation est insérée entre '{' et '}'. Elles peuvent contenir des paramètres. ex: {$IfDef MSWINDOWS}

$IfDef Execute le code si le symbole a été définit par $Define $Define Définit un symbole de compilation - utilisé par $IfDef .$Define Définition inactive facillement activable $Else Commence la section alternative d'un IfDef ou IfNDef $EndIf Termine le code conditionnel de compilation $IfNDef Execute le code si le symbole n'a pas été définit par $Define $IfOpt Test l'état d'une directive de compilation $UnDef Supprime un symbole de directive de compilation $R *.xfm Définit un fichier ressourse pour la liaison

Chaque compilateur définit plusieurs symboles; - MSWINDOWS pour Delphi sous envinnement Microsoft - LINUX pour kylix sous environnement Linux - FPC pour free pascal - LCL pour Lazarus

1.5. Structure d'un programme

Cette partie explique la déclaration et la création des fonctions, ainsi que la portée des variables. Les déclarations de variables locales doivent se faire avant le begin de la procédure ou de la fonction. Self permet d'accéder à des paramètres de la forme en cour (ex: self.GetNamePath, Form1.xx <=> self.xx). Sous Delphi faites File | New | Application CLX .


unit Unit1;
interface
uses
  SysUtils, Types, Classes, Variants, QTypes, QGraphics, QControls, QForms,
  QDialogs, QStdCtrls;
type
  TForm1 = class(TForm)
    Label1: TLabel;
    ButtonAjoute: TButton;  // déclaration globales compatibles aux évenements.
  private
    { Déclarations privées }
    VarGlobale : string;  // variable globale initialisee à 0 false, ou ''
    procedure SansParams; // declaration d'une procedure (ne retourne rien)
    procedure AvecParams( DeCombien : integer ; S : string);
  public
    { Déclarations publiques }
end;

var
  Form1: TForm1;
  { Déclarations externes }

function fct:Integer; // déclaration d'une fonction (retourne: result)

implementation
{$R *.xfm}       // lie tous les fichiers .xfm

procedure TForm1.SansParams;  // implémentation de la procédure.
  var UneVariableLocale:integer;  // variable locale non initialisée.
begin
  AvecParams(1,'mess');
end;

procedure TForm1.AvecParams( DeCombien : integer ; S : string);
begin
end;

function fct:Integer ;
begin
  result := 0;
end;

end.

// application console  ParamStr(0) : chemin + nom de l'exe
program Project1;

{$APPTYPE CONSOLE}
{ corp des fonctions et des procédures }
{ variables globales }
begin
  writeln('Hello world!');
  readln;
end.
 

1.6. Structures de controle


  // structure if then else    // structure case         // with
  if i >= 10 then              case str of               with canvas do
    begin                        a: instruction;         begin
    end                          b:                        ...
  else { facultatif }          begin                     end;
    begin                        end;                    // cf canvas
  end;                         end;                      

  // structure for             // structure while        //structure repeat
  for i:=5 downto 1 do         while i*2<22 do           repeat
  { for i:=1 to 5 do }           begin                     S := IntToStr(i);
  begin                            S := IntToStr(i);       ShowMessage(S);
    S := IntToStr(i);              ShowMessage(S);         inc(i);
    ShowMessage(S);                inc(i);               until i*2>22 ;
  end;                           end;                    
 

Il est possible d'interrompre immédiatement une boucle avec l'instruction Break. Tant qu'une boucle n'est pas fini, le programme prendra toutes les ressources. Lancer la procédure Application.ProcessMessages dans la boucle permet au système de reprendre la main à chaque tour, et ainsi mettre à jour l'interface. Cela correspond à l'association TranslateMessage(Msg) DispatchMessage(Msg) en pascal.


procedure TurboPascalDelay(Numsec : integer) ;
var
  EndTime : LongInt ; Message : TMsg ;
begin
  EndTime := GetTickCount + NumSec*1000 ;
  repeat
    if GetMessage(Message, 0, 0, 0) then
    begin
      TranslateMessage(Message);
      DispatchMessage(Message)
    end ;                             { en Delphi, repeat ProcessAppMessages ; }
  until GetTickCount > EndTime ;      {            until ... ; }
end {Delay} ;
 

1.7. passage de paramètres par réference

Dans le passage par valeur, il s'agit d'une recopie de la variable, mais dans le passage par référence c'est la même variable parente qui est utilisée. Elle est realisée par le mot var lors de la déclaration de la fonction.


procedure TForm1.EtudeParametre( var A : string);
begin
  ShowMessage(A);
end;
 

Il est possible d'acceder aux variables parentes par Sender:


LabelAffichage.Caption := (Sender as TButton).Caption;
 

Le mot clé const permet de définir un paramètre qui ne pourra pas être modifiée.

1.8. passage d'une fonction en paramètre et fonctions locales


Type
   TMaProcedure = procedure(i,j:Integer);

Procedure LanceProcedure(UneProcedure: TMaProcedure; Param1, Param2 : Integer);
begin
   UneProcedure(Param1,Param2);
end;

procedure Add(i, j: Integer);    procedure TForm1.Button1Click(Sender: TObject);
begin                            begin
  ShowMessage(IntToStr(i+j));      LanceProcedure(Add, 10, 5);
end;                             end;
 

La procédure 'Add' doit avoir les mêmes paramètres que lors de la définition de TMaProcedure, (function/procedure, et paramètres).

Une fonction locale est une fonction déclarée dans une fonction parente. Elle peut accéder à tous les paramètres et variables locales du parent, déclarées au- dessus d'elle.


constructor TMyClass.Create(AOwner: TComponent);
var
  I: Integer;

  procedure locproc;
  begin
    writeln(inttostr(I));
  end;
begin
 

ou


constructor TMyClass.Create(AOwner: TComponent);

  procedure locproc(i : integer);
  begin
    writeln(inttostr(I));
  end;

var
  I: Integer;
begin
 

1.9. Surdéfinition des fonctions

Le compilateur fait la différence entre fonctions, par le nom, le nombre d'arguments, les types des arguments. Le type retourné n'est pas pris en compte. Lors de la déclaration, il faut rajouter le parametre "overload;".


  ex:   Function Somme(St1,St2 :String):Integer;  overload;
        Function Somme(I1,I2 :Integer):Integer;   overload;
        Function Somme(S1,S2 :TSpinEdit):Integer; overload;
 

1.10. Les pointeurs

L'utilisation des pointeurs est supplantée par la programmation objet. La classe TStringList permet de faire une liste de chaînes de caractères. La gestion des pointeurs et de l'allocation de la memoire, est masquée dans la classe. Mais le recour aux pointeurs est toujours utile (fonction externes par ex). Un pointeur est un type special qui contient l'adresse d'un objet. L'incrémentation se fait de maniere dynamique; il s'ajoute la taille de l'objet à l'adresse, afin de pointer sur l'objet suivant.

ptr : PChar; pointeur sur un caractère. ptr : PExtended; pointeur sur un decimal étendu. ptr : Pointer; pointeur sur un objet quelconque.

SizeOf(Int64) Recupere le nombre de bit ocupe par un objet Addr(obj) @obj Recupere l'addresse d'un objet ptr^ Renvoit l'élement pointée ^type Déréférence le type GetMem Alloue et réalloue un espace mémoire FreeMem Supprime l'espace alloué StrPLCopy Recopie un string en l'emplacement du pointeur.

Exemples:


var                                         type
   myString  : string;                         TMyRecord = Record
   myCharPtr : PChar;                            name : String[20];
   i : Integer;                                  age  : Integer;
begin                                          end;
   myString  := 'Hello World';
   i := 1;                                  var
   myCharPtr := Addr(myString[i]);             myRecord    : TMyRecord;
                                               myRecordPtr : ^TMyRecord;
   while i <= Length(myString) do
   begin                                    begin
     ShowMessage(myCharPtr^);                  myRecord.name := 'Fred Bloggs';
     Inc(i);                                   myRecord.age  := 23;
     Inc(myCharPtr);                           myRecordPtr := @myRecord;
   end;                                        ShowMessage(myRecordptr.name);
end;                                        end;

        GetMem(newMem, (maxCount + ALLOCATE_SIZE) * SizeOf(Int64));
        newPtr := newMem;
        for i := 1 to maxCount do
             begin
               newPtr^ := oldPtr^;
               Inc(oldPtr);
               Inc(newPtr);
             end;
        FreeMem(newMem);
 

1.11. Traduction des notions de classes et objets

Une classe est une structure évoluée, qui permet de regrouper non seulement des données, mais aussi des fonctions (méthodes). L'accé aux champs, et aux méthodes se fait avec l'operateur ".". Un objet est une representation dynamique de la classe. Tous les objets d'une même classe auront les mêmes possibilités. Sous Delphi, à part Tobject toutes les classes héritent d’une autre classe.

L'héritage permet de définir une nouvelle classe à partir d'une classe de base. On parle alors de sous classe, ou de classe dérivée. Cela permet de hiérarchiser et de créer des modèles entre les classes.

Les accés aux membres de la classe de base, par la classe dérivée, dépand du statut des membres (méthodes et propriétés) dans la classe de base: ______________ ________________________ _____________________ Statut dans la Accés aux membres de la Accés aux membres de classe de base classe de base par un la classe de base par utilisateur de la classe une classe derivée ______________ ________________________ _____________________ private non non protected non oui public oui oui

Toutes les méthodes et propriétés, sont visibles et utilisables à l’intérieur de la classe elle-même: à l’ implémentation de la classe et de ses méthodes. L'héritage entre les 2 classes est implémenté par la déclaration de la classe Tclasse_derivee=class(Tclasse_de_base) - a mettre dans la section var.


TMonObjet1=class(Tobject)        TMonObjet2=class(TMonObjet1)
  private                          private
  public                           public
    Nom:String;                     // on peut rajouter ce que l'on veut.
    procedure afficheNom;           // TMonObjet2 descend de TMonObjet1.
    Constructor Create;
    Destructor Destroy; override;
  end;                             end;
 

Le lançement des constructeurs se fait du sommet vers le bas de la pyramide d'héritage. Et les destructeurs du bas vers le haut.


implementation                             MonObjet1:=TMonObjet1.Create;
constructor TMonObjet1.Create;
begin { appelle le create de TObject }     La copie d'objets est en fait une
  Inherited create; {        ------- }     simple copie d'
adresses.
  Nom:='';                                 MonObjet2:=MonObjet1;
end;
                                           MonObjet1.Destroy; // detruit l'objet
destructor TMonObjet1.Destroy;
begin
  FreeAndNil(...);
  inherited;  // lance le Destroy du père
end;
 

Considérons les déclarations suivantes :


Type
  TObj = object;
    Constructor init;
  end;
  Pobj = ^TObj;
Var PP : Pobj;
//Les appels suivants sont équivalents :
pp := new (Pobj,Init);
new(pp,init);
new (pp); pp^.init;
 

La surcharge d'une méthode, se fait en la déclarant Override, depuis le plus vieil ancêtre. Si jamais on utilise une méthode virtuelle sans avoir appelé un constructeur, les résultats seront imprévisibles. La surcharge indexée possère un identifiant choisit par le programmeur (Override id).


               TMonObjet1:                       TMonObjet2:
déclaration    procedure afficheNom; Override;   procedure afficheNom; Override;
implémentation procedure afficheNom;             procedure afficheNom;
 

Les méthodes normales sont des méthodes qui ont été déclarées sans mot-clé. Lors de l'appel d'une méthode, la méthode déclarée au moment de la compilation est utilisée. Considérons les déclarations suivantes :


  program Hello;
  Type
    TParent = Object
      Constructor init;
      procedure Doit;
      end;
    PParent=^TParent;
    TChild = Object(TParent)
      procedure Doit;
      end;
    PChild = ^TChild;
 
  Constructor TParent.init; begin end;
 
  procedure TParent.Doit;
  begin writeln('TParent.Doit'); end;
 
  procedure TChild.Doit;
  begin writeln('TChild.Doit'); end;
 
  Var
   ParentA,ParentB : PParent;
   Child      : PChild;
 
  begin
    ParentA := New(PParent,Init);
    ParentB := New(PChild,Init);
    Child := New(PChild,Init);
    ParentA^.Doit; // appellera TParent.Doit
    ParentB^.Doit; // appellera TParent.Doit
    Child^.Doit;   // appellera TChild.Doit
  end.
 

Puisque ParentB est de type TParent, le compilateur décide qu'il doit appeler TParent.Doit, même s'il sera créé en tant que TChild. Si la méthode réellement appelée dépend du type réel de l'objet au moment de l'exécution, la méthode ne peut pas être une méthode statique, mais doit être une méthode virtuelle.

Pour remédier à la situation, des méthodes virtuelles sont créées. Cela se fait simplement en ajoutant le modificateur virtuel à la déclaration de méthode. L'objet descendant peut alors re-déclarer la méthode (avec la même liste de paramètres) à l'aide du mot-clé virtual.


Type
  TParent = Object
    ...
    procedure Doit;virtual;
  end;
  PParent = ^TParent;
  TChild = Object(TParent)
    ...
    procedure Doit;virtual;
  end;
  PChild = ^TChild;
 
  Var
    ParentA,ParentB : PParent;
    Child      : PChild;
  begin
    ParentA := New(PParent,Init);
    ParentB := New(PChild,Init);
    Child := New(PChild,Init);
    ParentA^.Doit; // appellera TParent.Doit
    ParentB^.Doit; // appellera TChild.Doit
    Child^.Doit;   // appellera TChild.Doit
 

Désormais, différentes méthodes seront appelées, en fonction du type d'exécution réel de l'objet. Il est possible d'accéder au TParent.Doit depuis le TCild.Doit, avec le mot-clé inherited :


Procedure TChild.Doit;
begin
 inherited Doit;
 ...
end;
 

Une méthode abstraite, est une méthode qui doit être obligatoirement surchargée. Elle se déclare avec Abstract.

NB: Override equivaut à Virtual en Turbo Pascal, et Object à Class. Abstract équivaut à


      procedure TMonObjet1.MethodeAbs;
      begin
        Abstract;
      end;
 

  program Hello;
  Type
    TParent = Object
      Constructor init;
      procedure Doit;virtual;abstract;
      end;
    PParent=^TParent;
    TChild = Object(TParent)
      procedure Doit;virtual;
      end;
    PChild = ^TChild;
 
  Constructor TParent.init;
  begin
  end;
 
  procedure TChild.Doit;
  begin
  end;
 
  Var
   ParentA,ParentB : PParent;
   Child      : PChild;
 
  begin
    ParentA := New(PParent,Init);
    ParentB := New(PChild,Init);
    Child := New(PChild,Init);
    //ParentA^.Doit;
    ParentB^.Doit;
    Child^.Doit;
  end.
 


https://fbeaulieu.developpez.com/guide/?page=page_11

Une interface, est une définition de propriétés et de méthodes obligatoires pour toutes les classes utilisant cette interface. Cela permet de pouvoir passer un type interface en paramètre d'une fonction, pour pouvoir passer des classes différentes utilisant cette interface. Cette fonction pourra accéder directement aux méthodes définis dans l'interface. Elle pourra si besoin retrouver le type précis de la classe passé en variable, et appeller une méthode non définie dans l'interface en castant la variable avec le type de classe correspondant.


type
  IMovieClip = Interface(IInterface)
    function Assign(Parent: TWinControl; ParentMovieClip:IMovieClip = nil)
      :IMovieClip;
    function gotoAndStop(sLabel:String):IMovieClip;
    function BringToFront():IMovieClip;
  end;

  // interface evenements movieClip générique
  ImcEvent = Interface(IInterface)
    function GetTarget : IMovieClip;
    procedure SetTarget(value:IMovieClip);
    function GetCurrentTarget : IMovieClip;
    procedure SetCurrentTarget(value:IMovieClip);

    property target : IMovieClip read GetTarget write SetTarget;
    property currentTarget : IMovieClip
      read GetCurrentTarget write SetCurrentTarget;
  end;
  // fin interface evenements movieClip

  Event = class(TInterfacedObject, ImcEvent)
  private
    _currentTarget: IMovieClip;
    _target: IMovieClip;
  public
    sType:string;
    function GetTarget : IMovieClip;
    procedure SetTarget(value:IMovieClip);
    function GetCurrentTarget : IMovieClip;
    procedure SetCurrentTarget(value:IMovieClip);
    property target : IMovieClip read GetTarget write SetTarget;
    property currentTarget : IMovieClip read GetCurrentTarget
      write SetCurrentTarget;
  end;

  TmovieClip = class(TInterfacedObject, IMovieClip)
  public
    parentMc:IMovieClip;
    function Assign(Parent: TWinControl; ParentMovieClip:IMovieClip = nil)
      :IMovieClip;
    function gotoAndStop(sLabel:String):IMovieClip;
    function BringToFront():IMovieClip;
  end;

implementation


function Event.GetTarget():IMovieClip;
begin result := _target; end;

procedure Event.SetTarget(value:IMovieClip);
begin _target := value; end;

function Event.GetCurrentTarget():IMovieClip;
begin result := _currentTarget; end;

procedure Event.SetCurrentTarget(value:IMovieClip);
begin _currentTarget := value; end;

function TmovieClip.Assign(Parent: TWinControl; ParentMovieClip:IMovieClip= nil)
  :IMovieClip;
begin
  result := self;
  if ParentMovieClip <> nil then
    self.ParentMc := ParentMovieClip;
end;


 

1.12. gestion des saisies et des erreurs

créer un composant de type "TEdit", faites un double clic sur "OnKeyPress".


procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key <> chr(8)) and ((Key < '0') or (Key > '9')) then
    begin
      Key := chr(0); { ou #0 permet d'annuler la frappe de la touche }
    end;
end;
 

Pour connecter une procédure à l'événement "OnClick", vous devez, dans le volet "Evénements" de l'inspecteur d'objet, choisir cette procédure dans la liste des procédures compatibles avec cet événement.

Se positionner sur le champ suivant avec la touche entrer dans l'événement OnKeyDown ajoutez:


if key = VK_RETURN then perform(WM_NEXTDLGCTL,0,0);
 

1.13. exceptions

Avant tout développement, désactiver l'option outils/options de debug/ stopper si exception.


  try
    i:=edit1.text div 0; // valeurs bizarres ou division par 0
  except
    on E:Edivbyzero do // voir l'aide de SysUtils
    begin
      sho     wmessage'Nomdel''objet'+Self.ClassName+
      #13+'Nature de l''exeption: '+E.Message+  // #0Dh /r.
      #13+'exeption survenue à l''adresse: '+
      Format('%p',[ExceptAddr])); // %p : pointeur en styring
    end;
    on EConvertError do ShowMessage('valeur non valide');
  end;
 

Il est possible d'utiliser les 2 blocs imbriqués.


function Somme(NomFichier:String):integer;
var fic : TextFile;
    Nombre, i : integer;
begin
result:=0;
AssignFile(fic, NomFichier);
reset(fic);
  try
    try
      for i := 1 to 10 do
        begin
        ReadLn(Nombre);
        result:=result+Nombre;
        end
    except
        result:=0; // valeur de retour result
    end
  finally  // excecuter dans tous les cas
    closeFile(fic);
  end;
end;
 

Vous pouvez évidemment créer vos propres exceptions pour prévenir des erreurs par exemple dans l'utilisation des composants que vous distribuez.


type EMonException = class(Exception); // declare l'exception
raise EMonException.Create('Ceci est mon exception'); //génére l'exception
 

1.14. Déclarations externes

La directive external qui remplace le bloc dans une déclaration de procédure ou de fonction permet d'appeler des routines compilées séparément de votre programme. Les routines externes peuvent être issues de fichiers objet ou de bibliothèques à chargement dynamique. Quand vous importez une fonction C qui prend un nombre variable de paramètres, utilisez la directive varargs.


  ex:  function printf(Format: PChar): Integer; cdecl; varargs;
 

La directive varargs fonctionne uniquement avec des routines externes et uniquement avec la convention d'appel cdecl. La convention d'appel pour l'API windows est stdcall. Il y a aussi Pascal, Register, Safecall.

Les déclarations externes se placent après la déclaration de la forme. var // voir le chapitre Structure d'un programme. MainForm: TMainForm; Function Voir(Key :PChar): Integer;stdcall;external 'protekt.dll' name 'Voir';

Pour créer une librairie, faites "File/New/Other", "DLL Wizard"


  library DLL1;                        Attention aux types de donnees des params
  { ... gestion de mémoire ... }       Chaines: PChar,PAnsiChar,ShortString
  uses                                 Entiers: Shortint,Smallint,Longint,Int64,
    SysUtils,                                   Byte, Word, LongWord
    Classes;
 
  {$R *.res}
  function Somme(A, B: Integer)
    : Integer; stdcall;
  begin
    Result := A + B;
  end;
 
  exports
    Somme; // Somme1 par defaut
 
  begin
  end.
 

Pour débuguer une dll, il vous faut d'abord créer une application qui l'utilise. Puis dans "Exécuter/Paramètres" ou "Run/Parameters", choisir l'application hôte.

1.15. Liaison de fichiers objet

Pour appeler des routines d'un fichier objet compilé séparément, commencez par lier le fichier objet à votre application en utilisant la directive de compilation $L (ou $LINK). Puis déclarez les procedures du fichier objet:


  ex: Avec Windows :             Avec Linux :
      {$L BLOCK.OBJ}             {$L block.o}
      procedure MoveWord(var Source, Dest; Count: Integer); external;
      procedure FillWord(var Dest; Data: Integer; Count: Integer); external;
 

Vous pouvez placer directement de l'assembleur dans votre code source Delphi.

1.16. Importation des fonctions de bibliothèques

Pour importer des routines d'une bibliothèque à chargement dynamique (.so ou .DLL), attachez une directive de la forme :


  function UneFonction(S: string): string; external 'strlib.dll'; // Windows
  function UneFonction(S: string): string; external 'strlib.so';  // Linux
  function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer):
    Integer;   stdcall; external 'user32.dll' name 'MessageBoxA';
 

La dernière forme permet de renomer la fonction importée. Sous Windows, à la place du nom, vous pouvez utiliser un indice pour identifier la routine. L'indice sera stocké dans la table d'exportation.


  external constanteChaîne index constanteEntière;

type
  Tmy_sum = function (A, B: Integer): Integer; cdecl;
var
  my_sum: Tmy_sum;

implementation
uses Libc, SysUtils;

var
  Handle: HMODULE;

procedure LoadLib;
begin  // 'libtest.so'doit se trouver soit dans usr/lib soit dans /lib
  Handle := LoadLibrary('libtest.so');
  if Handle = 0 then
    raise Exception.Create('Error: ' + dlerror);
  my_sum := GetProcAddress(Handle, 'my_sum');
end;

procedure FreeLib;                     ->  initilization
begin                                      LoadLib;
  FreeLibrary(Handle);                 ->  finalization
end;                                       FreeLib;
 

1.17. Déploiement d'une application Delphi

Pour le déploiement d'une application Delphi 1-7 VCL sous Windows, il suffit de copier l'executable generée lors de la compilation. Pour certaines applications base de donnée ou QuickReports il faudras rajouter des dlls.

Pour le deploiement d'une application Delphi CLX sous Windows (cross-platform : File | New | CLX Application), il faut inclure une des dlls de 4Megs; qtintf.dll (Delphi6) ou qtintf70.dll (Delphi7).

Le déploiement d'une application Kylix3 CLX sous Linux est plus compliqué, car elle requière un certain nombre d'objets partagés. - sur une machine où kylix est installé, il suffit de rajouter le dossier /bin /usr/local/kylix3/bin dans le fichier de configuration /etc/ld.so.conf, et de lancer en tant que root la commande /sbin/ldconfig - sur une machiche sans kylix il faut libborqt ou libttintf + libqt suivant la variable d'environnement CLX_USE_LIBQT, qui doit être définit ou non suivant la platforme. CLX_USE_LIBQT=1 -> libttintf+libqt CLX_USE_LIBQT non definit -> libborqt Le mieux est de fournir les 3 librairies qui sont dans /usr/local/kylix3/bin

Dans certains cas, l'affichage des textes s'arrête au niveau des accents. Alors, par sécurité, forcez l'utilisation du français dans le script de démarrage.

Dans tous les cas il faut définir l'emplacement des librairies. On peut le faire dans /etc/ld.so.conf, ~/.baschrc ou dans un script de lancement du type:


    #!/bin/bash
    # Application et librairies installees dans ~/kylix/deploy
    export LD_LIBRARY_PATH=~/kylix/deploy
    #export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
    export CLX_USE_LIBQT=1
    export LANG=fr_FR
    ./~/kylix/deploy/votre_application
 

Lors de la création d'un package Linux, vous devez gerer les dépendances. Vous pouvez les afficher avec ldd votre_application.

CHAPITRE 2 - Free Pascal

1.18. Conversion d'un source Delphi en source Lazarus et mode objfpc

Pour rendre compatible avec Lazarus: - recreer un projet avec les memes nom d'unités - cela ajouttera les fichiers suivant: .lpi .lpr .lps .lfm - recopier les unités d'origine - recopier le contenu des fichiers DFM dans les fichiers lfm en rajouttant LCLVersion = '1.4.0.4' dans le TForm - Il sera ensuite necessaire de refaire le cadrage des composants.

Le guide de reference de Free Pascal est disponible sur ce lien fichier ref
https://sourceforge.net/projects/freepascal/files/Documentation/3.2.2/

Le compilateur Free Pascal prend en charge 5 modes pascal différents. Il existe un mode de compatibilité DELPHI qui peut être défini pour faciliter la conversion du code existant. Lazarus préfère le mode OBJFPC, qui est moins ambigu que la syntaxe Delphi. Le mode peut varié d'une unité à une autre au sein du même projet. A noter que seul le mode DELPHI permet d'utiliser les collections. La plupart des unités Delphi peuvent être compilées par le compilateur Free Pascal en ajoutant juste après le nom de l'unité :


{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
 

Pour plus d'informations, consultez le Guide de programmation multiplateforme.
https://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide

En raison de la rigueur inhérente à FPC, certaines modifications de syntaxe sont nécessaires, entre {$Mode Delphi} et {$Mode ObjFPC}. Le modeFPC est recommandé car il permet de meilleures pratiques, et parfois parce que le mode Delphi n'est pas entièrement précis ou, dans quelques cas, le code de Delphi ne fonctionne pas comme prévu avec FPC, même s'il peut être compilé.

Attribution de fonctions:


begin
  if not Assigned(MyButton.OnClick) then
    MyButton.OnClick:= {$IFDEF FPC}@{$ENDIF}SomeFunction;
    //@ is required under FPC - but not allowed under Delphi
    //more code...
end;
 

Pour l'appel de fonction sans parametres, utiliser la syntaxe FPC avec des parenthèses


  OnMyCallback();
 

Lorsque vous accédez aux valeurs d'un pointeur vers un enregistrement, vous devez d'abord déréférencer


Function GetSomeValue(ARecord: PMyRecord):Integer;
begin
  If Assigned(ARecord) then
    Result:=ARecord^.SomeValue
  else
    Result:=0;
end;
 

Lors de l'accès aux caractères d'une chaîne indexée Propriété d'un objet, elle doit être mise entre parenthèses. Avec Delphi, il est possible de traiter une propriété exactement comme n'importe quelle autre const ou var, par exemple jusqu'à accéder directement aux caractères individuels d'une chaîne, alors que cela n'est pas toujours possible dans FPC, en particulier pour les propriétés indexées. Au lieu de cela, il doit être mis entre parenthèses pour être distinct.


Type TSomeComponent=class(TComponent)
//More code...
Published
Property MyString:String index 3 read GetMyString;
//More code...
End;

var
  MyChar:char;
begin
  If Length(MyString)>2 then
    //parenthesis sometimes needed
    MyChar:= (MyString)[3];
    //More code...
end;
 

Vous devez transtyper les pointeurs vers le type réel lors de l'utilisation avec var ou fonction de ce type. Parfois, dans Delphi, vous aurez une variable de pointeur nulle représentant un objet. Bien que cela puisse sembler une situation complexe, elle est curieusement assez courante, en particulier dans les grands packs de composants, comme méthode permettant d'éviter trop d'inclusions circulaires entre des objets dans différentes unités. Dans Delphi, il est alors possible d'envoyer ce pointeur nul vers une fonction attendant cet objet, sans se soucier du transtypage en type réel, dans fpc vous devez transtyper.


Unit 1
  Type
    TSomeObject=class(TComponent)
   //More code...
  End;

  Procedure DoSomething(Value: TSomeObject);
  Function GetSomeObject: TSomeObject;

Unit 2
  Type TSomeComponent=class(TComponent)
    //More code...
    Published SomeObject: Pointer;
    //More code...
  End;

Application
var
  MyComponent: TSomeComponent;
begin
  MyComponent.SomeObject:=Pointer(GetSomeObject);
  //MyComponent.SomeObject:=GetSomeObject; // Delphi way
  //More code...
  DoSomething(TSomeObject(MyComponent.SomeObject));
  //DoSomething(MyComponent.SomeObject); // Delphi way
end;
 

Il existe un compilateur en ligne qui permet de tester son code FPC
https://www.onlinegdb.com/online_pascal_compiler

1.19. Conteneurs (listes, dictionnaires) utilisant des génériques

Le langage et la bibliothèque d'exécution proposent divers conteneurs flexibles. Il existe un certain nombre de classes non génériques (comme "TList" et "TObjectList" depuis l'unité "Contnrs"), il existe également des tableaux dynamiques ("array of TMyType").

Les conteneurs génériques vous offrent de nombreuses méthodes utiles pour ajouter, supprimer, itérer, rechercher, trier… Le compilateur sait également (et vérifie) que le conteneur ne contient que des éléments du type approprié.

Il existe trois bibliothèques fournissant des conteneurs génériques dans FPC :

  • "Generics.Collections" (depuis FPC >= 3.2.0)
  • "FGL"
  • "GVector" (ensemble dans "fcl-stl")

L'unité "Generics.Collections" est la plus utiles. Les conteneurs génériques qu'il implémente sont

  • très efficace (notamment important pour accéder aux dictionnaires par clés),
  • compatible entre FPC et Delphi,
  • le nom est cohérent avec d'autres parties de la bibliothèque standard (comme les conteneurs non génériques de l'unité "Contnrs").

Les classes les plus importantes de "Generics.Collections" sont

  • TList : Une liste générique de types.
  • TObjectListe : Une liste générique d'instances d'objet. Il peut posséder des enfants, ce qui signifie qu’il les libérera automatiquement.
  • TDictionnaire : Un dictionnaire générique.
  • TObjectDictionary : Un dictionnaire générique, qui peut posséder les clés et les valeurs.

Certaines opérations de tri et de recherche ("Sort" et "IndexOf"), nécessitent de comparer deux éléments. Les conteneurs "Generics.Collections" utilisent pour cela un comparateur. Le comparateur par défaut est plus que satisfaisant en comparant le contenu de la mémoire pour les type enregistrements. mais il est aussi possible d'en créer un personnalisé. Il sera une classe implémentant l'interface "IComparer". En pratique, vous définissez généralement le rappel approprié et utilisez la méthode "Construct" pour envelopper ce rappel dans une instance "IComparer". Voici comment utiliser un générique simple "TObjectList" :


{$ifdef FPC}{$mode objfpc}{$define objfpc}{$endif}{$H+}{$J-}
uses SysUtils,
  Generics.Defaults,    // TComparer
  Generics.Collections; // TObjectList

type
  TStudent = class
    Name: string;
  end;
  TStudentList = {$ifdef objfpc}specialize{$endif} TObjectList<TStudent>;

  function CompareStudentName(constref Left, Right: TStudent): Integer;
  begin
    Result := AnsiCompareStr(Left.Name, Right.Name);
  end;
type  
   TStudentComparer = {$ifdef objfpc}specialize{$endif} TComparer<TStudent>;
var
  Student: TStudent;
  StudentsList: TStudentList;
begin
  StudentsList := TStudentList.Create(true);

  Student := TStudent.Create;
  Student.Name := 'Steeve';
  StudentsList.Add(Student);

  Student := TStudent.Create;
  Student.Name := 'Jhon';
  StudentsList.Add(Student);
 
  StudentsList.Sort(TStudentComparer.Construct(@CompareStudentName));

  Writeln('Count: ', StudentsList.Count);
  Writeln(StudentsList[0].Name);
  Writeln(StudentsList[1].Name);
  FreeAndNil(StudentsList)
end.
 

La classe "TDictionary" implémente un dictionnaire , également appelé map (clé / valeur) , également appelé tableau associatif . Son API est un peu similaire à la classe C# "TDictionary". Il contient des itérateurs utiles pour les clés, les valeurs et les paires clé / valeur. Un exemple de code utilisant un dictionnaire :


{$ifdef FPC}{$mode objfpc}{$define objfpc}{$endif}{$H+}{$J-}
uses SysUtils, Generics.Collections;

type
  TStudent = class
    Name: string;
  end;

  TStudentDictionary
   = {$ifdef objfpc}specialize{$endif} TDictionary<string, TStudent>;

var
  StudentClassment: TStudentDictionary;
  Student, FoundStudent: TStudent;
  StudentPair: TStudentDictionary.TDictionaryPair;
  StudentKey: string;
begin
  StudentClassment := TStudentDictionary.Create;

  Student := TStudent.Create;
  Student.Name := 'John';
  StudentClassment.AddOrSetValue('1', Student);
 
  if StudentClassment.TryGetValue('1', FoundStudent) then
    Writeln('Found student under key "1" with name: ' +
      FoundStudent.Name);
 
  for StudentKey in StudentClassment.Keys do
    Writeln('Found student key: ' + StudentKey);
  for Student in StudentClassment.Values do
    Writeln('Found student value: ' + Student.Name);
  for StudentPair in StudentClassment do
    Writeln('Found student key->value: ' +
      StudentPair.Key + '->' + StudentPair.Value.Name);
  // StudentClassment['1'] := ... ;
 
  StudentClassment.Remove('1');
 
  // TDictionaryPair ne libere pas les valeurs, il faut le faire manuellement.
  Student.Free;
  FreeAndNil(StudentClassment);
end.
 

Si on veut un dictionnaire qui libère les objets automatiquement, il faut utiliser TObjectDictionary. remplacer juste TDictionary par TObjectDictionary et ajouter [doOwnsValues] en premier paramétre du Create, et supprimer la ligne Student.Free;

Si vous préférez utiliser l'unité "FGL" plutôt que "Generics.Collections", les classes les plus importantes de l' FGLunité sont :

  • Liste TFPGListe Une liste générique de types.
  • TFPGObjectList Une liste générique d'instances d'objet. Il peut « posséder » des enfants.
  • TFPGCarte Un dictionnaire générique.

Le "TFPGList" ne peut être utilisé que pour les types pour lesquels l'opérateur d'égalité (=) est défini. Pour "TFPGMap" les opérateurs « supérieur à » et « inférieur à » doivent être définis pour le type de clé. Si vous souhaitez utiliser ces listes avec des types qui n'ont pas d'opérateurs de comparaison intégrés (par exemple avec des enregistrements), vous devez surcharger leurs opérateurs comme indiqué dans Surcharge d'opérateurs.

Une fonctionnalité puissante de toute langue moderne. La définition de quelque chose (généralement d’une classe) peut être paramétrée avec un autre type. L'exemple le plus typique est celui où vous devez créer un conteneur (une liste, un dictionnaire, un arbre, un graphique…) : vous pouvez définir une liste de type T , puis la spécialiser pour obtenir instantanément une liste d'entiers , une liste de chaînes , une liste de TMyRecord , et ainsi de suite.

Les génériques en Pascal fonctionnent un peu comme les génériques en C++. Ce qui signifie qu'ils sont "étendus" au moment de la spécialisation, un peu comme les macros (mais beaucoup plus sûrs que les macros ; par exemple, les identifiants sont résolus au moment de la définition générique, pas à la spécialisation, donc on ne peut pas "injecter" d'inattendu comportement lors de la spécialisation du générique). En fait, cela signifie qu'ils sont très rapides (peuvent être optimisés pour chaque type particulier) et fonctionnent avec des types de n'importe quelle taille. Vous pouvez utiliser un type primitif (entier, float) ainsi qu'un enregistrement, ainsi qu'une classe lors de la spécialisation d'un générique.


{$mode objfpc}{$H+}{$J-}
uses
  SysUtils;

type
  generic TMyCalculator<T> = class
    Value: T;
    procedure Add(const A: T);
  end;

procedure TMyCalculator.Add(const A: T);
begin
  Value := Value + A;
end;

type
  TMyFloatCalculator = specialize TMyCalculator<Single>;
  TMyStringCalculator = specialize TMyCalculator<string>;

var
  FloatCalc: TMyFloatCalculator;
  StringCalc: TMyStringCalculator;
begin
  FloatCalc := TMyFloatCalculator.Create;
  try
    FloatCalc.Add(3.14);
    FloatCalc.Add(1);
    WriteLn('FloatCalc: ', FloatCalc.Value:1:2);
  finally
    FreeAndNil(FloatCalc);
  end;

  StringCalc := TMyStringCalculator.Create;
  try
    StringCalc.Add('something');
    StringCalc.Add(' more');
    WriteLn('StringCalc: ', StringCalc.Value);
  finally
    FreeAndNil(StringCalc);
  end;
end.
 

Les génériques ne se limitent pas aux classes, vous pouvez également avoir des fonctions et des procédures génériques :


{$mode objfpc}{$H+}{$J-}
uses
  SysUtils;

generic function Min<T>(const A, B: T): T;
begin
  if A < B then
    Result := A else
    Result := B;
end;

begin
  WriteLn('Min (1, 0): ', specialize Min<Integer>(1, 0));
  WriteLn('Min (3.14, 5): ', specialize Min<Single>(3.14, 5):1:2);
  WriteLn('Min (''a'', ''b''): ', specialize Min<string>('a', 'b'));
end.
 

Plus d'informations sur ce lien
https://wiki.freepascal.org/TCollection

1.20. Clonage

Pour copier le contenu de l'instance de classe, l'approche standard consiste à dériver votre classe de "TPersistent" et à remplacer sa méthode "Assign". Une fois qu'il est correctement implémenté dans "TMyObject" :


{$mode objfpc}{$H+}{$J-}
uses
  SysUtils, Classes;

type
  TMyClass = class(TPersistent)
  public
    MyInt: Integer;
    procedure Assign(Source: TPersistent); override;
  end;

  TMyClassDescendant = class(TMyClass)
  public
    MyString: string;
    procedure Assign(Source: TPersistent); override;
  end;

procedure TMyClass.Assign(Source: TPersistent);
var
  SourceMyClass: TMyClass;
begin
  if Source is TMyClass then
  begin
    SourceMyClass := TMyClass(Source);
    MyInt := SourceMyClass.MyInt;
    // Xxx := SourceMyClass.Xxx; // add new fields here
  end else
    { Since TMyClass is a direct TPersistent descendant,
      it calls inherited ONLY when it cannot handle Source class.
      See comments below. }

    inherited Assign(Source);
end;

procedure TMyClassDescendant.Assign(Source: TPersistent);
var
  SourceMyClassDescendant: TMyClassDescendant;
begin
  if Source is TMyClassDescendant then
  begin
    SourceMyClassDescendant := TMyClassDescendant(Source);
    MyString := SourceMyClassDescendant.MyString;
    // Xxx := SourceMyClassDescendant.Xxx; // add new fields here
  end;

  { Since TMyClassDescendant has an ancestor that already overrides
    Assign (in TMyClass.Assign), it calls inherited ALWAYS,
    to allow TMyClass.Assign to handle remaining fields.
    See comments below for a detailed reasoning. }

  inherited Assign(Source);
end;

var
  C1, C2: TMyClass;
  CD1, CD2: TMyClassDescendant;
begin
  // test TMyClass.Assign
  C1 := TMyClass.Create;
  C2 := TMyClass.Create;
  try
    C1.MyInt := 666;
    C2.Assign(C1);
    WriteLn('C2 state: ', C2.MyInt);
  finally
    FreeAndNil(C1);
    FreeAndNil(C2);
  end;

  // test TMyClassDescendant.Assign
  CD1 := TMyClassDescendant.Create;
  CD2 := TMyClassDescendant.Create;
  try
    CD1.MyInt := 44;
    CD1.MyString := 'blah';
    CD2.Assign(CD1);
    WriteLn('CD2 state: ', CD2.MyInt, ' ', CD2.MyString);
  finally
    FreeAndNil(CD1);
    FreeAndNil(CD2);
  end;
end.
 

1.21. Nombre variable d'arguments

Il est possible de passer un tableau arbitraire d'éléments à une procédure :


{$ifdef FPC}{$mode objfpc}{$define objfpc}{$endif}{$H+}{$J-}
uses
  Classes, Crt, SysUtils;

procedure Testit (Args: Array of const);
Var I : longint;  
begin  
  If High(Args)<0 then  
    begin  
    Writeln ('No aguments');  
    exit;  
    end;  
  Writeln ('Got ',High(Args)+1,' arguments :');  
  For i:=0 to High(Args) do  
    begin  
    write ('Argument ',i,' has type ');  
    case Args[i].vtype of  
      vtinteger    :  
        Writeln ('Integer, Value :',args[i].vinteger);  
      vtboolean    :  
        Writeln ('Boolean, Value :',args[i].vboolean);  
      vtchar       :  
        Writeln ('Char, value : ',args[i].vchar);  
      vtextended   :  
        Writeln ('Extended, value : ',args[i].VExtended^);  
      vtString     :  
        Writeln ('ShortString, value :',args[i].VString^);  
      vtPointer    :  
        Writeln ('Pointer, value : ',Longint(Args[i].VPointer));  
      vtPChar      :  
        Writeln ('PChar, value : ',Args[i].VPChar);  
      vtObject     :  
        Writeln ('Object, name : ',Args[i].VObject.Classname);  
      vtClass      :  
        Writeln ('Class reference, name :',Args[i].VClass.Classname);  
      vtAnsiString :  
        Writeln ('AnsiString, value :',AnsiString(Args[I].VAnsiString));  
    else  
        Writeln ('(Unknown) : ',args[i].vtype);  
    end;  
    end;  
end;

Var
  S, T :Ansistring;
  P1, P2 : PChar;
begin
  S:='Ansistring 1';  
  T:='AnsiString 2';  
  Testit ([]);  
  Testit ([1,2]);  
  Testit (['A','B']);  
  Testit ([TRUE,FALSE,TRUE]);  
  Testit (['String','Another string']);  
  Testit ([S,T])  ;  
  Testit ([P1,P2]);  
  Testit ([@testit,Nil]);  
  //Testit ([ObjA,ObjB]);  
  Testit ([1.234,1.234]);  
  //TestIt ([AClass]);
end.
 

plus d'information sur ce lien
https://www.freepascal.org/docs-html/current/ref/refsu69.html

CHAPITRE 2 - Fiches, Composants et ressources.

2.1. Utilisation des fiches

Il existe 2 manières de gérer les fiches lors de l'execution. La première charge la fiche au démarrage de l'application, puis la rend visible ou non sur demande. La deuxième, crée la fiche dynamiquement lors de l'exécution. Par defaut, Delphi crée les fiches avec la première méthode, vous pouvez la changer dans 'Projet -> Options -> Fiches'.

Avec la méthode automatique, il suffit de lancer la methode Show, pour afficher la nouvelle fiche (Form2.Show;). La méthode close permet de la refermer (close;)

La méthode manuelle, implique de rajouter le nom de l'unitée à charger dans la section uses (ex: Unit2 pour l'unité Unit2.pas).


// sur la fiche mere                                 //sur la fiche fille
procedure TForm1.Button1Click(Sender: TObject);      procedure TForm2.Button1...
var                                                  begin
  f : TForm2;                                          close
begin                                                end
  f :=TForm2.Create;
  f.Scaled := False;   // évite le redimentionnement
  f.Show;              //   suivant la taille de la police
end;
 

La méthode TForm.SetBounds(aleft, atop, awidth, aheight) permet de modifier les coordonnées et la taille de la fenetre sans réaffichages intermédiaires. Hide sert à masquer une fiche.

Une valeur différente de 0 à ModalResult ferme une fenêtre ouverte de façon modale. La valeur prise par la propriété lors de la fermeture de la fenêtre est retourné par la fonction ShowModal, ce qui permet de l'analyser depuis la fonction appelante.

Constantes employée avec modalResult :

  • mrNone (0) la fenêtre reste ouverte
  • mrOk idOk (1) Valider
  • mrCancel idCancel (2) Annuler,Alt F4,fermeture
  • mrAbort idAbort(3) Abandonner
  • mrRetry idRetry (4) Réessayer
  • mrIgnore idIgnore (5) Ignorer
  • mrYes idYes () Oui
  • mrNo idNo () Non
  • mrAll mrNo + 1 Autre

D'autres constantes peuvent être définies manuellement (f.modalResult := 1000;).

2.2. Boites de dialogue integrées

Une boîte de dialogue est une fiche crée dynamiquement. On l'affiche avec une fonction.


InputBox            Saisie utilisateur avec une valeur par defaut.
InputQuery          Saisie utilisateur.
MessageDlg          Message, avec symbole et boutons au choix.
MessageDlgPos       Message positionné, avec symbole et boutons au choix.
PromptForFileName   Choix de fichier.
ShowMessage         Message simple, avec le bouton OK.
ShowMessageFmt      Message formatée, avec le bouton OK.
ShowMessagePos      Message positionné, avec le bouton OK.
Type TOpenDialog    Boite de selection d'un fichier à charger.
Type TPrintDialog   Boite d'impression et de contrôle.
Type TSaveDialog    Boite de sélection d'un fichier à sauver.

2.3. Création Dynamique d'un composant


type                            Procedure TForm1.MonClick(Sender: TObject);
  TForm1 = class(TForm          Begin
    procedure FormCreate          ShowMessage(TButton(Sender).name);
    (Sender: TObject);          End;
  private
  public                        procedure TForm1.FormCreate(Sender: TObject);
    Procedure MonClick          begin
    (Sender: TObject);            With TButton.Create(Self) Do
  end;                            Begin
                                    Parent := Self;
var                                 Name := 'but1';
  Form1: TForm1;                    Caption := 'Un bouton !';
                                    OnClick := MonClick;
implementation                    End;
{$R *.xfm}                      end;

Exemple avec les menus:

var
  element: TMenuItem;
begin
  element := TMenuItem.Create(Self);
  element.onclick := testClick;
  element.Caption := 'élément';
  Monmenu.Add(element);
end;
 

2.4. Parcours de chaque composants

ControlCount nous donne le nombre de controles dans la fiche. 'is' permet d'agir différemment selon le type trouvé.


for i:=0 to ComponentCount-1 do
  if components[i] is Tbutton then Tbutton(Components[i]).Caption := 'Toto';

for i:=0 to ControlCount-1 do
    if controls[i] is Tbutton then Tbutton(Controls[i]).Caption := 'Toto';

for i:=0 to application.componentCount-1 do
  if application.components[i] is TForm then
    TForm(application.components[i]).show;

for i:= 1 to 30 do
  TTrackBar(FindComponent('Trk3p' + IntToStr(i))).position := 0;
 

Lors de l'utilisation de l'application par l'utilisateur, il est possible de se positionner sur chaques composant avec la touche Tabulation. Pour modifier l'ordre allez dans 'Menu/Tab Order'. L'important est de savoir que Chaque GroupBox possède son propre ordre de tabulation, et que pour les radio, seul le GroupBox doit posséder un ordre de tabulation.

2.5. Fiches MDI

Une fenêtre MDI est une fiche dont la particularité est qu'elle peut contenir d'autres fiches, appelées fenêtres MDI filles. Une application MDI permet de visualiser simultanément plusieurs documents, et éventuellement d'échanger des données entre eux dans un espace de travail commun.

fsMDIChild fenêtre MDI fille fsMDIForm fenêtre MDI mère unique fsNormal fenêtre non MDI fsStayOnTop la fenêtre reste toujours en avant plan

La fiche MDI mère doit être la fiche principale de l'application. Par ailleurs, il est recommandé de ne pas déclarer les fiches filles dans la liste des fiches autocréer. Les méthodes Next et Previous permettent d'activer la fiche MDI fille suivante et précédente, par rapport à l'ordre d'ouverture.

ActiveMDIChild represente la fiche fille active MDIChildren[I] références des fenêtres enfants de l'application de 0 à N MDIChildCount nombre de fiches enfants N = MDIChildCount-1


//Exemple : réduction de toutes les fenêtres filles de l'application
for i := MDIChildCount - 1 downto 0 do
  MDIChildren[i].WindowState := wsMinimized;
 

Pour ce qui est des menus des fenêtres MDI, il existe 3 solutions. Créer tous les menus dans la fiche mère, et en rendre certains visibles ou invisibles selon la présence d'au moins une fiche fille. Créer les menus spécifiques dans les fiches et les fusionner avec les menus de la fiche mère lors de l'ouverture de la fille. Définir plusieurs menus principaux et associer un menu à la fiche.


    mnuEdition.visible:=MDIChildCount > 0;
    if MDIChildCount > 0 then menu:=mnu1 else menu:=mn2;
 

Pour obtenir une liste des fenetres filles ouvertes dans l'un des menus, déclarer l'une des options de menu de la barre principale des menus dans WindowMenu. Les applications MDI doivent inclures des options de menu contenant les commandes Mosaique, Cascade et Reorganiser les icones afin que les utilisateurs puissent modifier la disposition de leurs documents ouverts.

  • présentation en mosaïque: TileMode:=tbVertical; Tile; //sur MDI mère
  • présentation en cascade: Cascade //sur MDI mère
  • réorganisation des icones: ArrangeIcons; //sur MDI mère

2.6. Utilisation des Frames

Une frame (ou un cadre) est un conteneur de composants. La frame ressemble à la form (fiche ou fenêtre) dans sa façon de gérer et détenir les composants, en revanche elle n'a pas de bordure, on ne peut pas l'afficher par une méthode "Show" et elle n'a pas de menu. C'est juste un "intérieur de fenêtre".

L'utilisation des frames permet d'obtenir une interface plus souple car les frames peuvent être mises n'importe où, dans des fenêtres évidemment, mais aussi dans des onglets ou bien dans d'autres frames. Par exemple, on peut passer très facilement d'un affichage par onglets à un affichage en fenêtres MDI en changeant simplement la propriété Parent de la frame.

Lorsque l'on conçoit une application, on a tendance à créer tous les écrans dans des TForm. Idéalement, il faudrait créer uniquement des frames et n'utiliser les forms que comme un moyen de visualiser les frames.


// Exemple avec un bouton
procedure TForm1.Button1Click(Sender: TObject);
var
  temp: TFrame;
begin
  temp := TFrame.Create(self);
  temp.Parent := self;
end;
 

Utilisation de Formes dans les Pages en Execution


procedure TForm1.newsheet(sFile:shortstring);
var
   Form: TForm;
   Sheet: TTabSheet;
begin
  // create a tabsheet within the page control
  Sheet := TTabSheet.Create(PageControl1);
  Sheet.PageControl := PageControl1;
  // create the form and place it in the tabsheet
  Form := TForm2.Create (Application);
  Form.BorderStyle := bsNone;
  Form.Align := alClient;
  Form.Parent := Sheet;
  Form. Visible := True;
  // Access to sheet specific elements
  TForm2(Form).SynMemo.Lines.LoadFromFile(sFile);
  // activate and set title
  PageControl1.ActivePage := Sheet;
  Sheet.Caption := Form.Caption;
end;

procedure TForm1.MenuItem3Click(Sender: TObject);
var
  Sheet: TTabSheet;
  cmp:TControl;
begin
  Sheet := PageControl1.Pages[PageControl1.PageIndex];
  cmp := Sheet.FindChildControl('Form2');
  TForm2(cmp).SynMemo.Lines.SaveToFile('aa');
  Sheet.Destroy;
end;
 

2.7. Intégration de fichiers dans l'executable

Pour intégrer des fichiers dans l'executable, il faut d'abord générer un fichier de ressources avec BRCC32, à partir d'un script '.rc'. Puis on inclut le fichier généré '.res' au projet grâce à une directive de compilation {$R fichier.res }, que l'on place dans l'unité principale.

ressources.rc Cloche WAVE ding.wav BRCC32 ressources.rc image BITMAP androm.bmp video AVI cool.avi {$R ressources.RES} diversfichier RCDATA testimg.jpg


{---------------------------------------------------------------------}
{                          Données audio                              }
{---------------------------------------------------------------------}

// rajouter uses mmsystem;
procedure TForm1.ButSndClick(Sender: TObject);
var
  AdrSon: PChar;
  hRessourceVoulue : THandle; // handle désignant la ressource située dans l'exe
  hBlockMemRes : THandle; // handle sur le bloc mémoire contenant la ressource
begin
  // Initialisation du handle désignant la ressource située dans l'exe
  hRessourceVoulue:=FindResource(HInstance, 'Cloche', 'WAVE');
  if hRessourceVoulue<>0 then // s'il l'a trouvé
  begin
    // chargement de la ressource en mémoire
    hBlockMemRes:=LoadResource(HInstance, hRessourceVoulue);
    if hBlockMemRes<>0 then //si cela s'est bien passé
    begin
      // on bloque la mémoire contenant le bloc mémoire et au passage on
      // récupère le pointeur désignant le premier octet de la ressource
       AdrSon:=LockResource(hBlockMemRes);
       // on joue le son par SndPlaySound
       if Assigned(AdrSon) then SndPlaySound(AdrSon, snd_ASync or snd_Memory);
       UnlockResource(hBlockMemRes); // on débloque la mémoire
    end;
    FreeResource(hRessourceVoulue); // libération de la mèmoire
  end;
end;

{---------------------------------------------------------------------}
{                         Données images                              }
{---------------------------------------------------------------------}

procedure TForm1.ButImgClick(Sender: TObject);
begin
     Image1.Picture.Bitmap.LoadFromResourceNameHInstance,'image');
end;

procedure TForm1.ButImg2Click(Sender: TObject);
var
 BitMap1 : TBitMap;  // sans utiliser de TImage
begin
  Bi   tMap1=TBitMap.Create
  try
    // les Bitmap possèdent une méthodes permettant decharger directement une
    // ressource de type BITMAP :  LoadFromResourceName
    BitMap1.LoadFromResourceName(HInstance,'image');
    Canvas.Draw(12,12,BitMap1);
  finally
    BitMap1.Free;
  end;
end;

{---------------------------------------------------------------------}
{                          Données vidéo                              }
{---------------------------------------------------------------------}

procedure TForm1.ButVidClick(Sender: TObject);
begin
  Animate1.ResName='video'
  Animate1.ResHandle:=hinstance;
  Animate1.Active:=true;
end;

{---------------------------------------------------------------------}
{ Enregistrement sur le disque du fichier contenu dans la ressource.  }
{ Cette technique permet de traiter n'importe quel type de fichier.   }
{---------------------------------------------------------------------}

procedure TForm1.ButAllClick(Sender: TObject);
var
 StrNomFichier:string;
 ResourceStream:TResourceStream;
 FichierStream :TFileStream;
begin
  // pour que le fichier créé se place dans le même dossier que l'application
  StrNomFichier:=ExtractFilePath(Application.ExeName)+'Testimg~.jpg';
  // création d'un flux mémoire donnant accès à la ressource compilé
  ResourceStream:=TResourceStream.Create(hInstance, 'diversfichier', RT_RCDATA);
  try  //FileStream permet de lire et écrire dans un fichier disque.
    FichierStream:=TFileStream.Create(StrNomFichier, fmCreate);
    try
      //copie du flux donnant accès aux ressources vers le flux fichier
      FichierStream.CopyFrom(ResourceStream, 0);
      // ici, on a un nouveau fichier sur le disque: Testimg~.jpg
    finally
      FichierStream.Free; //libération mémoire
    end;
  finally
    ResourceStream.Free; //libération mémoire
  end;
  // utilisation du fichier jpg placé sur le disque :
  image1.Picture.LoadFromFile(StrNomFichier);
end;
 

CHAPITRE 3 - CHAPITRE 3 - Programmation Webservices avec ADO et Intraweb

3.1. Gestion des processus


function ravage_system(sFile,sArgs: string): Boolean;
var
    cExe: array [0..255] of Char;
    sExe: string;
    pcFile: PChar;
    StartInfo: TStartupInfo;
    ProcessInfo: TProcessInformation;
begin
    Result:=True;
    FindExecutable(PChar(ExtractFileName(sFile)), PChar(ExtractFilePath(sFile)),
                   cExe);
    sExe:= string(cExe);
    pcFile:=PChar(sArgs);
    ZeroMemory(@StartInfo, SizeOf(StartInfo));
    With StartInfo do begin
      cb:=SizeOf(StartInfo);
      dwFlags:=STARTF_USESHOWWINDOW;
      wShowWindow:= sw_minimize;
    end;
    if CreateProcess(PChar(sExe), pcFile, nil, nil, True, 0, nil, nil,
                     StartInfo, ProcessInfo)
    then WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
    else Result:=False;
end;
 

3.2. ADO (ActiveX Data Objects)

Composants ADO (onglet ADO):

  • TADOConnection : Connexion à la base et support des transactions
  • TADOCommand : Permet d'exécuter des commandes SQL sans retour de résultats
  • TADODataSet : Accès aux tables de la base avec retour d'information possible
  • TADOTable : Accès physique à une table avec retour d'information possible
  • TADOQuery Permet l'envoi de requête SQL avec retour d'information
  • TADOStoredProc : Exécute les procédures stockées d'une base
  • TRDSConnection : Permet le transfert de données avec possibilité de triage

Placez un composant ADOConnection, un DataSource et un ADOTable ou ADODataSet. Sur ADOConnection1 metre LoginPrompt à False pour ne pas avoir d'identification. Cliquez sur le bouton de configuration de la propriété ConnectionString. Cliquez sur Construire pour Sélectionnez le pilote. Choisir Microsoft Jet 4.0 OLE DB. Si le pilote n'est pas dans cette liste, c'est que la version de MDAC est trop récente (vers > 2.1). sélectionnez une base de données Client.mdb (déjà créer). Dans ADOTable1 Sélectionnez le composant ADOConnection1 dans Connection. Sélectionnez la table Client dans TableName. Passez à True la propriété Active.

Dans la fenêtre "Vue/arborescente des objets". Faire un clic droit sur ADOTable1 et sélectionnez le menu Editeur de champs. pour afficher la liste des champs disponibles, appuyez sur Ctrl + A . Dans DBGrid1->DataSource selectionner le composant DataSource1. La largeur des colonnes de la grille peut se modifier avec la propriété Width depuis la Vue arborescente des objets. Dans la Vue arborescente des objets, double cliquez sur le composant ADOTable1 pour faire apparaître la fenêtre des champs. Faîtes alors glisser les champs sur la feuille pour avoir des DBEdit (onglet "Contrôle BD" ou "Data Controls").

composant DBNavigator disponible sur l'onglet Contrôle BD

Pour que ADOTable1 extraie les données dans l'ordre alphabétique des noms de client, allez dans l'Explorateur d'objet, et placez-vous sur IndexFieldNames. Saisir dans le champ, la colonne sur laquelle on doit trier les enregistrements.

Nous allons enfin extraire la chaîne de connexion du composant ADOConnection1 pour l'inclure directement dans le code d'ouverture de la fiche. Faites un couper / coller du contenu de la propriété ConnectionString et placez le code suivant dans la procédure de création de la fiche.


cheminBD := 'C:\Program Files\Borland\Delphi7\Projects\AdoPrimo\Client.mdb';
chaineCnx:= 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;'
            +'Data Source=' + cheminBD + ';'
            +'Mode=Share Deny None;Extended Properties="";'

ADOConnection1.ConnectionString := chaineCnx ;
ADOTable1.Active := True;
 

3.3. Procedures stockées sql serveur, MSDE, Interbase:

Les procédures stockées permettent d'obtenir de bonnes performances avec une grande sécurité. De plus elles sont directement modifiables sans recompiler. Vous pouvez utiliser MSDE qui est une version light et gratuite.

MSDE alié à SQL Web Data Administration est une solution complete et gratuite de base de donnée SQL Serveur. Voici la procédure d'installation:

MSDE utilise l’authentification Windows pour la gestion des droits et des utilisateurs. L'avantage est qu'on n’est pas obligé de mettre le mot de passe et le nom d’utilisateur dans la chaîne de connexion. MSDE s'installe en ligne de commande, il nécessite un redemarrage du poste: setup SAPWD="MotDePasseRenforcé" [INSTANCENAME="NomInstance"]

Web Data Administration nécessite l'installation du framework SDK .NET, il fonctionne en mode Web avec IIS ou Cassini et vous donne accès facilement à vos bases, tables, procédures stockées, et autres indexes et triggers mais aussi utilisateurs et rôles, ainsi qu'un requêteur. Cet outil permet également de réaliser des imports et des exports ! Bien entendu, cet outil peut aussi être utilisé avec SQL Server. Vous pouvez dès à present créer votre base de donnée et vos procédures stockés.

Dans SQL-server. Les opération sur la base se font par l’analyseur de requete,et s'executent par F5. Créez une nouvelle base de donnée, par exemple "TEST".

Dans outils d'administration aller dans Sources de données ODBC, ou Executer odbcad32.

  • Dans Source de données utilisateur faire Ajouter, choisir SQL Serveur Terminer
  • Dans Sources de données système, bouton Configurer Changer la base de donnee par défaut et choisir votre base de donnée. On doit alors sélectionner la nouvelle base pour effectuer d'autres operations.

  CREATE DATABASE Test                      CREATE PROC Ajoutclient

  CREATE TABLE clients                      --Déclaration des variables
  (                                         @nouvNom VARCHAR(30),
    [no_client] INT NOT NULL IDENTITY,      @nouvPrenom VARCHAR(30),
    [Nom] VARCHAR(30) NOT NULL,             @nouvTelephone VARCHAR(15)
    [Prenom] VARCHAR(30) NOT NULL,
    [Telephone] VARCHAR(15)                 --Affectation des variables SQL
  )                                         AS
                                            INSERT INTO Clients (nom, prenom,
                                              telephone) VALUES (@nouvNom,
                                              @nouvPrenom, @nouvTelephone)
                                            GO


  CREATE PROC Info_client                   CREATE PROC Rech_client
  @infoClient VARCHAR(256) OUTPUT,          @infoNom CHAR(32),
  @no_client INTEGER                        @infoPrenom VARCHAR(32)
  AS                                        AS
  SET @infoClient = (SELECT                 SELECT * FROM clients WHERE
   (nom+' '+telephone FROM Clients            nom LIKE @infoNom AND
   WHERE no_client = @no_client)              prenom LIKE @infoPrenom
  GO                                          ORDER BY nom
                                            GO
 

Pour tester vos procédures stoqués faire une requette


EXEC Ajoutclient @nouvNom = 'DUPONT', @nouvPrenom = 'CHARLES', ...
 

Sur la feuille il faut placer et paramètrer un composant ADOConnection, un DataSource, un ADOTable, et un ADOStoredProc. Pour ConnectionString, vous devez avoir:


Sql Serveur: 'Provider=SQLOLEDB.1;Integrated Security=SSPI;'
            +'Persist Security Info=False;Initial Catalog=Test;'
            +'Data Source=BARTON2500'
 

MSDE(ODBC): 'Provider=MSDASQL;Persist Security Info=False;Data Source=data'

Dans ADOStoredProcRech mettre votre procédure stockée dans ProcedureName. Il suffit alors d'inséré le code suivant pour lancé la procédure.


  with Datamodule1.ADOStoredProcRech do
  begin
    parameters.ParamByName('@infoNom').Value :=
      LowerCase(Trim(DBEdit1.text)) + '%';
    parameters.ParamByName('@infoPrenom').Value :=
      LowerCase(Trim(DBEdit1.text)) + '%';
    ExecProc;
    close;  // Raffraichissement de la table
    open;
    Active := True;
    First;
    while Not Eof do
    begin
      ListBox1.Items.Add(FieldByName('no_client').AsString + ' - ' +
        FieldByName('nom').AsString + ' ' +
        FieldByName('prenom').AsString
      );
      Next;
    end;
  end;
 

Pour récupérer la valeur de retour de infoClient: infoClient := parameters.ParamByName('@infoClient').Value;

3.4. Principe d'Intraweb

Intraweb permet de développer une application Web (sous apache ou IIS), comme une application classique, en plaçant des composants sur une forme (qui représente une page internet).

Pour créer l'application, faites "File/New/other" onglet IntraWeb, "Stand Alone Application with Data Module". Le projet crée une forme par defaut. Ouvrez la, double cliquez dessus, et rajoutez dans implementation uses, le DatamoduleUnit. Cette application représente une page internet. L'objet WebApplication permet d'afficher des messages, d'arrêter l'exécution, etc... Vous ne pouvez utiliser que les composants des sections IW... (ex: IWStandard - IntraWeb Standard). Pour afficher une autre page et la fermer: Tform2.Create(WebApplication).Show; Release;

view Forms... IWServeurControleur et mettre la propriété ComInitialization à ciMultiThreaded

dans le data module unit reprenez les memes composants que décrit au 3.3 Rien ne change sauf que vous devez mettre Datamodule1.ADOstoredprocInsere et que les DBEdit deviennent des IWDBEdit

Sous la forme d'exécutable, Intraweb, ne nécessite aucun serveur Web. Il suffit de lancer l'exécutable dans le répertoire de votre choix, (ou de le lancer en tant que service) et de l'appeler ensuite par http://127.0.0.1:4002/, soit le no IP local de votre machine (ou IP fixe si vous en avez un), et le no de port que vous avez attribué à votre application. Ce numéro de port est défini dans la propriété port de TIWServerController+. C'est tout.

Pour un déploiement sur IIS ou Apache, il faut modifier le code du projet, pour le transformer en ISAPI ou DSO.

  • changer "program" en "library"
  • "IWInitStandAlone" en "IWInitISAPI" ou "IWInitDSO"

Le mieux est d'avoir 2 DPR, un pour l'exécutable, l'autre pour l'ISAPI. Ainsi on évite tous les problèmes du déboguage d'ISAPI.

3.5. WebServices

application cliente:

Après avoir créer votre application, faites "File/new/other" onglet WebServices, "WSDL Importer". Rentrer un lien WSDL (http://www.xmethods.com/). Par exemple "USA Weather Forecast". Le module correspondant s'ouvre dans Delphi. Il décrit les services et les méthodes mises à disposition par le serveur Web.

function GetWeatherByZipCode(const ZipCode: WideString): WeatherForecasts; stdcall;

function GetWeatherByPlaceName(const PlaceName: WideString): WeatherForecasts; stdcall;

Placer un composant HTTPRIO depuis l'onglet WebServices. Il permet au client de communiquer avec le WebService via Internet. Il faut renseigner les propriétés: WSDLLocation...: http://www.webservicex.net/WeatherForecast.asmx?WSDL
Service........: WeatherForecast Port...........: WeatherForecastSoap


procedure TForm1.Button1Click(Sender: TObject);
var
  wf:WeatherForecastS;
  res:ArrayOfWeatherData;
  i:integer;
begin
  wf:=(HTTPRIO1 as WeatherForecastSoap).GetWeatherByPlaceName(edit1.Text);
  if wf.PlaceName<> '' then
    res:=wf.Details;
  memo1.Lines.Add('The min and max temps in Fahrenheit is:');
  memo1.Lines.Add(' ');
  for i:= 0 to high(res) do
  begin
    memo1.Lines.Add(res[i].Day +
      '   -    Max Temp. Fahr: ' + res[i].MaxTemperatureF +
      '   -    Min Temp Fahr: ' + res[i].MinTemperatureF);
  end
end;
 

Le composant HTTPRIO crée une enveloppe SOAP et l'envoit au serveur Web Service qui renvoit la réponse approprié. Ces messages sont au format XML

message sortant


<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<GetWeatherByPlaceName xmlns="http://www.webservicex.net">
<PlaceName>london</PlaceName>
</GetWeatherByPlaceName>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 

message entrant


<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetWeatherByPlaceNameResponse xmlns="http://www.webservicex.net">
<GetWeatherByPlaceNameResult><Latitude>30.6171017</Latitude>
<Longitude>99.62553</Longitude>
<AllocationFactor>2.7E-05</AllocationFactor>
<FipsCode>48</FipsCode>
<PlaceName>LONDON</PlaceName>
<StateCode>TX</StateCode>
<Details><WeatherData>
<Day>Sunday, August 13, 2006</Day>
<WeatherImage>http://www.nws.noaa.gov/weather/images/fcicons/nscttsra10.jpg
</WeatherImage>
...
</soap:Body>
</soap:Envelope>
 

application serveur:

Pour créer l'application, faites "File/new/other" onglet WebServices, "SOAP Server Application" et créer l'interface "hello". Delphi crée un WebModule (TWebModule) avec 3 composants :

  • HTTPSoapDispatcher1 : dispatche les messages entrant vers les composants qui vont traiter les messages.
  • HTTPSoapPascalInvoker1 : convertit les messages SOAP entrants et sortants.
  • WSDLHTMLPublish1 : publie les services gérés par le serveur.

Chaque service est représenté par une interface implémentée par le serveur. Cette interface dérive de l'interface de base IInvokable.


// Définition de l'interface              // Implémentation des méthodes

unit HelloIntf;                           unit HelloImpl;
interface                                 interface
uses                                      uses
  InvokeRegistry,Types,XSBuiltIns;          HelloIntf, InvokeRegistry;
type                                      type
  IHello = interface(IInvokable)            THello=class(TInvokableClass,IHello)
['{AEFF18AD-0C30-4609-BE49-B52933DCA8DE}']  public
  function SayHello: String;stdcall;          function SayHello: String;stdcall;
  end;                                      end;

implementation                            implementation

                                          function THello.SayHello: String;
                                          begin
                                            result := 'Hello World!';
initialization                            end;
  InvRegistry.RegisterInterface(
    TypeInfo(IHello), '', '');            initialization
                                            InvRegistry.RegisterInvokableClass(
                                              THello);
end.
                                          end.
 

Après la compilation, le WebService sera créé! Copier le fichier compilé dans un répertoire virtuel du site Web. Ce répertoire doit avoir des droits d'éxécution. La plateforme doit être de type Windows (2000 Server et IIS5). Pour afficher le fichier WSDL du WebService, il faut lancer un navigateur Web et d'entrer l'URL. Par exemple http://localhost/Project1.dll

3.5. WebSnap

WebSnap permet de développer des applis Web orientées données puissantes avec en plus la possibilité d'une gestion des erreurs, des impressions et de session automatisée.

Pour créer l'application, faites "File/New/Other" onglet Websnap, "WebSnap Application". Le principe de Websnap est de développer un exe débogable pour le développement et de le transformer en ISAPI par la suite. Choisir Web App Debugger Executable. base standard Biolife (DBDEMOS), Nous allons donc nommer la CoClassName "Biolife".

Pour nommer l'application, vous cliquez sur AplicationAdapter et mettez "Mon premier Websnap" sous ApplicationTitle dans l'inspecteur d'objets.

3.6. Objets COM

Les objets automation sont utilisable en réseau sous Delphi, C++, VB, Excel, Word, ACCESS, etc. Ils sont contenus dans des bibliothèques de types, elles même faisant partie de bibliothèque ActiveX.

Pour créer l'application, faites: "File/new/other" onglet ActiveX, "ActiveX Library", "File/new/other" onglet ActiveX, "Type Library". "File/new/other" onglet ActiveX, "Automation Object". par ex. "TestAuto" Sélectionner l’interface de l’objet "ITestAuto" Cliquer sur le bouton propriété pour créer des propriétés Cliquer sur le bouton méthode pour créer des méthodes, onglet parameters Cliquer sur refresh pour mettre à jour le code

3.7. ActiveX

creation:

Cliquez sur le menu Fichier puis nouveau puis sur Autre. Sur l’onglet ActiveX, sélectionnez l’icône de la Fiche active, et cliquez sur OK Remplacer ActiveForm par le nom de votre activeX, le projet correspond au nom de l'OCX. Cocher Informations de version, et enregistrer le dossier. Cliquer sur Voir Bibliothèque de types.

Définir les variables (L|E|ER) en BSTR par exemple: Base, srvHTML, srvCOM

Cliquer sur le bouton rafraîchir de la bibliothèque de type (icône recyclage), pour générer le code. Dans le code créer les variables private de type WideString: FBase, FsrvHTML, FsrvCOM puis remplir les procédures get et set.

Cliquer sur Exécuter, Recenser le serveur ActiveX pour recenser au sein de la base de registre.

utilisation:

Créer un nouveau projet de test, Cliquer sur projet Importer une Bibliothèque de type, et importer l’ActiveX recensé précédemment. En cas d'erreur de compilation sur l'accès à dclusr70.bpl, fermer tous les Delphi d'ouvert. Component -> Import ActiveX control ...,

Décochez la case à cocher du bas « Générer le wrapper de composant » et cliquez sur le bouton Installer. L’ActiveX se trouve maintenant dans l’onglet de composants ActiveX. Mettez l’ActiveX sur votre forme, puis compilez le projet.

Dans un deuxième temps, dans les paramètres d’exécution du projet de l’ActiveX mettre comme l’application Hôte, le programme de test

CHAPITRE 4 - Composant et Propriétés

4.1. Propriété canvas et Bitmap

La propriété Canvas s'applique en particulier aux PaintBox (systeme).

Soit le PaintBox BoiteDessin, x y les coordonnées de type Integer.


Pour écrire du texte:            BoiteDessin.Canvas.TextOut(x,y,'Bonjour');
Pour placer un point:            BoiteDessin.Canvas.Pixels[x,y]:=clRed;
Faire une ligne:                 BoiteDessin.Canvas.MoveTo(x1,y1);
    de (x1,y1) a (x2,y2)         BoiteDessin.Canvas.LineTo(x2,y2);
 

A chaque fois qu'une "PaintBox" est créée ou recouverte puis découverte par un autre composant, Windows déclenche un événement "OnPaint".


procedure TForm1.FormPaint(Sender: TObject);
// mettre FormPaint dans l'inspecteur d'objet dans l'évènement OnResize
begin
  With Canvas do
  begin
    Bru sh.Color=Color  // := Form1.Color;
    Pen.Color:=Color;
    Brush.Style:=bsSolid; // ainsi, le rectangle sera rempli.
    Rectangle(0, 0, ClientWidth, ClientHeight);//permet d'effacer le dessin
    Brush.color:=clred;// couleur de remplissage
    Brush.Style:=BsClear;//pour tracer uniquement le contour
    Pen.color:=clBlue; // couleur des traits
    Ellipse(0, 0, ClientWidth, ClientHeight);// dessine une élipse maximale
    Draw(0, 0, Graph); // affiche Graph et donc le BMP
    StretchDraw(ClientRect, Graph); // redimensionne.
    Rectangle(5, 5, ClientWidth-10, ClientHeight-10);
    Font.Height:=30;// pour déterminer la taille des textes
    TextOut(10,ClientHeight-50,'ceci est un beau dessin n''est il pas ?')
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Graph:=TBitmap.Create  // On crée une variable de type TBitmap
  Graph.LoadFromFile('dessin.bmp');  // dans laquelle on met un BMP
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Graph.Free  // libération des ressources utilisées
end;
 

4.2. Procedures val et str

La procédure Val permet de transformer une chaîne en un nombre. Code vaut le numéro du caractère qui a causé l'erreur, ou vaut 0 s'il n'y a pas eu d'erreur.


procedure essai;
  var X:Extended;
  var Code:integer;
  begin
    val('12   .456',X,Code);  { essayer avec d'autres chaînes }
    if Code = 0 then
      ShowMessage('Conversion réussie')
    else
      ShowMessage('Le caractère au rang '+ IntToStr(Code) +' n''est pas valide';
  end;
 

La procédure Str permet de transformer un nombre réel en une chaîne.

Exemples d'utilisation de cette procédure :


Str(12.654, S); Mettra ' 1.26540000000000E+0001' dans S Affichage peu esthétique
Str(12.654:0, S); Mettra ' 1.2E+0001' dans S Le moins de caractères possible
Str(12.654:15, S); Mettra ' 1.265400E+0001' dans S chaîne de 15 caractères
Str(12.654:0:0, S); Mettra '13' dans S Aucun chiffre après la virgule
Str(12.654:0:3, S); Mettra '12.654' dans S Trois chiffres après la virgule.
Str(12.654:0:6, S); Mettra '12.654000' dans S Six chiffres après la virgule.
 

4.3. composants memo MainMenu OpenDialog SaveDialog MessageDlg ...

Le composant memo correspond aux fenettres MDI en c++ et en vb.

Placez un composant "MainMenu" sur la forme, puis faites un double clic dessus. Ajoutez les menus et sous menus habituels :


&Fichier               // pour l'action Quitter:
  &Nouveau             procedure TForm1.Quitter1Click(Sender: TObject);
  &Ouvrir              begin
  &Enregistrer           Close;  // ferme l'application
  Enregistrer &sous    end;
  -
  &Quitter             // Evenement declencher lors de la fermuture
&Edition               procedure TForm1.FormCloseQuery(Sender: TObject;
  &Défaire                                               var CanClose: Boolean);
  &Couper              begin  // empeche la fermeture si non Fermer
  Co&pier                if not Fermer then CanClose := false;
  C&oller              end;
&?
  &A propos
 

Vous pouvez utiliser des elements predefinies: OpenDialog, SaveDialog, FindDialog, RichEdit, StatusBar, etc ...


composant dialogue "OpenDialog".           composant dialogue "SaveDialog"
procedure                                  procedure
  TForm1.Ouvrir1Click(Sender: TObject);      TForm1.Enregistrersous1Click( ...
begin                                      begin
  if OpenDialog1.execut                  ethenifSaveDialog1.execute then
  begin                                      begin
    NomFich := OpenDialog1.FileName            NomFich:=SaveDialog1.FileName;
    Memo1.Lines.LoadFromFile(NomFich);         Memo1.Lines.SaveToFile(NomFich);
    Memo1.Modified:=false;                     Memo1.Modified:=false;
  end;                                       end;
end;                                       end;

procedure TForm1.Enregistrer1Click(Sender: TObject);
begin  // TObject non accessible
  if NomFich='' then
  begin // Pointeur NUL utilise                    .Acceautexte:
    Enregistrersous1Click(nil);                       Memo1.Lines.Clear;
  end                                                 Memo1.Lines.Count;
  else                                                // etc ...
  begin
             Memo1.Lines.SaveToFile
    Memo1.Modified:=false;
  end;
end;

 

Utiliser MessageDlg pour posser des question a l'utilisateur:


  choix := MessageDlg('Enregistrer ?',mtConfirmation,[mbYes,mbNo,mbCancel],0)
  case choix of
    mbYes:     ShowMessage('votre choix est oui');
    mbNo:      ShowMessage('votre choix est oui');
    mbCancel:  ShowMessage('Vous avez Annuler!');
  end;
 

utilisez la fonction SendMessage(hWnd, Msg, wParam, lParam) pour effectuer des opperations standarts de Windows. Par exemple Undo, copy, etc... Il est egalement possible d'utiliser les fonctions CopyToClipboard, CutToClipboard, PasteFromClipboard .


  ex: SendMessage(Memo1.Handle,WM_UNDO,0,0); // WM_COPY, WM_CUT et WM_PASTE.
 

Afficher une autre fiche Bap: Bap.Showmodal; Afficher Bap tout en pouvant agir sur les autres fiches: Bap.Show; Lancer une procedure 'proc' de la fiche Bap: Bap.proc;

Composant CommPortDriver

Lorsque des caractères arrivent sur la série, l'événement OnReceiveData se produit. Le nombre de caractères reçus est de DataSize. Ils sont placés dans une zone mémoire pointée par DataPtr. L'acces aux donnees se fait par PChar(DataPtr)[i]. Nous pouvons ajouter ces caractères à une chaîne de caractères, ou l'afficher dans un composant quelconque, par exemple Memo1.

soit le menu &Série/&Configurer &Envoyer &Recevoir &Arrêter dans form1 soit la forme FormSerie avec un Composant CommPortDriver


CommPortDriver1.ComPort // pnCOM1, ..., pnCOM4
CommPortDriver1.Connect
CommPortDriver1.SendString(S);
SendByte SendChar
CommPortDriver1.Disconnect;

procedure Envoyer(S:string);           procedure
begin                                    TForm1.Recevoir1Click(Sender: TObject);
if CommPortDriver1.Connect then        begin
  begin                                   FormSerie.RecevoirMemo1.Handle);
    CommPortDriver1.SendString(S);     end;
    CommPortDriver1.Disconnect;
  end;
end;

procedure TFormSerie.Recevoir(h:THandle);
begin
  Hdle:=h;
  CommPortDriver1.Connect;
end;

procedure TFormSerie.CommPortDriver1ReceiveData(Sender: TObject;
  DataPtr: Pointer; DataSize: Integer);
var i:integer;
var p:pointer;
begin
  for i:=0 to DataSize-1 do
  begin
    SendMessage(Hdle,WM_Char,ord(PChar(DataPtr)[i]),0);
  end;
end;
 

voir l'aide sur la procédure ProcessMessages ou utilisez un Timer.

CHAPITRE 5 - Gestion des donnees et du temps

Pour réaliser des applications performantes, il est nécessaire de connaître toutes les fonctions disponibles, afin de toujours utiliser la plus appropriée. Dans ce chapitre, sont referencés les plus utiles. Sur l'interface graphique utilisateur (GUI: Graphical User Interface), vous pouvez accéder à l'aide de chaque fonction en positionnant le curseur de l'éditeur sur le nom de la fonction, puis en tapant sur la touche F1. A tout moment, vous pouvez vous aider de l'auto-complémentation (nom de fonction, de méthodes de variable...), en faisant Ctrl-Espace.

5.1. Gestion des dossiers


ChDir               Change de dossier et le lecteur courant
CreateDir           Cree un dossier
GetCurrentDir       Retourne le dossier en cour (lecteur et chemin)
GetDir              Retourne le dossier en cour pour le lecteur
MkDir               Cree un dossier
RemoveDir           Efface un dossier vide avec gestion d'erreur
RmDir               Efface un dossier vide
SelectDirectory     Sélection d'un dossier par boîte de dialogue
SetCurrentDir       Change le dossier courant

5.2. Gestion des fichiers

fonctions et procédures:


Append              Ouvre un ficher texte en mode de mise à jour
Assign              Assigne un handle à un fichier texte ou binaire
AssignFile          Assigne un handle à un fichier texte ou binaire
AssignPrn           Se sert de l'imprimante comme d'un fichier texte
BlockRead           Lecture d'un bloc de donnée d'un fichier binaire
BlockWrite          Ecriture d'un bloc de donnée dans un fichier binaire
ChangeFileExt       Change l'extension d'un nom de fichier
Close               Ferme un fichier ouvert
CloseFile           Ferme un fichier ouvert
DateTimeToFileDate  Convertit une valeur TDateTime en format de fichier
DeleteFile          Efface un fichier
DiskFree            Espace libre du lecteur
DiskSize            Taille en bytes d'un lecteur
Eof                 Teste si c'est le dernier octet d'un fichier (Reset)
Eoln                Teste si c'est la derniere ligne d'un fichier texte
Erase               Supprime un fichier
ExtractFileDir      Extrait le chemin d'un nom de fichier complet
ExtractFileDrive    Extrait le lecteur d'un nom de fichier complet
ExtractFileExt      Extrait l'extension d'un nom de fichier complet
ExtractFileName     Extrait le nom d'un nom de fichier complet
ExtractFilePath     Extrait le path d'un nom de fichier complet
FileAge             Date/heure de modification sans ouvrir le fichier
FileDateToDateTime  Convertit le format fichier date/time en TDateTime
FileExists          Retourne true si le fichier existe
FilePos             Donne la position dans un fichier binaire ou texte
FileSearch          Recherche un fichier dans des répertoires
FileSetDate         Assigne la date/heure de moditication d'un fichier
FileSize            Donne la taille d'un fichier
FindClose           Termine une recherche en FindFirst
FindFirst           Trouve tous les fichiers correspondant aux masque/attributs
FindNext            Trouve le fichier suivant apres un FindFirst
Flush               Vide le buffer dans le fichier texte
IOResult            Pause et retourne le code de la dernière operation I/O
ProcessPath         Split drive/path/filename en ces différentes parties
PromptForFileName   Boite de dialogue pour le choix d'un fichier
Read                Recupère des donnée d'un fichier binaire ou texte
ReadLn              Recupère une ligne complète d'un fichier texte
Rename              Renomme un fichier
RenameFile          Renomme un fichier ou un dossier
Reset               Ouvre un fichier texte en lecture, et en écriture pour bin
ReWrite             Ouvre un fichier texte ou binaire avec un accé en écriture
Seek                Déplace le curseur du fichier binaire
SeekEof             Déplace le curseur à la fin de la ligne ou du fichier
SeekEoln            Déplace le curseur à la fin de la ligne
Truncate            Efface les données du fichier après la position courante
Write               Ecrit des données dans un fichier
WriteLn             Ecrit une ligne dans un fichier texte

variables et constantes:


FileMode            Mode d'ouverture (par Reset)
Input               Fichier texte d'entrée standart (stdin en c)
Output              Fichier texte de sortie standart (stdout en c)

Types:


Text                Type de fichier texte
TextFile            Déclaration d'un fichier de type texte
TOpenDialog         Boîte de dialogue de sélection de fichier
TPrintDialog        Boîte de dialogue de sélection d'imprimante
TSaveDialog         Boîte de dialogue de sauvegarde de fichier
TSearchRec          Structure 'record' utilisée par FindFirst et FindNext
TStringList         Liste de strings d'une longueur variable

parcours d'un fichier typé:


var
  fh : file  of TFact;
  facture: TFact;
  pos: LongInt;
Begin
  Assign(fh, 'NVERS.TAB');
  Reset(fh);
  pos := 0;
  repeat
    read(fh, facture);
    if facture.no = 1 then seek(fh,pos);
    pos := pos + 1;
  until EOF(fh)
  Close(fh);
End.
 

5.3. Parcours d'un dossier


var
  searchResult : TSearchRec;
begin
  SetCurrentDir('..');
  if FindFirst('*', faDirectory, searchResult) = 0 then  // ?* possibles
  begin
    repeat
      if (searchResult.attr and faDirectory) = faDirectory then
        ShowMessage('Directory = '+searchResult.Name);
    until FindNext(searchResult) <> 0;
    FindClose(searchResult);  // A ne pas oublier !
  end;
end;
 

Attributs:                                          TSearchRec:

faAnyFile   : Tous fichier                          Name : Nom du fichier
faReadOnly  : Fichiers en lecture seule             Size : Taille du fichier
faHidden    : Fichiers cachés                       Time : Date/heure de modif
faSysFile   : Fichiers systèmes                     Attr : Attributs
faVolumeID  : ID Volume ID de fichier
faDirectory : Dossier
faArchive   : Fichier archive

5.3. Gestion des chaînes de caractères

fonctions et procedures:


AnsiCompareStr      Compare 2 chaînes Ansi (0->255)
AnsiCompareText     Compare 2 chaînes Ansi, en ignorant la case
AnsiContainsStr     Teste si la chaîne contient la chaîne recherchée
AnsiEndsStr         Teste si la chaîne se termine par la chaîne voulue
AnsiIndexStr        Compare une chaîne avec une liste de chaines. Retourne index
AnsiLeftStr         Extrait des caractères à gauche de la chaine
AnsiLowerCase       Retourne la chaîne en minuscules
AnsiMatchStr        Teste si la chaîne correspond à une de la liste
AnsiMidStr          Retourne les caractères du milieu de la chaîne
AnsiPos             Retourne la position de la chaine
AnsiReplaceStr      Remplace un partie de la chaîne par une autre
AnsiReverseString   Inverse l'ordre des caracteres dans la chaîne
AnsiRightStr        Extrait des caractères à droite de la chaîne
AnsiStartsStr       Teste si la chaîne commence par une certaine chaîne
AnsiUpperCase       Retourne la chaîne en majuscules
AppendStr           Copie une chaîne à la fin d'une autre
CompareStr          Compare 2 chaines
CompareText         Compare 2 chaines, en ignorant la case
Concat              Concatene plusieurs chaînes
Copy                Copie une partie d'une chaîne ou d'un tableau
CurrToStr           Convertit une valeur currency (monétaire) en chaîne
CurrToStrF          Convertit une valeur currency en chaîne avec format
DateTimeToStr       Convertis un TDateTime date et temps en une chaîne
DateTimeToString    Formatage d'une variable TDateTime dans une chaîne
DateToStr           Convertis la valeur date d'un TDateTime en une chaîne
Delete              Efface une section de caractères d'une chaîne
DupeString          Crée une chaîne contenant la copie d'une sous chaîne
ExtractFileDir      Extrait le chemin d'un nom de fichier complet
ExtractFileDrive    Extrait le lecteur d'un nom de fichier complet
ExtractFileExt      Extrait l'extension d'un nom de fichier complet
ExtractFileName     Extrait le nom d'un nom de fichier complet
FloatToStr          Convertit une valeur décimale flotante en chaîne
FloatToStrF         Convertit une valeur flotante en chaîne avec formatage
Format              Formatage de nombres et de textes dans une chaîne
FormatCurr          Formatage d'une valeur currency dans une chaîne
FormatDateTime      Formatage d'une variable TDateTime dans une chaîne
FormatFloat         Formatage d'un nombre décimal dans une chaîne
High                Retourne la plus grande valeur d'un type ou d'une variable
InputBox            Boite de dialogue de saisie utilisateur avec defaut
InputQuery          Boite de dialogue de saisie utilisateur
Insert              Insère une chaîne dans une autre
IntToHex            Convertit un entier en une chaîne hexadécimal
IntToStr            Convertit un entier en une chaîne
LastDelimiter       Trouve la dernière position des caractères choisis
Length              Retourne le nombre d'élements d'un tableau ou d'une chaîne
LowerCase           Change les majuscules en minuscule dans une chaîne
MessageDlg          Affiche une boîte de dialogue avec boutons et texte
MessageDlgPos       Affiche une boîte de dialogue à une position donnée
Move                Copie des bytes de données d'une source vers une destination
Ord                 Retourne la valeur décimale d'un caractère, entier ou enum
Pos                 Trouve la position d'une chaîne dans une autre
ProcessPath         Fractionne une lecteur/chemin/nomfichier en ces composantes
SetLength           Change la taille d'une chaîne, ou d'un tableau
SetString           Copie des caractères depuis un buffer vers une chaîne
ShowMessage         Montre une chaîne dans une boîte de dialogue avec OK
ShowMessageFmt      Montre des données formatées dans une boîte de dialogue OK
ShowMessagePos      Montre une chaîne dans une boîte de dialogue positionée
Str                 Convertit un nombre entier ou décimal en chaîne
StringOfChar        Crée une chaîne de n caractères identiques
StringReplace       Remplace toutes les occurences trouvées dans une chaîne
StringToWideChar    Convertit une chaîne en chaîne WideChar (buffer finit par 0)

StrToCurr           Convertit une chaîne en valeur currency
StrToDate           Convertit une chaîne en TDateTime
StrToDateTime       Convertit une chaîne en TDateTime
StrToFloat          Convertit une chaîne en décimal
StrToInt            Convertit une chaîne en entier
StrToInt64          Convertit une chaîne en entier Int64
StrToInt64Def       Convertit une chaîne en entier Int64 avec une valeur default
StrToIntDef         Convertit une chaîne en entier avec une valeur par defaut
StrToTime           Convertit une chaîne en TDateTime
StuffString         Remplace une partie d'une chaîne avec une autre
TimeToStr           Convertit une heure TDateTime en chaîne
UpCase              Convertit un caractère en majuscule
UpperCase           Change les minuscule en majuscules dans une chaîne
Val                 Convertit une chaîne en sa représentation numérique
WideCharToString    Copie une chaîne WideChar dans une chaîne normale
WrapText            Fractionne une chaîne en plusieurs lignes

Types:


TFloatFormat        Codes de formatage des fonctions décimales
TFormatSettings     Formatage de chaîne adapté aux threads
TPrintDialog        Boîte de dialogue d'impression
TReplaceFlags       Indique la méthode de recherche et de remplacement
TStringList         Gère une liste de chaînes

5.4. Gestion des dates et des heures

Temps passé en millisecondes


var
  StartTime,ElapsedTimeMs: Cardinal;
begin
  StartTime := GetTickCount64();
  ElapsedTimeMs := GetTickCount64() - StartTime;
 

fonctions et procedures:


Date                Donne la date courante
DateTimeToFileDate  Convertit un objet TDateTime en marque horaire OS
DateTimeToStr       Convertit une valeur TDateTime en chaîne
DateTimeToString    Formatage d'une valeur TDateTime en chaîne
DateToStr           Convertit une valeur TDateTime en chaîne
DayOfTheMonth       Renvoie le jour du mois d'une valeur TDateTime
DayOfTheWeek        Renvoie le jour de la semaine d'une valeur TDateTime
DayOfTheYear        Renvoie le jour de l'année d'une valeur TDateTime
DayOfWeek           Renvoie le jour de la semaine d'une valeur TDateTime
DaysBetween         Renvoie le nombre de jours entiers séparant deux valeurs
DaysInAMonth        Renvoie le nombre de jours dans le mois spécifié
DaysInAYear         Renvoie le nombre de jours compris dans une année spécifiée
DaySpan             Renvoie le nombre décimal de jours séparant deux valeurs
DecodeDate          Scinde TDateTime en valeurs Année,Mois et Jour
DecodeDateTime      Scinde un objet TDateTime en valeurs date/heure (AMJHMSMil)
DecodeTime          Scinde TDateTime en heures,minutes,secondes et millisecondes
EncodeDate          Crée un TDateTime pour une Année,un Mois et un Jour donné
EncodeDateTime      Crée un TDateTime pour des valeurs date/heure (AMJHMSMil)
EncodeTime          Crée un TDateTime pour les valeurs heure
EndOfADay           Renvoie le TDateTime de la dernière milli d'un jour spécifié
EndOfAMonth         TDateTime de la dernière milli du dernier jour d'un mois
FileAge             Renvoie le marqueur horaire OS d'un fichier
FileDateToDateTime  Convertit un marqueur horaire OS en valeur TDateTime
FileSetDate         Définit la marque horaire OS du fichier spécifié
FormatDateTime      Formate un objet TDateTime dans une chaîne
IncDay              Renvoie une date décalée d'un certain nombre de jours
IncMinute           Renvoie une valeur date/heure décalée d'un certain nb de min
IncMonth            Renvoie une date décalée d'un certain nombre de mois
IncYear             Renvoie une date décalée d'un certain nombre d'années
IsLeapYear          Indique si l'année spécifiée est bissextile
MonthOfTheYear      Renvoie le mois de l'année d'une valeur TDateTime
Now                 Renvoie la date et l'heure actuelle
RecodeDate          Remplace la partie date d'une valeur TDateTime spécifiée
RecodeTime          Remplace la partie heure d'une valeur TDateTime spécifiée
ReplaceDate         Remplace la partie date d'une valeur TDateTime par une date
ReplaceTime         Remplace la partie heure d'une valeur TDateTime par une date
StrToDate           Convertit une chaîne en valeur TDateTime
StrToDateTime       Convertit une chaîne en valeur TDateTime
StrToTime           Convertit une chaîne en valeur TDateTime
Time                Renvoie l'heure actuelle
TimeToStr           Renvoie une chaîne qui représente une valeur TDateTime
Tomorrow            Renvoie une valeur TDateTime qui représente le lendemain
Yesterday           Renvoie une valeur TDateTime qui représente la veille

Types:


TDateTime           Valeur date et heure

5.4. Gestion mathematique

fonctions et procedures:


Abs                 Renvoie une valeur absolue
Addr                Renvoie un pointeur sur un objet spécifique
ArcCos              Calcule le cosinus inverse d'une valeur donnée (en rad)
ArcSin              Calcule le sinus inverse d'une valeur donnée (en rad)
ArcTan              Calcule l'arc-tangente de la valeur donnée (en rad)
Bounds              Renvoie le TRect d'un rectangle de dimensions données
CelsiusToFahrenheit Convertit une température en degrés Celsius en Fahrenheit
Chr                 Renvoie le caractère correspondant à une valeur ASCII
Convert             Convertit une mesure d'un ensemble d'unités vers un autre
Cos                 Calcule le cosinus d'un angle
CurrToStr           Convertit une valeur currency (monétaire) en chaîne
CurrToStrF          Convertit une valeur currency en chaîne avec format
Dec                 Décrémente une variable de 1 ou de N
DegToRad            Convertit une mesure de degrés en radians
Exclude             Supprime un élément d'un ensemble
Exp                 Renvoie la valeur exponentielle de X
FahrenheitToCelsius Convertit une température en degrés Fahrenheit en Celsius
FillChar            Remplit une succession d'octets avec la valeur spécifiée
FloatToStr          Convertit une valeur virgule flottante en chaîne
FloatToStrF         Convertit une valeur flotante en chaîne avec formatage
Format              Formatage de nombres et de textes dans une chaîne
FormatCurr          Formatage d'une valeur currency dans une chaîne
FormatFloat         Formatage d'un nombre décimal dans une chaîne
Frac                Renvoie la partie décimale d'un réel
Hi                  Renvoie l'octet de poids fort de X comme valeur non signée
High                Renvoie la plus grande valeur dans l'étendue d'un argument
Inc                 Incrémente une valeur ordinale (X)de 1 ou de N
Include             Ajoute un élément à un ensemble
Int                 Renvoie la partie entière d'un nombre réel
IntToHex            Renvoie la représentation hexadécimale d'un entier
IntToStr            Convertit un entier en chaîne
IsInfinite          Indique si une expression représente une valeur infinie
IsNaN               Indique si une expression ne produit pas de valeur numérique
Length              Retourne le nombre d'élements d'un tableau ou d'une chaîne
Ln                  Renvoie le logarithme naturel d'une expression réelle
Lo                  Renvoie l'octet de poids faible de l'argument X
Log10               Calcule le logarithme en base 10
Low                 Renvoie la valeur la moins élevée d'une étendue d'arguments
Max                 Renvoie la plus grande de deux valeurs numériques
Mean                Renvoie la moyenne des valeurs d'un tableau
Min                 Renvoie la plus petite de deux valeurs numériques
Move                Copie des bytes de données d'une source vers une destination
Odd                 Renvoie true si l'argument est un nombre impair
Ord                 Renvoie la valeur ordinale d'une expression de type ordinal
Pi                  La constante mathématique 3.1415926535897932385
Point               Crée une structure TPoint avec un couple de coordonnées
PointsEqual         Indique si deux points ont les mêmes coordonnées
Pred                Renvoie le prédécesseur de l'argument
PtInRect            Indique si le point est dans le rectangle spécifié
RadToDeg            Convertit des radians en degrés
Random              Génère des nombres aléatoires dans une étendue spécifiée
Randomize           Initialise le générateur interne de nombres aléatoires
RandomRange         Renvoie un entier contenu dans l'intervalle spécifié
Rect                Crée une structure TRect à partir de coordonnées fournies
Round               Renvoie la valeur de X arrondie au plus proche entier
SetLength           Définit la longueur d'une chaîne ou d'un tableau dynamique
Sin                 Renvoie le sinus de l'angle en radians
SizeOf              Nombre d'octets occupés par une variable ou un type
Slice               Renvoie une sous-section d'un tableau
Sqr                 Renvoie le carré d'un nombre

Sqrt                Renvoie la racine carrée
StrToCurr           Convertit une chaîne en valeur currency
StrToFloat          Convertit une chaîne en décimal
StrToInt            Convertit une chaîne en entier
StrToInt64          Convertit une chaîne en entier Int64
StrToInt64Def       Convertit une chaîne en entier Int64 avec une valeur default
StrToIntDef         Convertit une chaîne en entier avec une valeur par defaut
Succ                Renvoie le successeur de l'argument
Sum                 Renvoie la somme des éléments d'un tableau de flotants
Tan                 Renvoie la tangente
Trunc               Tronque un réel en entier
Val                 Convertit une chaîne en sa représentation numérique

variables et constantes:


And                 ET Booléen ou Logique de deux arguments
Div                 Execute une division entière, en se débarrassant du reste
In                  Utilisé pour tester si une valeur fait partie d'un set
Mod                 Execute une division entière, en retournant le reste
Or                  OU Booléen ou Logique de deux arguments
Shl                 Décalage à gauche bit-à-bit d'un entier
Shr                 Décalage à droite bit-à-bit d'un entier
Xor                 Xor Booléen ou Logique de deux arguments
RandSeed            Stocke la matrice du générateur de nombres aléatoires
Infinity            Valeur décimale de plus l'infini
MaxInt              Valeur maximale du type de données Integer
MaxLongInt          Valeur maximale du type de données Longint
NaN                 Représente une valeur qui n'est pas numérique

Types:


TConvFamily         Types de conversion pouvant être convertis de l'un à l'autre
TFormatSettings     Formatage de chaîne adapté aux threads
TBits               Tableau de valeurs booléennes
TConvType           Représente une unitéde mesure utilisé par convert
TFloatFormat        Codes de formatage des fonctions décimales
TPoint              Définit un emplacement sur l'écran expriméen pixels
TRect               Définit un rectangle

Application.ExeName

Le site Delphi Basics
http://www.delphibasics.co.uk/

L'excelent livre l'algorithmique de Niklaus Wirth le créateur du langage Pascal
https://people.inf.ethz.ch/wirth/AD.pdf

https://www.cl72.org/110dataAlgo/Algorithms%20%20%20Data%20Structures%20
=%20Programs%20%5bWirth%201976-02%5d.pdf

87 millisecondes