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

C++Builder Discussion :

[SRC] Cherche piste pour TLabel orientable


Sujet :

C++Builder

  1. #1
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut [SRC] Cherche piste pour TLabel orientable
    Bonjour,

    je dois écrire un composant, héritant de TLabel, orientable à 360°. Le seul exemple trouvé sur le net est justement disponible sur la partie Delphi de ce site, language que je ne maîtrise absolument pas


    Ma question est simple : j'ai besoin d'une piste où commencer à chercher. Existe-t'il des fonctionnalités du canvas qui seraient utilisables ? dans l'objet TFont ?

    Merci pour toute réponse.


    En lien le composants en version Delphi (bravo à l'auteur) : http://nono40.developpez.com/sources/source0011/

    Edition par la rédaction : retrouvez cette réalisation sur la page sources http://c.developpez.com/sources/bcb/?page=composants#labelorientable

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    Bonjour,

    Il faut dériver le composant Parent de TLabel (je te laisse chercher ).
    Ensuite tu dois écrire la fonction Paint de ce composant.

    A noter que seul les polices True Type peuevnt être directement inclinée, sinon il faut faire tourner l'image résultante.

    Regarde la stuctute de la font native Windows (LOGFONT), paramétre escapement (lfEscapement) et rotation (lfRotation).

    J'ai un exemple.

  3. #3
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    L'héritage du TLabel n'est pas un problème en soit, je ne suis (heureusement) pas à mon 1er composant

    Par contre merci beaucoups pour les indications au niveau de la Font. Je chercherais de ce coté.

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    De rien.

    A noter que tu dois créer une Font compatible Windows et affecter le Handle à un objet TFont.
    C'est un peut space mais ça fonctionne.

  5. #5
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Il me semble qu'il y a ça dans le projet "Jedi"

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    Le projet Jedi est écrit en Pascal, Langage que notre Padawan ne maitrise pas

    Le seul exemple trouvé sur le net est justement disponible sur la partie Delphi de ce site, language que je ne maîtrise absolument pas

  7. #7
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    OK, désolé

  8. #8
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    Rebonjour,

    merci encore pour votre aide à tous. Ci-dessous mon composants à l'état actuel. La rotation du texte au centre du label fonctionne, mais il me reste quelques petits points à corriger.

    1/ Lorsque l'angle est de 90, 180, 270 ou 360°, la LOGFONT prend un angle de 0°. Alors qu'un angle de 91° par exemple marche très bien. Pourquoi ?

    2/ J'ai essayé de nombreuses choses, mais j'ai quelques difficultés avec les polices. Ma LogFont ne prend tient pas compte de la police définie dans les propriétés. Comment modifier cela ?
    Autre amélioration facultative, comment modifier la liste déroulante des Name pour la font, afin de n'afficher que les polices True Type ?

    3/ Autre amélioration, j'ai quelques doutes sur la faisabilité : permettre au développeur utilisant le composant de modifier graphiquement l'angle en rajoutant une Ancre au centre du label (de manière similiaire aux ancres pour aggrandir/réduire).

    Voilà, désolé si je pose bcps de questions

    Note, si vous avez des commentaires, remarques, ou si vous voyez des horreures dans ce code, n'hésitez pas à m'en faire part.

    Le <.h>
    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
     
    //Gard sébastien
    //Mai 2005
    #ifndef CustomLabelOrientableH
    #define CustomLabelOrientableH
    #include <SysUtils.hpp>
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <math.h>
    class PACKAGE TCustomLabelOrientable : public TCustomLabel
        {
        private:
            bool FVertical ;
            int FAngle ;
            LOGFONT LogFont ;
        protected:
            void __fastcall SetAngle(int angle) ;
            virtual void __fastcall AngleChanged() ;
            virtual void __fastcall Paint(void) ;
        public:
            __fastcall TCustomLabelOrientable(TComponent* Owner) ;
        __published:
            //Properties
            __property Align ;
            __property Anchors ;
            __property int Angle = {read=FAngle, write=SetAngle, default=0} ;
            __property AutoSize ;
            __property Caption ;
            __property Color ;
            __property Constraints ;
            __property Cursor ;
            __property DragCursor ;
            __property DragKind ;
            __property DragMode ;
            __property Enabled ;
            __property Font ;
            __property Height ;
            __property HelpContext ;
            __property HelpKeyword ;
            __property HelpType ;
            __property Hint ;
            __property Layout ;
            __property Left ;
            __property Name ;
            __property ParentColor ;
            __property ParentShowHint ;
            __property ShowHint ;
            __property Tag ;
            __property Top ;
            __property Transparent ;
            __property bool Vertical = {read=FVertical, write=FVertical, default=false} ;
            __property Visible ;
            __property Width ;
            __property WordWrap ;
     
            //Events
            __property OnClick ;
            __property OnContextPopup ;
            __property OnDblClick ;
            __property OnDragDrop ;
            __property OnDragOver ;
            __property OnEndDock ;
            __property OnEndDrag ;
            __property OnMouseDown ;
            __property OnMouseEnter ;
            __property OnMouseLeave ;
            __property OnMouseMove ;
            __property OnMouseUp ;
            __property OnStartDock ;
            __property OnStartDrag ;
        } ;
    #endif
    le <.cpp>
    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
     
    #include <vcl.h>
    #pragma hdrstop
    #include "CustomLabelOrientable.h"
    #pragma package(smart_init)
     
    static inline void ValidCtrCheck(TCustomLabelOrientable *)
        {
        new TCustomLabelOrientable(NULL) ;
        }
     
    namespace Customlabelorientable
        {
        void __fastcall PACKAGE Register()
            {
            TComponentClass classes[1] = {__classid(TCustomLabelOrientable)} ;
            RegisterComponents("Standard", classes, 0) ;
            }
        }
     
    __fastcall TCustomLabelOrientable::TCustomLabelOrientable(TComponent* Owner)
        : TCustomLabel(Owner)
        {
        AutoSize = false ;
        FVertical = false ;
     
        ZeroMemory(&LogFont, sizeof(LOGFONT)) ;
        SetAngle(0) ;
        }
     
    void __fastcall TCustomLabelOrientable::SetAngle(int angle)
        {
        if (angle < 0 || angle > 360)
            FAngle = 0 ;
        else
            FAngle = angle ;
     
        AngleChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::AngleChanged()
        {
        LogFont.lfEscapement = 10 * FAngle ;
        LogFont.lfOrientation = 10 * FAngle ;
        Invalidate() ;
        }
     
    void __fastcall TCustomLabelOrientable::Paint(void)
        {
        Canvas->Brush->Style = bsSolid ;
        Canvas->Brush->Color = Color ;
        Canvas->FillRect(Rect(0,0,Width,Height)) ;
     
        Canvas->Brush->Style = bsClear ;
        Canvas->Font->Handle = CreateFontIndirect(&LogFont) ;
     
        int centreVer = Height/2 ;
        int centreHor = Width/2 ;
        int angle = FAngle ;
     
        angle <= 180 ? angle += 180 : angle -= 180 ;
        angle -= Canvas->TextHeight(Caption)/2 ;
     
        double rad = M_PI * angle / 180.0 ;
        double rayon = Canvas->TextWidth(Caption)/2 ;
     
        int posVer =  centreVer - (sin(rad) * rayon) ;
        int posHor =  centreHor + (cos(rad) * rayon) ;
     
        Canvas->TextOut(posHor, posVer, Caption) ;
        }

  9. #9
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    Rapidement, je n'ai pas trop le temps aujourd'hui :

    Tu peux m'expliquer ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        angle <= 180 ? angle += 180 : angle -= 180 ;
        angle -= Canvas->TextHeight(Caption)/2 ;
    Tu enléves la moitié de la hauteur (en pixel) à l'angle (en degré) ?
    Bizard ???

  10. #10
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    angle <= 180 ? angle += 180 : angle -= 180 ;
    Tu peux écrire ça comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (angle <= 180) angle += 180
    else                    angle -=180;
    Je pense que ce code doit servir à calculer l'angle dans le bon quadrant ?
    Après soustraire à l'angle la moitié de la hauteur tu texte Caption... soustraire une métrique à un angle hum... enfin c'est plutôt une erreur de "notation". Je ne comprend pas non plus le but de ces deux lignes de code ...

    Pour le fonctionnement, le texte est centré en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int centreVer = Height/2 ; 
        int centreHor = Width/2 ;
    où Width et Height sont la largeur et la hauteur de la zone de dessin.

    Pour le calcul de posVert et de PosHor, ce n'est juste qu'un bête triangle par rapport au centre du Canvas. Quoique moi je rajouterais p-e la demi-hauteur et la demi-largeur du texte à posVer et posHor respectivement...
    Lorsque l'angle est de 90, 180, 270 ou 360°, la LOGFONT prend un angle de 0°. Alors qu'un angle de 91° par exemple marche très bien. Pourquoi ?
    Bon pour 360°, c'est normal!

  11. #11
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    Ces 2 lignes servent à positionner le milieu du texte au centre du label. Comme un bon dessin vaut mieux qu'un long discours, ci-dessous l'effet avec et sans les 2 lignes de code.



    Effectivement, je pourrais rajouter la moitié de la longeur et hauteur du texte après le traitement à posVer et posHor comme le suggère Rodrigue plutot qu'utiliser ma manière.

    Par contre, en quoi l'utilisation de l'opérateur ternaire (test ? : ) est une erreure de notation ?

  12. #12
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    L'utilisation de l'opérateur ternaire n'est pas une erreur. Je parlais d'erreur de notation en ce qui concerne la soustraction d'un angle avec un métrique. Tu soustraies des poires et des pommes mais bon si ça fonctionne ...
    Comme tu le dis un dessin vaut mieux qu'un long discours :
    http://cjoint.com/?fDaAWKnJR3
    Le centre O (là où l'on va écrire le texte) est de coordonnées :
    O := (Ox, Oy) = (centre_x - largeur/2, centre_y + hauteur/2)
    Tu as donc les coordonnées d'un vecteur auquel tu vas effectuer une rotation 2D. Pour rappel, les nouvelles coordonnées se calculent de cette façon :
    x' = x * cos(A) + y * sin(A);
    y' = -x * sin(A) + y * cos(A);
    Tu as donc que le nouveau point O' vaut :
    O' =Ox* cos(Angle) + Oy * sin(Angle);
    y' = -Ox * sin(Angle) + Oy * cos(Angle);
    Voilà en espérant avoir pu solutionner ton problème...

    Cordialement,
    Rodrigue

  13. #13
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    J'ai modifié cette partie 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
     
        int centreVer = Height/2 ;
        int centreHor = Width/2 ;
        int angle = FAngle ;
     
        angle <= 180 ? angle += 180 : angle -= 180 ;
        angle -= Canvas->TextHeight(Caption)/2 ;
     
        double rad = M_PI * angle / 180.0 ;
        double rayon = Canvas->TextWidth(Caption)/2 ;
     
        int posVer =  centreVer - (sin(rad) * rayon) ;
        int posHor =  centreHor + (cos(rad) * rayon) ;
    Par celle-ci, en utilisant ta manière de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        int posX = Width/2 - Canvas->TextWidth(Caption)/2 ;
        int posY = Height/2 + Canvas->TextHeight(Caption)/2 ;
     
        int posXfinal = posX * cos(FAngle) + posY * sin(FAngle) ;
        int posYfinal = -posX * cos(FAngle) + posY * sin(FAngle) ;
    Oui, c'est beaucoup plus propre, mais malheureusement, ca marche moins bien. La coordonné O(x,y) du texte n'évolue plus du tout de manière circulaire autour du centre du label, et je me retrouve avec un texte positionné un peu n'importe comment à l'interieur de l'espace du label.

    Est-ce du à une erreur de ma part dans l'implémentation de ton explication ?

  14. #14
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Est-ce du à une erreur de ma part dans l'implémentation de ton explication ?
    Oui !

    O := (Ox, Oy) = (centre_x - largeur/2, centre_y + hauteur/2)
    Ox' =Ox* cos(Angle) + Oy * sin(Angle);
    Oy' = -Ox * sin(Angle) + Oy * cos(Angle);
    Le point O est le point où tu vas écrire le texte ...
    centre, ce le point milieu de ton canvas
    donc centre_x = width/2 et centre_y = height/2
    largeur c'est la largeur de ton texte d'où TextWidth
    longueur c'est la longueur de ton texte d'où TextHeight
    Angle c'est la valeur de l'angle qui fait pivoter ton texte ...

    J'ai fait l'exemple qui fonctionne. Je vais le publier dans les sources BCB. J'attends une réponse pour savoir comment procéder...

    Cordialement,
    Rodrigue

  15. #15
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    Merci pour l'explication, mais finalement le problème était tout autre

    Après une bonne prise de tête avec un de mes anciens profs, on a identifié la source :

    L'erreur provient de la structure LOGFONT elle-même qui doit fonctionner par quartier et qui ne gère pas (ou bug) les angles 90, 180 et 270°.

    La solution est simple, comme la propriété lfEscapement est en dixième de degré, il suffit de rajouter +1 à celle-ci. Par exemple pour un angle de 90°, celui ci devient égale à 901 dixièmes de degrés. Imperceptible par l'oeil, mais ca évite le bug.

    1 semaine de posts pour résoudre un bug dont je ne suis même pas l'auteur... merci Microsoft

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        LogFont.lfEscapement = 10 * FAngle +1  ;
        LogFont.lfOrientation = 10 * FAngle +1 ;

    Par contre il me reste toujours 2 questions en suspend :

    1) Comment modifier la liste des polices disponibles affichées dans l'éditeur de propriété, afin de ne garder que les True Type. Et comment faire le lien entre le choix du développeur et ce qui est affiché.
    Peut etre avec ceci ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Canvas->Font->Name = Font->Name
    2) Est-il possible de modifier l'angle graphiquement au moyen d'une nouvelle ancre sur le label ?

    Merci encore pour tout le mal que vous vous donnez

  16. #16
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    la librairie LMD tools pour Delphi ET Borland C++ offre des label orientables.
    La version complète est payante, une version lmd tools 7 se existe et est gratuite downloadable du web.

    http://www.lmdtools.com/

  17. #17
    Nouveau membre du Club

    Inscrit en
    Novembre 2004
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 17
    Points : 31
    Points
    31
    Par défaut
    Encore merci à tous pour votre aide. J'ai terminé mon composant.

    Si on veut faire plus, il y a toujours de quoi faire, mais la version actuelle quoique imparfaite (p.ex pour les fonts) me convient. (Et surtout l'échéance approche ) Je clos donc le sujet.

    Ci dessous le code source complet si ca peut aider des gens par la suite :

    <.cpp>
    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
     
    //Date : 8 juin 05
    //Auteurs : Gard Sébastien - Martin Grégory
    #include <vcl.h>
    #pragma hdrstop
    #include "CustomLabelOrientable.h"
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
    // ValidCtrCheck is used to assure that the components created do not have
    // any pure virtual functions.
    //
    static inline void ValidCtrCheck(TCustomLabelOrientable *)
        {
        new TCustomLabelOrientable(NULL) ;
        }
     
    namespace Customlabelorientable
        {
        void __fastcall PACKAGE Register()
            {
            TComponentClass classes[1] = {__classid(TCustomLabelOrientable)} ;
            RegisterComponents("Standard", classes, 0) ;
            }
        }
     
    __fastcall TCustomLabelOrientable::TCustomLabelOrientable(TComponent* Owner)
        : TCustomLabel(Owner)
        {
        AutoSize = true ;
        FAngle = 0 ;
        //Si la font Tahoma n'est pas disponible sur le système, la structure
        //LogFont utilise par défaut une autre police valable
        FFontName = "Tahoma" ;
        FFontColor = clBlack ;
        FFontHeight = 16 ;
        FFontBold = FW_NORMAL ;
        FFontItalic = false ;
        FFontStrikeOut = false ;
        FFontUnderline = false ;
     
        //Créé dynamiquement la liste des fonts disponible sur le système
        FFontNameList = new TStringList() ;
        for (int i = 0 ; i < Screen->Fonts->Count ; i++)
            FFontNameList->Add(Screen->Fonts->Strings[i]) ;
     
        //Remplit l'espace mémoire utilisé par l'objet LogFont de zéros
        ZeroMemory(&LogFont, sizeof(LOGFONT)) ;
        //Affecte rééllement les propriétés définies plus haut à l'objet LogFont
        LogFontChanged() ;
        }
     
    __fastcall TCustomLabelOrientable::~TCustomLabelOrientable()
        {
        delete FFontNameList ;
        }
     
    void __fastcall TCustomLabelOrientable::SetAngle(unsigned int angle)
        {
        if (angle >= 360)
            FAngle = 0 ;
        else
            FAngle = angle ;
     
        LogFontChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontName(AnsiString name)
        {
        //Vérifie que le nom de la font existe bien sur le système.
        int i = 0 ;
        bool found = false ;
        while (i < FFontNameList->Count && found == false)
            {
            if (name == FFontNameList->Strings[i])
                found = true ;
            i++ ;
            }
     
        if (found == true)
            {
            FFontName = name ;
            LogFontChanged() ;
            }
        }
     
    TStrings* __fastcall TCustomLabelOrientable::GetFontNameList()
        {
        return FFontNameList ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontNameList(TStrings *list)
        {
        FFontNameList->Assign(list) ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontColor(TColor color)
        {
        FFontColor = color ;
        LogFontChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontHeight(unsigned int height)
        {
        FFontHeight = height ;
        LogFontChanged() ;
        }
     
    bool __fastcall TCustomLabelOrientable::GetFontBold()
        {
        if (FFontBold == FW_BOLD)
            return true ;
        else
            return false ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontBold(bool state)
        {
        state == true ? FFontBold = FW_BOLD : FFontBold = FW_NORMAL ;
        LogFontChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontItalic(bool state)
        {
        FFontItalic = state ;
        LogFontChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontStrikeOut(bool state)
        {
        FFontStrikeOut = state ;
        LogFontChanged() ;
        }
     
    void __fastcall TCustomLabelOrientable::SetFontUnderline(bool state)
        {
        FFontUnderline = state ;
        LogFontChanged() ;
        }
     
    //Applique les propriétés à l'objet LogFont, utilisé pour dessiner le texte
    void __fastcall TCustomLabelOrientable::LogFontChanged()
        {
        //Choix du nom de la police. Le nom (lfFaceName)est un tableau de char,
        //il est nécessaire d'effectuer ces opérations pour utiliser l'AnsiString
        //de la propriété FFontName
        char f[32] ;
        strcpy(f, FFontName.c_str()) ;
        strcpy(LogFont.lfFaceName, f) ;
     
        //L'angle est en 10ème de degré. A cause d'une erreur ou d'une mauvaise
        //gestion dans la structure, les angles de 90, 180 et 270 degrés ne sont
        //pas appliqués (le résultat est similaire à un angle de 0°), il faut
        //ajouter +1 à la valeur passée. Le résultat donne 901 dixième de degrés. La
        //différence est imperceptible à l'oeil nu, mais évite le bug.
        //Pour une meilleure solution, il faudrait avoir accès au code source
        //de cette structure (fichier d'en-tête wingdi.h)
        LogFont.lfEscapement = 10 * FAngle +1  ;
        LogFont.lfOrientation = 10 * FAngle +1 ;
        LogFont.lfHeight = FFontHeight ;
        LogFont.lfWeight = FFontBold ;
        LogFont.lfItalic = FFontItalic ;
        LogFont.lfStrikeOut = FFontStrikeOut ;
        LogFont.lfUnderline = FFontUnderline ;
     
        Invalidate() ;
        }
     
    void __fastcall TCustomLabelOrientable::Paint(void)
        {
        //Clear le label en redessinant une rectangle par dessus
        Canvas->Brush->Style = bsSolid ;
        Canvas->Brush->Color = Color ;
        Canvas->FillRect(Rect(0,0,Width,Height)) ;
     
        Canvas->Brush->Style = bsClear ;
        //Créé une Font avec les caractéristiques de LogFont et la passe au Canvas
        Canvas->Font->Handle = CreateFontIndirect(&LogFont) ;
        Canvas->Font->Color = FFontColor ;
     
        int longueurCaption = Canvas->TextWidth(Caption) ;
        int hauteurCaption = Canvas->TextHeight(Caption) ;
        //converti l'angle en radian pour utiliser les méthodes cos et sin de math.h
        double rad = M_PI * FAngle / 180.0 ;
     
        //Ajuste la taille du label en hauteur et largeur à la taille du texte
        if (AutoSize == true)
            {
            //On ajoute +1 à cause de la convertion du résultat, nombre à virgule,
            //en entier tel que demandé par la propriété Width et Height
            Width = abs(cos(rad) * longueurCaption) +
                abs(cos(M_PI * (90+FAngle) / 180.0) * hauteurCaption) +1 ;
     
            Height = abs(sin(rad) * longueurCaption) +
                abs(sin(M_PI * (90+FAngle) / 180.0) * hauteurCaption) +1 ;
            }
     
        //Défini les coordonnées X et Y à partir d'où sera dessiné le texte afin de
        //l'avoir parfaitement centré dans le label, quel que soit son angle et sa
        //taille
        int posHor = Width/2.0 - (cos(rad) * longueurCaption/2.0) -
                (sin(rad) * hauteurCaption/2.0) ;
        int posVer = Height/2.0 - (cos(rad) * hauteurCaption/2.0) +
                (sin(rad) * longueurCaption/2.0) ;
     
        //Dessine le texte
        Canvas->TextOut(posHor, posVer, Caption) ;
        }
    <.h>
    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
     
    #ifndef CustomLabelOrientableH
    #define CustomLabelOrientableH
    #include <SysUtils.hpp>
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <math.h>
     
    class PACKAGE TCustomLabelOrientable : public TCustomLabel
        {
        private:
            unsigned int FAngle ;
     
            AnsiString FFontName ;
            //Liste des polices disponibles sur le système, à vocation indicative
            TStringList* FFontNameList ;
            TColor FFontColor ;
            unsigned int FFontHeight ;
            unsigned int FFontBold ;
            bool FFontItalic ;
            bool FFontStrikeOut ;
            bool FFontUnderline ;
     
            LOGFONT LogFont ; // Windows native font structure
        protected:
            virtual void __fastcall SetAngle(unsigned int angle) ;
            virtual void __fastcall SetFontName(AnsiString name) ;
            virtual TStrings* __fastcall GetFontNameList() ;
            virtual void __fastcall SetFontNameList(TStrings *list);
            virtual void __fastcall SetFontColor(TColor color) ;
            virtual void __fastcall SetFontHeight(unsigned int height) ;
            virtual bool __fastcall GetFontBold() ;
            virtual void __fastcall SetFontBold(bool state) ;
            virtual void __fastcall SetFontItalic(bool state) ;
            virtual void __fastcall SetFontStrikeOut(bool state) ;
            virtual void __fastcall SetFontUnderline(bool state) ;
     
            virtual void __fastcall LogFontChanged() ;
            virtual void __fastcall Paint(void) ;
        public:
            __fastcall TCustomLabelOrientable(TComponent* Owner) ;
            virtual __fastcall ~TCustomLabelOrientable() ;
        __published:
            //Properties
            __property Align ;
            __property Anchors ;
            __property unsigned int Angle = {read=FAngle, write=SetAngle, default=0} ;
            __property AutoSize ;
            __property Caption ;
            __property Color ;
            __property Constraints ;
            __property Cursor ;
            __property DragCursor ;
            __property DragKind ;
            __property DragMode ;
            __property Enabled ;
            __property AnsiString FontName = {read=FFontName, write=SetFontName} ;
            __property TStrings *FontNameList = {read=GetFontNameList, write=SetFontNameList} ;
            __property unsigned int FontHeight = {read=FFontHeight, write=SetFontHeight, default=16} ;
            __property TColor FontColor = {read=FFontColor, write=SetFontColor, default=clBlack	} ;
            __property bool FontBold = {read=GetFontBold, write=SetFontBold, default=0} ;
            __property bool FontItalic = {read=FFontItalic, write=SetFontItalic, default=0} ;
            __property bool FontStrikeOut = {read=FFontStrikeOut, write=SetFontStrikeOut, default=0} ;
            __property bool FontUnderline = {read=FFontUnderline, write=SetFontUnderline, default=0} ;
            __property Height ;
            __property HelpContext ;
            __property HelpKeyword ;
            __property HelpType ;
            __property Hint ;
            __property Layout ;
            __property Left ;
            __property Name ;
            __property ParentColor ;
            __property ParentShowHint ;
            __property ShowHint ;
            __property Tag ;
            __property Top ;
            __property Transparent ;
            __property Visible ;
            __property Width ;
            __property WordWrap ;
     
            //Events
            __property OnClick ;
            __property OnContextPopup ;
            __property OnDblClick ;
            __property OnDragDrop ;
            __property OnDragOver ;
            __property OnEndDock ;
            __property OnEndDrag ;
            __property OnMouseDown ;
            __property OnMouseEnter ;
            __property OnMouseLeave ;
            __property OnMouseMove ;
            __property OnMouseUp ;
            __property OnStartDock ;
            __property OnStartDrag ;
        } ;
    #endif

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

Discussions similaires

  1. Cherche pistes pour démarrer
    Par StringBuilder dans le forum Android
    Réponses: 15
    Dernier message: 16/07/2012, 12h41
  2. Debutant en C cherche aide pour fonctions!!!!
    Par benji17c dans le forum C
    Réponses: 5
    Dernier message: 30/09/2003, 12h47
  3. Réponses: 3
    Dernier message: 01/07/2003, 16h04
  4. Cherche conseil pour choisir mon orientation.
    Par AslDice dans le forum Débuter
    Réponses: 6
    Dernier message: 24/04/2003, 17h07
  5. [Kylix] cherche composants pour les sockets
    Par coriolis dans le forum EDI
    Réponses: 1
    Dernier message: 09/04/2003, 10h18

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