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

Lazarus Pascal Discussion :

Problème de création d'un composant comportant un TEdit [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut Problème de création d'un composant comportant un TEdit
    Bonjour à toutes et à tous,

    A partir d'un TGraphicControl, j'ai créé un composant TBoutonCoinRond qui n'est autre qu'un joli cadre dessiné avec TBGRABitmap et à qui j'ai affecté les deux procédures parentes MousDown et MouseUp. Cela fonctionne très bien.

    Maintenant, je voudrais créer un nouveau composant à partir de mon TBoutonCoinRond sur lequel je souhaite ajouter un TEdit. Tout ça pour avoir un TEDit avec un joli cadre.

    Et là, je tourne en rond, je patauge, je n'arrive pas à positionner le TEdit dans mon cadre, il se positionne par rapport à la fenêtre dans laquelle je dépose mon composant. Voilà le code que j'ai écrit :

    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
    type
      TEditeurCoinRond = class(TBoutonCoinRond)
      private
        Editeur: TEdit;
      protected
     
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
     
      end;
     
    procedure Register;
     
    implementation
     
    procedure Register;
    begin
      {$I editeurarrondi_icon.lrs}
      RegisterComponents('ChP',[TEditeurCoinRond]);
    end;
     
    constructor TEditeurCoinRond.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Editeur:= TEdit.Create(AOwner);
      Editeur.Parent:= TWinControl(Self.Parent);
      Editeur.AutoSize:= False;
      Editeur.Left:= Left+18;
      Editeur.Top:= Top+4;
      Editeur.Width:= Width-36;
      Editeur.Height:= Height-8;
    end;
     
    destructor TEditeurCoinRond.Destroy;
    begin
      Editeur.Free;
      inherited Destroy;
    end;
     
    end.
    J'ai essayé pour la création, le parent, les positions et tailles d'utiliser Aowner, Parent, Self, ... Je n'arrive à rien, je tourne en rond.

    Question : est-ce ce que je veux faire est réalisable et si oui, comment faire ?

    NOTA : le composant TBoutonCoinRond : BoutonCoinRond.zip

    Cordialement.

    Pierre.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 691
    Points : 13 121
    Points
    13 121
    Par défaut
    La position du contrôle n'est pas encore définie au moment du Create, Left et Top sont à 0.

    Surcharge SetBounds et positionne l'edit depuis là.

  3. #3
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    La position du contrôle n'est pas encore définie au moment du Create, Left et Top sont à 0.

    Surcharge SetBounds et positionne l'edit depuis là.
    En attendant une réponse, j'ai regardé mon composant parent et c'est là que je me suis dit : mais quel bougre d'an...lle ! si je veux que ça se dessine, redessine, c'est dans la procédure Paint qu'il faut faire cela --> dont acte et cela fonctionne.

    J'ai essayé avec la seule surcharge de SetBounds, ça plantait à la simple dépose du composant dans une fenêtre avec une erreur du type "Access violation".

    Cordialement.

    Pierre.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 691
    Points : 13 121
    Points
    13 121
    Par défaut
    Si tu as une VA c'est que tu forces la position avant que l'edit soit créé. Tu as certainement un Left/Top := 0 dans TBoutonCoinRond.Create.

    Soit tu supprimes ces Left/Top qui ne sont de toute façon pas utiles puisque les champs sont mis à zéro (ou nil) à l'instanciation, soit tu conditionnes SetBounds avec un if Assigned(Editeur) then.

    Mais Paint n'est clairement pas la bonne place pour faire ce genre de chose.

  5. #5
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Si tu as une VA c'est que tu forces la position avant que l'edit soit créé. Tu as certainement un Left/Top := 0 dans TBoutonCoinRond.Create.

    Soit tu supprimes ces Left/Top qui ne sont de toute façon pas utiles puisque les champs sont mis à zéro (ou nil) à l'instanciation, soit tu conditionnes SetBounds avec un if Assigned(Editeur) then.

    Mais Paint n'est clairement pas la bonne place pour faire ce genre de chose.

    J'ai supprimé le Left et le Top de mon composant TBoutonCoinRond qui effectivement ne servait à rien.

    Dans mon composant TEditeurCoinRond, j'ai surchargé la procédure SetBounds. Puis j'ai utilisé ou non le if Assigned(Editeur) :

    Si je l'utilise, quand je place le composant sur la Form, j'ai l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur en déplaçant le composant EditeurCoinRond1 : TEditeurCoinRond
    Si je ne l'utilise pas, j'ai l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur de création du composant TEditeurCoinRond : Access Violation.
    Voici le code de mon composant TEditeurCoinRond :

    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
    unit EditeurArrondi;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, StdCtrls, LResources, Forms, Controls, Graphics, Dialogs, BoutonArrondi;
     
    type
      TEditeurCoinRond = class(TBoutonCoinRond)
      private
        Editeur: TEdit;
      protected
    //    procedure Paint; override;
        procedure SetBounds(L, T, W, H: Integer); override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer); override;
        procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
                          X, Y: Integer); override;
      published
        property OnClick;
        property OnMouseDown;
        property OnMouseUp;
        property Enabled;
        property Visible;
      end;
     
    procedure Register;
     
    implementation
     
    procedure Register;
    begin
      {$I editeurarrondi_icon.lrs}
      RegisterComponents('ChP',[TEditeurCoinRond]);
    end;
     
    constructor TEditeurCoinRond.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Parent:= TWinControl(AOwner);
      Actif:= False;
      Editeur:= TEdit.Create(Parent);
      Editeur.Parent:= TWinControl(Parent);
      Editeur.BorderStyle:= bsNone;
      Editeur.AutoSize:= False;
      Editeur.Font.Style:= [fsBold];
    end;
     
    destructor TEditeurCoinRond.Destroy;
    begin
    //  Editeur.Free;
      inherited Destroy;
    end;
     
    procedure TEditeurCoinRond.SetBounds(L, T, W, H: Integer);
    begin
    //  inherited SetBounds(L, T, W, H); // Cette ligne ne change rien à l'affaire
    //  if Assigned(Editeur) then
    //  begin
        Editeur.Left:= Left+16;
        Editeur.Top:= Top+4;
        Editeur.Width:= Width-32;
        Editeur.Height:= Round((Height-8)*0.8);
        Editeur.Font.Size:= Round((Height-8)*0.5);
    //  end;
    end;
     
    {procedure TEditeurCoinRond.Paint;
    begin
      inherited Paint;
      Editeur.Left:= Left+16;
      Editeur.Top:= Top+4;
      Editeur.Width:= Width-32;
      Editeur.Height:= Round((Height-8)*0.8);
      Editeur.Font.Size:= Round((Height-8)*0.5);
    end;}
     
    procedure TEditeurCoinRond.MouseDown(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer);
    begin
      inherited MouseDown(Button, Shift, X, Y);
    end;
     
    procedure TEditeurCoinRond.MouseUp(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer);
    begin
      inherited MouseUp(Button, Shift, X, Y);
    end;
     
    end.
    Cordialement.

    Pierre.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 691
    Points : 13 121
    Points
    13 121
    Par défaut
    inherited est obligatoire dans SetBounds puisque le positionnement se fait dans TControl.

  7. #7
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    inherited est obligatoire dans SetBounds puisque le positionnement se fait dans TControl.
    Tu as raison, ça fonctionne mieux. Pour autant, je suis obligé de mettre le if Assigned(Editeur) sinon ça plante comme avant.

    Toutes choses égales par ailleurs, le comportement de mon composant est différent selon que j'utilise la méthode SetBounds ou la méthode Paint.

    Avec la méthode SetBounds :

    • Si je clique sur la partie Editeur de mon composant, je peux la désolidariser de son cadre. Elle reste désolidarisée à l’exécution. Pour la re-solidariser, il suffit que je déplace le cadre et la partie éditeur revient dans le cadre.
    • A l’exécution, si je mets la propriété Visible du composant à False, il reste à l'écran un rectangle blanc de la dimension de la partie Editeur.

    Avec la méthode Paint :

    • Si je clique sur la partie Editeur du composant, je ne peux pas la déplacer par rapport à son cadre. Si je clique sur la partie cadre, la partie Editeur suit.
    • A l’exécution, si je mets la propriété Visible de composant à False, le composant est totalement effacé.

    Voilà la dernière mouture du 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
    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
    unit EditeurArrondi;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils, StdCtrls, LResources, Forms, Controls, Graphics, Dialogs, BoutonArrondi;
     
    type
      TEditeurCoinRond = class(TBoutonCoinRond)
      private
        FEditeur: TEdit;
      protected
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure Paint; override;
    //    procedure SetBounds(L, T, W, H: Integer); override;
        procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer); override;
        procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
                          X, Y: Integer); override;
        procedure SetVisible(Value: Boolean); override;
      published
        property Editeur: TEdit read FEditeur write FEditeur;
        property OnClick;
        property OnMouseDown;
        property OnMouseUp;
        property Enabled;
        property Visible;
      end;
     
    procedure Register;
     
    implementation
     
    procedure Register;
    begin
      {$I editeurarrondi_icon.lrs}
      RegisterComponents('ChP',[TEditeurCoinRond]);
    end;
     
    constructor TEditeurCoinRond.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Parent:= TWinControl(AOwner);
      Actif:= False;
      Editeur:= TEdit.Create(Parent);
      Editeur.Parent:= TWinControl(Parent);
      Editeur.BorderStyle:= bsNone;
      Editeur.AutoSize:= False;
      Editeur.Font.Style:= [fsBold];
    end;
     
    destructor TEditeurCoinRond.Destroy;
    begin
      Editeur.Free;
      inherited Destroy;
    end;
     
    {procedure TEditeurCoinRond.SetBounds(L, T, W, H: Integer);
    begin
      inherited;
      if Assigned(Editeur) then
      begin
        Editeur.Left:= L+16;
        Editeur.Top:= T+4;
        Editeur.Width:= W-32;
        Editeur.Height:= Round((H-8)*0.8);
        Editeur.Font.Size:= Round((H-8)*0.5);
      end;
    end;}
     
    procedure TEditeurCoinRond.SetVisible(Value: Boolean);
    begin
      if Visible <> Value then
      begin
        inherited;
        Editeur.Visible:= Value;
      end;
    end;
     
    procedure TEditeurCoinRond.Paint;
    begin
      inherited Paint;
      Editeur.Left:= Left+16;
      Editeur.Top:= Top+4;
      Editeur.Width:= Width-32;
      Editeur.Height:= Round((Height-8)*0.8);
      Editeur.Font.Size:= Round((Height-8)*0.5);
    end;
     
    procedure TEditeurCoinRond.MouseDown(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer);
    begin
      inherited MouseDown(Button, Shift, X, Y);
    end;
     
    procedure TEditeurCoinRond.MouseUp(Button: TMouseButton; Shift: TShiftState;
                            X, Y: Integer);
    begin
      inherited MouseUp(Button, Shift, X, Y);
    end;
     
    end.
    Remarque complémentaire : Si je fais l'analogie entre mon composant et le TLabeledEdit, chacun est composé de deux composants. Pour le TLabeledEdit, il s'agit d'un TLabel et d'un TEdit (ou leurs parents proches). Pour mon composant, il s'agit d'un TGraphicControl et d'un TEdit.

    Mais alors que dans l'inspecteur d'objets, pour le TLabeledEdit, je ne vois qu'un composant, pour le mien, je vois deux composants : le cadre et le TEdit. Ce qui me fait dire que mon composant ne dois pas être, dans la forme que je lui ai donnée, un assemblage très cohérent. Partant de là, ça fonctionne, mais cela ne me satisfait pas.

    Cordialement.

    Pierre.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 691
    Points : 13 121
    Points
    13 121
    Par défaut
    Créer un composant n'est pas aussi simple que de poser quelques contrôles sur une fiche.

    Ici le premier problème est que tu dérives TBoutonCoinRond de la mauvaise classe. Pour que ce composant soit un conteneur, il doit être de type TCustomControl. Il pourra ainsi devenir le parent de l'edit (en plus de son propriétaire). Simplement cela corrigera déjà certains problèmes remarqués.

    Après il y a les interdépendances que tu devras gérer toi-même. Par exemple lorsque tu cliqueras sur la bordure, tu voudras que l'edit prenne le focus. Ce sera à toi de lancer un Edit.SetFocus dans OnMouseDown de TEditeurCoinRond. Même chose au design si tu veux déplacer le groupe en cliquant dans l'edit, il faudra notifier le parent qu'un déplacement est demandé.

    Ensuite il y a certaines propriétés de l'edit qui devront être encapsulées au niveau de TEditeurCoinRond. La propriété Text par exemple :
    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
    type
      TEditeurCoinRond = class(TBoutonCoinRond)
      private
        function GetText: TCaption;
        procedure SetText(const Value: TCaption);
      published
        property Text :TCaption read GetText write SetText;
      end;
     
    function TEditeurCoinRond.GetText: TCaption;
    begin
      if Assigned(Editeur) then
        Result := Editeur.Text
      else
        Result := '';
    end;
     
    procedure TEditeurCoinRond.SetText(const Value: TCaption);
    begin
      if Assigned(Editeur) then
        Editeur.Text := Value;
    end;

    Enfin le comportement à la conception ne sera pas forcément le même qu'en exécution (l'application n'est pas lancée hein !). Il sera peut-être nécessaire de conditionner certaines choses en fonction du mode par if csDesigning in ComponentState then.


    En bref tu n'es qu'au début de tes découvertes sur la création de composant, le meilleur reste à venir

  9. #9
    Membre éprouvé
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 022
    Points : 1 049
    Points
    1 049
    Par défaut
    Merci beaucoup Andnotor pour tous ces bons conseils.

    Je viens d'appliquer les deux premiers :

    Changer la classe parent et l'Edit.SetFocus.

    Cordialement.

    Pierre.

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

Discussions similaires

  1. [Lazarus] Problème de création de composant
    Par Gouyon dans le forum Lazarus
    Réponses: 24
    Dernier message: 05/11/2011, 23h25
  2. Réponses: 1
    Dernier message: 29/05/2007, 00h00
  3. [AS2] Problème avec ComboBox lors création d'un composant perso
    Par aldo-tlse dans le forum ActionScript 1 & ActionScript 2
    Réponses: 12
    Dernier message: 24/05/2006, 18h51
  4. Réponses: 3
    Dernier message: 16/05/2006, 16h24
  5. Problème avec la création d'un composant
    Par jeromelef dans le forum Composants VCL
    Réponses: 6
    Dernier message: 01/10/2005, 00h51

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