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

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

Composants VCL Delphi Discussion :

Lier/Coller des TPanels


Sujet :

Composants VCL Delphi

  1. #1
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut Lier/Coller des TPanels
    Bonjour,

    Dans mon application, je cherche à connecter des objets (panels ou shapes dans l'idéal) entre eux.

    Dans une TForm, l'utilisateur dessine des schémas de machines complexes à l'aide de formes simples (cercle, rectangle...). L'utilisateur choisit sa forme en cliquant sur le bouton puis dessine la forme sur le canvas de la TForm. Je souhaite que les formes soient connectées entre elles et j'aimerais savoir comment le rendre visible graphiquement. Je détaille: j'ai 1 cercle et 1 rectangle qui ne sont pas connectés, je peux les déplacer indépendamment.
    --> Mon but est de les connecter visuellement: avec la souris, je rapproche le cercle du rectangle et hop le cercle et le rectangle se collent pour former une forme. Cette alors cette forme qui se déplace. Évidemment je dois pouvoir délier le cercle du rectangle.

    Je ne sais pas du tout par quel bout prendre ce bazar. Je ne sais même pas comment nommer cette fonction de "coller" 2 composants (j'ai regardé "dock" mais c'est pour les TForm). Est-ce que des propriétés/événements du TPanel, TShape, TadvPanel (TMS) permettent de faire cela ?


    Mes outils de dev:
    - XE5
    - VCL Delphi
    - VCL TMS Component Pack.

    Merci pour vos conseils et bonne fin d'année à vous

    LefjuCabro

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Snap to - aimanter

    Comment coder cette fonctionnalité?

    Je commencerais par faire un voisinage qui va dépendre de la forme (*) et tester si un objet est dans ce voisinage.
    Si un objet est dans un voisinage on le colle (**).

    * -> par exemple: un cercle de rayon R, le voisinage serait compris entre une distance de R et (R + a)

    ** -> Il faut voir ce qui est le plus joli. Peut-être le coller en cherchant la plus petite distance entre les 2 formes

  3. #3
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    Bonjour Foetus,

    Merci pour ta réponse.

    Je comprends comment coder cette fonctionnalité mais je bloque.

    Dans mon exemple, j'ai posé sur une forme 3 TPanel, je souhaite les déplacer à la souris et les aimanter lorsqu'ils sont proches. Pour déplacer les Panels, j'utilise le code ci-dessous dans le MouseDown des TPanels:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    const
      SC_DragMove = $F012 ;
    begin
      ReleaseCapture ;
      TPanel(Sender).Perform (WM_SysCommand, SC_DragMove, 0) ;
    end;
    Dans l'évènement MouseUp des TPanels, je code la fonction qui teste et aimante si nécessaire. Le problème est que l'évènement MouseUp ne se lance pas... Quelle erreur je fais ? Comment déplacer des TPanels (sachant que ces Panels contiendront ensuite des TImage) autrement ?

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Tu confonds les évènements :-)

    L'évènement OnMouseUp est appelé lorsque tu relaches le bouton de la souris.

    http://docwiki.embarcadero.com/Libra...ol.OnMouseMove

    C'est l'évènement OnMouseMove qui permet de faire des actions lorsqu'on déplace la souris.

    OnMouseDown -> OnMouseMove -> OnMouseUp

    D'ailleurs cela serait mieux de tester quel bouton de la souris est appuyé et éventuellement si aucune touche est appuyée.

  5. #5
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    J'ai placé mon code de déplacement dans le MouseDown puis sur le MouseMove (suite à tes conseils) mais j'ai toujours le même problème qui est que l'évènement MouseUp ne s'exécute pas.

    Mon évènement pour déplacer le TPanel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.Panel1MouseMove(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    const
      SC_DragMove = $F012 ;
    begin
      ReleaseCapture ;
      TPanel(Sender).Perform (WM_SysCommand, SC_DragMove, 0) ;
    end;
    Si je clique sur le Panel sans le déplacer alors l'évènement MouseUp s'exécute. C'est un peu dommage car c'est sur le MouseUp que je veux tester si je dois aimanter...

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par lefju cabro Voir le message
    C'est un peu dommage car c'est sur le MouseUp que je veux tester si je dois aimanter...
    Dans ce cas, tu n'as qu'à faire un bouton "Tout aimanter"

  7. #7
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    Dans ce cas, tu n'as qu'à faire un bouton "Tout aimanter"
    Je ne peux pas faire un bouton "Tout aimanter" car, par exemple, sur 3 éléments je ne veux qu'en aimanter 2, le troisième restant malheureux et seul.

    C'est pour cela que je dois tester quel élément peut être aimanté à un autre puis l'aimanter. Je pensais tester cela dans le OnMouseUp.

  8. #8
    Rédacteur/Modérateur

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

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

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

    est-ce que le dragging et ses fonctions ne serait pas mieux pour faire ce truc ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Dans ce cas, c'est plus complexe : il faut pouvoir sélectionner les formes avant de cliquer sur le bouton. Par exemple
    • Soit avoir la liste des formes avec cases à cocher
    • Soit implémenter clic gauche ou Ctrl + clic gauche. Et changer la couleur du contour pour voir les formes sélectionnées.


    Et ainsi cela permettrait d'éviter d'aimanter tes formes 1 par 1.

  10. #10
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    est-ce que le dragging et ses fonctions ne serait pas mieux pour faire ce truc ?
    Bonjour Sergio Master,
    Merci pour ton message.
    J'avais étudié cette possibilité mais ça me paraissait, comme Foetus, un peu plus compliqué. En plus cette méthode ne serait pas assez conviviale pour l’utilisateur. La méthode initiale pourrait suffire car le user n’aimantera pas plus de 3 formes (c'est une spec de leurs métiers).

    Avez-vous une idée pour que l'évènement OnMouseUp s'exécute après le déplacement d'un objet ?
    Je déplace mes panels avec ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.Panel1MouseMove(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    const
      SC_DragMove = $F012 ;
    begin
      ReleaseCapture ;
      TPanel(Sender).Perform (WM_SysCommand, SC_DragMove, 0) ;
    end;
    Peux-être que je n'utilise pas le bon code pour déplacer le panel.

  11. #11
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 952
    Points
    40 952
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    est-ce que le dragging et ses fonctions ne serait pas mieux pour faire ce truc ?
    pour me détendre, j'ai fait un essai rapide avec le drag and drop
    sur ma forme 3 shapes , chacune avec la propriété dragmode=dmAutomatic

    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
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
     
    type
      TForm8 = class(TForm)
        Shape1: TShape;
        Shape2: TShape;
        Shape3: TShape;
        procedure FormDragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
        procedure FormDragDrop(Sender, Source: TObject; X, Y: Integer);
        procedure ShapesDragOver(Sender, Source: TObject; X, Y: Integer;
          State: TDragState; var Accept: Boolean);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form8: TForm8;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm8.FormDragDrop(Sender, Source: TObject; X, Y: Integer);
    begin
    TShape(Source).Brush.Color:=ClWhite;
    TShape(Source).pen.Style:=psSolid;
    TShape(Source).Top:=Y;
    TShape(Source).Left:=X;
    end;
     
    procedure TForm8.FormDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    begin
    Accept:=true;
    // déplacement de l'objet
    TShape(Source).Top:=Y;  
    TShape(Source).Left:=X;
    end;
     
    procedure TForm8.ShapesStartDrag(Sender: TObject; var DragObject: TDragObject);
    begin
    TShape(Sender).Brush.Color:=clRed;
    TShape(Sender).pen.Style:=psDot;
    end;
     
    procedure TForm8.ShapesDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    begin
    Accept:=Sender<>Source;
    end;
    "l'aimantage" que je n'ai pas codé pourrait se faire/calculer soit dans le FormDragDrop (pour l'instant je fait juste le déplacement)
    soit dans un DragDrop sur une shape (ce qui, dans mon code est refusé)

    Avantage de cette solution pas d'évents sur la souris

    [Edit] amélioration du code pour modifier couleur et dessin en cours de déplacement , le seul truc qui me gêne encore c'est le drop sur une shape existante
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Je vois 2 raisons:
    • Soit ton code est trop spécifique et le refaire en codant en manuel
    • Soit tu relâches le bouton de ta souris sur un ui qui prend l'évènement pour lui. Ou alors, c'est ta fenêtre parente qui ne transmet pas l'évènement.

  13. #13
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    Merci pour votre aide.

    Je vais creuser les 2 solutions et voir laquelle me convient le mieux.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    Citation Envoyé par lefju cabro Voir le message
    Le problème est que l'évènement MouseUp ne se lance pas... Quelle erreur je fais ?
    En appelant ReleaseCapture, les messages souris ne sont plus envoyés à ce composant et tant que le bouton reste pressé, aucun autre ne sera sélectionné. Pourquoi ne pas simplement passer par MouseMove ?

    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
    var
      Pt :TPoint;
     
    procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      Pt := Mouse.CursorPos;
    end;
     
    procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    begin
      if ssLeft in Shift then
        with TControl(Sender) do
        begin
          Left := Left +Mouse.CursorPos.X -Pt.X;
          Top  := Top  +Mouse.CursorPos.Y -Pt.Y;
     
          Pt := Mouse.CursorPos;
        end;
    end;
    EDIT:
    Sinon ce que tu peux imaginer est de générer toi-même le up puisque dès que le bouton est relâché, le panel recapture à nouveau la souris (mais c'est pour le moins pervers) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ReleaseCapture;
    TPanel(Sender).Perform(WM_SysCommand, SC_DragMove, 0);
    Mouse_Event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

  15. #15
    Membre régulier
    Développeur informatique
    Inscrit en
    Décembre 2010
    Messages
    228
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 228
    Points : 113
    Points
    113
    Par défaut
    En appelant ReleaseCapture, les messages souris ne sont plus envoyés à ce composant et tant que le bouton reste pressé, aucun autre ne sera sélectionné
    Bonjour Andnotor, merci pour l'explication du ReleaseCapture.

    Ton code avec le TPoint est efficace.

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

Discussions similaires

  1. Coller des liens horizontalement
    Par Gary dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 03/03/2006, 09h27
  2. Réponses: 5
    Dernier message: 14/02/2006, 14h32
  3. [datagrid]lier avec des données
    Par Alex35 dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 11/12/2005, 10h10
  4. Transparence non désirée des TPanel
    Par Manopower dans le forum Composants VCL
    Réponses: 3
    Dernier message: 07/11/2005, 09h25
  5. Améliorations du "Copier / Coller" des XMLInstruct
    Par mchicoix dans le forum XMLRAD
    Réponses: 3
    Dernier message: 29/03/2005, 09h25

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