vendredi 29 décembre 2000

Barre d'outils

BARRE D'OUTILS

Les barres d'outils sont utilisées pour rendre les fonctions les plus utilisées plus accessibles à l'usager.
Delphi possède quelques composants pour construire des barres d'outils : ControlBar, CoolBar, ToolBar.

Type de barre d'outils

Toolbar

  • Ajouter un composant ToolBar sur la fiche
  • Sélectionner la ToolBar que vous venez de créer
  • Cliquer sur le bouton droit de la souris
  • Sélectionner ajouter un bouton
  • Ajouter un composant ImageList sur la fiche
  • Double cliquer sur le composant

  • Ajouter les images que vous désirez mettre sur les boutons
  • Sélectionner la propriété Image de ToolBar et inscrivez le nom du composant ImageList
  • Sélectionner un bouton et mettre sa propriété ImageIndex à l'image désirée


Quelques propriétés peuvent être modifiées afin de changer l'apparence des boutons et de la barre d'outils: EdgeInner, EdgeOuter, Flat, EdgeBorders. Ces propriétés sont valides pour toutes les barres d'outils mentionnés ci-dessus.
Code source disponible ici.

CoolBar

Ce composant permet de créer des barres d'outils ancrables, c'est à dire qu'elles ne sont pas fixes, on peut changer leurs positions durant l'exécution du programme.
  • Ajouter un composant CoolBar sur la fiche
  • Ajouter un composant ToolBar sur le composant CoolBar
  • Cliquer sur le bouton droit de la souris
  • Sélectionner ajouter un bouton
  • Ajouter un composant ImageList sur la fiche
  • Double cliquer sur le composant
  • Ajouter les images que vous désirez mettre sur les boutons
  • Sélectionner la propriété Image de ToolBar et inscrivez le nom du composant ImageList
  • Sélectionner un bouton et mettre sa propriété ImageIndex à l'image désirée
  • Mettre la propriété DragKind de CoolBar et ToolBar à dkDock et leurs propriétés DragMode à dmAutomatic


Code source disponible ici.

ControlBar

Lorsqu'on ajoute une ToolBar au dessus d'une ControlBar, la barre d'outils devient ancrable. Étant donné son indépendance face à la dll de Microsoft, je vous conseille fortement de l'utiliser. Elle est beaucoup plus aisée de l'utiliser et le résultat est d'allure vraiment professionnel. On peut aisément créer des barres d'outils comme celles de photoshop, delphi....



Barre d'état

Les barres d'états sont de plus en plus utilisées dans les programmes utilisés de nos jours. Elles permettent de donner de l'information à l'usager.

Barre d'état simple

Une barre d'état simple comporte qu'un seul volet, il n'y aura qu'une seule information qui sera affichée sur la barre. On affiche rarement qu'une seule information.
  • Ajouter le composant status bar sur la fiche
  • Mettre la propriété SimplePanel du composant à true
  • Inscrivez ce que vous désirez afficher sur la barre dans la propriété SimpleText
Code source disponible ici.

Barre d'état complexe

Une barre d'état complexe comporte plusieurs volets.
  • Ajouter le composant status bar sur la fiche
  • Ajouter autant de volets que vous le désirez grâce à la propriété Panels
  • Inscrivez ce que vous désirez afficher sur la barre dans la propriété Text
Étant donné qu'il y a plusieurs volets, vous devez spécifier l'index du panel.
statusbar.panels[1].text:= 'x: ' + inttostr(x)+' y: '+ inttostr(y);




Code source disponible ici.

jeudi 28 décembre 2000

Menu

MENU

Les menus sont un moyen efficace et simple d'accéder aux fonctions d'un programme. Nous allons voir comment en créer un. Il existe deux types de menus, les mainmenu et les popupmenu.

Type de menu

MainMenu

Ce type de menu est utilisé dans la plupart des programmes créés de nos jours.
  • Sélectionner le composant MainMenu de l'onglet Standard
  • Double cliquer sur l'icône du composant
L'Éditeur de menu apparaîtra

  • Inscrivez Fichier dans la propriété caption et menFichier pour son nom
  • Créez un nouveau item de menu, Envoyez
  • Faite un clique doit de la souris, un menu apparaîtra, sélection


Ces sous-menus sont utilisés dans de nombreuses applications dont ms office
La propriété Bitmap permet d'attribuer une image à un menu.

Standard

Les ... a la suite du nom dans un menu, signifie qu'il y aura une boîte d'édition qui sera affiché. Les barres de séparation permettent de grouper ensemble les menus.
Allez voir sur xp_netscape_menu pour avoir des menus dans le style netscape 6 et office xp

PopupMenu

Ce menu aussi appelé menu contextuel est accessible dans un programme lorsqu'on clique sur le bouton droit de la souris.
  • Sélectionner le composant popupmenu de l'onglet standard
  • Double cliquer sur l'icône du composant
  • Inscrivez un nom pour la propriété caption


Il ne faut pas oublier d'affecter le nom du popupmenu à la propriété PopupMenu des composants qui sont concernés par le menu.Ainsi lorsqu'on fera un clique droit de la souris sur les composants qu'on aura préalablement affectés au Popmenu, il s'affichera

Conseil

L'insertion et l'effacement d'un menu peuvent se faire avec le menu pop up du bouton droit de la souris
Un nouvel élément est ajouté en dessous du menu qu'on vient de créer, de plus, on peut en ajouter un autre à droit de celui qu'on avait créé.
  • Ajouter & dans la propriété caption permet de créer un raccourci
  • Ajouter un - dans la propriété caption permet de créer un séparateur
Ajouter un sous menu, ce fait en sélectionnant un menu et en appuyant sur ctrl -> ou en cliquant sur le bouton droit de la souris et en sélectionnant create submenu.

Pour rendre votre application plus aisée à manipuler, utilisez les mêmes touches raccourcies des autres programmes Windows et linux. La propriété ShortCut permet des créer des raccourcis comme ctrl x pour la commande couper.

Programme sur les menus disponible ici.

Fichier


FICHIER

Les fichiers sont absolument nécessaires lorsqu'on doit garder certaines informations lorsque le programme est terminé. Il existe de nombreuses routines pour manipuler les fichiers.

Opération sur les fichiers

Copier un fichierFichier

Les fichiers sont absolument nécessaires lorsqu'on doit garder certaines informations lorsque le programme est terminé. Il existe de nombreuses routines pour manipuler les fichiers.

Copier un fichier

Le premier paramètre est le nom du fichier à copier et le deuxième et le nom du fichier copié. Si le dernier paramètre est à false, le fichier sera écrasé s'il existe.
copyfile('c:\test\1.tmp','d:\2.tmp',false);

Renommer un fichier

La fonction RenameFile sert à renommer un fichier. On inscrit l'ancien nom de fichier et ensuite le nouveau nom voulu function
RenameFile('ancien.c','nouveau.c');

La fonction retourne true si l'opération a bien été réalisée. 

Déplacer un fichier

La fonction movefile sert à déplacer un fichier, le premier paramètre est la source, le deuxième est la cible.

movefile('d:\2.tmp','c:\1.tmp');

Effacer un fichier

Cette opération efface le fichier du disque et enlève son entré du disque.

DeleteFile(NomDuFichier);
Cette procédure retourne true si le fichier a été effacé avec succès.
On devrait demander confirmation avant d'effacer le fichier.

