2009-07-06 1 views
19

Sto provando a creare un pulsante trasparente in C# (.NET 3.5 SP1) da utilizzare nella mia applicazione WinForms. Ho provato di tutto per rendere il pulsante trasparente (dovrebbe mostrare lo sfondo sfumato sotto il pulsante) ma non funziona.Disegno di un pulsante trasparente

Ecco il codice che sto utilizzando:

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... 

} 

Il problema è che il pulsante sembra afferrare la memoria UI caso da qualche parte e si riempire con un po 'di buffer dall'interfaccia utente di Visual Studio (quando è in modalità di progettazione). In fase di esecuzione sta acquisendo un po 'di buffer zero ed è completamente nero.

Il mio obiettivo finale è dipingere un'immagine su un pulsante invisibile anziché sul rettangolo. Il concetto dovrebbe rimanere lo stesso comunque. Quando l'utente passa sopra il pulsante, viene disegnata una forma di tipo pulsante.

Qualche idea?

EDIT: Grazie a tutti, i seguenti ha lavorato per me:

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

sembra essere un duplicato di: http://stackoverflow.com/questions/201778/can-i-create-transparent-buttons-in-visual -studio-2005-with-c – Aamir

+0

Ciò che è stato suggerito in quella discussione non ha funzionato per me. – rein

+0

prova a dipingere con un nuovo colore con valore di opacità 0 invece di Color.Transparent – TheVillageIdiot

risposta

17

WinForms (e Utente32 sottostante) non supporta affatto la trasparenza. Tuttavia, WinForms può simulare la trasparenza usando lo stile di controllo che si fornisce - SupportsTransparentBackColor, ma in questo caso tutto ciò che il controllo "trasparente" fa, consente al genitore di disegnare lo sfondo.

ButtonBase utilizza alcuni stili di Windows che impediscono il funzionamento di questo meccanismo. Vedo due soluzioni: una è quella di derivare il controllo da Control (anziché da ButtonBase), e la seconda è usare Parent DrawToBitmap per ottenere lo sfondo sotto il tuo pulsante, e quindi disegnare questa immagine in OnPaint.

+0

+1 per ottime informazioni @arbiter ma un esempio di codice sarebbe sicuramente andato molto più lontano. – TheVillageIdiot

+0

Qualcosa del genere era quello che aveva in mente, ma piuttosto che l'etichetta. (penso) http://christian-helle.blogspot.com/2008/01/transparent-controls-in-netcf.html – TEEKAY

1

Non sono sicuro ButtonBase supporta la trasparenza ... hai controllato che fuori?

Ho scritto un numero di controlli trasparenti, ma ho sempre ereditato da Control o UserControl.

Quando si desidera bloccare un control painting è di base. È necessario eseguire l'override di OnPaintBackground anziché OnPaint e non chiamare la classe base.

Riempire un rettangolo con Brushes.Transparent è divertente però - stai dipingendo con un colore invisibile su ciò che è lì. O per dirla in altro modo: non fa nulla!

10

In winforms ci sono alcuni accorgimenti per consentire a un controllo di avere lo sfondo correttamente dipinto quando si usa la trasparenza. È possibile aggiungere questo codice al OnPaint o OnPaintBackground per ottenere i controlli che avete nel fondo da verniciare:

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

So che questa domanda è vecchia, ma se qualcuno non vuole creare un controllo per fare questo Ho trovato questo codice da un altro articolo e l'ho modificato come metodo di estensione.

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); 
} 

E la chiamata come:

buttonUpdate.ToTransparent(Color.Magenta);