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 :

Créer un composant conteneur de type TPopupMenu


Sujet :

C++Builder

  1. #1
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut Créer un composant conteneur de type TPopupMenu
    Bonjour je souhaite créer un composant réagissant exactement comme un TPopupMenu, comprenant la possibiliter d'ajouter à la place d'un Item, un TEdit pour avoir une zone de saisie dans le Popup.

    J'ai créé un composant dérivé du TPopupMenu, mais celui-ci ne peux pas contenir d'autre composant, (propriété à changer inaccessible). J'ai donc créé un composant dérivé du TCustomControl pour obtenir toutes les propriétés disponibles mais je perds tout le fonctionnement du Popup.

    J'ai lu le tutoriel pour la création de composants, mais je n'ai rien trouvé de semblable pouvant m'aiguiller dans la réalisation de mon composant.

    Comment intégrer ce fonctionnement au TCustomControl? comment faire un mix de 2 composants avec les liens qui vont biens?


    Merci

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Je ne sais pas dans quel sens va cette réalisation mais je pense qu'il faut poursuivre dans le sens du TCustomControl (peut-être également TGraphicControl) et développer les événementielles permettant de simuler un fonctionnement et une apparence comparable à celle d'un TPopopMenu sans jamais atteindre parfaitement un composant idéal.
    - Comme on peut dessiner ce que l'on veut, il devient facile de gérer les apparences.
    - On peut lui ajouter un TEdit et le positionner la où il faut.
    - Pour créer un sous menu, la par contre, ça risque de se compliquer...

    Il faudrait tester au moins deux méthodes (j'écarte une troisième voie purement graphique car je pense qu'ici elle n'a pas lieu d'être) :

    - soit on raisonne par MenuItem
    Dans ce cas, on peut imaginer de dérouler les objets les uns sous les autres en y incluant un TEdit.
    C'est facile à dérouler mais compliqué à gérer... (sans doute une classe pour superviser...)
    - soit on raisonne par MenuBox
    Dans ce cas, les items sont dessinés sur l'objet et le TEdit est enfant de l'objet, donc apparait quelque part en lieu et place d'un item.
    Il n'y a rien à dérouler (l'objet dessine l'ensemble) et c'est probablement plus facile à gérer...

    Ca représente du boulot et de la réflexion... mais je vais essayer de tester... sans pouvoir aller très loin puisque j'ai BCB3 Pro (on doit disposer avec BCB6 de plus d'événementielles... je pense... ???).

    A plus !

  3. #3
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Le hic c'est que je pensais que l'on pouvait simplement partir d'un PopUpMenu complet et de forcer la création du premier Item, pour y placer le TEdit, en gros le créer en même temps et l'affilier au TMenuItem, (affiliation apparament impossible) et le plcer à l'endroit du premier item créé.

    Jusqu'à présent, j'ai toujours codé sans les class et donc je ne sais pas comment dériver celles-ci pour obtenir ce que je souhaite. De plus lors de la création de composant, je souhaite inclure un composant dans un autre, et ce que c'est faisable?

    Est ce que l'on doit obligatoirement passer par la re-création de tous les items?

    Si oui, je pense que le raisonnement par MenuBox serait le plus simple, mais je trouve la démarche très compliqués. Sur un autre poste, kmaniche m'a proposer de faire la même chose en utilisant des TPanel, et simulant les PopUps (suivant un de tes conseils il me semble). Cette méthode est longue est fastidieuse mais à le mérite d'être simple à mettre en oeuvre.

    Dernière question, si dans mon composant, je créé un TEdit, est-ce que sa parenté est automatiquement faites au composant en création, ou faut-il la faire par code (partie problématique)?

    Merci de t'intéresser à mon problème.

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    J'en suis là pour l'instant :

    - une classe jMenuItem dérivée de TComponent avec comme propriétés :
    Caption. C'est tout bêtement le texte !
    OnClick. Bien que TComponent ne soit pas un composant pouvant générer ce type d'événement, il est possible malgré tout d'utiliser cette astuce simplement pour y affecter une méthode.
    SubMenu. Théoriquement, devrait pouvoir servir à dérouler un jMenuBox... Ce qui reste à faire...

    - une classe jMenuBox dérivée de TCustomControl
    Cette classe permet d'afficher l'ensemble donc également le TEdit (s'il y en a un) et de gérer le graphisme.
    Lorsque l'on clique sur un Item sélectionné on fait appel à sa OnClick.

    //Comme on a un croisement au niveau des déclarations
    class jMenuBox;

    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
    class jMenuItem : public TComponent
    {
    private :
    AnsiString FCaption;
    TNotifyEvent FOnClick;
     
    protected :
     
    public :
    jMenuBox *SubMenu;
        __fastcall jMenuItem(TComponent *Owner, AnsiString N);
        __fastcall ~jMenuItem();
    __property AnsiString Caption = {read=FCaption, write=FCaption};
    __property Classes::TNotifyEvent OnClick = {read=FOnClick, write=FOnClick};
     
    };
    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
    class jMenuBox : public TCustomControl
    {
    private :
    int Index;
     
    public :
    TEdit *Edit;
    TList *MenuItems;
        __fastcall jMenuBox(TComponent *Owner, bool HasEdit);
        __fastcall ~jMenuBox();
        void __fastcall Paint();
        void __fastcall Popup(int X, int Y);
        void __fastcall WhenMouseMove(TObject *Sender, TShiftState Shift,
            int X, int Y);
        void __fastcall WhenMouseDown(TObject *Sender, TMouseButton Button,
            TShiftState Shift, int X, int Y);
        void __fastcall WhenMouseUp(TObject *Sender, TMouseButton Button,
            TShiftState Shift, int X, int Y);
        void __fastcall WhenEditMouseMove(TObject *Sender, TShiftState Shift,
            int X, int Y);
        jMenuItem* __fastcall AddItem(AnsiString N);
    };
    Voici les méthodes pour ces deux classes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    __fastcall jMenuItem::jMenuItem(TComponent *Owner, AnsiString N)
        : TComponent(Owner)
    {
    FCaption = N;
    FOnClick = NULL;
    }
     
    __fastcall jMenuItem::~jMenuItem()
    {
    }
    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
    __fastcall jMenuBox::jMenuBox(TComponent *Owner, bool HasEdit)
        : TCustomControl(Owner)
    {
    if(Owner->InheritsFrom(__classid(TWinControl))) Parent = (TWinControl*)Owner;
    MenuItems = new TList;
    Index = -1;
    Edit = NULL;
    if(HasEdit)
        {
        Edit = new TEdit(this);
        Edit->Parent = this;
        Edit->OnMouseMove = WhenEditMouseMove;
        }
    Visible = false;
    OnMouseDown = WhenMouseDown;
    OnMouseMove = WhenMouseMove;
    OnMouseUp = WhenMouseUp;
    }
     
    __fastcall jMenuBox::~jMenuBox()
    {
    MenuItems->Clear();
    delete MenuItems;
    }
     
    void __fastcall jMenuBox::Paint()
    {
    int we = Width;
    int he = Height;
    if(Edit != NULL)
        {
        Edit->SetBounds(2,2,we-4, 21);
        }
    Canvas->Brush->Style = bsSolid;
    Canvas->Brush->Color = clSilver;
    Canvas->FillRect(Rect(0,0,we,he));
    Canvas->Pen->Style = psSolid;
    Canvas->Pen->Mode = pmCopy;
    Canvas->Pen->Color = clWhite;
    Canvas->MoveTo(0,he); Canvas->LineTo(0,0);Canvas->LineTo(we,0);
    Canvas->MoveTo(1,he); Canvas->LineTo(1,1);Canvas->LineTo(we,1);
    Canvas->Pen->Color = clWhite;
    we--; he--;
    Canvas->Pen->Color = clGray;
    Canvas->MoveTo(1,he); Canvas->LineTo(we,he);Canvas->LineTo(we,1);
    we--; he--;
    Canvas->MoveTo(2,he); Canvas->LineTo(we,he);Canvas->LineTo(we,2);
     
    int top = 4;
    if(Edit != NULL) top = top + Edit->Height;
     
    if(Index != -1)
        {
        Canvas->Brush->Color = clNavy;
        Canvas->Pen->Color = clNavy;
        int y = top + (Index * 16);
        Canvas->Rectangle(8,
                          y,
                          Width - 8,
                          y + 15);
        }
    Canvas->Brush->Style = bsClear;
    for(int j = 0; j < MenuItems->Count; j++)
        {
        if(j != Index) Canvas->Font->Color = clBlack;
        else Canvas->Font->Color = clWhite;
        Canvas->TextOut(16, top, ((jMenuItem*)MenuItems->Items[j])->Caption);
        top = top + 16;
        }
    }
     
    void __fastcall jMenuBox::Popup(int X, int Y)
    {
    int we;
    Width = 0;
    for(int j = 0; j < MenuItems->Count; j++)
        {
        we = Canvas->TextWidth(((jMenuItem*)MenuItems->Items[j])->Caption);
        if(we > Width) Width = we;
        }
    Width = Width + 32;
    Height = 6;
    if(Edit != NULL) Height = Height + Edit->Height;
    Height = Height + (MenuItems->Count * 16);
    SetBounds(X-8, Y-8, Width, Height);
    BringToFront();
    Show();
    }
     
    void __fastcall jMenuBox::WhenMouseMove(TObject *Sender, TShiftState Shift,
            int X, int Y)
    {
    int top = 4;
    if(Edit != NULL) top = top + Edit->Height;
    int y = (Y - top) / 16;
    if(y >= 0)
        {
        if(Index != y)
            {
            Index = y;
            Repaint();
            }
        }
    }
     
    void __fastcall jMenuBox::WhenMouseDown(TObject *Sender, TMouseButton Button,
            TShiftState Shift, int X, int Y)
    {
    if((Index != -1) && (Index < MenuItems->Count))
        {
        jMenuItem *MenuItem = (jMenuItem*)MenuItems->Items[Index];
        Hide();
        if(MenuItem->OnClick != NULL) MenuItem->OnClick(MenuItem);
        }
    }
     
    void __fastcall jMenuBox::WhenMouseUp(TObject *Sender, TMouseButton Button,
            TShiftState Shift, int X, int Y)
    {
    }
     
    void __fastcall jMenuBox::WhenEditMouseMove(TObject *Sender, TShiftState Shift,
            int X, int Y)
    {
    if(Index != -1)
        {
        Index = -1;
        Repaint();
        }
    }
     
    jMenuItem* __fastcall jMenuBox::AddItem(AnsiString N)
    {
    jMenuItem *Item = new jMenuItem(this, N);
    MenuItems->Add(Item);
    return Item;
    }
    Voici comment j'ai testé sur Form1 :

    Ces 3 méthodes sont à déclarer dans la classe de TForm1

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void __fastcall TForm1::Item1Click(TObject *Sender)
    {
    ShowMessage("Item 1");
    }
    void __fastcall TForm1::Item2Click(TObject *Sender)
    {
    ShowMessage("Item 2");
    }
    void __fastcall TForm1::Item3Click(TObject *Sender)
    {
    ShowMessage("Item 3");
    }
    Je crée les objets depuis le constructeur de la form

    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
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    MenuBox = new jMenuBox(this, true);
    jMenuItem *MenuItem;
    MenuItem = MenuBox->AddItem("Menu Item1");
    MenuItem->OnClick = Item1Click;
    MenuItem = MenuBox->AddItem("Menu Item2 large");
    MenuItem->OnClick = Item2Click;
    MenuItem = MenuBox->AddItem("Menu Item3");
    MenuItem->OnClick = Item3Click;
    }
     
     
    void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
    if(Button == mbRight)
        {
        if(!MenuBox->Visible) MenuBox->Popup(X,Y);
        }
    else
        {
        if(MenuBox->Visible)
            {
            MenuBox->Visible = false;
            }
        }
    }
    C'est juste un premier jet pour mettre en oeuvre quelque chose qui soit visible et fonctionnel (dans les limites de ce que j'ai apporté)!
    On pourrait probablement faire plus simple avec un TPanel...
    En ce qui me concerne j'avais envie de le faire comme ça, car Ici, l'avantage est que l'objet sait se dimensionner.

    A plus !

Discussions similaires

  1. Réponses: 11
    Dernier message: 02/10/2014, 09h47
  2. Créer un composant type gauge
    Par Baxter67 dans le forum C++Builder
    Réponses: 3
    Dernier message: 17/03/2008, 17h17
  3. Intercepter un Message Windows ? Créer un Composant Grille !
    Par TOTO32 dans le forum Composants VCL
    Réponses: 6
    Dernier message: 21/07/2004, 13h41

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