Image dans un userControl qui hérite d'un bouton

Résolu
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 - 23 janv. 2012 à 10:32
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 - 5 mars 2012 à 12:34
Bonjour !

Je vais vous exposer un problème dont je pressens que la solution est simple ^^

J'ai créé un userControl qui hérite de la classe Button, afin de créer un bouton personnalisé (dans le but d'intégrer ma Form à une autre interface).
J'avais besoin d'ajouter plusieurs éléments à ce bouton : 2 labels et une image.

J'ai commencé par les labels, tout fonctionne bien ! j'ai repris des idées d'un tutoriel sur la question, pour ce qui est de gérer les clics, le survol avec la souris...

Dès que j'essaie de faire la même chose avec une pictureBox pour afficher une image, rien ne marche ! l'image ne s'affiche jamais... Et j'ai tout essayé avec les propriétés de la pictureBox.

A noter : j'utilise Visual Studio 2010

voici quelques éléments de code :

- Début du code de mon bouton (j'ai mis dans le constructeur le code de ma picture pour débugger pour le moment, et j'ai chargé de méthode pour tenter d'afficher l'image :s) :

namespace WindowsFormsIHMProceduresPalpage
{

    public partial class UserControlBoutonMenu : Button
    {

        //DECLARATION MEMBRES

        private GraphicsPath FondBouton;

        private bool _clicked = false;
        private bool _entered = false;



        //CONSTRUCTEUR

        public UserControlBoutonMenu()
        {
            InitializeComponent();

            //Test PictureBox
            this.pictureBoxImg.SizeMode = PictureBoxSizeMode.AutoSize;
            this.pictureBoxImg.Image = new Bitmap(@"D:\Projet Procédures Palpage\WindowsFormsIHMProceduresPalpage\WindowsFormsIHMProceduresPalpage\bin\Debug\Img\Fraise à grain A_icone.bmp");
            this.pictureBoxImg.Location = new Point(5, 3);
            this.pictureBoxImg.BorderStyle = BorderStyle.Fixed3D;
            this.pictureBoxImg.BackColor = Color.Azure;
            //this.pictureBoxImg.Bounds = new Rectangle(new Point(6, 4), new Size(70, 45));
            this.pictureBoxImg.ClientSize = new Size(70, 45);
            this.pictureBoxImg.CreateControl();
            this.pictureBoxImg.MinimumSize = new Size(60, 40);
            this.pictureBoxImg.Visible = true;
            this.pictureBoxImg.Show();
            //this.pictureBoxImg.Enabled = true;
        }

J'ai déclaré mes 2 labels et ma pictureBox automatiquement dans le designer, en les rajoutant avec Visual Studio.

- J'utilise un override de la méthode OnPaint() du contrôle pour gérer le design de mon bouton perso :

//DECLARATION METHODES

        //Cette méthode est une surcharge de la méthode OnPaint() du bouton standard
        protected override void OnPaint(PaintEventArgs pevent)
        {
            Graphics g = pevent.Graphics;

            Rectangle rect = new Rectangle(0, 0, 85, 61);

            //Ces lignes définissent le fond du bouton (rectangle plein de couleur)
            Brush FondBrush new SolidBrush(Color.FromArgb(236, 233, 216));        //On défini ici la couleur (SolidBrush couleur unique. On peut aussi faire des dégradés ou autre ...)
            FondBouton = new GraphicsPath();                                        //Le graphicPath contient toutes les données graphiques géométrique
            FondBouton.AddLine(0, 0, 85, 0);
            FondBouton.AddLine(85, 61, 85, 61);
            FondBouton.AddLine(85, 61, 0, 61);
            FondBouton.AddLine(0, 61, 0, 0);
            g.FillPath(FondBrush, FondBouton);      //Cette ligne sert à afficher le GraphicPath défini ci-dessus, avec la couleur donnée par le SolidBrush

            //Ces 2 lignes représentent les 2 lignes présentent à l'origine sur les bords haut et gauche du bouton, de couleur plus foncée
            g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(0, 0), new Point(83, 0));
            g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(0, 0), new Point(0, 59));
//... Etcaetera !
}


C'est un peu lourd tout cela, si quelqu'un à une idée... ?
L'utilisation des graphics dans OnPaint peu masquer l'image ??