Trouver un fichier

Pour trouver un fichier, il existe 3 routines
  • FindFirst
  • FindNext
  • FindClose
FindFirst: recherche la première occurrence du fichier dans le répertoire et les attributs spécifiés.

FindNext: recherche la prochaine occurrence du fichier correspondant à l'appel de Find First.

FindClose: Libère la mémoire allouée par les précédentes routines.
On a avantage à utiliser la routine FileExists avec ces routines afin d'éviter les erreurs si le fichier n'existe pas.

Lorsqu'on trouve le fichier, on peut vérifier les attributs de celui-ci
Constant Value Descrition
faReadOnly $00000001 Lecture seulement
faHidden $00000002 Fichier caché
faSysFile $00000004 Fichier système
faVolumeID $00000008 Numéro de volume
faDirectory $00000010 Répertoire
faArchive $00000020 Archive
faAnyFile $0000003F N'importe quel fichier

Modifier les propriétés d'un fichier

Changer l'attribut d'un fichier, nécessite 3 opérations
  • Lecture
  • Changement
  • Configuration
On utilise la fonction FileGetAttr afin d'obtenir les attributs du fichier
Attr := FileGetAttr(txtNomFic.Text);

On modifie ses attributs en ajoutant ou en diminuant son nombre
AttrsChoisie:=AttrsChoisie+ fahidden;

On affecte les changements attribut au fichier
FileSetAttr(txtNomFic.Text, AttrsChoisie);


Le code source d'un programme permettant de modifier les attributs d'un fichier est disponible ici

Les types de fichiers en entrée/sortie

Lecture Ce type de fichiers comporte du texte tout simplement. L'utilisation d'une variable du type TextFile est nécessaire pour l'emploi d'un fichier texte. Il y a 4 étapes à la manipulation d'un fichier.
var
   Fic:Textfile;                         //1. Déclaration
begin
   AssignFile(Fic,'c:\autoexec.bat');    //2. Assignation
   //ou
   System.Assign(Fic,'c:\autoexec.bat');
                                         //3. Ouverture du fichier 
   reset(Fic);                              //en lecture
   rewrite(Fic);                            //en ecrire
   Append(Fic);                             //en ajout
   CloseFile(Fic);                       //4.fermeture du fichier
   //ou
   System.Close(Fic);
end;

Lecture d'un fichier texte

On utilise la procédure ReadLn pour la lecture d'un fichier texte, elle lie fichier, ligne par ligne.
var
   car:string;
begin
   readln( Fic, car);
end;
Étant donné qu'un fichier n'est pas infini, on doit vérifier s'il n'est pas rendu en fin de fichier.
while not Eof(Fic) do
   readln( Fic, car);
Finalement l'ouverture d'un fichier se ferait ainsi
var
   Fic:textfile;
   car:string;
begin
   AssignFile( Fic, 'c:\autoexec.bat');
   reset(Fic);
   try
     while not Eof(Fic) do
     readln(Fic,car);
   finally
     closefile(Fic);
end;

Écriture

L'écriture dans un fichier texte se fait par l'emploi de la méthode rewrite.
var 
   Fic:textfile;
   car:string;
