2009-07-06 11 views
19

Próbuję utworzyć przezroczysty przycisk w języku C# (.NET 3.5 SP1) do użycia w mojej aplikacji WinForm. Próbowałem wszystkiego, aby przycisk był przezroczysty (powinien pokazać gradient pod przyciskiem), ale po prostu nie działa.Rysowanie przezroczystego przycisku

Oto kod używam:

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

} 

Problem polega na tym, że przycisk wydaje się chwytając losowego pamięci UI z gdzieś i napełniania się z pewnym buforem z Visual Studio UI (w trybie projektowania). W czasie wykonywania chwyta bufor zerowy i jest całkowicie czarny.

Moim ostatecznym celem jest namalowanie obrazu na niewidocznym przycisku zamiast prostokąta. Koncepcja powinna pozostać taka sama. Kiedy użytkownik unosi się nad przyciskiem, rysowany jest kształt przycisku.

Wszelkie pomysły?

EDIT: Dzięki everybody, następujące pracował dla mnie:

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

spojrzenia być duplikat: http://stackoverflow.com/questions/201778/can-i-create-transparent-buttons-in-visual -studio-2005-with-c – Aamir

+0

Co zostało zasugerowane w tym wątku, nie działa dla mnie. – rein

+0

spróbuj malować z nowym kolorem z wartością 0 nieprzezroczystości zamiast Koloru. Przezroczysty – TheVillageIdiot

Odpowiedz

17

WinForms (i leżąca u podstaw User32) w ogóle nie obsługuje przezroczystości. WinForm może jednak symulować przezroczystość za pomocą stylu sterowania, który podasz - SupportsTransparentBackColor, ale w tym przypadku wszystko, co robi "przezroczysty" kontrolek, pozwala na rysowanie jego tła.

ButtonBase wykorzystuje niektóre style okien, które uniemożliwiają działanie tego mechanizmu. Widzę dwa rozwiązania: jeden polega na wyprowadzeniu kontroli z Control (zamiast ButtonBase), a drugi na użyciu DrawToBitmap Parent, aby uzyskać tło pod przyciskiem, a następnie narysuj ten obraz w OnPaint.

+0

+1 za wspaniałą informację @arbiter, ale niektóre przykłady kodu z pewnością znacznie się rozszerzyły. – TheVillageIdiot

+0

Coś takiego miało na myśli, ale przycisk zamiast etykiety. (myślę) http://christian-helle.blogspot.com/2008/01/transparent-controls-in-netcf.html – TEEKAY

1

nie jestem pewien ButtonBase obsługuje przezroczystość ... Czy można sprawdzić, że obecnie?

Napisałem kilka przejrzystych kontroli, ale zawsze odziedziczyłem po Control lub UserControl.

Jeśli chcesz zablokować obraz kontrolny, to jego tło - należy zastąpić OnPaintBackground zamiast OnPaint i nie wywoływać klasy bazowej.

Wypełnienie prostokąta pędzlem. Przezroczysty jest zabawny - malujesz niewidzialnym kolorem nad tym, co tam jest. Albo inaczej: nic nie robi!

10

W winformach są pewne sztuczki, które pozwalają kontrolować, czy tło jest poprawnie malowane przy użyciu przezroczystości. Możesz dodać ten kod do OnPaint lub OnPaintBackground aby uzyskać kontrole masz w tle są malowane:

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

Wiem, że to pytanie jest stary, ale jeśli ktoś nie chce, aby utworzyć formant, aby to zrobić Wpadłem na ten kod z innego artykułu i zmieniłem go metodą rozszerzenia.

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

I wywołanie jak:

buttonUpdate.ToTransparent(Color.Magenta);