IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

Composant "Compteur à tambours" pour D6


Sujet :

Composants VCL Delphi

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Composant "Compteur à tambours" pour D6
    Bonjour.

    La dernière fois (il y a un peu plus d'un an) que j'ai posé une question en rapport avec ce sujet, le tout a dérivé en une sorte de concours de programmation (avec troll à la clé ! ) vers un logiciel "monstre" qui en fait ne répondait à absolument pas à ce que je cherchais !

    Je dis "compteur" car c'est là que l'on trouvait ce type d'affichage (anciens compteurs kilométriques de voiture, compteurs bleu et d'eau). A l'époque on m'avait développé un compteur ... qui tournait tout seul, avec effets de transition par rotation etc.

    Très beau, mais CE N'EST PAS CE QUE JE CHERCHE !

    J'ai un composant qui s'appelle Counter, mais qui en fait n'est qu'un affichage d'une valeur fournie (sous forme String). Il a été développé en 1997 (!) par un certain M. Alexander Meeder (merci encore à lui), 20 chiffres maxi (nombre paramétrable) et téléchargé chez "Torry" ; dans ses styles d'affichage, il y a le "Nixie" ("Traditional") : joli vintage, mais je préférerais encore les tambours. Il peut afficher à partir d'un bitmap fourni mais hormis le fait que je n'ai pas ce genre de motif (avec les dégradés de la face bombée), il faut apparemment mettre ces motifs dans un fichier qui reste séparé. Or moi je cherche le même type d'AFFICHAGE où ce motif serait intégré, comme le Nixie dans le compteur précédent.

    Les raisons de ma recherche seraient trop longues à expliquer, sachez simplement que je travaille sur un programme qui "fait référence" aux anciens jeux "automatiques" des fêtes foraines des années 60, et ceux-ci avaient ce type de compteur (comme les flippers de la même époque).

    Qui connaît ce genre de composant ? Merci d'avance ...

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Avec le composant Counter, tu n'es pas obligé d'avoir un fichier externe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    procedure GradVertical(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor);
    var
      y: Integer;
      dr, dg, db: Extended;
      C1, C2: TColor;
      r1, r2, g1, g2, b1, b2: Byte;
      R, G, B: Byte;
      cnt: Integer;
      RectMiddle: Integer;
    begin
      C1 := FromColor;
      r1 := GetRValue(C1);
      g1 := GetGValue(C1);
      b1 := GetBValue(C1);
      C2 := ToColor;
      r2 := GetRValue(C2);
      g2 := GetGValue(C2);
      b2 := GetBValue(C2);
      dr := (r2 - r1) / Rect.Bottom - Rect.Top;
      dg := (g2 - g1) / Rect.Bottom - Rect.Top;
      db := (b2 - b1) / Rect.Bottom - Rect.Top;
      cnt := 0;
      RectMiddle := Rect.Top + (Rect.Bottom - Rect.Top) div 2;
      for y := 0 to (Rect.Bottom - Rect.Top) div 2 do begin
        R := r1 + Ceil(dr * cnt);
        G := g1 + Ceil(dg * cnt);
        B := b1 + Ceil(db * cnt);
        Canvas.Pen.Color := RGB(R, G, B);
        Canvas.MoveTo(Rect.Left, RectMiddle + y);
        Canvas.LineTo(Rect.Right, RectMiddle + y);
        Canvas.MoveTo(Rect.Left, RectMiddle - y);
        Canvas.LineTo(Rect.Right, RectMiddle - y);
        inc(cnt);
      end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      lBitmap:TBitmap;
      i:integer;
    begin
    lBitmap:=TBitmap.Create;
    lBitmap.Height:=24;
    lBitmap.Width:=180;
    GradVertical(lBitmap.Canvas,lBitmap.Canvas.ClipRect,clWhite, clBlack);
    for i := 0 to 9 do begin
      lBitmap.Canvas.Brush.Style := bsClear;
      lBitmap.Canvas.TextOut(i*18,5, IntToStr(i));
    end;
     MyCounter.UserBitmap:= lBitmap;
    end;
    Après si tu veux un autre rendu, tu peux changer la font, ou le remplissage du fond.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Est-ce-que Delphi déraille ?
    Merci pour ta réponse, mais la structure du programme me semble bizarre ... voire fausse : il manque un "end;" à la fin de la première procedure. Bref, tu recalcules chaque fois les motifs. C'est compliqué, mais cela devrait marcher.

    Ceci étant corrigé, j'ai créé un programme "standalone" d'essai, j'ai changé les coordonnées du txtout (ajout de 4 à la première, pour centrer un peu plus les chiffres). Ok, tout baigne ...

    J'ai alors intégré la procedure Gradvertical dans mon programme en la déclarant au début ... OK en ajoutant "Math" dans les "uses" pour Ceil

    Mais c'est quand j'ai intégré la partie de ta FormCreate au début de MA routine d'initialisation que plus rien ne marchait : à la compilation, sur la ligne "lBitmap:=TBitMap.Create;" il passe en rouge, me fait clignoter le curseur avant le point virgule et me répond :
    [Erreur] Unit1c.pas(241): Type Object ou Class requis

    Pourtant cette ligne m'a l'air tout à fait correcte ... Faut-il appeler l'exorciste ou GhostBusters ?

    Au passage, j'ai trouvé "quelque chose d'analogue" sur le net, mais le point commun à tous ces affichages est de recalculer chaque fois les tambours. Je cherche quelque chose de SIMPLE que je pourrais installer une fois pour toutes dans la Lib, comme le counter, et qui intégrerait une fois pour toutes les images. Il y aurait bien moyen de prendre un tel composant et de modifier les bitmaps (dans .res ? ) avant de l'installer mais encore une fois, où les prendre ? Cela existe comme fontes ... en général payantes !

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Tu as une deuxième déclaration portant le nom TBitMap. Trouve l'unité et déplace-la avant Graphics dans les uses.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Très compliqué tout cela ...
    En fait merci pour vos efforts, mais comme dit, je préfère KISS : keep It Simple and Stupid.
    Je vais partir d'un compteur simple dont on peut éditer le Bitmap (rcadigi sur torry semble le permettre), et ensuite recompiler le composant en l'intégrant dans le compilateur Delphi. Inutile de recalculer chaque fois !
    J'ai trouvé une police "à tambours", elle s'appelle counter-dial font et traîne sur "n" sites, mais elle est moche et ne permet pas de faire des images de 24 points de haut (illisible). Quelqu'un a-t-il une autre idée ? Autre que de générer à nouveau le bitmap avec le programme précédent ?

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut La solution retenue en définitive ...
    Voilà ... Je suis parti du composant "Counter" dont j'avais déjà parlé. En mode "Traditional", il affiche les chiffres en 18*24. J'ai donc créé un double-dégradé16*22 pour simuler un tambour, que j'ai encadré de noir pour obtenir le 18*24 (tout cela avec un PhotoFiltre d'il y a 6 ans ...). Dans cette image j'ai successivement mis les chiffres de 0 à 9 en jaune, j'avais ainsi les BMP de mes 10 chiffres.

    Je les ai alignés dans un bmp 180*24 que j'ai enregistré après conversion en 256 couleurs. A l'aide de l'éditeur d'images, j'ai dans le fichier cnt.res remplacé le bitmap "Trad" par ma nouvelle ligne via copier-coller.

    Après intégration du composant dans Delphi (entre temps j'avais fait un Ghost) j'ai maintenant obtenu un composant Counter où l'affichage Nixie est remplacé par un affichage à tambours.

    Une recompilation de mon projet a mis le style d'affichage à jour.

    Donc : pas de programmation, que du graphique. KISS !

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Merci
    Je l'avais déjà vu ...

    En fait ce que je cherchais, c'était un simple AFFICHEUR à tambours rotatifs, sans les transitions (qui compliquent trop les choses : ce n'est qu'un simple composant ANNEXE dans un projet plus vaste), avec les chiffres affichés comme sur des cylindres ... et du coup j'ai réussi à le faire en adaptant les bitmaps de Counter.

    Le hic, c'est que, quand on regarde bien et qu'il n'y a pas les transitions de la rotation, "cela ne rend pas". Et les Nixies originaux sont mieux dans le style "vintage".

    Bref, j'aurai essayé ! Merci à tous ...

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut J'ai réussi ... mais c'est une usine à gaz !
    Le code est absolument inutilisable pour créer un composant et ne fonctionne bien qu'en compteur d'événements (+1 chaque fois) ...

    L'idée est d'avoir une fenêtre dans laquelle on fait coulisser des bandes portant en vertical et de haut en bas les chiffres de 0 à 9 puis à nouveau 0 (comme si on avait réalisé le tout avec des bandes de papier). On place sur la fiche un bmp (réalisé avec un logiciel de dessin et intégré dans une TImage) représentant un fond dégradé correspondant aux tambours (image qui reste fixe).

    Les bandes sont des images contenant les chiffres précédents au format gif (donc extension GIFImage nécessaire) avec un fond transparent. Elles sont placées DEVANT le bmp et "coulissent" (bien choisir la couleur des chiffres pour obtenir un contraste par rapport aux tambours). Et devant tout cela se trouve encore une autre image gif, opaque et assez grande pour masquer les bandes précédentes dans toutes les positions (sauf si elles sortent de la fiche), sauf une fenêtre qui laisse voir le bmp (et les chiffres devant).

    Un timer d'intervalle 25 (valeur réaliste ... ) décrémente le Top de la bande du chiffre des unités, un nombre de fois correspondant à la hauteur d'un chiffre. Il détecte si le chiffre des unités était sur 9 avant, auquel cas il place un booléen report à true (effacé à la fin). L'instruction suivante décrémente le Top du chiffre des dizaines en cas de report (donc les chiffres passent de 9 à 0 et de la dizaine à la suivante en même temps, comme les vrais). Enfin si à la fin la bande des unités a affiché le dernier 0 (donc en cas de report), elle est replacée au début. Je n'ai réalisé qu'un compteur de 0 à 40, mais je pense que le principe pourrait se généraliser.

    Malheureusement il y a un bémol : pendant la rotation (simulée) d'un tambour des flashs apparaissent à proximité de l'image correspondante ; je pense qu'il s'agit d'un problème de carte graphique ... Pour cette raison je reste MALGRE TOUT aux Nixies !

    Bon courage à ceux qui veulent se lancer malgré tout ; le code est très court, mais la partie graphique nécessite une adaptation à l'application, donc est à concevoir à partir de 0 !

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 031
    Points : 40 930
    Points
    40 930
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    as-tu songé aux animations (TAnimate) ? c'est vrai que avec D6 (que je n'ai pas) on se limite pas mal mais sur mon vieux D3 que j'utilise encore j'ai installé la RXLib qui fourni un rxGifAnimator ou un animatedimage par exemple . Ce qui me fait penser : as-tu songé aux composants de la JVCL (ceux du pack globus par exemple)
    je crois que la jvcl démarre à partir de D5.
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut STOOOOOP !
    Je constate malheureusement que mon appli deviendrait de plus en plus une usine à gaz ! TAnimate m'obligerait, à première vue, à créer une séquence AVI pour chacune des 10 transitions possibles.

    De toute manière ce compteur n'est qu'un tout petit composant dans un coin d'une fiche qui fait 726 x 528 pixels ... avec en plus 5 voyants de couleur qui s'allument, clignotent, etc, en fonction de l'état du programme et de la communication avec une interface externe. C'est dire s'il a une importance "fondamentale" !

    Non, les Nixies sont aussi bien, ils allient "vintage" et modernité (on voit une ligne de Nixies dans la bande annonce de "A la poursuite de demain"). Une autre version du programme, plus moderne, n'a que 2 voyants qui peuvent prendre 3 et 2 couleurs respectivement, et un affichage ... 7 segments !

    Voilà, je vais dériver : il s'agit d'une interface logicielle entre un programme de commande vocale (Game Commander) et un émetteur pour chars radiocommandés. L'afficheur compte le nombre de coups, le char et le logiciel se bloquent (au niveau tir) au bout de 40 coups ... si on les a démarrés en même temps !

    Comme il s'agit d'un tir infrarouge sur cibles photoélectriques, cela m'a fait penser au premier du genre : le tir à l'ours des années 60 dans les fêtes foraines, avec je crois à l'époque encore de la lumière visible ; et cela m'a incité à délirer un peu en direction d'une certaine nostalgie ...

    Voilà, c'est tout ! Merci encore à vous tous ...

  11. #11
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Mon code n'était qu'une piste pour ton composant.

    L'idée était de modifier le composant original, voici ce que ça donne (le bitmap n'est dessiné qu'une fois):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
     
    unit Counter;
     
     
    interface
     
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
     
     
    type
      TCounterType = (ctSmall, ctTraditional, ctTypographical, ctLed, ctGold, ctTambour, ctUserdefined);
      TNumDigits = 1 .. 20;
      TValStr = integer;
     
     
      TCounter = class(TGraphicControl)
      private
        FAutoSize: boolean;
        FCounterType: TCounterType;
        FCounterBmp: TBitmap;
        FNumDigits: TNumDigits;
        FStretch: boolean;
        FTmpBmp: TBitmap;
        FUserBmp: TBitmap;
        FValue: TValStr;
     
     
        DigitDims: TRect;
     
     
        procedure SetCounterType(value: TCounterType);
        procedure SetCounterBmp;
        procedure SetNumDigits(value: TNumDigits);
        procedure SetStretch(value: boolean);
        procedure SetUserBmp(value: TBitmap);
        procedure SetValue(value: TValStr);
        function CountWidth: integer;
     
     
        function isResourceBitmap: boolean;
        procedure GradVertical(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor);
        function getTextLength: integer;
        procedure DrawTambourBitmap;
     
     
      protected
        procedure SetAutoSize(value: boolean); override;
        procedure PaintPrefix;
        procedure PaintSuffix;
        procedure Loaded; override;
        procedure Paint; override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property AutoSize: boolean read FAutoSize write SetAutoSize default true;
        property CounterType: TCounterType read FCounterType write SetCounterType default ctTraditional;
        property NumDigits: TNumDigits read FNumDigits write SetNumDigits default 8;
        property Stretch: boolean read FStretch write SetStretch default false;
        property UserBitmap: TBitmap read FUserBmp write SetUserBmp;
        property value: TValStr read FValue write SetValue;
        property ShowHint;
      end;
     
     
    procedure Register;
     
     
    implementation
     
     
    {$R cnt.res}
     
     
     
     
    uses Math;
     
     
    procedure TCounter.PaintPrefix;
    var
      NumPrefix: word;
      FX: integer;
      DstRect: TRect;
    begin
      FTmpBmp.Width := NumDigits * DigitDims.Right;
      FTmpBmp.Height := DigitDims.Bottom;
      FTmpBmp.Canvas.Brush.Color := Color;
      FTmpBmp.Canvas.FillRect(Rect(0, 0, Width, Height));
     
     
      NumPrefix := NumDigits - getTextLength;
      for FX := 0 to NumPrefix - 1 do
      begin
        DstRect := Rect(FX * DigitDims.Right, 0, (FX * (DigitDims.Right)) + DigitDims.Right,
          DigitDims.Bottom);
        FTmpBmp.Canvas.CopyRect(DstRect, FCounterBmp.Canvas, DigitDims);
      end;
    end;
     
     
    procedure TCounter.PaintSuffix;
    var
      NumSuffix: word;
      NumPrefix: word;
      FX: integer;
      DstRect, SrcRect: TRect;
    begin
      NumSuffix := getTextLength;
      NumPrefix := NumDigits - NumSuffix;
      for FX := 1 to NumSuffix do
      begin
        case Trunc(value / power(10, FX - 1)) mod 10 of
          0:
            SrcRect := Rect(0, 0, DigitDims.Right, DigitDims.Bottom);
          1:
            SrcRect := Rect(1 * DigitDims.Right, 0, (1 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          2:
            SrcRect := Rect(2 * DigitDims.Right, 0, (2 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          3:
            SrcRect := Rect(3 * DigitDims.Right, 0, (3 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          4:
            SrcRect := Rect(4 * DigitDims.Right, 0, (4 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          5:
            SrcRect := Rect(5 * DigitDims.Right, 0, (5 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          6:
            SrcRect := Rect(6 * DigitDims.Right, 0, (6 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          7:
            SrcRect := Rect(7 * DigitDims.Right, 0, (7 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          8:
            SrcRect := Rect(8 * DigitDims.Right, 0, (8 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
          9:
            SrcRect := Rect(9 * DigitDims.Right, 0, (9 * DigitDims.Right) + DigitDims.Right,
              DigitDims.Bottom);
        end;
     
     
        DstRect := Rect(((NumPrefix + NumSuffix - FX) - 1) * DigitDims.Right, 0,
          (NumPrefix + NumSuffix - FX) * (DigitDims.Right), DigitDims.Bottom);
        FTmpBmp.Canvas.CopyRect(DstRect, FCounterBmp.Canvas, SrcRect);
      end;
    end;
     
     
    procedure TCounter.Paint;
    begin
      inherited Paint;
      PaintPrefix;
      PaintSuffix;
      if Stretch then
        Canvas.StretchDraw(ClientRect, FTmpBmp)
      else
        Canvas.Draw(0, 0, FTmpBmp);
    end;
     
     
    procedure TCounter.Loaded;
    begin
      inherited Loaded;
      SetCounterBmp;
    end;
     
     
    function TCounter.CountWidth: integer;
    begin
      Result := (FCounterBmp.Width div 10) * FNumDigits;
    end;
     
     
    procedure TCounter.SetAutoSize(value: boolean);
    begin
      if value <> FAutoSize then
      begin
        FAutoSize := value;
        if value and (getTextLength > NumDigits) then
          NumDigits := getTextLength;
      end;
    end;
     
     
    procedure TCounter.SetCounterType(value: TCounterType);
    begin
      if value <> FCounterType then
      begin
        if (value = ctUserdefined) and (FUserBmp.Empty = true) then
          Exit;
        FCounterType := value;
        SetCounterBmp;
        Refresh;
      end;
    end;
     
     
    procedure TCounter.SetCounterBmp;
    var
      bmpRes: string;
    begin
      case FCounterType of
        ctSmall:
          bmpRes := 'SMALL';
        ctTraditional:
          bmpRes := 'TRAD';
        ctTypographical:
          bmpRes := 'TYPO';
        ctLed:
          bmpRes := 'LED';
        ctGold:
          bmpRes := 'GOLD';
        ctTambour: begin
            DrawTambourBitmap;
          end;
      end;
     
     
      if isResourceBitmap then
        FCounterBmp.Handle := LoadBitmap(hInstance, PChar(bmpRes))
      else
        FCounterBmp.Assign(FUserBmp);
     
     
      if not FStretch and (csDesigning in ComponentState) then
      begin
        Width := CountWidth;
        Height := FCounterBmp.Height;
      end;
      DigitDims := Rect(0, 0, FCounterBmp.Width div 10, FCounterBmp.Height);
    end;
     
     
    procedure TCounter.SetNumDigits(value: TNumDigits);
    begin
      if value <> FNumDigits then
      begin
        if (value < getTextLength) and FAutoSize then
          FNumDigits := getTextLength
        else
          FNumDigits := value;
        if not Stretch then
          Width := CountWidth;
      end;
    end;
     
     
    procedure TCounter.SetStretch(value: boolean);
    begin
      if value <> FStretch then
      begin
        FStretch := value;
        if not value then
        begin
          Width := NumDigits * DigitDims.Right;
          Height := DigitDims.Bottom;
        end;
        Repaint;
      end;
    end;
     
     
    procedure TCounter.SetUserBmp(value: TBitmap);
    begin
      FUserBmp.Assign(value);
      if Assigned(FUserBmp) then
        CounterType := ctUserdefined;
    end;
     
     
    procedure TCounter.SetValue(value: TValStr);
    begin
      if value <> FValue then
      begin
        FValue := value;
        if AutoSize and (getTextLength > NumDigits) then
          NumDigits := getTextLength;
        Refresh;
      end;
    end;
     
     
    constructor TCounter.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ControlStyle := ControlStyle + [csOpaque];
      FCounterBmp := TBitmap.Create;
      CounterType := ctTraditional;
      FNumDigits := 8;
      FTmpBmp := TBitmap.Create;
      FUserBmp := TBitmap.Create;
      FAutoSize := true;
      FStretch := false;
      FValue := 0;
      SetCounterBmp;
    end;
     
     
    destructor TCounter.Destroy;
    begin
      FCounterBmp.Free;
      FTmpBmp.Free;
      FUserBmp.Free;
      inherited Destroy;
    end;
     
     
    procedure TCounter.DrawTambourBitmap;
    var
      i: integer;
    begin
      FUserBmp.Height := 24;
      FUserBmp.Width := 180;
      GradVertical(FUserBmp.Canvas, FUserBmp.Canvas.ClipRect, clWhite, clBlack);
      for i := 0 to 9 do begin
        FUserBmp.Canvas.Brush.Style := bsClear;
        FUserBmp.Canvas.TextOut(i * 18, 5, IntToStr(i));
      end;
    end;
     
     
    function TCounter.getTextLength: integer;
    var
      RUAdder: integer;
      x: Extended;
    begin
      if value < 2 then
        Result := 1
      else begin
        x := (Ln(value) / Ln(10));
        if Frac(x) > 0 then
          RUAdder := 1
        else
          RUAdder := 0;
        Result := Trunc(x) + RUAdder;
      end;
    end;
     
     
    procedure TCounter.GradVertical(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor);
    var
      y: integer;
      dr, dg, db: Extended;
      C1, C2: TColor;
      r1, r2, g1, g2, b1, b2: Byte;
      R, G, B: Byte;
      cnt: integer;
      RectMiddle: integer;
    begin
      C1 := FromColor;
      r1 := GetRValue(C1);
      g1 := GetGValue(C1);
      b1 := GetBValue(C1);
      C2 := ToColor;
      r2 := GetRValue(C2);
      g2 := GetGValue(C2);
      b2 := GetBValue(C2);
      dr := (r2 - r1) / Rect.Bottom - Rect.Top;
      dg := (g2 - g1) / Rect.Bottom - Rect.Top;
      db := (b2 - b1) / Rect.Bottom - Rect.Top;
      cnt := 0;
      RectMiddle := Rect.Top + (Rect.Bottom - Rect.Top) div 2;
      for y := 0 to (Rect.Bottom - Rect.Top) div 2 do begin
        R := r1 + Ceil(dr * cnt);
        G := g1 + Ceil(dg * cnt);
        B := b1 + Ceil(db * cnt);
        Canvas.Pen.Color := RGB(R, G, B);
        Canvas.MoveTo(Rect.Left, RectMiddle + y);
        Canvas.LineTo(Rect.Right, RectMiddle + y);
        Canvas.MoveTo(Rect.Left, RectMiddle - y);
        Canvas.LineTo(Rect.Right, RectMiddle - y);
        inc(cnt);
      end;
    end;
     
     
    function TCounter.isResourceBitmap: boolean;
    begin
      Result := not(FCounterType in [ctTambour, ctUserdefined]);
    end;
     
     
    procedure Register;
    begin
      RegisterComponents('Samples', [TCounter]);
    end;
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  12. #12
    Nouveau Candidat au Club
    Homme Profil pro
    Retraité, ancien développeur
    Inscrit en
    Mai 2015
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Retraité, ancien développeur

    Informations forums :
    Inscription : Mai 2015
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Et cela marche quand même : perseverare diabolicum est !
    Le mot de la fin : ce qui me gênait dans mon système avec les "rubans coulissants", c'étaient les parasites de l'image pendant le défilement.

    La solution : mettre dans la routine d'initialisation :
    DoubleBuffered:=True;

    Problème résolu ... POUR DE BON !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SQL] magic quotes ou double apostrophes pour échapper apostrophe
    Par zorian dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 13/03/2006, 16h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo