2009-07-06 7 views
19

J'essaie de créer un bouton transparent en C# (.NET 3.5 SP1) à utiliser dans mon application WinForms. J'ai tout essayé pour que le bouton soit transparent (il devrait montrer l'arrière-plan dégradé sous le bouton) mais ça ne marche pas.Dessin d'un bouton transparent

Voici le code que je utilise:

public class ImageButton : ButtonBase, IButtonControl 
{ 
    public ImageButton() 
    { 
     this.SetStyle(
      ControlStyles.SupportsTransparentBackColor | 
      ControlStyles.OptimizedDoubleBuffer | 
      ControlStyles.AllPaintingInWmPaint | 
      ControlStyles.ResizeRedraw | 
      ControlStyles.UserPaint, true); 
     this.BackColor = Color.Transparent; 
    } 

    protected override void OnPaint(PaintEventArgs pevent) 
    { 
     Graphics g = pevent.Graphics; 
     g.FillRectangle(Brushes.Transparent, this.ClientRectangle); 
     g.DrawRectangle(Pens.Black, this.ClientRectangle); 
    } 


    // rest of class here... 

} 

Le problème est que le bouton semble saisir la mémoire de l'interface utilisateur au hasard de quelque part et se remplissant une mémoire tampon de l'interface utilisateur de Visual Studio (en mode de conception). Au moment de l'exécution, il saisit un tampon zéro et est complètement noir.

Mon but ultime est de peindre une image sur un bouton invisible au lieu du rectangle. Le concept devrait rester le même cependant. Lorsque l'utilisateur survole le bouton, une forme de type bouton est dessinée.

Des idées?

EDIT: Merci tout le monde, ce qui suit a fonctionné pour moi:

public class ImageButton : Control, IButtonControl 
{ 
    public ImageButton() 
    { 
     SetStyle(ControlStyles.SupportsTransparentBackColor, true); 
     SetStyle(ControlStyles.Opaque, true); 
     SetStyle(ControlStyles.ResizeRedraw, true); 
     this.BackColor = Color.Transparent; 

    } 

    protected override void OnPaint(PaintEventArgs pevent) 
    { 
     Graphics g = pevent.Graphics; 
     g.DrawRectangle(Pens.Black, this.ClientRectangle); 
    } 


    protected override void OnPaintBackground(PaintEventArgs pevent) 
    { 
     // don't call the base class 
     //base.OnPaintBackground(pevent); 
    } 


    protected override CreateParams CreateParams 
    { 
     get 
     { 
      const int WS_EX_TRANSPARENT = 0x20; 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= WS_EX_TRANSPARENT; 
      return cp; 
     } 
    } 

    // rest of class here... 
} 
+0

semble être un double de: http://stackoverflow.com/questions/201778/can-i-create-transparent-buttons-in-visual -studio-2005-with-c – Aamir

+0

Ce qui a été suggéré dans ce fil n'a pas fonctionné pour moi. – rein

+0

essayez de peindre avec une nouvelle couleur avec une valeur d'opacité 0 au lieu de Color.Transparent – TheVillageIdiot

Répondre

17

WinForms peut cependant simuler la transparence en utilisant le style de contrôle que vous fournissez - SupportsTransparentBackColor, mais dans ce cas tout ce que fait le contrôle "transparent", il permet de dessiner son arrière-plan parent. ButtonBase utilise des styles de fenêtres qui empêchent le fonctionnement de ce mécanisme. Je vois deux solutions: l'une consiste à dériver votre contrôle de Control (au lieu de ButtonBase), et la seconde est d'utiliser DrawToBitmap de Parent pour obtenir l'arrière-plan sous votre bouton, puis dessiner cette image dans OnPaint.

+0

+1 pour de superbes informations sur @arbiter mais un exemple de code aurait certainement parcouru un long chemin. – TheVillageIdiot

+0

Quelque chose comme ça est ce qu'il avait en tête, mais pas un bouton. (je pense) http://christian-helle.blogspot.com/2008/01/transparent-controls-in-netcf.html – TEEKAY

1

Je ne suis pas sûr ButtonBase soutient la transparence ... avez-vous vérifié cela?

J'ai écrit un certain nombre de contrôles transparents, mais j'ai toujours hérité de Control ou UserControl. Lorsque vous souhaitez bloquer une peinture de contrôle, c'est l'arrière-plan. Vous devez remplacer OnPaintBackground au lieu de OnPaint et ne pas appeler la classe de base.

Remplir un rectangle avec Brushes.Transparent est amusant: vous peignez avec une couleur invisible sur ce qui est déjà là. Ou pour le dire autrement: ça ne fait rien! WinForms (et User32 sous-jacent) ne prend pas en charge la transparence du tout.

10

Dans Winforms, il existe quelques astuces pour permettre à un contrôle dont l'arrière-plan est correctement peint lors de l'utilisation de la transparence. Vous pouvez ajouter ce code au OnPaint ou OnPaintBackground pour obtenir les contrôles que vous avez en arrière-plan étant peint:

if (this.Parent != null) 
{ 
GraphicsContainer cstate = pevent.Graphics.BeginContainer(); 
pevent.Graphics.TranslateTransform(-this.Left, -this.Top); 
Rectangle clip = pevent.ClipRectangle; 
clip.Offset(this.Left, this.Top); 
PaintEventArgs pe = new PaintEventArgs(pevent.Graphics, clip); 

//paint the container's bg 
InvokePaintBackground(this.Parent, pe); 
//paints the container fg 
InvokePaint(this.Parent, pe); 
//restores graphics to its original state 
pevent.Graphics.EndContainer(cstate); 
} 
else 
    base.OnPaintBackground(pevent); // or base.OnPaint(pevent);... 
1

Je sais que cette question est vieux, mais si quelqu'un ne veut pas créer un contrôle pour ce faire Je suis venu avec ce code d'un article différent et l'ai changé une méthode d'extension.

public static void ToTransparent(this System.Windows.Forms.Button Button, 
    System.Drawing.Color TransparentColor) 
{ 
    Bitmap bmp = ((Bitmap)Button.Image); 
    bmp.MakeTransparent(TransparentColor); 
    int x = (Button.Width - bmp.Width)/2; 
    int y = (Button.Height - bmp.Height)/2; 
    Graphics gr = Button.CreateGraphics(); 
    gr.DrawImage(bmp, x, y); 
} 

Et l'appel comme:

buttonUpdate.ToTransparent(Color.Magenta);