begin
   assignfile(Fic,car);
   rewrite(Fic);
   Writeln(Fic,'Bienvenue dans le monde fabuleux de Delphi ');   
   Writeln(Fic,'Vous venez d'écrire dans un fichier texte, bravo');
   closefile(fic);
end;

Les fichiers binaires

Nous utiliserons la classe TFileStream pour faciliter la manipulation des fichiers binaires. Cette classe offre de multiples fonctionnalités aux niveaux des entrées-sorties
Création et ouverture de fichier
Valeur Description
fmCreate Ouvre le fichier en écriture, s'il existe
fmOpenRead Ouvre le fichier en lecteur seulement
fmOpenWrite Ouvre le fichier en écriture seulement
fmOpenReadWrite Ouvre le fichier pour le modifier
Nous déclarons une variable de type TFileStream
var
  fs: TFileStream;
Crée une instance(variable) de TFileStream
fs := TFileStream.create('c:\test.txt',fmCreate or fmOpenWrite');
Après ces deux opérations, nous pouvons écrire et lire dans le fichier

Boite de dialogue

Windows fournit plusieurs boîtes de dialogue que n'importe qu'elle programmeur peut aisément incorporer dans ses programmes. Nous allons nous attarder à celles utilisées pour ouvrir et sauvegarder un fichier.

La méthode exécutée

On doit utiliser la méthode exécutée pour utiliser une boîte de dialogue, cette méthode permet de créer et d'afficher la boîte de dialogue
If openDialog1.Execute then

Ouverture d'un fichier

L'ouverture d'un fichier se fait en employant la propriété filename
If openDialog1.Execute then
   Memo1.Lines.LoadFromFile(OpenDialog1.FileName);

Ces deux lignes de code affectent le contenu d'un fichier choisi à un mémo
La sauvegarde d'un fichier se ferait par

If saveDialog1.Execute then
  Memo1.Lines.savetoFile(saveDialog1.FileName);

Ces deux lignes de code sauvegardent le contenu du mémo dans un fichier.
Propriété de Topendialog et Tsavedialog
Voici quelques propriétés de ces composants

Title

Donne le titre de la boîte de dialogue opendialog1.Title:='Ouverture';

Filter

Extension de fichier admis pour ouvrir ou sauvegarder un fichier savedialog1.Filter:='Text files (*.txt)|*.TXT|Pascal files (*.pas)|*.PAS';

InitialDir

Change le répertoire courant pour celui spécifié savedialog1.InitialDir:='c:\';
Toutes les propriétés de ces composants peuvent être modifiées en mode création en sélectionnant le composant et en allant dans les propriétés qui nous intéressent dans l'inspecteur d'objet
Code source disponible ici.

samedi 28 octobre 2000

Pointeur

POINTEUR

On accède habituellement à une variable par son nom.
Nb1:=Nb2;

On localise l'adresse par le nom de la variable, mais on peut aussi accéder 
   à son contenu directement par son adresse. L'adresse sert à 
localiser    un emplacement en mémoire. Un pointeur est une constante 
ou variable    qui possède l'adresse d'une variable. Le pointeur pointe 
vers la variable    concernée. 

Les pointeurs sont plus rapides et utilisent moins de mémoire que si on utiliserait directement la variable. Les variables utilisent la mémoire locale qui est en quantité minime. Lorsqu'on utilise un pointeur, seul ce dernier est dans la mémoire locale. Les éléments pointés sont eux dans la mémoire globale qui est beaucoup plus grande. On peut aisément se rendre compte de l'importance d'utiliser les pointeurs.



Le type pointer est utilisé en delphi pour désigner un pointeur. On utilise @ pour avoir l'adresse de la variable

var
  ptrNote : Pointer;
  Note : integer;
begin
  ptrNote := @Note;
end;
 

La variable stocke l'adresse l'adresse de ptrNote. C'est un pointeur non typé.
Les pointeurs ne pointent pas obligatoirement vers une adresse, on peut leur assigner une valeur nulle avec le mot «nil». On utilise beaucoup cette affectation afin de vérifier si le pointeur pointe quelque part.

var ptrNote : pointer;
begin
  ptrNote := nil;
end;
 

Le type pointer déclare un pointeur sur    n'importe quoi. Le type
de donnée pointé ne peut être connu    même si
on peut accèder à son contenu. Ce n'est vraiment    pas pratique
dans un programme. On doit utiliser des pointeurs spécifiques    à
un type pour régler le problème. Un pointeur sur un integer,
   sur un real... Au lieu d'utiliser directement le pointeur, on préfèrera
   créer un nouveau type et on déclarera les variables ou les
paramètres    en utilisant ce nouveau type. Pointeur vers s'écrit
en delphi ^, ce qui    équivaut à * du c.  

Langage c Delphi
int *ptrNote;
int Note=74;
ptrNote=&Note;
type
  pNote:=^integer;
var
  Note:pNote;
begin
  Note^:=74;
end;

type
pNote:=^integer;
 

Dans cet exemple, la  variable pNote pointe sur un type integer. On déclare 
ainsi un pointeur sur un integer. pNote := ^long; Ici pNote serait un pointeur 
sur un long. Lorsque ^ est avant un type de donnée (déclaration) 
comme dans les exemples ci-dessus, le ^ signifie pointe sur. Le ^ est avant 
le type de donnée, c'est typique à la déclaration.

variable :=^ <type de donnée>

Lorsqu'on veut effectuer des opérations sur le contenu de la valeur 
pointé par le pointeur, on utilise encore ^. Le ^ est après 
le nom du pointeur comparativement au cas de déclaration qui est situé 
après.

pNote ^:= 54;

Dans cette exemple, on affecte 54 à la valeur contenu à l'adresse
pointé par le pointeur. On effectue ainsi une affectation.

Les éléments pointés par les pointeurs sont gérés dynamiquement et c'est au programmeur qui doit coordonner, le tout. La gestion de l'élément pointé se fait en deux étapes
  • Initialisation
  • Destruction
Un pointeur doit être créé avant de pouvoir l'utiliser. La procédure «new» initialise le pointeur, le nom du pointeur doit être passé en paramètre. Un espace en mémoire lui est ainsi alloué. Des problèmes surviennent aussitôt si cette étape n'est pas faite. Lorsque l'utilisation du pointeur sera terminée, il faudra le détruire afin de remettre l'espace alloué au système et d'augmenter ses performances. La procédure «dispose» détruit l'espace alloué par le pointeur. Le nom du pointeur doit être passé en paramètre.

type
  pNote = ^Integer;
var
  Note : pNote;
begin
  new(Note);       //initialisation du pointeur
  Note^ := 54;     //affectation du pointeur
  dispose(Note);   //destruction du pointeur
end;

Opération sur les pointeurs


Les pointeurs sont limités aux opérations d'affection et de comparaison.

Affectation

Les pointeurs doivent pointer vers le même type avant de pouvoir faire une affectation

var
  PNote : ^Integer;
  PNbEleve :^Integer;
begin
  new(PNote);
  new(PNbEleve);
  PNote := PNbEleve;
  dispose(PNote);
  dispose(PNbEleve);
end;


L'affectation ci-dessus est possible, car les deux pointeurs pointent sur des integers. Étant donnée qu'après cette affectation les deux pointeurs pointent au même endroit, il faut détruire qu' un seul pointeur. Il est aussi possible de copier le contenu d'un pointeur dans un autre pointeur, mais les deux pointeurs doivent pointer sur le même type de donnée.

var
  PNote :^Integer;
  PNbEleve :^Integer;
begin
  new(PNote);
  new(PNbEleve);
  PNote :=PNbEleve;
  PNote^ := 5;
  dispose(PNote);
end;

Comparaison

La comparaison sert à savoir si les pointeurs pointent au même endroit. Les signes «=» et «<>» peuvent être utilisés.

if PNbEleve = PNote then
Si cette ligne de code retourne true (vrai), les deux pointeurs pointent à la même adresse.

Pointeurs d'enregistrements

Ce type de pointeur est tout simplement un pointeur vers un enregistrement. On utilise beaucoup ce type de pointeur. Prenons comme exemple un enregistrement du chapitre 5

type TInfoClient = record
  Prenom:string[20];
  Nom:string[20];
  Adresse:string[30];
  Ville:string[20];
  CodePostal:string[6];
end;
  PInfoClient:TInfoClient;
var 
  InfoClient:PInfoClient;
begin
  New(InfoClient);
  InfoClient^.Prenom := 'Paul';
  InfoClient^.Nom := 'Houle';
  InfoClient^.Adresse := '1024 Des Chênes';
  InfoClient^.Ville := 'Montreal';
  InfoClient^.CodePostal := 'J4S2R4';
  Dispose(InfoClient);
end;

Pour mieux comprendre les pointeurs, nous allons étudier    les 
listes.

Liste

Les listes sont une suite d'éléments mis les uns à la suite des autres. On les utilise constamment dans la vie de tous les jours. En programmation, leurs utilités ne sont plus à faire. Les listes peuvent être utilisées pour y mettre n'importe quel type de donnée. Souvent, on les utilise avec les enregistrements.


Chaque noeud possède un champ information et un champ pointeur qui pointent sur le prochain noeud. Lorsqu'il n'y a pu de noeud, le dernier pointeur pointe sur nulle c'est alors là fin de la liste.

Opération sur les pointeurs

Création


type //Création des informations pour la liste
  TInfoClient = record
  Prenom:string[20];
  Nom:string[20];
  Adresse:string[30];
  Ville:string[20];
  CodePostal:string[6];
end;

Déclaration


type //Déclaration de la liste
  PListClient = ^TListClient;
  TListClient = record
  InfoClient :TInfoClient;
  ProchainNoeud:PListClient;
end;

Construction


var
  PremierClient,TempClient:PListClient;
begin
  PremierClient:=nil; //Initialise le premier pointeur
  new(TempClient); //Crée un noeud temporaire
  TempClient^.InfoClient.Prenom:='Paul';
  TempClient^.InfoClient.Nom:='Prenom';
  TempClient^.InfoClient.Adresse:='23 Nobert';
  TempClient^.InfoClient.Ville:='Longueuil';
  TempClient^.InfoClient.CodePostal:='J3S1H4';
  TempClient^.ProchainNoeud:=PremierClient;
end;
 

La dernière ligne permet d'ajouter le noeud à la liste afin
qu'il pointe à la même adresse que le premier pointeur.



Cette instruction permet de faire pointer PremierClient au début de la liste
PremierClient:=TempClient;
 

Un petit programme illustrant les principes de base des listes est disponible en téléchargement ici.

mercredi 11 octobre 2000

Comment prendre des caractère dans une string?

Comment prendre des caractère dans une string?
function RightStr
   (Const Str: String; Size: Word): String;
begin
 if Size > Length(Str) then Size := Length(Str);
 RightStr := Copy(Str, Length(Str)-Size+1, Size)
end;

function MidStr
   (Const Str: String; From, Size: Word): String;
begin
 MidStr := Copy(Str, From, Size)
end;

function LeftStr
   (Const Str: String; Size: Word): String;
begin
 LeftStr := Copy(Str, 1, Size)
end;
end;

lundi 9 octobre 2000

Fonction et procédure

FONCTION ET PROCÉDURE

Les fonctions et procédures sont des sous-programmes qui exécutent des tâches en particuliers. Ils permettent de rendre le programme plus lisible et de pouvoir les réutiliser sans devoir réécrire la portion de code. La différence entre les procédures et fonctions est que la fonction retourne une valeur. Ils peuvent avoir un, plusieurs ou aucun paramètre. Un paramètre est une valeur que l'on passe à une procédure ou fonction pour qu'elle puisse effectuer des traitements avec cette valeur.

Lorsqu'on a créé notre fonction ou procédure, on peut l'appeler dans notre programme. Ils nécessitent d'être déclarés avant la partie implémentation

Fonction

function <nom de la fonction>(<liste de paramètre>):<type de résultat>;

function CalculerTaxe(PrixSousFinal:real):real;
begin
  result := PrixSousFinal * 0.07 + PrixSousFinal;
end;

On utilise le mot result lorsqu'on veut retourner une valeur dans
une    fonction. Le nom de la fonction était anciennement utilisé
pour retourner    la valeur, on utilise moins cette technique, mais il est
toujours possible de    l'utiliser. 

Code source disponible ici.

Procédure

procedure <nom de la procédure>(<liste de paramètre>);

procedure AfficherErreur(Message_Erreur:string); 
begin 
   messagedlg(Message_Erreur,mtInformation,[mbOk], 0);
end;

Lorsqu'on a aucune valeur à retourner ou qu'on a plus d'une valeur à retourner, on peut utiliser les procédures.

Code source disponible ici

Paramètre

Il existe plusieurs types de paramètre, voici les trois plus utilisés.

Paramètre par valeur

La fonction ou procédure reçoit une copie de la valeur passée en paramètre. La valeur originale ne sera jamais modifiée. Le programme que je vous ai fait inverse deux nombres. Lorsque la procédure est terminée, les deux nombres sont les mêmes qu'avant l'inversion. Les passages par valeur sont souvent utilisés lorsqu'on ne doit pas modifier le contenu des variables ou que l'on doit afficher des variables. Ce type de paramètre requit plus de ressources système et est plus lent.

procedure ChangerValeur(premier,deuxieme:integer);
var
  temp:integer;
begin
  temp:=premier;
  premier:=deuxieme;
  deuxieme:=temp;
end;

La fonction accède à une copie locale des variables passées en paramètre.

Code source disponible ici.

Paramètre par adresse

La fonction ou procédure utilise l'adresse de la variable que le compilateur lui transmet. Lorsqu'on utilise l'adresse de la variable, on accède directement à son contenu. La valeur originale sera donc modifiée. On ajoute le mot «var» devant les paramètres afin d'avoir des paramètres par adresses.

procedure ChangerValeur(var premier,deuxieme:integer);
var
  temp: integer;
begin
  temp:=premier;<
  premier:=deuxieme;
  deuxieme:=temp;
end;

La fonction accède au contenu des emplacements mémoire où sont stockées les variables. C'est beaucoup plus rapide que le passage de paramètre par valeur.

Code source disponible ici.

Paramètre constant

Un paramètre constant ne peut pas être modifié dans la fonction ou procédure. La valeur du paramètre ne pourra changer, c'est comme une constante.

procedure AfficherErreur(const Message_Erreur:string);
begin
  messagedlg(Message_Erreur,mtInformation,[mbOk], 0);
end;

Surchage de méthode (Overloading)

Il peut arriver qu'on doit utiliser la même fonction mais les paramètres ne sont pas du même type. La surchage de méthode comble cette lacune depuis Delphi 4.
Imaginons que nous devons calculer la taxe sur un prix donné. Le prix peut donc être un entier ou un réel. Nous pourrons créer une fonction avec un nom différent pour chaque type de données, mais avec la surchage de méthode, on peut utiliser le même nom de fonction pour chaque type de donnée et même changer le nombre de paramètre. Le compilateur se charge d'appeler la fonction adéquate au paramètre qu'on lui a fourni.

Pour effectuer une surchage de méthode, on doit ajouter le mot overload après la déclaration de la fonction.

function CalculerTaxe(Prix:integer):double;overload;
function CalculerTaxe(Prix:double):double;overload;

Par la suite on définie autant de fonctions qu'on n a déclaré de fonction. On simplie l'écriture de programme en utilisant la surchage.

Code source disponible ici.

Paramètre par défaut

Imaginer que vous employez une fonction ou procédure la majorité du temps les mêmes paramètres, avec Delphi vous pouvez créer des paramètres par défaut. Si vous employez les valeurs par défaut vous omettez les paramètres sinon vous les inscrivez.
La déclaration se fait comme à l'habitude, les paramètres par défaut doivent par contre être placés à la fin de la liste de paramètre.

procedure ShResize(Hauteur,Largeur:double;Taux : double = 2);

Appel de la fonction avec les paramètres par défaut
ShResize(Shape1.Height,Shape1.Width,Taux);

Appel de la fonction sans les paramètres par défaut
ShResize(Shape1.Height,Shape1.Width);

samedi 16 septembre 2000

Récursivité

RÉCURSIVITÉ

La récursivité est la caractéristique d'un programme ou d'une procédure de s'appeler par lui-même (au moins une fois). Grâce à la récursivité, on peut résoudre de façon simple et concie de nombreux problèmes informatiques. Du fait de cette puissance, faut faire attention, car ce point positif peut revenir contre nous. Le programme ou la procédure peut s'ils ont mal été programmés s'appeler indéfiniment et causer l'arrêt de la machine. Il faut donc bien faire attention à la condition d'arrêt qu'on utilise.

Factoriel

Nous allons débuter par les factoriels. Voici la définition de la récurence des factoriels
n! = n * (n-1) * (n-2) * ... * 1
l! = 1
La fonction factorielle sans l'utilisation de récursion

function Factorielle(number:integer):integer;
var
  factoriel,i:integer;
begin
  if number = 0 then factoriel := 0
  else
  begin
    factoriel := 1;
    for i := number downto 1 do
      factoriel := factoriel * i
  end;
  result := factoriel;
end;

La fonction factorielle avec la récursion

function factorielle_recursion( n: integer): integer;
begin
  if n <= 0 then
    factorielle_recursion := 1  
  else
  result := n * factorielle_recursion( n - 1 ); {return n*(n-1)! }
end;

On peut remarquer que la fonction des factoriels qui utilise la récursion est plus courte. La pile est grandement
utilisée puisque que chaque appel à la fonction créée à nouveau les variables... le tout est ajouté à la pile. La récursivité
est un gouffre pour la mémoire.

Fibonacci

Voici la définition de la récurence de Fibonacci
Fib(n) = Fib(n-1) + Fib(n-2) for n > 1
Fib(0) = 0
Fib(1) = 1

La fonction fibonacci sans la récursion

function fibonacci(n:integer):integer;
var 
 i, Un, Un_1, Un_2 : integer;
begin
  Un_1 := 1 ;
  Un_2 := 1 ;
  for i:=2 to n do
  begin
    Un := Un_1 + Un_2 ;
    Un_2 := Un_1 ;
    Un_1 := Un ;
  end;
  result := Un ;
end;
La fonction fibonacci avec la récursion

function fib( n: integer): integer;
begin
  if n <= 1 then
    fib := n 
  else
    fib := fib(n-1) + fib(n-2); 
end;

Vous allez vous rendre compte rapidement des différences de performances qu'il y a entre les deux versions de 
fibonacci, et ce, aussitôt qu'une valeur de 20 et plus sera attribuée à n.
Pour de plus amples renseignements sur la récursivité, rendez-vous à l'excellent tutoriel sur Chambily.

Hashage

HASHAGE

Le hachage est une méthode est une méthode pour entreposer des données dans un tableau, liste... Les recherches, insertion et les effacements de données sont très rapide. La complexité est théoriquement de O(1). Pour arriver à un tel résultat, chaque valeur doit avoir sa propre clé. Il y a une fonction de hashage qui retourne la position.
Dans cet exemple, nous dirons que Jean hashe 0, Paul hashe 1...

0 Jean Durocher
1 Paul Rivet
2
3
4 Sam Piq
5 Eric Melvin
Il faut avoir une fonction de hashage qui permet de placer chaque clé au bon endroit. Il faut aussi décider ce qu'on va faire lorsque deux clés hashe la même valeur.
type
  THash_Record = record
  cle   : integer;
  donne  : integer;
end;

const
  HASH_LENGTH = 100;

type
  THash_Table = array[0..HASH_LENGTH-1] of THash_Record;

function fonction_hash(cle : integer) : integer;
begin
  Hash_Function := cle MOD HASH_LENGTH;
end;

procedure Inserer( var hash : THash_table;rec  : THash_record);
begin
  hash[ fonction_hash(rec.cle) ] := rec;
end;

Telle que je l'ai souvent vu, j'ai décidé d'employer le modulo pour la fonction d'hashage.
Il est possible lors d'insertion d'enregistrement qu'il y ait des collisions.
C'est-à-dire que deux clés différentes retournent la même adresse avec la même fonction de haschage.
En pratique ça arrive rarement, mais faut tenir compte de cette situation.

Nous allons un peu modifier la structure de départ pour nous adapter à cette réalité. La technique ici utilisée est dite ouverte. C'est-à-dire que nous allons mettre les éléments qui hashent sur la même valeur dans une liste. Cette méthode est moins performante.
const
  HASH_LENGTH = 100;

type
  PHash_Record = ^THash_Record;
  THash_Record = record
    cle   : integer;
    donne  : integer;
    prochain  : PHash_Record; //pointeur sur le prochain élément
  end;

THash_Table = array[0..HASH_LENGTH-1] of PHash_Record;

procedure Inserer( var hash : THash_Table; rec  : THash_Record);
var
  hash_address : integer;
  item         : PHash_record;
begin
  hash_address := fonction_hash(rec.cle);
  new(item);
  item^ := rec;
  item^.prochain = hash[ hash_address ];
  hash[ hash_address ] := item;
end;

procedure Obtenir(hash : THash_Table;cle  : integer; var rec  : THash_Record);
var
  hash_address : integer;
  item         : PHash_record;
begin
  hash_address := fonction_hash(rec.cle);
  item := hash[ hash_address ];
  while (item <> nil) and (item^.cle <> cle) do
    item := item^.next;
  if (item<>nil) then //si dans la liste
    rec := item^
end;

Maintenant si une clé retourne la même adresse de hashage (élément du tableau),
nous insérons cette donnée dans la liste de cette donnée hashé.

Afin d'améliorer les performances, il est possible au lieu de mettre les éléments qui hashent sur la même valeur dans la liste, d'utiliser des fonctions quadratiques ou faire du double hashage.

Optimisation


OPTIMISATION

L'optimisation dans un logiciel doit être une des dernières étapes de son développement. Avant de penser à optimiser un logiciel, il faut d'abord s'assurer que celui ne contiendra pas de bug. Rien ne sert d'optimiser au maximum un logiciel qui fait des erreurs sans arrêt. Vaut mieux primer sur la stabilité que l'optimisation.

Type d'optimisation

Lorsqu'on veut optimiser un logiciel on peut soit augmenter sa vitesse ou réduite la taille du programme. Habituellement lorsqu'on augmente sa vitesse, sa taille augmentera et vice versa. Le meilleur des deux mondes ne peut pas réellement être réunis. On verra quelques astuces pour augmenter l'efficacité de nos programmes. Les routines les plus susceptibles d'être optimisées sont celles étant souvent appelées.
On peut dénombrer plusieurs étapes pour optimiser un programme, en voici quelques une.
  • Compilation
  • Goulots d'étranglement
  • Structure et algorithme
  • Assembleur

Compilation

Avant de commencer à optimiser notre programme, nous pouvons choisir les meilleures directives de compilation pour avoir des performances optimales.



La case optimization permet de rendre actif l'optimisation du programme.

Optimisation faite pas Delphi

Registre

Les variables souvent utilisées ainsi que les paramètres sont directement mis dans les registres afin d'avoir du code plus rapide. Le compilateur vérifie aussi la durée de vie. Il peut ainsi placer plusieurs variables qui ne sont pas utilisées simultanément dans un même registre.

Élimination de la pile

Lorsque c'est possible, les paramètres sont placés dans les registres. Les intérêts sont mentionnées ci-dessus. Du même coup, ça évite de créer une pile pour y mettre les valeurs temporairement. Les instructions de création, d'élimination, d'ajout et de suppression pour la pile sont ainsi inexistantes. Lorsque plus de 3 paramètres sont utilisés dans une procédure ou fonction, le compilateur doit créer une pile. Sachant cela, lorsqu'il est possible de ne pas utiliser des paramètres ou du moins réduire leurs usages, on économise aussi l'accès au registre et la création d'une pile.

Élimination de code

Delphi n'inclut pas dans l'exécutable le code inutile. On peut remarquer ce genre de code par des pastilles lorsqu'on compile.


Goulots d'étranglement

Outils

Divers outils sur le marché permette de voir les points où l'on pourrait améliorer le code de notre logiciel. Ce genre d'application ce nomme des profilings.
Ce genre d'application permet en général de trouver les fuites mémoires, de savoir combien de temps prend une fonction ou une procédure à se dérouler... Chaque produit emmène son lot de nouvelle fonctionnalité. Il y a même des produits qui permettent de savoir si les api fonctionneront sur win9x, nt 2000,linux...

Nom du programme Adresse web
Memory Sleuth et Sleuth QA Suite Memory Sleuth et Sleuth QA Suite
MemProof MemProof
QTime QTime
DUnit DUnit
BoundsChecker BoundsChecker
ProDelphi ProDelphi

Avec ce genre d'outils, on sera en mesure de savoir où notre programme passe beaucoup de temps dans notre code. Le programme pourra ainsi être beaucoup plus facilement optimisé lorsqu'on connaît d'où viennent ses lacunes.
Ce genre d'outils facile grandement la vie des programmeurs, je vous conseille fortement de les essayer.

Structure et algorithme

Après avoir identifié les pointent faibles du programme avec les profilers, on peut dès lors commencer à améliorer leurs codes. Lorsqu'on améliore les performances d'un algorithme, on augmente sa taille. On doit trouver l'algorithme qui fait défaut et en prendre un plus performant.

Structure

Instruction if

Il arrive souvent que des gens utilisent ce genre de code dans leurs programmes au lieu d'utiliser le else if.

 
IF Cours=0 THEN lblNom.caption := 'francais';
IF Cours=1 THEN lblNom.caption := 'chimie';

C'est plus rapide d'utiliser ceci
IF Cours = 0 THEN lblNom.caption := 'francais';
ELSE IF Cours =1 THEN lblNom.caption := 'chimie';
ELSE lblNom.caption := 'autre';

ou la structure du choix multiple

CASE Cours OF
  0 : lblNom.caption := 'francais';
  1 : lblNom.caption := 'chimie';
  ELSE lblNom.caption := 'autre';
END;

Souvent, les langages de programmation ont des moyens de faciliter la vie des programmeurs. Très souvent ces moyens sont pénalisants côté vitesse.
Lorsqu'on utilise l'instruction suivante pour un intervalle donnée, le code est plus compact, mais moins performant.


IF Chiffre IN [3, 9, 11] THEN lblChiffre.caption := 'impair';

C'est plus performant ce code là

IF Chiffre i = 3 THEN lblChiffre.caption := 'impair';
ELSE IF Chiffre = 9 lblChiffre.caption := 'impair';
ELSE IF Chiffre = 11 lblChiffre.caption := 'impair';

Instruction for

Mes professeurs de C me l'ont assez souvent répété, c'est la boucle à utiliser lorsqu'on connaît le nombre d'itération à exécuter. C'est la plus rapide des boucles.

Nombre

Si vous avez un processeur inférieur aux Pentium 2 ou AMD k6 2 essayés d'utiliser faire des chiffres entiers.
Les opérations sont ainsi plus rapides et simples et ça demandera moins d'espace.
Les générations de processeur supérieur ont une unité spéciale de traitement dédié au nombre à virgule. Les opérations seront ainsi plus rapide que sur des nombres entiers.
Donc dépendant du type de processeur que vous avez, utilisez le format le plus adéquat
Utilisez le type de données adéquat en sachant que les types de données 32 bits sont plus rapides que celle n'ayant que 16 bits. Si vous voulez économiser de l'espace utilisé le type de donné approprié sinon pour la vitesse privilégiée les types 32bits

Les types entiers

Type Intervalle Format/taille
Byte 0..255 non signé, 1 octet
Shortint -128..127 signé, 1 octet
Char 0..255 non signé, 1 octet
Widechar 0..65 535 non signé, 2 octets
Smallint -32 768..32 767 signé, 2 octets
Word 0..65 535 non signé, 2 octets
Longint -2147483648.. 2147483647 signé, 4 octets
Integer -2147483648.. 2147483647 signé, 4 octets
Cardinal 0..4 294 967 295 non signé, 4 octecs
Int64 -9 223 372 036 854 775 808..9 223 372 036 854 775 807 signé, 8 octect

Les types réels

Type Intervalle Taille en octets
Real 2.9 10-39..1.7 1038 6
Double 5.0 10-324..1.7 10308 8
Real 2.9 10-39..1.7 1038 6
Extended 1.9 10-4951..1.1 104932 10
Comp -263+1..263-1 8
Currency -922337203685477.5808..
922337203685477.5807
8

Évitez de mélanger des chiffres à virgules flottantes, car il y aura des conversions qui devront être faites et elles seront ajoutées à la pile ce qui peut prendre 3 à 4 fois plus de temps.
N'utilisez pas le type variant, il est très lent et prend beaucoup de place. Certes on peut lui mettre n'importe quel type de donnée dedans, mais vous perdez beaucoup avec lui. Il y a toujours moyen de ne pas l'utilisez.
Les opérations les plus rapides sont les additions/soustraction viennent ensuite la multiplication et finalement la division.
Fraction -> nombre décimal
34/2 = 34 *.5
34 *.5 sera plus rapide que son équivalent fractionnaire. Lorsqu'on connait le nombre d'avance, choisissez le nombre décimal plutôt que la fraction.
Division -> multiplication
x/y = x* 1/y

Cette transformation est simple, on doit seulement inverser y et faire une multiplication
67/3= 67 * .33

Lorsque les nombres sont infinis tel que 1/3 on perd un peu de la précision. Alors on peut
ajouter quelques chiffres après la virgule afin d'augmenter le degré de précision.

Les exposants peut être remplacés par une multiplication
5 exposant 3 est plus lent que faire 5*5*5

Opérateurs logiques

Lors d'opération a base 2, on peut aisément supprimer les divisions et multiplication
par des décalages de bit.

donc exemple pour faire une division
shr 1 = divise par 2
shr 2 = divise par 4
shr 3 = divise par 8
shr 4 = divise par 16
shr 5 = divise par 32
shr 6 = divise par 64
shr 7 = divise par 128
shr 8 = divise par 256
.....
au lieu de x/2 on peut faire x shr 2
donc exemple pour faire une multiplication
shl 1 = multiplie par 2
shl 2 = multiplie par 4
shl 3 = multiplie par 8
shl 4 = multiplie par 16
shl 5 = multiplie par 32
shl 6 = multiplie par 64
shl 7 = multiplie par 128
shl 8 = multiplie par 256
...
au lieu de x*2 on peut faire x shl 2

Privilièger round à trunc

Trunc fait quelques manipulations sur le FPU qui sont très coûteux en temps, il vaut mieux utiliser round.

Variable locale

Il est avantageux d'utiliser des variables locales puisqu'elles peuvent être entreposées dans les registres du processeur. Une telle manoeuvre accélère beaucoup le traitement des données. Un gain important peut être fait en utilisant de telles variables dans une boucle. Il est souvent avantageux de copier des données dans une variable locale avant de l'utiliser. Ainsi, le temps système de copier est compensé par la réutilisation prompte des données copiées. Il y a une exception à cette règle, c'est les tableaux avec une dimension constante. Les mètres globaux feront économiser un registre durant les calculs.

Pointeur variable

On peut utiliser à notre avantage des pointeurs comme référence sur des données temporaires. Ces données temporaires seront optimisées dans les registres.

Liste chaîné vs tableau

dans la plupart des cas, les listes gagnent puisque la multiplication est devenue plus rapide avec les processeurs de nouvelle génération. Pour des accès aléatoires, tableau demeure le plus rapide pour n'importe types de données avec plus de 5 éléments. Les tableaux sont gagnants pour les types de données simples et les listes pour les complexes.

Statique vs Dynamique

Il arrive souvent que nous devions grouper des données, nous faisons alors appel au tableau. Jusqu'à la version 3 Delphi, nous étions obligés de créer des tableaux statistiques. Ce genre de tableau a une dimension fixe, on ne peut pas le réduire ou l'agrandir. Pour être sur de ne pas manquer de place, il fallait créer un tableau d'une grandeur immense. Maintenant, on peut faire appel au tableau dynamique. Ce genre de tableau nous permet d'épargner de l'espace.
La création d'un tableau dynamique est beaucoup plus lent qu'un tableau statistique, mais l'accès y est beaucoup plus rapide

Les procédures et fonctions

Faire appel aux procédures et fonctions augmente l'efficacité et la lisibilité du code, mais entraîne aussi une perte de performance (très peu). On doit savoir que plusieurs opérations sont faites sur la pile lors d'un appel. On ne doit pas arrêter leurs utilisations pour autant.
Pour ma part j'ai comparé l'appel d'une fonction 1 million de fois et l'exécution 1 millions du même code sans fonction. Au final, je n'ai même pas gagné 2 secondes...
Un point où l'on peut gagner aisément de la performance est le passage de paramètre.
Le passage par valeur doit recopier les variables qu'on passe à la fonction et le temps varient selon le type de variable: bytes, integer, variant...
Le plus rapide demeure le passage par adresse puisque la copie de l'adresse de la variable est passée. On utilise donc directement la variable en question. L'adresse d'une variable nécessite beaucoup moins d'espace qu'une variable.

Routine imbriqué

Imbriquer des routines ensemble ajoute des manipulations sur la pile pour que les variables de la routine externe puissent voir celle à l'interne. Beaucoup de temps système est ainsi perdu. Mettre les routines au niveau de l'unité et ajouter des paramètres tend à résoudre ce problème

String

Initialition

Le type de chaîne par défaut, AnsiString est initialisé automatiquement à vide. Il est donc inutile de le refaire.

Shortstring

Évitez ce type de donnée, depuis la version 5 de Delphi, ils sont convertis en longstrings avant d'être manipulés. Du temps est perdu durant ces convertions.

Privilièger Delete à copy

Copy copiera toujours la chaîne de caractères entière. Alors que delete découpera juste la fin de la chaîne.

Caster en pchar

La solution la plus rapide et la plus simple pour caster une string en pchar est de caster un pointeur. p:=pointer(s);

Trie

De nombreux algorithmes de tri existent dont un des plus rapide est le quicksort. On peut accélérer davantage le tri en ne bougeant pas les données. On peut s'échanger l'adresse entre pointeurs. Allez-voir dans la section des tris pour en savoir davantage

Fichier

Graphique

Réduisez le nombre de couleurs. Si vous employez des JPEG, optimisez-les en les compressant. Les fichiers gif sont favorisés par les petites tailles et leurs qualités.

Musical

Les wav deviennent rapidement gros, une solution consiste à employer des fichiers mp3. Si vous n'avez pas de parole dans la musique, utilisez les fichiers midi. Ils sont très petits.

Assembleur

L'assembleur est le langage le plus près de la machine, le plus rapide, mais aussi le plus incompréhensible. En utilisant l'assembleur, on réduit la lisibilité du code. Ce revers de la médaille ne sera connu que par le programmeur. L'appel à l'assembleur devrait se faire lorsqu'on a réellement besoin de vitesse: recherche, tri, encoder... car ça exige plus de temps de développement qu'utiliser un langage comme le pascale ou le c. On peut aussi utiliser les fonctions spécifiques au processeur comme le mmx, sse, sse2 3dnow... Ce genre d'instruction permet d'augmenter sensiblement les performances d'un programme faisant beaucoup appel au calcul.

Comme mettre le focus sur un contrôle?


Comme mettre le focus sur un contrôle?

form1.ActiveControl := Edit1;

lundi 11 septembre 2000

Comment mettre une image sur un bouton?

Comment mettre une image sur un bouton?
var
  Bitmap, Bitmap2: TBitmap;
  MyHandle: THandle;
  Rec: TRect;
begin
  Bitmap:=TBitmap.Create;
  Bitmap2:=TBitmap.Create;
  Bitmap2.LoadFromFile('c:\a.bmp');
  Rec:=Rect(2, 2, Button1.Width-2, Button1.Height-2);
  MyHandle:=GetDC(Button1.Handle);
  Bitmap.Canvas.Handle:=MyHandle;
  Bitmap.Canvas.StretchDraw(Rec, Bitmap2);
end;

mercredi 26 juillet 2000

Delphi in a Nutshell



Ce livre est une référence générale sur delphi. Elle combine une vue d'ensemble des conseils que le programmeur a besoin.

Commençant par un regard très précis d'un projet Delphi, comment il est contrôlé, et les nombreux fichiers qui le composent, L'auteur continue dans la manipulation de types, d'alignements, de méthodes, d'exception, les flèches indicatrices, et ainsi de suite...

Le modèle d'objet de Delphi, , l'unité de SysUtils décomposée dans lui est intégralité: ce sont des sujets que vous trouvez peu ou pas d'information dans les autres bouquins. Le plus grand chapitre s'appelle la " référence de langage ".

 Il documente chaque mot-clé, directive, fonction, procédé, variable, classe, méthode, et propriété. Il y a des explications détaillées de leur utilisation, y compris les valeurs de retour, de paramètres, et de cas d'erreur égaux.

lundi 8 mai 2000

Comment afficher les variables d'environnements


Comment afficher les variables d'environnements

export
export ou env affichera toutes les variables d'environnements
declare -x CLASSPATH="/usr/lib/jvm/java/bin:/usr/share/java/"
declare -x COLORTERM=""
declare -x CPU="i686"

samedi 26 février 2000

Delphi 5 Developers guide



Le developers Guide c'est ma bible depuis D4.

Il est méga complet, le seul regret c'est que beaucoup de chapitres sont sur cd au format pdf, mais c'est normal, le libre est déjà un pavé de plus de 1000 pages.

Tous les sources, exemples, sont sur le cd. Il ne faut pas oublier que les auteurs ont fait partie des développeurs Borland mêmes s'ils sont consultants indépendants maintenant. Leur bouquin est quand même plutôt niveau intermédiaire avancé (mais tout y est, les api, com, dcom, corba, midas, client/serveur, internet, etc etc).

jeudi 24 février 2000

Outils de développement Delphi 1, 2, 3



Ce livre s'adresse aux personnes déjà initiées à Delphi, car il ne contient que du code.

On y retrouve des astuces, des idées, des liens internets, des composants.... selon différents sujets.

Il y a des routines avec le matériel.

On voit beaucoup de code et on peut ainsi mieux comprendre la disposition d'un programme Delphi ainsi que ses caractéristiques. On peut facilement trouver du code semblable sur le net.

mercredi 9 février 2000

Comment mettre le titre invisible d'une fenêtre?

Comment mettre le titre invisible d'une fenêtre?
procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowLong( Handle,
    GWL_STYLE,
    GetWindowLong( Handle, GWL_STYLE )
    and not WS_CAPTION );
  ClientHeight := Height;
end;

samedi 29 janvier 2000

Structure de flux


STRUCTURE DE FLUX

Les structures de flux permettent de choisir le déroulement du programme. Nous allons voir deux groupes de structures de flux.
  • instruction alternative
  • instruction répétitive

Instruction alternative

Ces instructions permettent d'exécuter certaines parties de programmes selon certains critères. Nous allons voir le if, if..else et le case.

Insctruction if

La syntaxe n'est pas la même dépendant du nombre d'instruction
Instruction simple Multiple instruction
if <instruction> then
         <opération>
if <instruction> then 
      begin
        <opération>;
        <opération>;
      end;
if NbEnfant > 3 then
        AjouterFrais;
      
if Frais > 1200 then 
      begin
        CalculerTaxe(Frais);
        SommeTotale;
      end;

Insctruction if else

Cette instruction est nécessaire lorsqu'on désire rajouter des opérations à effectuer lorsque la condition n'est pas remplie. On ne doit pas mettre de point virgule lorsqu'il y a seulement une instruction au if, mais on en met un pour le else.

Instruction simple Multiple instruction
if <instruction> then
        <opération> 
      else
        <opération>;
      end;
if <instruction> then begin 
   <opération>;
end else begin
   <opération>;
   <opération>; 
end;
if NbChaine < 20 then
        Commander
      else
        FaireInventaire;
      end;
if NbAuto > 18 then 
      begin
        NbAuto:=NbAuto+3;
      end 
      else begin
        NbAuto:=NbAuto+8;
        Recalculer(NbAuto);
      end;

Insctruction if imbriquée

On peut imbriquer les instructions if si nécessaire, mais si on doit en imbriquer plusieurs, il est préférable d'utiliser le case afin d'améliorer la clarté de notre code.
if x > 10 then 
begin 
  x := x + 5;
  if x > 20 then 
  begin
    x := x + 15;
    if x < 100 then 
    begin
      x := x + 25;
    end;
  end;
end;

Insctruction case

On peut remplacer des if imbriquées par un case. On gagne en compréhension.
case x of
  10..19: x := x + 5;
  20..25: x := x + 15;
else
  x := x + 25;
end;

Instruction répététive

Ces instructions permettent de réexécuter certaines parties de programmes sans qu'il soit nécessaire de les réécrire.

Boucle for

Une valeur initiale et une valeur finale sont nécessaires pour le fonctionnement de cette boucle. On incrémente et décrémente que par pas de 1, ce qui est un peu étrange lorsqu'on a déjà programmé dans d'autres langages. Habituellement, on utilise cette boucle lorsqu'on connaît le nombre de fois qu'on va parcourir la boucle. On est toutefois pas obligé de suivre cette logique, mais pourquoi pas se standardiser?

Le mot to permet d'incrémenter
for <valeur_initiale> to <valeur_final> do begin
  instruction;
end;

for ligne:=0 to maxLigne 
do 
   Calculer(tabNote); 
end;

On doit rajouter begin si le bloc comporte plusieurs instructions

for ligne:=0 to maxLigne do
begin
  Calculer(tabNote);
  Afficher(tabNote);
end;

Le mot downto permet de décrémenter

for ligne:=maxLigne downto do
begin
  Calculer(tabNote);
end;

Décrementer signifie de diminuer à chaque itération de la boucle.

Boucle while

Cette boucle teste à chaque itération si la valeur est vraie (true).
while <expression> do begin
    <instruction>
  end;
  // lire jusqu'à la fin d'un fichier
  while not Eof(InputFile) do begin
    Readln(InputFile, Line);
    Process(Line);
  end;
  while tabNote[Colonne,Min] < tabNote[Colonne,Mid] do begin 
    Inc(Min);
  end;

Boucle repeat

La boucle repeat équivaut à la boucle do while en langage c. Cette boucle ressemble beaucoup à une boucle while, elle évalue l'expression qu'à la fin de la boucle. Les instructions de la boucle seront ainsi exécutées au moins une fois.

repeat
    <instruction>
    until <expression>;
    repeat   
    inc(Min);
  until tabNote[Colonne,Min] < tabNote[Colonne,Mid];

vendredi 28 janvier 2000

Borland Delphi 4 (Formation en 21 jours)



C'est un excellent livre pour débuter en delphi.

Il présente de façon claire la syntaxe de ce langage. Les exemples sont instructifs et bien conçu.

La programmation nous ait facilité grâce à la bonne information concernant l'environnement de développement intégré.

Vous saurez davantage ce que le logiciel peut vous offrir. Ce livre touche de façon sommaire à de nombreux aspects de la programmation en delphi, c'est pour cette raison que je le trouve indispensable pour quiconque qui veut démarrer dans ce merveilleux langage.

vendredi 7 janvier 2000

Squelette

SQUELETTE

Type de fichier

Delphi génère plusieurs fichiers en voici quelques uns
Type Création Nécessaire pour compiler Description
DPR développement oui Projet (programme principal)
PAS développement oui Source des units
DCU compilation non Units compilées
EXE compilation non Code exécutable de l'application
DFM développement oui Contient la description des propriétés d'une fiche et des contrôles qu'elle contient
RES développement oui Fichier binaire associé au projet. Contient l'icon par défaut. Plusieurs fichiers RES peuvent être ajoutés au projet
~PA développement non Copie de sauvegarde du PAS correspondant
~DP développement non Copie de sauvegarde du DPR correspondant
~DF développement non Copie de sauvegarde du DFM correspondant

D'autres fichiers peuvent être générés par delphi, nous allons nous concentrer sur les deux types de fichiers les plus utilisés par les programmeurs

Fichier source

program Project1;
  uses
  Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES} 
begin 
  Application.Initialize;
  Application.CreateForm(TForm1, Form1); 
  Application.Run;
end.
Ce code est généré par delphi et ne devrait pas être modifié par le programmeur débutant.
L'application est initialisée, la fiche principale est créée et l'application s'exécute. C'est dans ce source qu'on peut empêcher delphi de créer notre formulaire au démarage de l'application.

Unité pascal

C'est ici que le programmeur travaille
unit Unit1; 
interface 
uses 
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 
Dialogs; 
type 
TForm1 = class(TForm) 
private 
{ Private declarations }
public { Public declarations } 
end;
var 
Form1: TForm1; 
implementation 
{$R *.DFM} 
end. 

Section uses

Remarquez le mot «use» dans le code, il spécifie les unités extérieures pointées par cette unité. Le uses équivaut au include du langage C
Ce code montre les principales unités utilisées.

Les composants qu'on ajoute sur la fiche, inscrivent automatiquement dans la partie «use» l'unité externe auxquelles ils ont besoin pour fonctionner correctement.
En ajoutant le composant wordapplication de l'onglet server, les unités OleServer, Word97 sont automatiquement inscrites dans la partie «use» de l'unité.

Section interface

La partie interface d'une unité sert à spécifier les identifiants extérieurs de l'unité, ça peut être un objet, fonction,procédure. On déclare les variables, classes, fonction et procédure dans cette section. Les éléments de cette partie sont accessibles aux autres unités.

Le mot «implementation» termine cette partie. La partie« implementation» contient directement le contenu des fonctions et procédures. C'est là qu'on inscrit le code.
unit Unit1;

interface

  uses Windows, Messages, SysUtils, Classes, Graphics, 
  Controls, Forms, Dialogs, OleServer, Word97, StdCtrls; 

type
  TForm1 = class(TForm) 
private { Private declarations } 
public { Public declarations } 

end;

function ajouter(x,y:double):double; 

var Form1: TForm1;

implementation 
{$R *.DFM}

function ajouter(x,y:double):double; 
begin 
   result := x+y;
end; 
end.

Plusieurs formulaires

Utiliser plusieurs formulaires devient vite essentiel lors du développement d'une application. Si on veut utiliser les variables, fonction, procédure.... d'un autre formulaire, on doit spécifier dans le uses du formulaire le nom de l'unité voulant être utilisée.

Exemple, on a une unité appelée uMain et une autre uMath. On veut utiliser une variable quelconque de uMath dans uMain. Il suffit d'inscrire uMath dans le uses de uMain.

Si on voudrait utiliser une variable de uMath dans uMain et vice versa, on pourrait seulement inscrire une des deux unités dans le uses et l'autre serait inscrite après le mot implentation de l'unité.

jeudi 6 janvier 2000

Comment entrer que des chiffres ou lettre dans un TEdit ?

Comment entrer que des chiffres ou lettre dans un TEdit ?
//que des chiffres
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
   if not (Key in ['0'..'9']) then
      Key := #0;
end;

//que des lettres
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
   if not (Key in ['a'..'z']) then
      Key := #0;
end;