Merci de votre aide !!

Mad Keyboard

14 réponses

cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
3 mars 2012 à 18:48
Salut

Il me parait plus simple de définir une, ou plusieurs, propriété Images dans ton UserButton et de dessiner les images adéquates.

Dans ta méthode OnPaint, pense à déssiner les images après le remplissage (FillPath(...)) sinon l'image ne sera pas visible.

un petit exemple que j'ai fais il y a longtemps, sans prétention c'était juste un test.
bool _buttonIsDown = false;
protected override void OnMouseUp(MouseEventArgs mevent)
{
_buttonIsDown = false;
base.OnMouseUp(mevent);
}
protected override void OnMouseDown(MouseEventArgs mevent)
{
if (mevent.Button == MouseButtons.Left)
_buttonIsDown = true;

base.OnMouseDown(mevent);
}
protected override void OnPaint(PaintEventArgs pevent)
{
//Dessine l'image de fond, si existante
if (BackgroundImage != null)
pevent.Graphics.DrawImage(BackgroundImage, this.ClientRectangle);
else
{// sinon on rempli le fond
using (SolidBrush backbrush = new SolidBrush(BackColor))
{
pevent.Graphics.FillRectangle(backbrush, pevent.ClipRectangle);
}
}
//Dessin de l'image et du texte
if (!Enabled)
{//disable
if (ButtonImageDisable != null)
pevent.Graphics.DrawImage(ButtonImageDisable, this.ClientRectangle);
}
else
{//Enable
if (_buttonIsDown)
{//bouton enfoncé
if (ButtonImageDown != null)
pevent.Graphics.DrawImage(ButtonImageDown, this.ClientRectangle);
}
else
{//bouton relevé
if (ButtonImageUp != null)
pevent.Graphics.DrawImage(ButtonImageUp, this.ClientRectangle);
}
}
//Reste à dessiner les bords par dessus l'image
//...
using (Brush FondBrush = new SolidBrush(Color.FromArgb(236, 233, 216)))
{
GraphicsPath FondBouton = new GraphicsPath();
FondBouton.AddLine(0, 0, Width-1, 0);
FondBouton.AddLine(Width-1, Height-1, Width-1, Height-1);
FondBouton.AddLine(Width-1, Height-1, 0, Height-1);
FondBouton.AddLine(0, Height-1, 0, 0);
pevent.Graphics.DrawPath(Pens.Black, FondBouton);   
}


//Puis le texte
if (!Enabled)
//Text grisé
pevent.Graphics.DrawString(Text, Font, Brushes.Gray, new PointF(0, 0));
else  //Text de la couleur prévue
using (SolidBrush penbrush = new SolidBrush(ForeColor))
{
pevent.Graphics.DrawString(Text, Font, penbrush, new PointF(0, 0));
}

}
protected override void OnPaintBackground(PaintEventArgs pevent)
{

}

Bob.
C# is amazing, enjoy it!
3
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
23 janv. 2012 à 12:44
Bonjour,

