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

 Delphi Discussion :

Problème avec Canvas.TextWidth


Sujet :

Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 46
    Points : 44
    Points
    44
    Par défaut Problème avec Canvas.TextWidth
    Bonjour,

    j'aimerais "décomposer" un mot en plusieurs lettres, et pour chacun d'entre-elles, créer un TLabel.
    Rien de bien sorcier, me direz-vous...
    Mais là où ça se gâte, c'est lorsqu'il faut les "placer".
    Tantôt, il y a trop de d'écart entre les lettres, tantôt elles se télescopent !

    Voici un p'tit bout de code :
    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
     
    procedure TForm1.DecomposerMot(Mot:String);
    var
    i,nbpixels,decalage:integer;
    MonLabel:TLabel;
    begin
    decalage:=0;
    for i := 0 to length(Mot) do
      begin
      MonLabel:=TLabel.create(self);
      MonLabel.parent:=Self;
      MonLabel.Top:=10;
      MonLabel.Font.Size:=12;
      nbpixels:=MonLabel.Canvas.TextWidth(Mot[i]);
      decalage:=decalage+nbpixels;
      MonLabel.Left:=decalage;
      MonLabel.Caption:=Mot[i];
      end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
    DecomposerMot('developpez.net');//placez la chaîne que vous voulez
    end;
    Le problème c'est que le Canvas.TextWidth des labels ne semble pas du tout donner la bonne information.
    J'ai d'ailleurs essayé directement avec un tout bête "Label.width" mais alors, c'est encore pire...

    Comment pourrais-je pallier ce problème ?

    Par avance, merci.
    Nuclear.

  2. #2
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 718
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 718
    Points : 15 097
    Points
    15 097
    Par défaut
    Salut,

    Ton problème vient surement du fait que tu utilises une police proportionnelle ; utilise donc une police fixe (tous les caractères y ont la même largeur), ça sera beaucoup plus facile.

    Et si tu trouves ça moche, tu peux l'utiliser en intermédiaire, juste pour faire les calculs de décomposition.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Petite erreur sur le début de boucle à Zéro, il faut partir à 1
    Et tu fais fait ton décalage trop tôt, il d'abord placer, puis gérer le décalage pour la prochaine lettre,
    c'est pour cela que les petites lettres comme l et t était mal placé car prenait en compte leur propre taille au lieu de la taille de la lettre précédente,
    tu aurais eu l'effet inverse avec un m ou w

    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
     
      procedure DecomposerMot(AParent: TWinControl; X, Y: Integer; const AMot: String);
      var
        I, NbPixels, Decalage: Integer;
        MonLabel: TLabel;
      begin
        Decalage := 0;
        for I := 1 to Length(AMot) do
        begin
          MonLabel:= TLabel.Create(AParent);
          MonLabel.Parent := AParent;
          MonLabel.Top := Y;
          MonLabel.Font.Size := 12;
          MonLabel.Left := X + decalage;
          MonLabel.Caption := AMot[I];
     
          NbPixels := MonLabel.Canvas.TextWidth(AMot[I]);
          Inc(decalage, NbPixels);
        end;
      end;
     
    procedure TForm1.btn1Click(Sender: TObject);
    begin
      DecomposerMot(Self, btn1.Left, btn1.Top + btn1.Height + 4, 'developpez.net');//placez la chaîne que vous voulez
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Bonjour,

    Vu le code c'est normal que le TextWidth du Canvas ne soit pas correct. Il faut d'abord préciser au canvas quelle police, quel style..etc utiliser. Sinon il utilise les valeurs par défaut du canvas.
    Voici un exemple de bout de code que j'utilise pour cela :

    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
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Label1.Text := 'TEXT TO TEST';
      Label1.Width := CalcTextWidth(Label1.Text,Label1.Font.Family,Label1.Font.Size,Label1.Font.Style);
      Label1.Height := CalcTextHeight(Label1.Text,Label1.Font.Family,Label1.Font.Size,Label1.Font.Style);
    end;
     
    Function TForm1.CalcTextHeight(TextToTest:String; FontFamily:String; FontSize:Single; FontStyle:TFontStyles):Single;
    begin
      Canvas.Font.Family := FontFamily;
      Canvas.Font.Size := FontSize;
      Canvas.font.Style := FontStyle;
      Result := Canvas.TextHeight(TextToTest);
    end;
     
    Function TForm1.CalcTextWidth(TextToTest:String; FontFamily:String; FontSize:Single; FontStyle:TFontStyles):Single;
    begin
      Canvas.Font.Family := FontFamily;
      Canvas.Font.Size := FontSize;
      Canvas.font.Style := FontStyle;
      Result := Canvas.TextWidth(TextToTest);
    end;

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Le TextWidth n'était pas totalement en cause,
    Seul la première lettre pouvait être mal calculée à cause d'une mauvaise fonte.
    C'était surtout juste une erreur de l'algo sur l'incrémentation de decalage.

    TextWidth fonctionne correctement à la seconde lettre grace à l'AutoSize qui change la Font du Canvas interne du TGraphicControl car dès que l'on fait un Caption := ... cela provoque l'appel à Perform, CMTextChanged, AdjustBounds qui fait appel à DoDrawText pour calculer la taille du TLabel (par défaut AutoSize)
    Hors DoDrawText fait de lui même l'affectation du Self.Font au Canvas.Font !

    Voici deux variantes

    DecomposerMotByAutoSize utilise AutoSize et donc directement Width
    DecomposerMot calcule manuellement la taille (variante recommandée car respecte les recommandations de Thierry Laborde)

    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
     
      procedure DecomposerMotByAutoSize(AParent: TWinControl; X, Y: Integer; const AMot: String);
      var
        I, NbPixels, Decalage: Integer;
        MonLabel: TLabel;
      begin
        Decalage := 0;
        for I := 1 to Length(AMot) do
        begin
          MonLabel:= TLabel.Create(AParent);
          MonLabel.AutoSize := True;
          MonLabel.Parent := AParent;
          MonLabel.Top := Y;
          MonLabel.Font.Name := Screen.Fonts[Trunc(Random(Screen.Fonts.Count))];
          MonLabel.Font.Size := 12;
          MonLabel.Left := X + decalage;
          MonLabel.Caption := AMot[I];
     
          Assert(SameText(MonLabel.Font.Name, MonLabel.Canvas.Font.Name), 'Oups ! AutoSize n''a pas fonctionné !');
     
          NbPixels := MonLabel.Width;
          Inc(decalage, NbPixels);
        end;
      end;
     
      procedure DecomposerMot(AParent: TWinControl; X, Y: Integer; const AMot: String);
      var
        I, NbPixels, Decalage: Integer;
        MonLabel: TLabel;
      begin
        Decalage := 0;
        for I := 1 to Length(AMot) do
        begin
          MonLabel:= TLabel.Create(AParent);
          MonLabel.AutoSize := False;
          MonLabel.Parent := AParent;
          MonLabel.Top := Y;
          MonLabel.Font.Name := Screen.Fonts[Trunc(Random(Screen.Fonts.Count))];
          MonLabel.Font.Size := 12;
          MonLabel.Left := X + decalage;
          MonLabel.Caption := AMot[I];
     
          MonLabel.Canvas.Font := MonLabel.Font; // Assigne la fonte !
          NbPixels := MonLabel.Canvas.TextWidth(AMot[I]);
          MonLabel.Width := NbPixels;
          Inc(decalage, NbPixels);
        end;
      end;
     
    procedure TForm1.btn1Click(Sender: TObject);
    begin
      DecomposerMotByAutoSize(Self, btn1.Left, btn1.Top + btn1.Height + 4, 'developpez.net');//placez la chaîne que vous voulez
      DecomposerMot(Self, btn1.Left, btn1.Top + btn1.Height + 34, 'developpez.net');//placez la chaîne que vous voulez
    end;

    Personnellement, pour éviter de passer par le Canvas (surtout sur un control qui n'en a pas), je me suis fait un class helper de TFont

    utilisation simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
         NbPixels := MonLabel.Font.TextWidth(AMot[I]);
    le Helper XE2

    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
      TFontSliteHelper = class helper for TFont
      public
        function GetTextHeight(const AText: string): Integer;
        function GetTextWidth(const AText: string): Integer;
      public
        class function GetConstratedColor(AColor: TColor): TColor;
      end;
     
    //------------------------------------------------------------------------------
    class function TFontSliteHelper.GetConstratedColor(AColor: TColor): TColor;
    begin
      Result := TCanvasSLTAssistant.GetConstratedColor(AColor);
    end;
     
    //------------------------------------------------------------------------------
    function TFontSliteHelper.GetTextHeight(const AText: string): Integer;
    begin
      Result := TFontSLTToolHelp.GetTextHeight(AText, Self)
    end;
     
    //------------------------------------------------------------------------------
    function TFontSliteHelper.GetTextWidth(const AText: string): Integer;
    begin
      Result := TFontSLTToolHelp.GetTextWidth(AText, Self);
    end;
    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
    //------------------------------------------------------------------------------
    (*                SoLuTions is an Versatile Library for Delphi                 -
     *                                                                             -
     *  Version alternative publiée sur "www.developpez.net"                       -
     *  Post : "Griser une couleur"                                                -
     *  Post Number : 2653867                                                      -
     *  Post URL = "http://www.developpez.net/forums/d439061/environnements-developpement/delphi/langage/griser-couleur/#post2653867"
     *                                                                             -
     *  Copyright ou © ou Copr. "SLT Solutions", (2006)                            -
     *  contributeur : ShaiLeTroll (2010) - Migration en C++Builder 2007           -
     *  contributeur : ShaiLeTroll (2012) - Renommage Fichier et Correction C++Builder XE2
     *  contributeur : ShaiLeTroll (2012) - Documentation Insight                  -
     *  contributeur : ShaiLeTroll (2014) - Reprise du TCanvasAssistant en C++Builder XE2 dans le TCanvasSLTAssistant en Delphi XE2
     *                                                                             -
     * ShaiLeTroll                                                                 -
     *                                                                             -
     * Ce logiciel est un programme informatique servant à aider les développeurs  -
     * Delphi avec une bibliothèque polyvalente, adaptable et fragmentable.        -
     *                                                                             -
     * Ce logiciel est régi par la licence CeCILL-C soumise au droit français et   -
     * respectant les principes de diffusion des logiciels libres. Vous pouvez     -
     * utiliser, modifier et/ou redistribuer ce programme sous les conditions      -
     * de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA    -
     * sur le site "http://www.cecill.info".                                       -
     *                                                                             -
     * En contrepartie de l'accessibilité au code source et des droits de copie,   -
     * de modification et de redistribution accordés par cette licence, il n'est   -
     * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,   -
     * seule une responsabilité restreinte pèse sur l'auteur du programme,  le     -
     * titulaire des droits patrimoniaux et les concédants successifs.             -
     *                                                                             -
     * A cet égard  l'attention de l'utilisateur est attirée sur les risques       -
     * associés au chargement,  à l'utilisation,  à la modification et/ou au       -
     * développement et à la reproduction du logiciel par l'utilisateur étant      -
     * donné sa spécificité de logiciel libre, qui peut le rendre complexe à       -
     * manipuler et qui le réserve donc à des développeurs et des professionnels   -
     * avertis possédant  des  connaissances  informatiques approfondies.  Les     -
     * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du      -
     * logiciel à leurs besoins dans des conditions permettant d'assurer la        -
     * sécurité de leurs systèmes et ou de leurs données et, plus généralement,    -
     * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.          -
     *                                                                             -
     * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez      -
     * pris connaissance de la licence CeCILL-C, et que vous en avez accepté les   -
     * termes.                                                                     -
     *                                                                             -
     *----------------------------------------------------------------------------*)
    unit SLT.Controls.VCL.GraphicsEx;
     
    interface
     
    uses System.SysUtils, System.Classes,
      Vcl.Themes, Vcl.Graphics, Winapi.Windows;
     
    type
      /// <summary>Boite à outil pour la classe TFont </summary>
      /// <remarks>Le TFontSLTToolHelp n'est pas un class helper car lors de sa création la version utilisée était C++Builder 2007,
      /// Traduction C++Builder vers Delphi en concervant ce concept des Assistances de classes (Class Helper) du Delphi.NET</remarks>
      TFontSLTToolHelp = class(TObject)
      public
        // Méthodes Publiques
        class function GetTextWidth(const AText: string; AFont: TFont): Integer; static;
        class function GetTextHeight(const AText: string; AFont: TFont): Integer; static;
        class function GetTextSize(const AText: string; AFont: TFont): TSize; static;
      end;
     
      /// <summary>Erreur liée à l'assistant TCanvasSLTAssistant de la classe TCanvas</summary>
      ECanvasSLTAssistantError = class(Exception);
     
      /// <summary>Assistance de la classe TCanvas </summary>
      /// <remarks>Le TCanvasSLTToolHelp n'est pas un class helper car lors de sa création en 2002 sous Delphi 5, le code était procédural,
      /// lors de la refonte en classe en 2007 et 2014, la version utilisée était Delphi 7 puis Delphi XE2, en s'inspirant du concept des Assistances de classes (Class Helper) du Delphi.NET</remarks>
      TCanvasSLTAssistant = class(TObject)
      private
        // Membres privés
        FCanvas: TCanvas;
     
      public
        // Constructeurs
        constructor Create(ACanvas: TCanvas); overload;
        constructor Create(Sender: TObject); overload;
     
        // Méthodes de dessin personnalisé
     
        /// <summary>Dessine une case à cocher centré dans la zone définie par ARect</summary>
        /// <param name="ARect">Zone à dessiner</param>
        /// <param name="AChecked">Etat de la case à cocher</param>
        /// <param name="AEnabled">la case à cocher est-elle active</param>
        procedure DrawCheckBox(const ARect: TRect; AChecked: Boolean; AEnabled: Boolean = True);
     
        /// <summary>Dessine une ligne via les méthodes MoveTo et LineTo</summary>
        procedure DrawLine(X1, Y1, X2, Y2: Integer; LineWidth: Integer);
     
        /// <summary>Dessine un triangle équilatéral selon un certain angle via la méthode Polygon</summary>
        procedure DrawTriangle(X, Y: Integer; Angle: Extended; Radius: Integer);
     
        /// <summary>Dessine une fleche via DrawLine et DrawTriangle avec éventuellement un texte dans la fleche</summary>
        procedure DrawArrow(X1, Y1, X2, Y2: Integer; LineWidth: Integer; TriangleRadius: Integer; const LineText: string = '');
     
        /// <summary>Tente de fournir une couleur avec un fort constrate, généralement une couleur quasi inverse</summary>
        /// <param name="AColor">Couleur de référence</param>
        /// <returns>Couleur a fort contraste</returns>
        class function GetConstratedColor(AColor: TColor): TColor; static;
     
        /// <summary>Tente de fournir une couleur qui donne l'impression que cette zone est grisée</summary>
        /// <param name="AColor">Couleur de référence</param>
        /// <returns>Couleur intermédiare avec le couleur grisée du thème</returns>
        class function GetGrayedColor(AColor: TColor): TColor; static;
     
        // Propriétés
        property Canvas: TCanvas read FCanvas;
      end;
     
      /// <summary>Type simplifiant la séparation des canaux RGB dans un TColor remplaçant le peut pratique Winapi.Windows.TRGBQuad /summary>
      /// <remarks>On parle de RGB en forme hexa 00BBGGRR comme dans le COLORREF ce qui donne en little endian RR, GG, BB, 00.
      /// <para>La déclaration du TRGBQuad est BB, GG, RR, 00 ce qui ne correspond à aucune architecture mémoire pour le TColor, ni LE ni BE</para></remarks>
      TSLTColorRGB = record
        case Integer of
          0:
            (
              Red, Green, Blue, Alpha: Byte;
            );
          1:
            (
              Color: TColor;
            );
      end;
     
    implementation
     
    uses Vcl.GraphUtil, System.Math,
      SLT.Common.TypesEx;
     
    const
      ERR_UNASSISTED_CLASS = 'La Classe d''Assistance %s ne prend pas en charge la classe %s mais la classe %s';
     
    { TFontSLTToolHelp }
     
    //------------------------------------------------------------------------------
    class function TFontSLTToolHelp.GetTextHeight(const AText: string; AFont: TFont): Integer;
    begin
      Result := GetTextSize(AText, AFont).cy;
    end;
     
    //------------------------------------------------------------------------------
    class function TFontSLTToolHelp.GetTextSize(const AText: string; AFont: TFont): TSize;
    var
      Len: Integer;
      DC: HDC;
      SaveFont: HFONT;
    begin
      ZeroMemory(@Result, SizeOf(Result));
      Len := Length(AText);
      if Len > 0 then
      begin
        DC := GetDC(0);
        try
          SaveFont := HFONT(SelectObject(DC, AFont.Handle));
          try
            GetTextExtentPoint32W(DC, PChar(AText), Len, Result);
          finally
            SelectObject(DC, SaveFont);
          end;
        finally
          ReleaseDC(0, DC);
        end;
      end;
    end;
     
    //------------------------------------------------------------------------------
    class function TFontSLTToolHelp.GetTextWidth(const AText: string; AFont: TFont): Integer;
    begin
      Result := GetTextSize(AText, AFont).cx;
    end;
     
    { TCanvasSLTAssistant }
     
    //------------------------------------------------------------------------------
    constructor TCanvasSLTAssistant.Create(ACanvas: TCanvas);
    begin
      inherited Create();
     
      FCanvas := ACanvas;
    end;
     
    //------------------------------------------------------------------------------
    constructor TCanvasSLTAssistant.Create(Sender: TObject);
    begin
      inherited Create();
     
      if Assigned(Sender) then
      begin
        if Sender is TCanvas then
          FCanvas := TCanvas(Sender)
        else
          raise ECanvasSLTAssistantError.CreateFmt(ERR_UNASSISTED_CLASS, [ClassName(), Sender.ClassName(), TCanvas.ClassName()]);
      end
      else
        raise ECanvasSLTAssistantError.CreateFmt(ERR_UNASSISTED_CLASS, [ClassName(), '[nil]', TCanvas.ClassName()])
    end;
     
    //------------------------------------------------------------------------------
    procedure TCanvasSLTAssistant.DrawArrow(X1, Y1, X2, Y2: Integer; LineWidth: Integer; TriangleRadius: Integer; const LineText: string = '');
    var
      Slope: Extended;
      OldBrush: TBrush;
    begin
      DrawLine(X1, Y1, X2, Y2, LineWidth);
      // Calcul de l'angle de rotation en considérant le point de fin comme point de rotation
      Slope := LineAngle(X2, Y2, X1, Y1);
      DrawTriangle(X2, Y2, Slope, TriangleRadius);
      if LineText <> '' then
      begin
        OldBrush := TBrush.Create();
        try
          OldBrush.Assign(Canvas.Brush);
          try
            Canvas.Brush.Style := bsClear;
            Canvas.Font.Orientation := -Trunc(RadToDeg(Slope) * 10);
            if Abs(Canvas.Font.Orientation) > 900 then
            begin
              Canvas.Font.Orientation := Canvas.Font.Orientation - 1800;
              Y1 := Y1 - Canvas.TextHeight(LineText);
            end
            else
              X1 := X1 - Canvas.TextWidth(LineText);
     
            Canvas.TextOut((X1 + X2) div 2, (Y1 + Y2) div 2, LineText);
          finally
            Canvas.Brush.Assign(OldBrush);
          end;
        finally
          OldBrush.Free();
        end;
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TCanvasSLTAssistant.DrawCheckBox(const ARect: TRect; AChecked: Boolean; AEnabled: Boolean = True);
    var
      uState: UINT;
      tbState: TThemedButton;
      Details: TThemedElementDetails;
      Buffer: Vcl.Graphics.TBitmap;
      BufferRect: TRect;
    begin
      if StyleServices.Enabled then
      begin
        // Pour ne pas pertuber le Canvas en cours, utilisation d'un Tampon intermédiaire
        Buffer := Vcl.Graphics.TBitmap.Create();
        try
          BufferRect := Rect(0, 0, ARect.Width, ARect.Height);
          Buffer.SetSize(BufferRect.Width, BufferRect.Height);
     
          tbState := tbCheckBoxUncheckedNormal;
          if AChecked then
            tbState := tbCheckBoxCheckedNormal;
     
          if not AEnabled then
          begin
            if AChecked then
              tbState := tbCheckBoxCheckedDisabled
            else
              tbState := tbCheckBoxUncheckedDisabled;
          end;
     
          Details := StyleServices.GetElementDetails(tbState);
          StyleServices.DrawElement(Buffer.Canvas.Handle, Details, BufferRect, BufferRect);
          // Dessin final
          Canvas.Draw(ARect.Left, ARect.Top, Buffer);
        finally
          Buffer.Free();
        end;
      end
      else
      begin
        uState := DFCS_BUTTONCHECK;
        if AChecked then
          uState := uState or DFCS_CHECKED;
     
        if not AEnabled then
          uState := uState or DFCS_INACTIVE;
     
        Canvas.FillRect(ARect);
        DrawFrameControl(Canvas.Handle, ARect, DFC_BUTTON, uState);
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TCanvasSLTAssistant.DrawLine(X1, Y1, X2, Y2: Integer; LineWidth: Integer);
    begin
      Canvas.Pen.Width := LineWidth;
      Canvas.MoveTo(X1, Y1);
      Canvas.LineTo(X2, Y2);
    end;
     
    //------------------------------------------------------------------------------
    procedure TCanvasSLTAssistant.DrawTriangle(X, Y: Integer; Angle: Extended; Radius: Integer);
    var
      P1, P2, P3: TPoint;
      Triangle: array[0..2] of TPoint;
    begin
      P1 := Point(X - Radius, Y - Radius);
      P2 := Point(X, Y);
      P3 := Point(X + Radius, Y - Radius);
     
      // Rotation du Triangle
      RotateTriangle(P1, P2, P3, Point(X, Y), Angle + DegToRad(90));
      Triangle[0] := P1;
      Triangle[1] := P2;
      Triangle[2] := P3;
     
      Canvas.Polygon(Triangle);
    end;
     
    //------------------------------------------------------------------------------
    class function TCanvasSLTAssistant.GetConstratedColor(AColor: TColor): TColor;
    var
      H, S, L: Word;
    begin
      ColorRGBToHLS(ColorToRGB(AColor), H, L, S);
      if L > 120 then
      begin
        if L < 168 then
        begin
          if H <= 140 then
          begin
            if (H in [0..20]) or (H in [220..240]) then
              Result := clWhite // Clair sur rouge
            else
              Result := clBlack // Foncé jaune et vert moyen
          end
          else
            Result := clWhite // Clair sur bleu ou violet moyen
        end
        else
          Result := clBlack // Foncé sur Clair
      end
      else
      begin
        if L > 90 then
        begin
          if (H in [0..20]) or (H in [48..240]) then
          begin
            if (S > 200) and (H in [48..128]) then
              Result := clBlack // Vert Citron
            else
              Result := clWhite // Clair sur Marron, Vert, Bleu et Pourpre
          end
          else
            Result := clBlack // Foncé sur le Jaune et Fuschia
        end
        else
          Result := clWhite; // Clair sur Foncé
      end;
    end;
     
    //------------------------------------------------------------------------------
    class function TCanvasSLTAssistant.GetGrayedColor(AColor: TColor): TColor;
    var
      StyleColor: TColor;
    begin
      StyleColor := ColorToRGB(StyleServices.GetStyleColor(scWindow)); // semble la même couleur que scGenericBackground
      // on mélange la couleur de fond et la couleur d'origine
      // cela marque que cette zone colorée est inactive, principe du clBtnFace
      TSLTColorRGB(Result).Red := (TSLTColorRGB(AColor).Red + TSLTColorRGB(StyleColor).Red) div 2;
      TSLTColorRGB(Result).Green := (TSLTColorRGB(AColor).Green + TSLTColorRGB(StyleColor).Green) div 2;
      TSLTColorRGB(Result).Blue := (TSLTColorRGB(AColor).Blue + TSLTColorRGB(StyleColor).Blue) div 2;
      TSLTColorRGB(Result).Alpha := (TSLTColorRGB(AColor).Alpha + TSLTColorRGB(StyleColor).Alpha) div 2;
    end;
     
    end.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 46
    Points : 44
    Points
    44
    Par défaut [Problème d'espacement des TLabels résolu]
    Citation Envoyé par ShaiLeTroll Voir le message
    Petite erreur sur le début de boucle à Zéro, il faut partir à 1
    Et tu fais fait ton décalage trop tôt, il d'abord placer, puis gérer le décalage pour la prochaine lettre,
    c'est pour cela que les petites lettres comme l et t était mal placé car prenait en compte leur propre taille au lieu de la taille de la lettre précédente,
    tu aurais eu l'effet inverse avec un m ou w

    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
     
      procedure DecomposerMot(AParent: TWinControl; X, Y: Integer; const AMot: String);
      var
        I, NbPixels, Decalage: Integer;
        MonLabel: TLabel;
      begin
        Decalage := 0;
        for I := 1 to Length(AMot) do
        begin
          MonLabel:= TLabel.Create(AParent);
          MonLabel.Parent := AParent;
          MonLabel.Top := Y;
          MonLabel.Font.Size := 12;
          MonLabel.Left := X + decalage;
          MonLabel.Caption := AMot[I];
     
          NbPixels := MonLabel.Canvas.TextWidth(AMot[I]);
          Inc(decalage, NbPixels);
        end;
      end;
     
    procedure TForm1.btn1Click(Sender: TObject);
    begin
      DecomposerMot(Self, btn1.Left, btn1.Top + btn1.Height + 4, 'developpez.net');//placez la chaîne que vous voulez
    end;
    Merci à tous pour vos réponses.
    J'ai finalement bien tenu compte des corrections de ShaiLeTroll !
    Il ne me manquait presque rien finalement....
    Je lui ai d'ailleurs piqué son :
    Que j'ai mis un p'tit temps à comprendre, plutôt que mon laborieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    decalage:=decalage+nbpixels;
    Dorénavant, ça fonctionne très bien !
    Je passe mon sujet à "résolu" du coup !

  7. #7
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Un TLabel par lettre ? Ça fait un peut usine à gaz non ?

    Quel est le but final ? Juste de l'affichage ? Dessiner directement chacune des lettre sur le Canvas de la fiche ou d'un TPaint ne serait-il pas plus à propos ?
    Bidouilleuse Delphi

  8. #8
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Et pour l'histoire de Textwidth je vous invite à explorer la FAQ :
    http://delphi.developpez.com/faq/?pa...els-d-un-texte
    Bidouilleuse Delphi

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

Discussions similaires

  1. Problème avec Canvas
    Par sfpx dans le forum Composants graphiques
    Réponses: 3
    Dernier message: 12/10/2011, 14h51
  2. Problème avec Canvas TextOut
    Par dadouuuu dans le forum Débuter
    Réponses: 4
    Dernier message: 22/12/2010, 10h08
  3. problème avec canvas
    Par nouvelesprit dans le forum Composants graphiques
    Réponses: 4
    Dernier message: 23/04/2010, 19h45
  4. Problème avec Canvas.ActualHeight
    Par Manhuman dans le forum Silverlight
    Réponses: 2
    Dernier message: 29/05/2009, 09h07
  5. Problème avec Canvas et drawImage
    Par marmarnas dans le forum AWT/Swing
    Réponses: 5
    Dernier message: 01/04/2008, 11h26

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