samedi 30 juin 2001

Création d'un composant

CRÉATION D'UN COMPOSANT

Beaucoup de composants visuel et non visuel existent pour Delphi. Il peut arriver que ces composants ne nous conviennent pas pour diverses raisons. On peut alors utiliser le composant existant et lui ajouter des fonctionnalités. Nous allons créer un composant qui défilera du texte à l'écran, un peu à la manière d'un générique au cinéma. Le composant fonctionnera sous Windows et Linux grâce à la CLX.

Nous allons utiliser l'expert Delphi pour créer le squelette du composant. Il faut cliquer dans le menu «component», ensuite cliquez sur «New component...». L'expert Delphi apparait, on doit sélectionner l'ancêtre de notre composant, c'est à dire son parent. Notre composant héritera de ses fonction et méthode. L'ancêtre de notre composant est le TCustomPanel et le nom de la classe choisie est TUnitTextSequence.


Squelette du composant

Lorsqu'on valide, Delphi nous génère le code.



La procédure Register permettra à notre composant d'être inséré dans la liste des composants disponible sous delphi. Le composant se trouvera dans l'onglet Sample. Vous pouvez modifier cette valeur pour le mettre dans un autre onglet.

Champs

Afin de rendre le composant un peu plus intéressant, quelques champs sont ajoutés au composant. Une image de fond, la vitesse de défilement du texte ainsi que le texte sont des éléments de la classe. Ces champs sont privés afin de ne pas être utilisé directement par une autre classe externe à l'unité.

private
     FAlignment:TAlignment;           //alignement du texte
     FFond:TPicture;                  //image de fond pour le composant
     FTexte:TStringList;              //ligne pour l'animation
     FSpeedMove:Integer;              //Vitesse que le texte bougera
     FTimer:TTimer;                   //Le timer pour l'animation
     FMinMove:Integer;                //Point le plus haut où l'animation peut aller
     FMaxMove:Integer;                //Point le plus bas où l'animation peut se rendre
     FMove:Integer;                   //Le déroulement courant au millième de pixel près

Procédure

Ces champs doivent pouvoir être modifié. Leur valeur doit être changée. Nous allons créer quelques procédures qui permettront de modifier la valeur de certains champs.