Pourquoi ne pas utiliser la propriété Image (ou Picture) du contrôle Button ?

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, ce lien ou encore celui-ci[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
25 janv. 2012 à 10:35
Parce que je n'avais pas vu que ça existait xD
J'essaie tout de suite...
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
30 janv. 2012 à 10:20
Salut !

Bon, j'ai eu quelques priorités ces derniers temps, j'ai juste eu le temps de voir ça !

Donc j'ai fait simple pour commencer :
Dans le constructeur de mon bouton, j'ai rajouté une définition de l'image :

//CONSTRUCTEUR

public UserControlBoutonMenu()
{
    InitializeComponent();

    this.Image = new Bitmap("Img\\Fraise à grain A_icone.bmp");
}


Dès que je génère tout ça, je retourne dans l'onglet du design de mon Formulaire principale (là où j'utilise les boutons), et tout plante !
Il m'affiche une exception pour chaque bouton que j'avais mis !
=> Avertissement : "La variable 'userControlBoutonMenuF1' n'est pas déclarée ou n'a jamais été assignée." (J'ai 11 boutons, de F1 à F11)

Si ensuite j'enlève la ligne et que je regénère la solution, l'avertissement persiste, il faut que je redémarre Visual studio pour enlever cette erreur.

Ce qui est sur, c'est que quand j'exécute le programme (avec les avertissements, donc), aucune image apparaît sur aucun des 11 boutons ! (La taille de l'image est inférieure à la taille du bouton)

Une idée sur le problème ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
30 janv. 2012 à 10:26
Un nouvel élément :
J'ai émis l'hypothèse dans mon premier post que l'utilisation d'un surcharge de OnPaint pour dessiner l'intérieur du bouton masque l'image : quand je met en commentaire ma surcharge de la fonction OnPaint, Je retrouve le design classique du bouton avec mon image à l'intérieur ! (pour chaque bouton)

C'est donc bien mes graphics qui masquent l'image !!!

Comment remédier à cela ?
0
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
30 janv. 2012 à 20:12
Bonjour,

Comment codes-tu ta surcharge ?

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, ce lien ou encore celui-ci[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
31 janv. 2012 à 12:21
Voici le code complet (ne faites pas attention aux commentaires, destinés à mes collègues !):

 protected override void OnPaint(PaintEventArgs pevent)
        {
            Graphics g = pevent.Graphics;

            Rectangle rect = new Rectangle(0, 0, 85, 61);

            //Ces lignes définissent le fond du bouton (rectangle plein de couleur)
            Brush FondBrush new SolidBrush(Color.FromArgb(236, 233, 216));        //On défini ici la couleur (SolidBrush couleur unique. On peut aussi faire des dégradés ou autre ...)
            FondBouton = new GraphicsPath();                                        //Le graphicPath contient toutes les données graphiques géométrique
            FondBouton.AddLine(0, 0, 85, 0);
            FondBouton.AddLine(85, 61, 85, 61);
            FondBouton.AddLine(85, 61, 0, 61);
            FondBouton.AddLine(0, 61, 0, 0);
            g.FillPath(FondBrush, FondBouton);      //Cette ligne sert à afficher le GraphicPath défini ci-dessus, avec la couleur donnée par le SolidBrush

            //Ces 2 lignes représentent les 2 lignes présentent à l'origine sur les bords haut et gauche du bouton, de couleur plus foncée
            g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(0, 0), new Point(83, 0));
            g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(0, 0), new Point(0, 59));


            //Ces 4 lignes représentent le cadre contenant le numéro de touche fonction
            g.DrawLine(new Pen(Color.Black), new Point(19, 6), new Point(33, 6));
            g.DrawLine(new Pen(Color.Black), new Point(34, 7), new Point(34, 15));
            g.DrawLine(new Pen(Color.Black), new Point(33, 16), new Point(19, 16));
            g.DrawLine(new Pen(Color.Black), new Point(18, 15), new Point(18, 7));

            //Cette ligne sert à peindre l'intérieur du cadre ci-dessus en blanc
            g.DrawLine(new Pen(Color.White, 9), new Point(19, 11), new Point(34, 11));


            //On récupère la valeur de texte du bouton pour l'afficher par le biai du labelF
            this.labelText.Text = this.Text;

            //On calcule la position du label de manière à la centrer dans le bouton
            this.labelText.Location = new Point((this.Size.Width - this.labelText.Size.Width) / 2, 25);



            this.Region = new Region(rect);
            //this.Size = new Size(85, 61);     //On ne donne pas de taille fixe, pour pouvoir l'adapter dans le projet principale (dernier bouton plus court d'un pixel)


            if (_entered == false)
            {
                g.DrawLine(new Pen(Color.FromArgb(236, 233, 216)), new Point(2, 2), new Point(81, 2));
                g.DrawLine(new Pen(Color.FromArgb(236, 233, 216)), new Point(2, 57), new Point(2, 2));
                g.DrawLine(new Pen(Color.FromArgb(236, 233, 216)), new Point(82, 2), new Point(82, 58));
                g.DrawLine(new Pen(Color.FromArgb(236, 233, 216)), new Point(2, 58), new Point(82, 58));
            }
            else
            {
                if (_clicked == false)
                {
                    g.DrawLine(new Pen(Color.White), new Point(2, 2), new Point(81, 2));
                    g.DrawLine(new Pen(Color.White), new Point(2, 57), new Point(2, 2));
                    g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(82, 2), new Point(82, 58));
                    g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(2, 58), new Point(82, 58));
                }
                else
                {
                    g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(2, 2), new Point(81, 2));
                    g.DrawLine(new Pen(Color.FromArgb(172, 168, 153)), new Point(2, 57), new Point(2, 2));
                    g.DrawLine(new Pen(Color.White), new Point(82, 2), new Point(82, 58));
                    g.DrawLine(new Pen(Color.White), new Point(2, 58), new Point(82, 58));
                }
            }

            FondBrush.Dispose();
        }


