Nombre d'auteurs : 121, nombre de questions : 910, dernière mise à jour : 13 janvier 2018 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).
Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.
L'équipe Delphi de Developpez.com.
Schématiquement à la question qui suis-je ?, le mot clé Self répond moi-même en renvoyant la référence de l'instance en cours d'utilisation au sein d'une méthode de sa classe. Self permet donc de connaître l'instance en cours et dans certains cas de lever toute ambiguité.
Par exemple ici :
Code delphi : | Sélectionner tout |
1 2 3 4 5 | procedure TObject.Free; begin if Self <> nil then Destroy; end; |
Code delphi : | Sélectionner tout |
1 2 3 | with TPaintBox(Sender).Canvas.Brush do begin Color := Self.Color; |
Supposons que vous souhaitez, pour telle ou telle raison utiliser une Méthode protégée d'un Objet particulier que l'on appellera MaSomme (cela peut être un composant visuel ou non par exemple).
Supposons que notre objet ai été défini comme suit, dans une unité à part :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | unit UnitSomme; interface type TSomme = class private FA,FB: Integer; FResultat: Integer; procedure SetA(const Value: Integer); procedure SetB(const Value: Integer); protected // La fonction que l'on souhaiterais utiliser... function Somme(A,B:Integer):Integer; public constructor Create; destructor Destroy; property A:Integer read FA write SetA; property B:Integer read FB write SetB; property Resultat:Integer read FResultat; end; ... implementation ... function TSomme.Somme(A,B:Integer):Integer; begin result:=A+B; end; ... end. |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 | var MaSomme:TSomme; ... MaSomme.A:=5; MaSomme.B:=9; Result:=MaSomme.Resultat; // ... |
Code delphi : | Sélectionner tout |
TPublicFactorielle(MaFactorielle)
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, unitFactorielle; type //Notre classe dérivée... //A travers sa définitions, toutes les méthodes protégées deviennent //visibles pour tout le code écrit dans notre unité unit1 TPublicSomme=class(TSomme); TForm1 = class(TForm) private { Déclarations privées } public { Déclarations publiques } procedure Calcule; end; ... implementation ... procedure TForm1.Calcule; var MaSOmme:TSomme; begin ... //On transtype MaSomme afin d'utiliser la méthode rendu visible Result:=TPublicSomme(MaSomme).Somme(A,B); .... end; |
Un exemple concret :
On souhaite, par exemple, accéder depuis le code d'une fiche à la variable privée FImageIndex d'un TMenuItem , (n'importe quelle variable privée de n'importe quel objet de n'importe quelle classe aurait pu faire l'affaire).
Solution :
Tout réside dans les possibilités du transtypage, et du fait que les types classes ne sont rien d'autre que des types de pointeurs particuliers.
Tout d'abord, Il faut déclarer la classe TMenuItemPublic de telle façon quelle dérive exactement du même objet que TMenuItem, en l'occurence de TComponent.
Vous remarquerez, que l'on y retrouve exactement les mêmes variables et exactement dans le même ordre que dans la classe TMenuItem, à la différence que ces variables sont toutes déclarées publiques.
Ainsi, on obtient une classe ayant la même structure en mémoire que la classe TMenuItem, ce qui nous autorise alors à transtyper un TMenuItem en TMenuItemPublic et nous permet alors d'accéder à toutes les variables privées de TMenuItem comme si elles avaient été déclarées Public !
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | type TMenuItemPublic=class(TComponent) public FCaption: string; FHandle: HMENU; FChecked: Boolean; FEnabled: Boolean; FDefault: Boolean; FAutoHotkeys: TMenuItemAutoFlag; FAutoLineReduction: TMenuItemAutoFlag; FRadioItem: Boolean; FVisible: Boolean; FGroupIndex: Byte; FImageIndex: TImageIndex; FActionLink: TMenuActionLink; FBreak: TMenuBreak; FBitmap: TBitmap; FCommand: Word; FHelpContext: THelpContext; FHint: string; FItems: TList; FShortCut: TShortCut; FParent: TMenuItem; FMerged: TMenuItem; FMergedWith: TMenuItem; FMenu: TMenu; FStreamedRebuild: Boolean; FImageChangeLink: TChangeLink; FSubMenuImages: TCustomImageList; FOnChange: TMenuChangeEvent; FOnClick: TNotifyEvent; FOnDrawItem: TMenuDrawItemEvent; FOnAdvancedDrawItem: TAdvancedMenuDrawItemEvent; FOnMeasureItem: TMenuMeasureItemEvent; FAutoCheck: Boolean; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 | var UnMenuItem:TMenuItem; begin .... TMenuItemPublic(UnMenuItem).FImageIndex:=NewIndex; .... end; |
Certains constructeurs de classe peuvent lors de leur exécution générer une exception. Dans ce cas son destructeur est appelé automatiquement.
Cette situation étant gérée le plus souvent par le bloc suivant :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | Var MonObjet : TUneClasse; ParametreUn : String; begin Try MonObjet:=TUneClasse.Create(ParametreUn); ...Traitement... Finally FreeAndNil(MonObjet); end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | Var MonObjet : TUneClasse; ParametreUn : String; begin Try MonObjet:=Nil; MonObjet:=TUneClasse.Create(ParametreUn); ...Traitement... finally FreeAndNil(MonObjet); end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | Class procedure TUneClasse.CreateAndNilIfExcept(Var AObjet:TUneClasse; ParametreUn:String); begin try AObjet:=TUneClasse.Create(ParametreUn); except On Exception do begin AObjet:=Nil; //Evite la violation d'accés Raise; // On redéclenche l'exception end; end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | Var MonObjet : TUneClasse; ParametreUn : String; begin Try TUneClasse.CreateAndNilIfExcept(MonObjet,ParametreUn); ...Traitement... finally FreeAndNil(MonObjet); end; end; |
L'utilisation de l'instruction case ... of en Delphi, quoique pratique dans la plupart des cas de programmation peut parfois se révéler inappropriée lorsque le nombre de branchements devient trop grand :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | procedure TForm1.UneActionADeterminer(Parametre:integer); begin ... case Parametre of 0:MaProcedure0; 1:MaProcedure1; 2:MaProcedure2; 3:MaProcedure3; 4:MaProcedure4; 5:MaProcedure5; ..... 203:MaProcedure203; //etc... end; ... end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 | procedure TForm1.UneActionADeterminer(Parametre:integer); begin ... MesProcedures[Parametre]; ... end; |
Code delphi : | Sélectionner tout |
<Nom du Type> = <procedure ou function>[(<paramètres>)[:<type de resultat>]] [of object;]
Code delphi : | Sélectionner tout |
1 2 | type TProcedureAvecParametres=procedure(a,b:integer;s:string) of object; |
Code delphi : | Sélectionner tout |
1 2 | type TProcedureSimple=procedure of object; |
Code delphi : | Sélectionner tout |
1 2 | type TOperationArithmetique=function(a,b:real):real of object; |
Code delphi : | Sélectionner tout |
1 2 | type TTraiterUnCodeErreur=function:boolean of object; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | type TOperationArithmetique=function(a,b:real):real of object; TForm1 = class(TForm) ... private { Déclarations privées } public { Déclarations publiques } ... TableauDeFonctions:array[0..3] of TOperationArithmetique; function Addition(a,b:real):real; function Multiplication(a,b:real):real; function Division(a,b:real):real; function Soustraction(a,b:real):real; ... end; ... implementation ... function TForm1.Addition(a,b:real):real; begin result:=a+b; end; function TForm1.Multiplication(a,b:real):real; begin result:=a*b; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | type TOperationArithmetique=function(a,b:real):real; TForm1 = class(TForm) ... private { Déclarations privées } public { Déclarations publiques } ... TableauDeFonctions:array[0..3] of TOperationArithmetique; ... end; function Addition(a,b:real):real; function Multiplication(a,b:real):real; function Division(a,b:real):real; function Soustraction(a,b:real):real; ... implementation ... function Addition(a,b:real):real; begin result:=a+b; end; function Multiplication(a,b:real):real; begin result:=a*b; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 | procedure TForm1.InitialisationDuTableau begin TableauDeFonctions[0]:=Addition; TableauDeFonctions[1]:=Multiplication; ... //etc. end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | procedure TForm1.UneActionADeterminer(Parametre:integer); begin //si Parametre est compris entre la borne inférieure et la borne supérieure du tableau de procédures if ((Parametre>=low(TableauDeProcedures)) and (Parametre<=high(TableauDeProcedures)) then //si l'entrée du tableau contient effectivement quelque chose (une procédure) if Assigned(TableauDeProcedures[Parametre]) then //exécution de la procédure ad hoc TableauDeProcedures[Parametre]; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 | procedure TForm1.Calcule(OperationChoisie:integer;NombreA,NombreB:real;var resultat:real); begin if ((OperationChoisie>=0) and (OperationChoisie<=3)) then if Assigned(TableauDeFonctions[OperationChoisie]) then resultat:=TableauDeFonctions[OperationChoisie](NombreA,NombreB); end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type //Définition d'un type de procedure simple TProcedureAffichage=procedure of object; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } TableauDeProcedures:array[0..2] of TProcedureAffichage; procedure AffichageShowMessage; procedure AffichageDansLaFiche; procedure AffichageBarreDeTitre; end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.AffichageShowMessage; begin showmessage('Procedure n°1'); end; procedure TForm1.AffichageDansLaFiche; begin canvas.font.Color:=random($ffffff); canvas.TextOut(10,10,'Procédure n°2'); end; procedure TForm1.AffichageBarreDeTitre; var i:integer; oldcaption:string; begin oldcaption:=Caption; for i:=0 to 9 do begin caption:='Procedure n°3'; sleep(200); caption:=''; sleep(100); end; caption:=oldcaption; end; //Événement OnClick du Bouton procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin //choix aléatoire d'une procedure d'affichage i:=Random(3); if assigned(TableauDeProcedures<i>) then TableauDeProcedures<i>; end; //Événement OnCreate de la fiche procedure TForm1.FormCreate(Sender: TObject); begin Randomize; TableauDeProcedures[0]:=AffichageShowMessage; TableauDeProcedures[1]:=AffichageDansLaFiche; TableauDeProcedures[2]:=AffichageBarreDeTitre; end; end. |
Quand vous importez une fonction en langage C qui prend un nombre variable de paramètres, utilisez la directive varargs.
Par exemple :
Code delphi : | Sélectionner tout |
function printf(Format: PChar): Integer; cdecl; varargs;
On souhaite parfois connaître le GUID d'une interface Delphi malheureusement il n'existe pas de méthode dans la VCL pour ce faire. Heureusement les RTTI nous offrent une solution au travers de l'appel à la fonction Typeinfo.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //Programme de type Console uses Typinfo; var DonneeDeType : PTypeData; begin //Récupére les information de RTTI d'une interface DonneeDeType := GetTypeData(typeinfo(ISWbemObject)); //Vérifie si l'interface posséde bien un GUID if ifHasGuid in DonneeDeType^.IntfFlags then Writeln(GUIDToString(DonneeDeType^.Guid)); Writeln(DonneeDeType^.IntfUnit); // Nom de l'unité où est déclarée l'interface readln; end. |
Pour vider le buffer du clavier on utilise l'API PeekMessage qui opère sur la file d'attente des messages du thread courant.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 | procedure VideBufferClavier; var Msg: TMsg; begin while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE or PM_NOYIELD) do; end; |
Voici une fonction permettant d'obtenir le nombre de bits "allumés" dans le contenu d'une variable de n'importe quel type.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function card(var UneVariable; size: integer): integer; const // table des bits actifs dans un groupe de 4 bits (exemple : 9=8+1-->2 bits) NBits: array[0..15] of integer=( 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4); var t: TbyteArray absolute UneVariable; //table pointant sur le premier octet de la variable //dont on souhaite connaître le nombre de //bits allumés j: integer; PoidsFort:byte; PoidsFaible:byte; begin result:=0; //Pour chaque octet du tableau for j := 0 to size - 1 do begin //chaque octet est coupé en deux groupe de 4 bits PoidsFort:=t[j] shr 4 PoidsFaible:=t[j] and $F; //On dénombre pour chaque groupe de 4 bits le nombre de bits allumés inc(result, NBits[PoidsFort] and $F] + NBits[PoidsFaible]); end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | var MonEnsemble:Set of Byte; NomBreDElements:integer; begin ... MonEnsemble:=[128,25,96,36,200]; //on passse à notre fonction notre variable //et aussi sa taille en octets, obtenue grace à la fonction SizeOf() ) NomBreDElements:=Card(MonEnsemble,SizeOf(MonEnsemble)); ShowMessage(IntToStr(NomBreDElements)); //affiche "5" ... end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var UnEntier:integer; UnBoolean:Boolean; UnReel:double; UneClasse:TForm; UneChaine:string; UnTableau:array[] of ... //QuelqueChose begin ... NomBreDElements:=Card(UnEntier,SizeOf(UnEntier)); NomBreDElements:=Card(UnBoolean,SizeOf(UnBoolean)); NomBreDElements:=Card(UnReel,SizeOf(UnReel)); NomBreDElements:=Card(UneClasse,SizeOf(UneClasse)); NomBreDElements:=Card(UneChaine,SizeOf(UneChaine)); NomBreDElements:=Card(UnTableau:,SizeOf(UnTableau)); ... end; |
On peut souhaiter quelquefois qu'un traitement au sein d'une même fonction puissent renvoyer un type de donnée différents selon les cas.
Vous trouverez une solution dans le tutoriel cité.
Quelques fois, on peut être amené à manipuler des DLL écrites en C ou C++ utilisant un nombre variable de paramètres. Dans ce cas, la solution se trouve ici.
En revanche, réaliser en natif une méthode utilisant un nombre variable de paramètres nécessite une autre approche. Dans un premier temps, on pourrait penser qu'un tableau de pointeurs suffirait mais au moins 2 questions se posent, à savoir comment :
Il existe dans Delphi un raccourci pour créer un GUID lors de l'écriture du code : Ctrl+Shift+G…
Mais comment faire lorsque l'on veut créer ce GUID dynamiquement pendant l'exécution d'un programme ?
Il suffit d'utiliser la fonction CoCreateGuid. On peut donc créer une fonction qui permet de retourner un GUID facilement:
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 | function CreateGuid: string; var GUID: TGUID; begin Result := ''; if CoCreateGuid(GUID) = S_OK then Result := GUIDToString(GUID); end; |
Code delphi : | Sélectionner tout |
function CreateClassID: string;
Code delphi : | Sélectionner tout |
function CreateGUID(out Guid: TGUID): HResult;
Un If immédiat permet de réaliser une affectation conditionnelle. Il s'agit suivant la valeur de vérité d'une condition (vraie ou fausse) d'affecter une valeur à une variable donnée. Ceci peut se faire soit à travers une construction if...then...else (trois instructions) ou avec l'opérateur ?..: pour ceux qui connaissent le langage C.
A partir de Delphi 6, nous pouvons utiliser l'instruction IfThen dont une signature est :
Code delphi : | Sélectionner tout |
function IfThen (AValue : Boolean; const ATrue : Integer; const AFalse : Integer = 0) : Integer; overload;
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | Interface { Immediate If } { IIF renvoyant un entier } function IIF(ACondition: boolean; ATruePart, AFalsePart: integer): integer; overload; { IIF renvoyant un extended } function IIF(ACondition: boolean; ATruePart, AFalsePart: Extended): Extended; overload; { IIF renvoyant une string } function IIF(ACondition: boolean; ATruePart, AFalsePart: string): string; overload; { IIF renvoyant un objet } function IIF(ACondition: boolean; ATruePart, AFalsePart: TObject): TObject; overload; Implementation function IIF(ACondition: boolean; ATruePart, AFalsePart: integer): integer; { Immediate IF pour les entiers } begin if ACondition then Result := ATruePart else Result := AFalsePart; end; function IIF(ACondition: boolean; ATruePart, AFalsePart: Extended): Extended; { Immediate IF pour les flottant } begin if ACondition then Result := ATruePart else Result := AFalsePart; end; function IIF(ACondition: boolean; ATruePart, AFalsePart: string): string; { Immediate IF pour les chaînes } begin if ACondition then Result := ATruePart else Result := AFalsePart; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 | function IIF(ACondition: boolean; ATruePart, AFalsePart: TObject): TObject; { Immediate IF pour les objets } begin if ACondition then Result := ATruePart else Result := AFalsePart; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 | procedure TMyObject.TestIIF; var idx: integer; MyString: String; begin idx := 10; { Par exemple } MyString := IIF(idx=0,'Zero','Différent de Zero'); end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | procedure TMyObject.TestIIF; var idx: integer; MyString: String; begin idx := 10; { Par exemple } if idx=0 then MyString = 'Zero' else MyString = 'Différent de Zéro'; end; |
Il est possible avec Delphi de calculer la distance entre deux points GPS, c'est-à-dire la distance à vol d'oiseau. Pour cela, nous allons travailler avec des degrés décimaux (DD). Si vous travaillez en DMS (degrés, minutes, secondes), il faudra convertir au préalable les données.
Il s'agit d'un calcul complexe, car il faut tenir compte de la rotondité de la terre. Pour cela, il faut utiliser une formule de trigonométrie sphérique. Les degrés passent en radians avec DegToRad de l'unité Math. On applique la formule et on passe la valeur qui est en miles puis en kilomètres (1 mile = 1.609344 km).
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | procedure TForm2.Button1Click(Sender: TObject); var eLatitude1, eLatitude2 : Extended; eLongitude1, eLongitude2 : Extended; rLatitude1, rLatitude2 : Extended; rTheta : Extended; eDistance : Extended; begin // coordonnées GPS de la ville de Dijon (21000) eLatitude1 := 47.366667; eLongitude1 := 5.033333; // coordonnées GPS de la ville d'Aubagne (13400) eLatitude2 := 43.283333; eLongitude2 := 5.566667; // conversion des degrés en radians rLatitude1 := DegToRad(eLatitude1); rLatitude2 := DegToRad(eLatitude2); // différence entre les deux longitudes rTheta := DegToRad(eLongitude1 - eLongitude2); // trigonométrie circulaire eDistance := Sin(rLatitude1) * Sin(rLatitude2) + Cos(rLatitude1) * Cos(rLatitude2) * Cos(rTheta); eDistance := ArcCos(eDistance); eDistance := eDistance * 180 / Pi; // 60 minutes par degré, et passage de mile en mile nautique eDistance := eDistance * 60 * 1.1515; // passage des miles en kilomètres eDistance := eDistance * 1.609344; // affichage de la valeur ShowMessage(eDistance.ToString); end; |
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2018 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
Copyright © 2000-2018 - www.developpez.com