protected
    { Déclarations protégées }
     procedure FondItemChange(ASender:TObject); {Quant FFond ou FItems sont modifiés}
     procedure SetAlignment(AAlignment:TAlignment);
     procedure SetFond(AFond:TPicture); virtual; {Losrqu'une affectation à Fond est fait: réf. property Fond}
     procedure SetTexte(ATexte:TStringList); virtual; {Lorsqu'une affecation à Items est effectuée: réf. property Items}
     procedure SetSpeedMove(ASpeedMove:integer); {Losrque l'utilisateur effectue un changement de vitesse de déroulement}
     procedure TimerTimer(Sender:TObject);virtual; {Quant FTimer a un événement selon l'intervalle de temps}

Propriété

Une propriété définie un attribut d'un objet. Elle permet d'associer une action à la lecture et modification de ses données Ces propriétés sont affichées dans l'inspecteur d'objet, car elles sont déclarées «published».

published
    { Déclarations publiées }
     property Alignment:TAlignment read FAlignment write SetAlignment;
     property Color;
     property Font;
     property Fond:TPicture read FFond write SetFond;
     property Texte:TStringList read FTexte write SetTexte;
     property SpeedMove:integer read FSpeedMove write SetSpeedMove;

Initiation du composant

Tel que vue dans le tutoriel sur la programmation orientée objet, un objet doit être initialisé avant d'être utilisé. Un constructeur doit être créé.

public
    { Déclarations publiques }
     constructor Create(AOwner:TComponent); override;
     destructor Destroy;override;
     procedure Paint; override; {la méthode responsable du redessinement}
     procedure SetBounds(ALeft,ATop,AWidth,AHeight:Integer); override; {Pour réactualiser la zone virtuelle de 
     déroulement sur un redimensionnement du composant}
     procedure SetRect1(var R: TRect; xLeft, yTop, xRight, yBottom: integer);

Dans la partie implémentation
constructor TTextSequence.Create(AOwner:TComponent);
begin
  inherited Create(AOwner); {Appele de méthode de son parent}
  FAlignment:=taCenter;
  Height:=150;
  Width:=100;
  FFond:=TPicture.Create;
  FTexte:=TStringList.Create;
  FTimer:=TTimer.Create(self);
  FFond.OnChange:=FondItemChange;  {Quand l'image de fond change, alors appelle de notre méthode FondItemChange}
  FTexte.OnChange:=FondItemChange; {Même chose pour les lignes d'animation}
  FMove:=0; {point de départ de l'animation au début}
  FTimer.OnTimer:=TimerTimer; {notre méthode TimerTimer sera appelée par FTimer}
  FTimer.Interval:=75; {1 = 1 ms environ}
  SpeedMove:=500; {vitesse de départ par défaut: peut-être autre chose si tu veux}
end;

Destuction du composant

Les éléments que nous avons créés dynamiquement doivent être libéré. Nous en avons créé 3 dans le constructeur.

destructor TTextSequence.Destroy;
begin
  FFond.Free;
  FTexte.Free;
  FTimer.Free;
  inherited Destroy;  {Appele le destructeur hérité}
end; 

Méthode

Le composant possède quelques méthodes, nous allons-nous attarder sur la méthode de dessinèrent. Cette méthode permet de rafraîchir le composant. Puisque le texte défile, le composant doit être constamment rafraichi.

procedure TTextSequence.Paint;
var
  DrawLine:integer;
  i:integer;
  Bitmap:TBitmap;
  Rectangle:TRect;
begin
  Bitmap:=TBitmap.Create;
  Bitmap.Width:=Width;     {largeur du bitmap}
  Bitmap.Height:=Height;   {Hauteur du bitmap}
  Bitmap.Canvas.Brush.Style:=bsSolid;
  Bitmap.Canvas.Brush.Color:=Color;
  SetRect1(Rectangle,0,0,ClientWidth,ClientHeight);
  Bitmap.Canvas.FillRect(Rectangle);
  if Assigned(FFond.Graphic) then
    if not FFond.Graphic.Empty then
      Bitmap.Canvas.StretchDraw(Rectangle,FFond.Graphic);
  Bitmap.Canvas.Brush.Style:=bsClear;
  Bitmap.Canvas.Font.Assign(Font);
  if FTexte.Count>0 then begin {si on a des lignes en animation}
    DrawLine:=FMove div 1000; {Nous conservons le déplacement au millième près}
    for i:=0 to Pred(FTexte.Count) do
    begin
      {calculs de l'affichage de la prochaine ligne d'animation}
      DrawLine:=DrawLine+Bitmap.Canvas.TextHeight(FTexte[i]);
      {si l'affichage est visible} 
      if (DrawLine>-Bitmap.Canvas.TextHeight(FTexte[i])) and (DrawLine<Height)  then
         case Alignment of
              TALeftJustify: Bitmap.Canvas.TextRect(Rectangle,Rectangle.Left+2,DrawLine,FTexte[i]);
              TARightJustify:Bitmap.Canvas.TextRect(Rectangle,
                Rectangle.Right-Bitmap.Canvas.TextWidth(FTexte[i])-2,DrawLine,FTexte[i]);
              TACenter:Bitmap.Canvas.TextRect(Rectangle,(Width div 2)-
                (Bitmap.Canvas.TextWidth(FTexte[i]) div 2),DrawLine,FTexte[i]);
         end;
    end;
  end;
  Canvas.Draw(0,0,Bitmap);{Dessine le bitmap en mémoire sur le canvas}
  Bitmap.Free;           {Libère l'objet de la mémoire}
end;

La méthode commence par créer un Bitmap, il servira à afficher le 
texte. On créer une zone de la dimension
du contrôle. On vérifie s'il a mouvement, on calcule la prochaine ligne 
et on ajuste l'alignement. Il est
possible d'augmenter la fluidité en diminuant la valeur du déplacement. 
Par défaut c'est 1000, une valeur plus faible
peut être mise. De plus, il est possible d'augmenter la valeur de 
l'intervalle du timer. Le composant se redessinera moins souvent
avec une valeur plus élevée.

Vous pouvez remarquer dans le code, que la méthode invalidate est utilisée. Cette méthode permet de redessiner le contrôle. La méthode paint à été définie comme override. Le composant n'appellera donc pas la méthode pain du parent du composant, mais cette qu'on a redéfini.

Au fur à mesure qu'on code un programme, on y décèle des problèmes. Afin de diminuer d'éventuel problème avec les composants existants, vous pouvez utiliser le composant tel qu'un objet. Il suffit de créer un programme, d'y ajouter l'unité de votre composant et de l'utiliser. Dans l'exemple ci-dessous, nous utilisons un trackbar pour diminuer ou augmenter la vitesse. La vitesse courante est affiché dans un label.



Lorsque vous pensez que votre composant être excent de problème, vous pouvez l'installer dans l'edi de Delphi. Il suffit de cliquer dans le menu Component ensuite sur Install component. Vous spécifiez le nom de l'unité. Le composant trouve alors dans l'onglet spécifié par la méthode register. Une fois que le composant est installé, vous n'avez qu'à le glisser sur la fiche pour l'utiliser.



Il est sage d'étudier les composants existants, les modifier afin dans créer de nouveau. Nous avons vue comment créer un composant visuel. D'autres fonctionnalités pourraient être ajoutées. Pratiquez-vous!

Un programme utilisant le composant est disponible ici

Je remercie Daniel Drouin de m'avoir initié à la programmation sous Delphi et de m'avoir initié à la programmation de composant à l'aide de cet exemple.

lundi 28 mai 2001

Comment rendre certaine touches inactive

Comment rendre certaine touches inactive
L'exemple ci-dessus désactive les touches ALT+TAB, CTRL+ESC, CTRL.
procedure SystemKeys(Disable: Boolean);
 var OldVal : LongInt;
begin
 SystemParametersInfo(SPI_SCREENSAVERRUNNING,
                      Word(Disable), @OldVal, 0);
end;

mercredi 2 mai 2001

Comment changer le clavier de la console?


Comment changer le clavier de la console?

Sous suse: regarder dans: /usr/share/kbd/keymaps/ (chercher où se trouve keymaps pour les autres distributions) si le clavier désiré est là sinon tenter de le trouver ensuite allez dans:

/etc/sysconfig/keyboard et mettez le nom du claiver désiré par exemple :
KEYTABLE="cf.map.gz"

Le numlock, capslock... peut être mis à on par défaut lors du démarrage à partir de ce fichier.

lundi 26 février 2001

Recherche


LES RECHERCHES

Nous utilisons différents types de recherche pour trouver des données spécifiques. Nous verrons qu'il y a divers types de recherche qui peuvent être faites.

Type de recherche

La recherche séquentielle

La recherche séquentielle consiste à vérifier du début  du tableau, liste... jusqu'à ce qu'on trouve ce qu'on désire ou parcoure totalement le tableau liste... C'est évidemment pas la recherche la plus efficace. Ce type de recherche est doit être utilisé si le tableau n'est pas trié.
//on définit les variables utilisées
Const
  Max=15;
  type
    tabType = array [1..Max] of integer;
function SequentialSearch(tab:tabType; item:integer):integer;
var
  i : integer;
  found : boolean;
begin
  SequentialSearch := 0;
  i := low(tab);
  found := false;
  while( i <= high(tab)) and (not found) do
  begin
    if tab[i] = item then
    begin
      SequentialSearch := i;
      found := true;
    end;
    inc(i);
  end;
end;

La recherche binaire

La recherche séquentielle consiste à comparer la valeur recherché par le milieu du vecteur.Si cet élément est plus grand que l'élément recherché, ce dernier est à gauche sinon à droite. On répète l'opération sur les sous-vecteurs. Le tableau doit évidemment être trié pour tirer parti de ce type de recherche

function BinarySearch(tab:tabType; item:integer):integer;
var
  Milieu:integer;
  Found:boolean;
  bas:integer;
  haut:integer;
begin
  bas := low(tab);
  haut := high(tab);
  Found := False;
  BinarySearch := 1;
  while(bas <= haut) and (not Found) do
  begin
    Milieu := (bas + haut) div 2;
    if tab[Milieu] = item then
    begin
      Found := True;
      BinarySearch := Milieu;
    end
    else
      if tab[Milieu] < item then
        bas := Milieu + 1
      else
        haut := Milieu - 1;
  end;
end;

jeudi 22 février 2001

Matrice

MATRICE

Une matrice est un genre de tableau
2 44 69
15 71 8
562 3 9
128 67 564
L'exemple précédent est une matrice 4 * 3 (4 lignes, 3 colonnes). Il est bien sûr possible de mettre des chiffres à virgule flottante dans une matrice. Diverses opérations peuvent être effectuées sur les matrices, c'est ce qu'on verra.

Opérations sur les matrices

Produit

Pour effectuer cette opération, il faut que le nombre de colonnes de la matrice A soit supérieur ou étal au nombre de ligne de la matrice B.

Matrice A

1 2 3
4 5 6

Matrice B

1 2
3 4
5 6
La multiplication de A et B donnera

Matrice A*B

1 2
22 28
49 64

Pour parvenir à ce résultat, il faut faire faire multiplier la ligne de la matrice A * la colonne de la matrice B.
Donc on a (1*1) + (2*3) + (3*5) , (1*2)+(2*4)+(3*6) , (4*1)+(5*3)+(6*5),(4*2)+(5*4)+(6*6).

Type
  matrice1=array[1..2,1..3]of integer;
  matrice2=array[1..3,1..2]of integer;
  matrice=array[1..high(matrice1),1..high(matrice2)]of integer;

function Produit(Mat1:matrice1;Mat2:Matrice2):matrice;
var
  i,j,k:integer;
  Mat3:matrice;
begin
for i:=1 to high(Mat1) do
  for j:=1 to high(Mat1) do
    begin
    Mat3[i,j]:=0;
    for k:=1 to high(Mat2) do
      Mat3[i,j] := Mat3[i,j]+Mat1[i,k]*Mat2[k,j];
    end;
    result := Mat3;
end;

Addition de matrice

L'addition de matrice est simple, il suffit d'additionner les valeurs des deux matrices qui sont situées au même endroit. Les matrices doivent être de même dimensions

Matrice A

1 2
3 4

Matrice B

5 6
7 8
On addition 1 avec 5, 2 avec 6 , 3 avec 7 et 4 avec 8 pour obtenir
6 8
10 12
Voici le code de la fonction
type
  matrice=array[1..2,1..2]of integer;

function Addition(Mat1:,Mat2:matrice):matrice;
var
  i,j:integer;
  Mat3:matrice;
begin
  for i:=1 to high(Mat1) do
    for j:=1 to high(Mat1) do
      Mat3[i,j] := Mat1[i,j]+ Mat2[i,j];
    result:=matc;
end;
Le principe de la soustraction est le même. Il suffit de remplacer le + par un - dans l'algo ci-dessus.

Produit boolean

Cette opération ressemble au calcul de matrice.Pour effectuer cette opération, il faut que le nombre de colonnes de la matrice A soit supérieur ou étal au nombre de ligne de la matrice B. Puisque c'est boolean, les éléments des matrices que peuvent avoir que des 0 ou des 1 comme valeur.

Matrice A

1 0 1
1 0 0
0 0 0

Matrice B

1 0 0
0 1 0
1 0 0

Le principe ressemble à la multiplication de deux matrices. On remplace les plus par des ou logiques. L'utilisation des ou logique implique qu'aussitôt qu'on retrouve 1*1, ça donnera 1.

Donc on a (1*1 ou 0*0 ou 1*1) ça donne 1. Puisqu'on a 1*1 et que c'est ou, on aurait pu arrêter à 1*1. Le résultat final donnera

1 0 0
1 0 0
0 0 0

Voici le code de la fonction pour calculer le produit boolean

type
  matrice=array [1..3,1..3] of integer;

function ProduitBoolean(matrice1,matrice2:matrice):matrice;
var
  i,j,k:integer;
  ok:boolean;
  matrice_result:matrice;
begin
  ok := false;
  for i:=1 to high(matrice1) do begin
    for j:=1 to high (matrice1) do
    begin
      for k:=1 to high(matrice1) do
        if (matrice1[i][k] = 1 ) and (matrice2[k][j]=1) and not(ok)then
          ok := true;
      if ok then
        matrice_result[i][j]:=1
      else
        matrice_result[i][j]:=0;
      ok := false;
    end;
  end;
  result := matrice_result;
end;

lundi 29 janvier 2001

Chaine de caractère

CHAÎNE DE CARACTÈRE

Type de chaîne

Chaîne courte

Les chaînes courtes ont une longueur fixe, elles ne peuvent dépasser plus de 255 caractères. Étant donné que les chaînes courtes ont une valeur fixe, leurs vitesses d'exécution sont très rapides. On peut les déclarer de deux façons, mais une seule est vraiment utile.

var
   Nom:shortstring;
   Prenom:string[30];

Lorsqu'on utilise shortstring, la longueur de la variable est automatiquement de 255 caractères. A moins d'avoir absolument besoin de 255 caractères, il n'est pas vraiment intéressant d'utiliser le type shortstring. Il est intéressant d'utiliser les chaînes courtes lorsqu'on sait que la longueur de la variable sera fixe ou que l'on sait le nombre de caractère maximum qu'il peut y avoir.

Le gain de vitesse sera appréciable si l'on fait beaucoup de manipulation sur les chaînes. Le premier élément d'une chaîne courte représente la longueur de la chaîne, ce qui peut s'avérer intéressant dans certaines situations.

Chaîne longue

Les chaînes longues sont allouées dynamiquement. Leur longueur est limitée à la taille de votre mémoire disponible. Tout le traitement pour allonger et réduire la taille de la chaîne est fait en coulisse, mais on perd un peu de vitesse.

var
  Nom:string;
  Prenom:string;

Les chaînes longues n'ont pas d'élément zéro.

Chaîne à zéro terminal

Ce type de chaîne est très utilisé lorsqu'on doit utiliser les fonctions de Windows. Les fonctions de Windows utilisent des tableaux de caractères (langage c) et utilisent donc un 0 à la fin de la chaîne afin de marquer la fin de la chaîne. On doit utiliser le type PChar lorsqu'on manipule les fonctions de windows ou bien faire de la conversion.

var
  libelle : string;
begin
  libelle := 'Bonjour'; messagebox (0, PCHAR(libelle), 'Message', mb_ok);
end;

Ce code utilise un api (très simple) afin d'afficher une boîte de message

Routine de gestion de chaîne

Voici quelques fonctions et procédures disponibles, il en existe de nombreuses autres.

Routines de traitement de chaîne AZT


Fonction Description
StrAlloc Alloue une zone tampon d'une taille donnée sur le tas.
StrBufSize Renvoie la taille d'une zone tampon de caractère alloué en utilisant StrAlloc ou StrNew.
StrCat Concatène deux chaînes.
StrComp Compare deux chaînes.
StrCopy Copie une chaîne.
StrDispose Dispose une zone tampon de caractère allouée en utilisant StrAlloc ou StrNew.
StrECopy Copie une chaîne et renvoie un pointeur à la fin de la chaîne.
StrEnd Renvoie un pointeur à la fin d'une chaîne.
StrFmt Formate une ou plusieurs valeurs dans une chaîne.
StrIComp Compare deux chaînes sans tenir compte des majuscules/minuscules.
StrLCat Concatène deux chaînes avec une longueur maximum donnée de la chaîne résultante.
StrLComp Compare deux chaînes pour une longueur maximum donnée.
StrLCopy Copie une chaîne jusqu'à une longueur maximum donnée.
StrLen Renvoie la longueur d'une chaîne.
StrLFmt Formate une ou plusieurs valeurs dans une chaîne avec une longueur maximum donnée.
StrLIComp Compare deux chaînes pour une longueur maximum donnée sans tenir compte des majuscules/minuscules.
StrLower Convertit une chaîne en minuscules.
StrMove Déplace un bloc de caractères d'une chaîne sur l'autre.
StrNew Alloue une chaîne sur le tas.
StrPCopy Copie une chaîne Pascal vers une chaîne à zéro terminal.
StrPLCopy Copie une chaîne Pascal vers une chaîne AZT avec une longueur maximum donnée.
StrPos Renvoie un pointeur sur la première occurrence d'une sous-chaîne donnée dans une chaîne.
StrRScan Renvoie un pointeur sur la dernière occurrence d'un caractère donné dans une chaîne.
StrScan Renvoie un pointeur sur la première occurrence d'un caractère donné dans une chaîne.
StrUpper Convertit une chaîne en majuscules.

Routines de traitement de chaînes shortstring (chaîne Pascal)


Fonction Description
AdjustLineBreaks Transforme les ruptures de lignes dans une chaîne en séquences CR/LF.
AnsiCompareStr Comparaison, en tenant compte des majuscules/minuscules, de deux chaînes.
AnsiCompareText Comparaison, sans tenir compte des majuscules/minuscules, de deux chaînes.
AnsiLowerCase Convertit des caractères en minuscules.
AnsiUpperCase Convertit des caractères en majuscules.
CompareStr Comparaison, en tenant compte des majuscules/minuscules, de deux chaînes.
CompareText Comparaison, sans tenir compte des majuscules/minuscules, de deux chaînes.
Concat Concatène une suite de chaînes.
Copy Renvoie une sous-chaîne d'une chaîne.
Delete Efface une sous-chaîne d'une chaîne.
DisposeStr Libère une chaîne du tas.
FmtLoadStr Charge une chaîne dans la ressource table de chaînes d'un programme.
Insert Insère une sous-chaîne dans une chaîne.
IntToHex Convertit un entier en hexadécimal.
IntToStr Convertit un entier en chaîne.
IsValidIdent Renvoie True si la chaîne spécifiée est un identificateur valide.
Length Renvoie la longueur dynamique de la chaîne.
LoadStr Charge la ressource chaîne depuis le fichier exécutable de l'application.
LowerCase Met en minuscule la chaîne spécifiée.
NewStr Alloue une nouvelle chaîne dans le tas.
Pos Recherche une sous-chaîne dans une chaîne.
Str Convertit une valeur numérique en chaîne.
StrToInt Convertit une chaîne en entier.
StrToIntDef Convertit une chaîne en entier ou à une valeur par défaut.
Trim Supprime les espaces de début et de fin et les caractères de contrôle d'une chaîne donnée.
TrimLeft Supprime les espaces de début et les caractères de contrôle d'une chaîne donnée
TrimRight Supprime les espaces de fin et les caractères de contrôle d'une chaîne donnée.
UpperCase Met en majuscule la chaîne spécifiée.
Val Convertit une valeur chaîne en sa représentation numérique.

StringList

Les stringlist permettent de gérer un tableau de phrase. Chaque ligne du tableau peut être accédées grâce à son index.

De nombreuses opérations peuvent être effectuées sur les stringlist: insertion, effacement, comparaison...

La création d'une stringlist est très aisée.

lstNom : TStrings; 
// Déclaration de TStrings au lieu de TStringList 
//pour des d'utilisations de paramatètres de la vcl.
//Création d'une instance de TStringList
lstNom := TStringList.Create;
//Ajout de chaîne dans la liste
lstNom.Add('Paul Smith');
lstNom.Add('Renée');
lstNom.Add('Nicolas');
Nom:=lstNom[2];
//insertion de plage dans la variable nom
insert('plage',Nom,3);
lstNom[2]:=Nom;

Les routines de traitement peuvent être facilement effectuées sur les stringslist.

Comment chercher et remplacer des caractères?

Comment chercher et remplacer des caractères?
function SearchAndReplace
  (sSrc, sLookFor, sReplaceWith : string) : string;
var
  nPos, nLenLookFor : integer;
begin
  nPos        := Pos(sLookFor, sSrc);
  nLenLookFor := Length(sLookFor);
  while (nPos > 0) do begin
    Delete(sSrc, nPos, nLenLookFor);
    Insert(sReplaceWith, sSrc, nPos);
    nPos := Pos(sLookFor, sSrc);
  end;
  Result := sSrc;
end;

Migration d’une application Spring Boot 2.2 vers Spring Boot 4.0 : retour d’expérience concret

 En 2019, nous avons développé une application métier basée sur : Java 8 Spring Boot 2.2.7 Gradle 6.6.1 Thymeleaf Boots...