Note : les membres _clicked et _entered sont définis dans des fonctions réagissant au survole et au clic sur le bouton ou sur les éléments présents sur le bouton (2 labels). Ils servent à adapter l'affichage du bouton selon l'interaction avec l'utilisateur.

Merci de ton aide !
0
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
31 janv. 2012 à 12:36
Bonjour,

Ce n'est pas une surcharge, tu remplaces la méthode de la classe mère.
Au début ou à la fin :
base.OnPaint(pevent)

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, ce lien ou encore celui-ci[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
10 févr. 2012 à 10:34
Bonjour !

Je reviens tard, je travail moins en ce moment ^^
En effet, c'était un override (je sais pas pourquoi j'ai dit surcharge, c'est une erreur !).

Cependant, c'est bien le but visé (je rappelle, j'ai pris ce code d'un exemple d'un forum, mais j'ai cherché à comprendre au mieux) : il faut en effet annuler le dessin d'origine du bouton pour le remplacer par le notre ! Pour cela, c'était le plus simple (je suppose ? Je connais rien d'autre en tout cas !) pour le faire.

Résultat : si je rajoute "base.OnPaint(pevent)", je retrouve en effet mon image ! Mais je retrouve aussi le design du bouton d'origine, et je perds tout l'intérêt de mon "OnPaint" perso !

Est-ce vraiment possible d'afficher une image et de modifier le dessin du bouton ???
0
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
3 mars 2012 à 15:04
Bonjour,

Peut être en héritant d'une PictureBox et en redessinant celle-ci à chaque modification.

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, ce lien ou encore celui-ci[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
3 mars 2012 à 18:51
J'ai oublié la déclaration des images

[DefaultValue("")]
[Localizable(true)]
public virtual Image ButtonImageUp { get; set; }
[DefaultValue("")]
[Localizable(true)]
public virtual Image ButtonImageDown { get; set; }
[DefaultValue("")]
[Localizable(true)]
public virtual Image ButtonImageDisable { get; set; }


Bob.
C# is amazing, enjoy it!
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
5 mars 2012 à 10:22
Yes, merci à vous !!
Je regarde ça dès que j'ai un moment et je vous tiens au jus...
Bonne journée
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
5 mars 2012 à 10:35
Euu, juste une petite précision Robert sur ton dernier post, j'ai pas bien compris la déclaration :s
Je n'ai jamais utilisé le mot clé virtuel, mais si j'ai bien compris, il sert a déclarer par la suite des méthodes du même nom avec les mots clé new ou override pour ajouter ou remplacer la méthode ?

la ou je bloque vraiment, c'est sur les 2 lignes :
[DefaultValue("")]
[Localizable(true)]

Est-ce que tu pourrais m'expliquer à quoi elles servent ?

Merci !
0
madkeyboard Messages postés 100 Date d'inscription mercredi 27 avril 2011 Statut Membre Dernière intervention 21 décembre 2012 1
5 mars 2012 à 12:34
Bon, au final, beaucoup de messages pour pas grand chose : C'est tout bon !!!

En effet, il fallait que je fasse un drawImage pour afficher mon image... Car d'origine, c'était fait dans le base.OnPaint !
J'ai rajouté la commande (avec le même test que toi Robert, si l'image existe) après la peinture du fond du bouton, et tout fonctionne nickel !
Pour le coup, pas besoin de déclarer l'image, c'est l'image de base du button, que je modifie à chaque affichage (avec un new Bitmap(..))

Merci à vous 2 pour avoir pris du temps pour mon cas !

Ciao,

Mad Keyboard
0
Rejoignez-nous