Composant bouton 4 cotés arrondis

Soyez le premier à donner votre avis sur cette source.

Vue 4 043 fois - Téléchargée 1 109 fois

Description

Bouton couleur avec scanline, 4 cotés arrondis, pouvant servir de label, cadre,...
Rotation de bitmap avec scanline, et exemple d'utilisation.

Source / Exemple :


unit BoutCoulArrondi;

interface

uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, ExtCtrls, ExtDlgs, Spin, FileCtrl, ComCtrls;

Const
   PixelCountMax=32768;                                    {Nombre maxi de pixels}

TYPE
   pRGBTripleArray=^TRGBTripleArray;                       {Nom de pointeur}
   TRGBTripleArray=ARRAY[0..PixelCountMax-1]of TRGBTRIPLE; {sur l'ensemble des pixels}
   TGlyphSite = (GLLeft, GLRight);                         {Position du Glypf : droite ou gauche}

type
  TBoutCoulArrondi = class(TGraphicControl)
  private
    { Déclarations privées }
    FBTimer:TTimer;                                        //Le timer pour le click sur bouton
    FBTimerEnabled:Boolean;                                //On le met ou pas
    FBTimerTemp:Integer;                                   //la temporisation du timer
    FBCaption: TCaption;                                   //Caption du bouton
    FBBosse : Boolean;                                     //Bouton en relief
    SavFBBosse:boolean;                                    //Variable pour arréter le clignotement du bouton
    FBMarge:Integer;                                       //Largeur de la laie pour l'écriture
    FBPourCent:Integer;                                    //Relief du bouton(de 0 à 100)
    FBColor:Tcolor;                                        //Couleur du cadre
    FBROUGE:Byte;
    FBVERT:Byte;
    FBBLEU:Byte;
    FBGlyphSite:TGlyphSite;                                //position du glyph
    FBGLyph:TBitmap;                                       //le glyph
    
    Procedure SETBTimerEnabled(Value:boolean);             //Mise en route ou pas du timer
    Procedure SETBTimerTemp(Value:integer);                //récupération de la durée de tempo
    Procedure SETBBosse(Value:Boolean);                    //en relief ou inversé
    Procedure SETBPourCent(Value:Integer);                 //La hauteur de relief
    Procedure SETBMarge(Value:Integer);                    //la largeur de laie
    Procedure SETBROUGE(Value:Byte);
    Procedure SETBVERT(Value:Byte);
    Procedure SETBBLEU(Value:Byte);
    Procedure SETBColor(Value:TColor);
    procedure SETBCaption(Value: TCaption);
    procedure SETBGlyph(Value:TBitmap);
    procedure SETBGlyphSite(Value:TGlyphSite);
    Procedure Controle(Var Rouge:Byte;Var Vert:Byte;Var Bleu:Byte);//contrôle des limites RVB
    procedure Rotation(LeBitmapSource, LeBitmapCible : TBitmap);//rotation de 90° du bitmap source sur cible

  protected
    { Déclarations protégées }
    procedure Paint; override;
    Procedure OnTimer(Sender:TObject);Virtual;             //Procedure pour le clignotement du bouton au click
    Procedure TransformeBouton(Var Rouge, Vert, Bleu:Byte; //Modification du bouton avec scanline
          Marge:Integer;FPourCent:integer;FBosse:boolean;M:string);

  public
    { Déclarations publiques }
    constructor Create(AOwner:TComponent); override;
    Destructor Destroy;Override;
    Procedure Click;Override;
    Procedure DblClick;Override;

  published
    { Déclarations publiées }
   Property TimerEnabled:Boolean READ FBTimerEnabled WRITE SETBTimerEnabled;
   Property TimerTemp:Integer READ FBTimerTemp WRITE SETBTimerTemp;
   property Propriete:boolean READ FBBosse WRITE SETBBosse;
   Property PourCent:Integer READ FBPourCent WRITE SETBPourCent;
   Property Marge:integer READ FBMarge WRITE SETBMarge;
   property Glyph:TBitmap READ FBGLyph WRITE SETBGlyph;
   Property GlyphSite:TGlyphSite READ FBGlyphSite WRITE SETBGlyphSite;
   property Caption: TCaption read FBCaption  WRITE SETBCaption;
   Property ROUGE:Byte READ FBROUGE WRITE SETBROUGE;
   Property VERT:Byte READ FBVERT WRITE SETBVERT;
   Property BLEU:Byte READ FBBLEU WRITE SETBBLEU;
   property Color: TColor READ FBColor WRITE  SETBColor;
   property Align;
   property Cursor;
   property DragCursor;
   property DragMode;
   property Enabled;
   property Font;
   property Hint;
   property ParentFont;
   property ParentShowHint;
   property PopupMenu;
   property Visible;
   property OnClick;
   property OnDblClick;
   property OnMouseDown;
   property OnMouseMove;
   property OnMouseUp;
  end;

procedure Register;

Var
   Image: TImage;

implementation

Procedure TBoutCoulArrondi.TransformeBouton(Var Rouge, Vert, Bleu:Byte;//Modification du bouton avec scanline}
          Marge:Integer;FPourCent:integer;FBosse:boolean;M:string);
VAR
   Btmap1,Btmap2 : TBitmap;                                {bitmaps}
   i : INTEGER;                                            {X avec scanline}
   j : INTEGER;                                            {y avec scanline}
   row : pRGBTripleArray;
   ScanlineBytes: INTEGER;
   Coef:array[1..3,1..2]of real;                           {coef pour les 3 couleurs et bosse avec ou sans}
   Coefi:array[1..3]of real;                               {coef pour les calculs des 3 couleurs}
   Laie,Posit : integer;                                   {Laie et position}
   R,G,B:Byte;
   R1,G1,B1:Byte;
   Re:Trect;
   T:integer;                                              {le % pour le relief}
   RGN:HRGN;
   W,H:integer;                                            {Largeur hauteur}
   CourantGlyph:^TBitmap;                                  {Pointeur sur Glyph}
   WBg,HBg,TBg,LBg:integer;                                {Largeur, hauteur, top, left}
   Dr,Ga:integer;                                          {droite et gauche}
   Recouvrement:integer;
begin
   Recouvrement:=3;
   W:=Width;
   H:=Height;
   T:=FPourCent;
   R:=Rouge;
   G:=Vert;
   B:=Bleu;                             //Calculs des coef R, V, B en fonction de Bosse
   coef[1,1]:=(255-Rouge)/100;
   coef[2,1]:=(255-Vert)/100;
   coef[3,1]:=(255-Bleu)/100;
   coef[1,2]:=Rouge/100;
   coef[2,2]:=vert/100;
   coef[3,2]:=Bleu/100;
   If W>=H then                          //eviter les erreurs en changement de dimension}
   Laie:=round(((Height-1)/2)-Marge)     //Calcul de la laie au milieu pour l'écriture du texte}
   else
   Laie:=round(((Width-1)/2)-Marge);
   Case Fbosse of
      True : begin                      //Calcul de la couleur de départ et du coef poun incrémentation
         R1:=Rouge-round(T*Coef[1,1]);
         G1:=Vert-round(T*Coef[2,1]);
         B1:=Bleu-round(T*Coef[3,1]);
         Controle(R1,G1,B1);
         Coefi[1]:=(Rouge-R1)/Laie;
         Coefi[2]:=(Vert-G1)/Laie;
         Coefi[3]:=(Bleu-B1)/Laie;
      end;
      False : begin
         R1:=Rouge+round(T*Coef[1,2]);
         G1:=Vert+round(T*Coef[2,2]);
         B1:=Bleu+round(T*Coef[3,2]);
         Controle(R1,G1,B1);
         Coefi[1]:=(R1-Rouge)/Laie;
         Coefi[2]:=(G1-Vert)/Laie;
         Coefi[3]:=(B1-Bleu)/Laie;
      end;
   end;
   Image:=TImage.Create(Self);      //Création et dimension de l'image
   Image.Width := Width;
   Image.Height := Height;
   Btmap1 := TBitmap.Create;
   TRY
      Btmap1.PixelFormat := pf24bit; //Création du premier bitmap aux mêmes dimentions que l'image
      Btmap1.Width := Width;
      Btmap1.Height := Height;
      row := Btmap1.Scanline[0];     //Initialisation de Scanline
      ScanlineBytes := Integer(Btmap1.Scanline[1]) - Integer(row);
      Dr:=0;                        //On va dessiner un angle jusqu'a la laie
      Ga:=Btmap1.Width-1;
      FOR j := 0 TO Laie DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               Case FBosse of
                  True :
                  begin
                     R:=round(R1+(coefi[1]*j));
                     G:=round(G1+(coefi[2]*j));
                     B:=round(B1+(coefi[3]*j));
                  end;
                  False :
                  Begin
                     R:=round(R1-(coefi[1]*j));
                     G:=round(G1-(coefi[2]*j));
                     B:=round(B1-(coefi[3]*j));
                  end;
               end;
               Controle(R,G,B);
               rgbtRed := Integer(R);
               rgbtGreen := Integer(G);
               rgbtBlue := Integer(B);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
         if J>Recouvrement then      //Le dessin de l'angle, attention, recouvrement nécessaire
         begin
            Dr:=Dr+1;
            Ga:=Ga-1;
         end;
      END;
      Posit:=Btmap1.Height-laie;  //Dessin de la plage plate pour l'écriture
      FOR j := Laie TO Posit DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               rgbtRed := Integer(Rouge);
               rgbtGreen := Integer(vert);
               rgbtBlue := Integer(Bleu);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
      END;
      R1:=Rouge;               //On repart des couleurs initiales
      G1:=vert;
      B1:=Bleu;
      FOR j := Posit TO Btmap1.Height-3 DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               Case FBosse of
                  True : Begin
                     R:=round(R1-(coefi[1]*(j-posit)));
                     G:=round(G1-(coefi[2]*(j-posit)));
                     B:=round(B1-(coefi[3]*(j-posit)));
                  end;
                  False : Begin
                     R:=round(R1+(coefi[1]*(j-posit)));
                     G:=round(G1+(coefi[2]*(j-posit)));
                     B:=round(B1+(coefi[3]*(j-posit)));
                  end;
               end;
               Controle(R,G,B);
               rgbtRed := Integer(R);
               rgbtGreen := Integer(G);
               rgbtBlue := Integer(B);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
         If Dr>0 then                       //Angle inversé
         begin
            Dr:=Dr-1;
            Ga:=Ga+1;
         end;
      END;
      Case Fbosse of
         True : begin
            R1:=Rouge-round(T*Coef[1,1]);
            G1:=Vert-round(T*Coef[2,1]);
            B1:=Bleu-round(T*Coef[3,1]);
            Controle(R1,G1,B1);
            Coefi[1]:=(Rouge-R1)/Laie;
            Coefi[2]:=(Vert-G1)/Laie;
            Coefi[3]:=(Bleu-B1)/Laie;
         end;
         False : begin
            R1:=Rouge+round(T*Coef[1,2]);
            G1:=Vert+round(T*Coef[2,2]);
            B1:=Bleu+round(T*Coef[3,2]);
            Controle(R1,G1,B1);
            Coefi[1]:=(R1-Rouge)/Laie;
            Coefi[2]:=(G1-Vert)/Laie;
            Coefi[3]:=(B1-Bleu)/Laie;
         end;
      end;
      Btmap2 := TBitmap.Create;      //Création du deuxième bitmap, avec dimentions inversées
      Btmap2.PixelFormat := pf24bit; //On va traiter l'image inversée de la même manière
      Btmap2.Width := Height;
      Btmap2.Height := Width;
      Rotation(Btmap1,Btmap2);      //Inversion de l'image dans le deuxième bitmap
      Dr:=0;
      Ga:=Btmap2.Width-1;
      row := Btmap2.Scanline[0];   //Initialisation de Scanline
      ScanlineBytes := Integer(Btmap2.Scanline[1]) - Integer(row);
      FOR j := 0 TO Laie DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               Case FBosse of
                  True :
                  begin
                     R:=round(R1+(coefi[1]*j));
                     G:=round(G1+(coefi[2]*j));
                     B:=round(B1+(coefi[3]*j));
                  end;
                  False :
                  Begin
                     R:=round(R1-(coefi[1]*j));
                     G:=round(G1-(coefi[2]*j));
                     B:=round(B1-(coefi[3]*j));
                  end;
               end;
               Controle(R,G,B);
               rgbtRed := Integer(R);
               rgbtGreen := Integer(G);
               rgbtBlue := Integer(B);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
         if J>Recouvrement then
         begin
            Dr:=Dr+1;
            Ga:=Ga-1;
         end;
      END;
      Posit:=Btmap2.Height-laie;
      FOR j := Laie TO Posit DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               rgbtRed := Integer(Rouge);
               rgbtGreen := Integer(Vert);
               rgbtBlue := Integer(Bleu);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
      END;
      R1:=Rouge;
      G1:=vert;
      B1:=Bleu;
      FOR j := Posit TO Btmap2.Height-3 DO
      BEGIN
         FOR i := Dr TO Ga DO
         BEGIN
            WITH row[i] DO
            BEGIN
               Case FBosse of
                  True : Begin
                     R:=round(R1-(coefi[1]*(j-posit)));
                     G:=round(G1-(coefi[2]*(j-posit)));
                     B:=round(B1-(coefi[3]*(j-posit)));
                  end;
                  False : Begin
                     R:=round(R1+(coefi[1]*(j-posit)));
                     G:=round(G1+(coefi[2]*(j-posit)));
                     B:=round(B1+(coefi[3]*(j-posit)));
                  end;
               end;
               Controle(R,G,B);
               rgbtRed := Integer(R);
               rgbtGreen := Integer(G);
               rgbtBlue := Integer(B);
            END;
         END;
         INC(Integer(Row), ScanlineBytes);
         If Dr>0 then
         begin
            Dr:=Dr-1;
            Ga:=Ga+1;
         end;
      END;
      Rotation(Btmap2,Btmap1); //On inverse à nouveau l'image dans le Bitmap N°1
      With Image do
      begin
         Picture.Graphic := Btmap1; //Récupération du Glyph s'il existe
         CourantGlyph:=ADDR(FBGlyph);
         WBg:=0;
         LBg:=0;
         if CourantGlyph<>nil Then
         begin
            Btmap1.Assign(CourantGlyph^);
            With Btmap1 do
            Begin
               HBg:=Btmap1.Height;
               WBg:=Btmap1.Width;
               TBg:=round((Image.Height-HBg)/2);
               If FBGlyphSite=GLLeft then
               LBg:=5
               else
               LBg :=(Image.Width-5)-(WBg);
               Transparent:=True;
               TransparentColor:=Btmap1.Canvas.pixels[5,5];
            end;
         end;
         Canvas.Brush.Style:=Bsclear;  //Dessin de l'image et du texte
         Canvas.Draw(LBg,TBg,Btmap1);
         RGN:=CreateRectRGN(0,0,W,H);
         SelectClipRGN(Canvas.Handle,RGN);
         Canvas.Font.Size:=Font.Size;
         Canvas.Font.Name:=Font.Name;
         Canvas.Font.Color:=Font.Color;
         Transparent:=True;
         If FBGlyphSite=GLLeft then
         Re:=Rect(WBg,0,W,H)
         else
         Re:=Rect(0,0,W-WBg,H);
         Drawtext(Canvas.Handle,PCHAR(FBCaption),-1,Re,DT_SINGLELINE or DT_VCENTER or DT_CENTER);
      END;
   FINALLY
      Btmap1.Free;
      Btmap2.free;
   END;
END;

procedure TBoutCoulArrondi.Rotation(LeBitmapSource, LeBitmapCible : TBitmap);//rotation de 90° du bitmap source sur cible
var
   BitmapSource, BitmapCible : TBitmap;        //source et cible}
   x,y : integer;
   LigneSource, LigneCible : pRGBTripleArray;  //Lignes source et cible
begin
   BitmapSource := TBitmap.Create;
   BitmapCible := TBitmap.Create;
   try
      BitmapSource.pixelformat := pf24bit;
      BitmapCible.pixelformat := pf24bit;
      BitmapSource.assign(LeBitmapSource);     //récupération du bitmap source
      BitmapCible.Height := BitmapSource.Width;//Dimentions inversées
      BitmapCible.Width := BitmapSource.Height;
      for y:=0 to BitmapSource.Height - 1 do  //On lit une ligne horizontale que l'on écrit verticalement
      begin
         LigneSource := BitmapSource.ScanLine[y];
         for x:=0 to BitmapSource.Width - 1 do
         begin
            LigneCible := BitmapCible.ScanLine[x];
            LigneCible[BitmapSource.Height - 1 - y] := LigneSource[x];
         end;
      end;
      LeBitmapCible.Height:=BitmapCible.Height;
      LeBitmapCible.Width:=BitmapCible.Width;
      with LeBitmapCible do
      Canvas.draw(0,0,BitmapCible);
   finally
      BitmapSource.free;
      BitmapCible.free;
   end;
end;                                          //génial avec scanline

Procedure TBoutCoulArrondi.Controle(Var Rouge:Byte;Var Vert:Byte;Var Bleu:Byte);//contrôle des limites RVB
begin
   If Rouge>255 then Rouge:=255 else if Rouge<0 then Rouge:=0;
   If Vert>255 then Vert:=255 else if Vert<0 then Vert:=0;
   If Bleu>255 then Bleu:=255 else if Bleu<0 then Bleu:=0;
end;

Procedure TBoutCoulArrondi.SETBTimerEnabled(Value:boolean);//Mise en route ou pas du timer}
Begin
   If Value<>FBTimerEnabled then
   FBTimerEnabled:=Value;
   If CsDesigning In ComponentState then //si on est en création, pas de démarrage
   begin
      FBTimer.Enabled:=false;
      exit;
   end;
   FBTImer.Enabled:=FBTimerEnabled;
end;

Procedure TBoutCoulArrondi.SETBTimerTemp(Value:integer);//récupération de la durée de tempo}
begin
   if Value<>FBTimerTemp then
   FBTimerTemp:=Value;
   FBTimer.Interval:=FBTimerTemp;
   If CsDesigning in componentState then //si on est en conception du bouton alors le timer ne démarre pas
   begin
      FBTimer.Enabled:=false;
      exit;
   end;
end;

Procedure TBoutCoulArrondi.Ontimer(Sender:Tobject);//Procedure pour le clignotement du bouton au click
Begin
   FBBosse:=Not FBBOsse;
   If CsDesigning in componentState then//si on est en conception du bouton alors  le timer ne démarre pas
   begin
      FBTimer.Enabled:=false;
      exit;
   end;
   Invalidate;
end;

procedure TBoutCoulArrondi.SETBCaption(Value: TCaption);
begin
   if Value <> FBCaption then
   begin
      FBCaption := Value;
      Invalidate;
   end;
end;

Procedure TBoutCoulArrondi.SETBBosse(Value:Boolean);
Begin
   if Value <> FBBosse then
   begin
      FBBosse := Value;
      SavFBBosse:=Value;
      Invalidate;
   end;
End;

Procedure TBoutCoulArrondi.SETBPourCent(Value:Integer);
Begin
   If Value<0 then Value:=0 else if Value>100 then Value:=100;
   if Value <> FBPourCent then
   begin
      FBPourCent := Value;
      Invalidate;
   end;
End;

Procedure TBoutCoulArrondi.SETBMarge(Value:Integer);//modifier la largeur de laie
Begin //Contrôle des limites, à revoir avec même modif sur MonBoutonCouleur
   If Value<0 then Value:=0;
   if Height>=Width then
   begin
      if Value>(Height/2.25)then
      Value:=round(Height/2.25);
   end
   else
   begin
      if Value>(Width/2.25)then
      Value:=round(Width/2.25);
   end;
   if Value <> FBMarge then
   begin
      FBMarge := Value;
      Invalidate; //Demande à Windows de repeindre le contrôle
   end;
End;

Procedure TBoutCoulArrondi.SETBROUGE(Value:Byte);
Begin
   if Value <> FBROUGE then
   begin
      FBROUGE := Value;
      Invalidate;
   end;
End;

Procedure TBoutCoulArrondi.SETBVERT(Value:Byte);
Begin
   if Value <> FBVERT then
   begin
      FBVERT := Value;
      Invalidate;
   end;
End;

Procedure TBoutCoulArrondi.SETBBLEU(Value:Byte);
Begin
   if Value <> FBBLEU then
   begin
      FBBLEU := Value;
      Invalidate;
   end;
End;

Procedure TBoutCoulArrondi.SETBColor(Value:TColor);
Begin
   if Value <> FBColor then
   begin
      FBColor := Value;
      Invalidate;
   end;
end;

Procedure TBoutCoulArrondi.SETBGlyphSite(Value:TGlyphSite);//position du glyph
begin
   If FBGlyphSite<>Value then
   FBGlyphSite:=Value;
   Invalidate;
end;

procedure TBoutCoulArrondi.SetBGlyph(Value:TBitmap);
begin
   FBGlyph.Assign(Value);
   Invalidate;
end;

Procedure TBoutCoulArrondi.Click;
Begin
   If FBTimerEnabled=true then
   FBTimer.Enabled:=true;
   InHerited Click;
end;

Procedure TBoutCoulArrondi.DblClick;
Begin
   If FBTimerEnabled=true then
   FBTimer.Enabled:=true;
   InHerited DblClick;
end;
procedure TBoutCoulArrondi.Paint;
begin
   inherited Paint;
   with Canvas do
   begin
      TransformeBouton(FBrouge,FBvert,FBbleu,FBMarge,FBPourcent,FBBosse,FBCaption);
      Canvas.Draw(0,0,Image.Picture.Graphic);
      Image.Free;
      Brush.Style:=bsClear;
      Pen.Width:=4;
      Pen.Color:=FBColor;
      Rectangle(0,0,Width,Height);
   end;
   If FBBOsse=SavFBBosse then
   FBTimer.Enabled:=False;
end;

constructor TBoutCoulArrondi.Create(AOwner:TComponent);
begin
   inherited Create(AOwner);
   FBGlyph:=TBItmap.Create;
   FBTimerEnabled:=True;
   FBTimerTemp:=50;
   FBTimer:=TTImer.Create(Self);
   FBTimer.Interval:=FBTimerTemp;
   FBTimer.OnTimer:=Ontimer;
   Width:=200;
   Height:=100;
   FBRouge:=154;
   FBVert:=134;
   FBBleu:=177;
   FBColor:=CLWhite;
   FBPourCent:=80;
   Font.Size:=16;
   Font.Color:=CLBlack;
   FBCaption:=TBoutCoulArrondi.ClassName;
   FBCaption:=Copy(FBCaption,2,Length(FBCaption)-2);
   FBBosse:=true;
   SAVFBBosse:=FBBosse;
   FBGlyphSite := glLeft;
   FBMarge:=10;
end;

Destructor TBoutCoulArrondi.Destroy;
Begin
   FBGlyph.Free;
   FBTimer.Free;
   Inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('Exemples', [TBoutCoulArrondi]);
end;

end.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

haitek
Messages postés
26
Date d'inscription
jeudi 25 octobre 2007
Statut
Membre
Dernière intervention
13 mars 2014
-
Bonjour,
En exécutant l'exemple sur Delphi 5, un message d'erreur apparaît

Classe TMonboutonCouleur non trouvé, Le fichier MonBoutonCouleur.dcu non trouvé

C'est pour apprécier le composant ...
Mowglinaute
Messages postés
42
Date d'inscription
dimanche 4 mars 2007
Statut
Membre
Dernière intervention
27 février 2013
-
Bonjour à tous,
Pour obtenir le composant:
j'ai d'abord sélectionner les codes ensuite les copier et coller dans un fichier que j'ai nommé "Touche4Arrondi.pas".
Et pour terminer j'ai créé un package pour installer le compiler et l'installer.
Enfin, je le trouve parfois utile d'après ce que l'on veut fabriquer comme projet.

Bonne continuation à l'auteur.

Pr. J.LOMBET ou Mowglinaute en pseudo.
dubois77
Messages postés
675
Date d'inscription
jeudi 17 avril 2008
Statut
Membre
Dernière intervention
19 février 2019
10 -
et le zip ?
et l'exemple ?
cs_cantador
Messages postés
4716
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
10 -
joli bouton sacré bouton veux-tu me laisser...
la guerre des boutons, c'est bien mais il faudrait peut-être passer à
autre chose..
non ?

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.