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

Windows Forms Discussion :

PictureBox, des questions, Galère Galère ^^


Sujet :

Windows Forms

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Points : 5
    Points
    5
    Par défaut PictureBox, des questions, Galère Galère ^^
    Salut à tous !

    Je suis entrain de faire une petite application en DotNet (winform). Le but est simple en fait : Créer un petit schéma.

    Je m'explique, j'ai une petite bibliothèque avec quelques images (des rectangles, des ronds, des fleches) et je peux les copier sur ma fenêtre principale. Clairement ce que je fais c'est que je crée dynamiquement des PictureBox dans ma fenêtre et je peux les bouger comme je veux.

    Par contre j'ai 3 petites questions qui me posent problème.

    1 - Comment puis-je gérer l'ordre d'affichage des PictureBox (le plan, l'axe Z, ...) cad faire en sorte que la pictureBox 1 passe au dessus de la 2 et vice-versa par exemple.

    2 - Comment gérer la transparence d'une PictureBox lorsqu'elle passe au dessus d'une autre ? (actuellement si je passe un pictureBox contenant un PNG avec une zone de transparence au dessus d'une autre, la zone de transparence n'est pas invisible mais elle a la couleur du fond.

    3 - Si je veux faire une rotation de ma pictureBox de 25degrès je sais faire une rotation d'une image mais pas de ma PictureBox, donc mon image est tournée de 25degrès dans une pictureBox qui a toujours la même taille.

    Si vous avez certaines réponses à mes questions ça me serait d'une grande aide en tout cas.

    Ps : peut être que l'utilisation des PictureBox n'est pas adaptée dans mon cas, mais je ne connais rien d'autre qui me permette de déplacer des formes sur mon écran et dans n'importe quel ordre.

    Merci.
    Greg.

  2. #2
    Membre habitué Avatar de swif79
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2009
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2009
    Messages : 79
    Points : 169
    Points
    169
    Par défaut
    Bonsoir,
    j'aurai une réponse pour les deux première questions

    Question 1:
    Il faut modifier le childIndex de la collection de control de ta form, exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    this.Controls.SetChildIndex(toncontrol, 10);
    Question 2:
    La je n'ai pas trouver comment faire à l'aide d'une pictureBox, dès qu'elle se trouve au-dessus d'une autre, la transparence ne joue qu'avec le fond de la form.
    Mais tu peux faire une petit control perso pour :
    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
     
    public class TransparentControl : Control
        {
            private readonly Timer refresher;
            private Image _image;
     
            public TransparentControl(Size size)
            {
                this.Size = size;
                SetStyle(ControlStyles.SupportsTransparentBackColor, true);
                BackColor = Color.Transparent;
                refresher = new Timer();
                refresher.Tick += TimerOnTick;
                refresher.Interval = 10;
                refresher.Enabled = true;
                refresher.Start();
            }
     
            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x20;
                    return cp;
                }
            }
     
            protected override void OnMove(EventArgs e)
            {
                RecreateHandle();
            }
     
     
            protected override void OnPaint(PaintEventArgs e)
            {
                if (_image != null)
                    e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));     
            }
     
            protected override void OnPaintBackground(PaintEventArgs e)
            {
     
            }
     
            public void Redraw()
            {
                RecreateHandle();
            }
     
            private void TimerOnTick(object source, EventArgs e)
            {
                RecreateHandle();
                refresher.Stop();
            }
     
            public Image Image
            {
                get
                {
                    return _image;
                }
                set
                {
                    _image = value;
                    RecreateHandle();
                }
            }
        }

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Merci beaucoup pour tes réponses Swif79 !
    Excuse moi de ne pas t'avoir répondu plus tôt je n'avais pas encore eu le temps de regarder les message à tête reposée.

    Pour la question n°1 je viens d'essayer et c'est nikel.

    Pour ce qui est de la seconde je vais tester ça tout de suite, on va voir

    PS : je suis plutôt novice en ce qui concerne DotNet, surtout en ce qui concerne l'interfacage.

    Merci

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Points : 5
    Points
    5
    Par défaut

    Mais c'est géant ça !!!
    ça marche !
    Merci

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Mouarf grosse galère, je dois avouer que j'ai du mal sur ce coup je ne comprends pas.

    Normalement avec un setChildIndex, plus le nombre est bas et plus le control est haut sur l'axe Z de l'affichage (c'est ce qui se passe avec les PictureBox par exemple)

    Et bien là avec la classe de notre nouveau controller c'est totalement l'inverse qui se passe en affichage.

    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
     
    // TEST AVEC 4 FORMESCHEMA
                FormeSchema FormeNoir;
                FormeSchema FormeVert;
                FormeSchema FormeViolet;
                FormeSchema FormeRouge;
     
                FormeNoir = new FormeSchema(Globales.ch_RepertoireImages + "Img1.png", new Point(10, 60), "noir", this);
                this.Controls.Add(FormeNoir);
                FormeVert = new FormeSchema(Globales.ch_RepertoireImages + "Img2.png", new Point(30, 70), "vert", this);
                this.Controls.Add(FormeVert);
                FormeViolet = new FormeSchema(Globales.ch_RepertoireImages + "Img3.png", new Point(15, 65), "violet", this);
                this.Controls.Add(FormeViolet);
                FormeRouge = new FormeSchema(Globales.ch_RepertoireImages + "Img4.png", new Point(30, 60), "rouge", this);
                this.Controls.Add(FormeRouge);
     
                this.Controls.SetChildIndex(FormeNoir, 4); 
                this.Controls.SetChildIndex(FormeVert, 1);
                this.Controls.SetChildIndex(FormeViolet, 3);
                this.Controls.SetChildIndex(FormeRouge, 2);
     
                // Normalement affichage : Vert/Rouge/Violet/Noir
    Normalement avec ce code je devrais avoir cet affichage : Vert/Rouge/Violet/Noir

    Cependant ce que j'ai, c'est exactement l'inverse :
    Noir/Violet/Rouge/Vert

    Est-ce qqn comprend pourquoi ?
    Merci.
    Greg

  6. #6
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Salut,
    Je ne comprend pas pourquoi passer par des picturebox. C'est inutilement lourd et limité.
    Pourquoi ne pas dessiner directement les images ? En les dessinant "manuellement", non seulement tu aurais un contrôle complet de l'ordre d'affichage, mais en plus tu pourrais faire les rotations/zoom/effets que tu veux, sans et la transparence serait gérée toute seule sans rien faire.

    Et pour répondre a ta question, SetChildIndex donne l'ordre dans la collection des contrôles, donc le parent va d'abord afficher le premier, puis le second, etc...
    Donc non, au contraire, plus le nombre est faible et plus il sera loin (un nombre plus élevé est peint au dessus d'un nombre plus faible)

    PS: Pas compris l'interet d'un timer ici, ni pourquoi recréer les handles.

  7. #7
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Je suis entièrement d'accord avec Ctxnop, mieux vaudrait faire un contrôle personnalisé et se débarrasser des PictureBox.

    Concrètement, que t'apportes le fait d'utiliser des PictureBox ?
    * Dessin automatique des images : c'est tellement simple à faire à la main de toute façon...
    * Le hittesting : rien de compliqué à faire à la main encore, il te suffit de maintenir à jour une liste de rectangles représentant chaque image pour détecter quelle figure a été cliquée. Cela te donnera aussi une plus grande liberté si tu souhaites évoluer vers quelque chose de plus fin (ignorer les pixels transparents, etc).

    Et à côté de ça tu vas éviter un tas de problèmes qui apparaîtront avec ta solution actuelle : flickering garanti, ajout de contrôles supplémentaires pour dessiner les ancres de la sélection, et tout ce à quoi je ne pense pas encore. Tu t'économises bien peu de travail mais tu te crées beaucoup de problèmes et tu prends des risques.

    Enfin, tu peux aussi regarder du côté de l'hébergement de contrôles WPF si tu veux faire quelque chose de très sophistiqué, tu aurais un support tout fait pour un hittesting fin et les ancres de sélection par exemple. Gaffe quand même à vérifier les limites imposées lors de l'hébergement de WPF dans Winforms, ça pourrait t’empêcher d'utiliser certains fonctionnalités bien pratiques.

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    En fait je n'utilise pas les PictureBox mais bel et bien un controle perso.
    Ce que j'utilise en fait c'est la classe TransparentControl donnée par swif79 dans le poste du dessus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public class TransparentControl : Control
    Et d'ailleurs j'ai trouvé ce qui me cause des soucis d'affichage dans cette classe, c'est ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x20;
                    return cp;
                }
            }
    En fait lorsque je laisse "cp.ExStyle |= 0x20;" la transparence est bien gérée sur les images cependant l'ordre d'affichage est inversé.
    Lorsque je retire cette ligne, l'ordre d'affichage est bon mais il n'y a plus de transparence ...

    Voilà mon gros soucis en fait ! ^^

    Par contre je ne pensais pas que l'on pouvait dessiner des images directement comme je crois le comprendre dans le post de ctxnop, je pensais qu'il fallait absolument un conteneur comme un controle perso ou une picturebox.

    Merci de vos réponses en tout cas, et si vous avez une idée du problème du CreateParams n'hésitez pas

  9. #9
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Pour simplifier, oui, il faut un contrôle perso pour y dessiner, mais ce que moi et DonQuiche t'expliquons, c'est que tu n'es absolument pas obligé d'avoir un contrôle PAR IMAGE.
    Tu met un seul et unique contrôle personnalisé, celui-ci va avoir une propriété, disons ImageList pour simplifier, dans laquelle tu met tes images. Tu crée également une propriété qui expose une collection d'instance.
    Et tu surcharge la méthode OnPaint de ce contrôle.
    Et voila, tu as un contrôle "Surface de dessin" dans lequel tu peux dessiner ce que tu veux, dans l'ordre que tu veux, avec les transformations et effets que tu veux, et une transparence gérée automatiquement.

  10. #10
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Bon, je me suis amusé à faire un début, je dis bien un début de classe pour faire ca.
    L'utilisation est la suivante :
    1 - Tu pose ce contrôle où tu veux
    2 - Tu ajoute une ImageList que tu affecte à la propriété "Images" du contrôle.
    3 - Tu met tes images dans l'ImageList, la propriété "Name" des image sert à les retrouver.
    4 - Tu utilises la méthode AddShape pour ajouter des formes à dessiner.

    Code csharp : 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
     
    	/// <summary>
    	/// Surface de dessin
    	/// </summary>
    	public class DrawingSurface
    		: UserControl
    	{
    		#region Type nesté
    		class Shape
    		{
    			public string Name { get; set; }
    			public string Image { get; set; }
    			public Point Position { get; set; }
    		}
    		#endregion
     
    		#region Variables membres
    		private System.ComponentModel.IContainer components = null; // Utilisée par le Designer de VS
     
    		private List<Shape> _Shapes;
    		#endregion
     
    		/// <summary>
    		/// Liste des images.
    		/// </summary>
    		public ImageList Images { get; set; }
     
    		/// <summary>
    		/// Constructeur
    		/// </summary>
    		public DrawingSurface()
    		{
    			InitializeComponent();
    			// Instanciation des collections
    			_Shapes = new List<Shape>();
    		}
     
    		/// <summary>
    		/// Ajoute une forme.
    		/// </summary>
    		/// <param name="Name">Nom de la forme.</param>
    		/// <param name="Image">Image utilisée par la forme.</param>
    		/// <param name="Position">Position de la forme.</param>
    		public void AddShape(string Name, string Image, Point Position)
    		{
    			Shape s = new Shape();
    			s.Name = Name;
    			s.Image = Image;
    			s.Position = Position;
    			_Shapes.Add(s);
    		}
     
    		/// <summary> 
    		/// Nettoyage des ressources utilisées.
    		/// </summary>
    		/// <param name="disposing">true si les ressources managées doivent être supprimées*; sinon, false.</param>
    		protected override void Dispose(bool disposing)
    		{
    			if (disposing && (components != null))
    			{
    				components.Dispose();
    			}
    			base.Dispose(disposing);
    		}
     
    		/// <summary> 
    		/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas 
    		/// le contenu de cette méthode avec l'éditeur de code.
    		/// </summary>
    		private void InitializeComponent()
    		{
    			this.SuspendLayout();
    			// 
    			// DrawingSurface
    			// 
    			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    			this.BackColor = System.Drawing.Color.White;
    			this.Name = "DrawingSurface";
    			this.Size = new System.Drawing.Size(777, 589);
    			this.ResumeLayout(false);
     
    		}
     
    		/// <summary>
    		/// Dessin du contrôle.
    		/// </summary>
    		/// <param name="e"></param>
    		protected override void OnPaint(PaintEventArgs e)
    		{
    			base.OnPaint(e);
    			if (Images != null && _Shapes != null)
    			{
    				foreach (Shape s in _Shapes)
    				{
    					Image img = Images.Images.ContainsKey(s.Image) ? img = Images.Images[s.Image] : null;
    					if (img != null)
    					{
    						e.Graphics.DrawImage(img, s.Position);
    					}
    				}
    			}
    		}
    	}

    Il reste plusieurs choses à faire :
    - Permettre de supprimer des Shape
    - Permettre de déplacer une Shape
    - Permettre d'influer sur l'ordre de dessin des Shape
    - Permettre d'appliquer une transformation/effet

    Je te laisses faire tout ca, l'exemple est suffisant comme départ.
    Petites pistes :
    - Utiliser un Dictionary<string, Image> plutot q'un ImageList.
    - Sortir le type Shape de la classe.
    - Rendre le type Shape surchargeable pour gérer différentes formes.
    - Exposer un Dictionary<string, Shape> dans lequel on peut ajouter/supprrimer les formes directement.
    - Ajouter une propriété Z (ou un truc du genre) à la forme et effectuer un tri de la liste de shape en fonction de cette propriété avant affichage.

    Voila, avec ca tu devrais pouvoir t'en sortir.

  11. #11
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut Rotate picturebox,gdi+,Matrix.RotateA
    bonjour greg34000

    J' ai suivi les peripities de la rotation du controle picturebox et en confirmation de ce qu'as Don Quiche et Ctxnop,tu as fait une mauvaise strategie au depart parce que la rotation des controles n'est pas prevu au menu de l'Api WinForms.

    Voici dans le sillage de ce qu'as suggere Ctxnop un "usercontrol" fin pret sorti tout arme comme Athena de la cuisse de Jupiter (je ne me rappelle plus ,vu mon age ,mes antiquites grecques) qui fera peut etre ton bonheur.
    -tourne les bmp(lues partir des images),les deplaces ,les scales,en plus des graphiques (rectangles ellipses et autres...) & du texte.
    -zoomable à la roulette
    -en gere autant qu'on veut (integre une collection- list of).
    -les imprimes
    -& pour finir les seriliazes (un peu comme la blague radiophique de fernand raynaud sur la moisseuse canadienne qui moissonne,meule,laboure et au final ferme le cycle et seme ).

    Il comporte en plus comme dit par Ctxnop une serie de classes graphiques encapsules d'accompagnement facilement extensibles.
    Ton probleme de z-index d'affichage sera simplement l'ordre dans la liste des objets graphiques.
    Il illustre surtout la gdi+ avec les matrices de transformations homogenes(translatetransform,rotatetransform,scaletransform et les containers graphiques imbriques)..
    voici le lien msdn de l'article et du codesource:

    http://www.google.fr/url?sa=t&source...QJGD8JEdyVB7QQ

    bon code....

Discussions similaires

  1. Connection réseau et Linux des questions
    Par kacedda dans le forum Réseau
    Réponses: 4
    Dernier message: 05/11/2005, 23h29
  2. des question datawarehouse??
    Par raslain dans le forum Alimentation
    Réponses: 1
    Dernier message: 09/10/2005, 15h44
  3. Poser des question pertinentes...
    Par lilibrik dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 1
    Dernier message: 21/06/2005, 18h12
  4. Des questions sur suse linux !
    Par barucca dans le forum SUSE
    Réponses: 3
    Dernier message: 07/04/2004, 11h35
  5. [Vim] et C++ ; Réponses à des questions de Richard
    Par Luc Hermitte dans le forum Autres éditeurs
    Réponses: 13
    Dernier message: 19/01/2004, 23h32

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