C # Picturebox transparent background ne semble pas fonctionner
pour un de mes projets j'ai besoin d'images à afficher avec un fond transparent. J'ai fait quelques .images png qui ont un fond transparent (pour vérifier cela, je les ai ouvertes dans Photoshop). Maintenant j'ai une classe qui étend PictureBox:
class Foo : PictureBox
{
public Foo(int argument)
: base()
{
Console.WriteLine(argument);//different in the real application of course.
//MyProject.Properties.Resources.TRANSPARENCYTEST.MakeTransparent(MyProject.Properties.Resources.TRANSPARENCYTEST.GetPixel(1,1)); //<-- also tried this
this.Image = MyProject.Properties.Resources.TRANSPARENCYTEST;
((Bitmap)this.Image).MakeTransparent(((Bitmap)this.Image).GetPixel(1, 1));
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.BackColor = System.Drawing.Color.Transparent;
}
}
cela cependant affiche juste la picturebox avec un fond blanc, Je ne peux pas sembler le faire fonctionner avec un fond transparent.
6 réponses
il fonctionne probablement parfaitement. Vous voyez ce qu'il y a derrière le contrôle de la boîte à images. Qui est la forme. Dont BackColor est probablement blanc. Vous pouvez définir la propriété Backgrounddimage du formulaire pour être sûr, vous devriez voir l'image à travers la boîte d'image. Comme ceci:
perforation d'un trou à travers à la fois the picture box et la forme nécessite une arme plus grande, Forme.TransparencyKey
si vous voulez superposer des images sur des images (et non des images sur la forme), cela ferait l'astuce:
overImage.Parent = backImage;
overImage.BackColor = Color.Transparent;
overImage.Location = thePointRelativeToTheBackImage;
où surimage et backImage sont des PictureBox avec png (avec fond transparent).
C'est parce que, comme dit précédemment, la transparence d'une image est affichée en utilisant la couleur de fond du conteneur Parent. PictureBoxes n'ont pas une propriété" Parent " donc vous devez le faire manuellement (ou créer un contrôle cutom bien sûr).
il y a une excellente solution sur le site du Codeprojet à
Faire Des Contrôles Transparents - Pas De Scintillement
essentiellement le truc est de passer outre l'événement paintbackground de manière à boucler toutes les commandes sous-jacentes à la picturebox et de les redessiner. La fonction est: -
protected override void OnPaintBackground(PaintEventArgs e)
// Paint background with underlying graphics from other controls
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (Parent != null)
{
// Take each control in turn
int index = Parent.Controls.GetChildIndex(this);
for (int i = Parent.Controls.Count - 1; i > index; i--)
{
Control c = Parent.Controls[i];
// Check it's visible and overlaps this control
if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
{
// Load appearance of underlying control and redraw it on this background
Bitmap bmp = new Bitmap(c.Width, c.Height, g);
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
bmp.Dispose();
}
}
}
}
I know your Question is founded in c# , but due to the similarity, & ease of conversion from VB.NET , je vais ajouter une version complète VB qui permet également la mise à jour de l'arrière-plan de la commande lorsque vous la déplacez.
vous avez déjà une réponse, mais c'est pour les autres qui trouvent ce post par les moteurs de recherche, & voudrait une VB version, ou tout simplement veulent trouver une pleine échantillon convertible s'ils en ont également besoin en c# .
créer un nouveau Custom Control Class , & coller ce qui suit dans elle... l'écrasement de la classe par défaut choses:
Contrôle Personnalisé De La Classe:
Public Class TransparentPictureBox
Private WithEvents refresher As Timer
Private _image As Image = Nothing
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
refresher = New Timer()
'refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
refresher.Interval = 50
refresher.Start()
End Sub
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20
Return cp
End Get
End Property
Protected Overrides Sub OnMove(ByVal e As EventArgs)
MyBase.OnMove(e)
MyBase.RecreateHandle()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'Add your custom paint code here
If _image IsNot Nothing Then
e.Graphics.DrawImage(_image, CInt(Width / 2) - CInt(_image.Width / 2), CInt(Height / 2) - CInt(_image.Height / 2))
End If
End Sub
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
' Paint background with underlying graphics from other controls
MyBase.OnPaintBackground(e)
Dim g As Graphics = e.Graphics
If Parent IsNot Nothing Then
' Take each control in turn
Dim index As Integer = Parent.Controls.GetChildIndex(Me)
For i As Integer = Parent.Controls.Count - 1 To index + 1 Step -1
Dim c As Control = Parent.Controls(i)
' Check it's visible and overlaps this control
If c.Bounds.IntersectsWith(Bounds) AndAlso c.Visible Then
' Load appearance of underlying control and redraw it on this background
Dim bmp As New Bitmap(c.Width, c.Height, g)
c.DrawToBitmap(bmp, c.ClientRectangle)
g.TranslateTransform(c.Left - Left, c.Top - Top)
g.DrawImageUnscaled(bmp, Point.Empty)
g.TranslateTransform(Left - c.Left, Top - c.Top)
bmp.Dispose()
End If
Next
End If
End Sub
Public Property Image() As Image
Get
Return _image
End Get
Set(value As Image)
_image = value
MyBase.RecreateHandle()
End Set
End Property
Private Sub refresher_Tick(sender As Object, e As System.EventArgs) Handles refresher.Tick
MyBase.RecreateHandle()
refresher.Stop()
End Sub
End Class
...sauvez la classe, puis nettoyez votre projet, et construire à nouveau. Le nouveau contrôle doit apparaître comme un nouvel outil. Trouver, & faites-le glisser à votre formulaire.
j'ai eu des problèmes avec ce contrôle cependant... Cela se produit lorsque j'essaie de charger un "chargement" animé .gif de l'image.
l'image ne s'Anime pas, et a également des problèmes d'affichage lorsque vous cachez la commande, puis essayez de l'afficher à nouveau.
trier ces questions, et vous aurez une classe de contrôle parfait personnalisé. :)
EDIT:
Je n'ai pas idée si ce qui suit fonctionnera en C# 's IDE ou pas, mais voici ma tentative de conversion:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class TransparentPictureBox
{
private Timer withEventsField_refresher;
private Timer refresher {
get { return withEventsField_refresher; }
set {
if (withEventsField_refresher != null) {
withEventsField_refresher.Tick -= refresher_Tick;
}
withEventsField_refresher = value;
if (withEventsField_refresher != null) {
withEventsField_refresher.Tick += refresher_Tick;
}
}
}
private Image _image = null;
public TransparentPictureBox()
{
// This call is required by the designer.
InitializeComponent();
// Add any initialization after the InitializeComponent() call.
refresher = new Timer();
//refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
refresher.Interval = 50;
refresher.Start();
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
base.OnMove(e);
base.RecreateHandle();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
base.OnPaint(e);
//Add your custom paint code here
if (_image != null) {
e.Graphics.DrawImage(_image, Convert.ToInt32(Width / 2) - Convert.ToInt32(_image.Width / 2), Convert.ToInt32(Height / 2) - Convert.ToInt32(_image.Height / 2));
}
}
protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
{
// Paint background with underlying graphics from other controls
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (Parent != null) {
// Take each control in turn
int index = Parent.Controls.GetChildIndex(this);
for (int i = Parent.Controls.Count - 1; i >= index + 1; i += -1) {
Control c = Parent.Controls(i);
// Check it's visible and overlaps this control
if (c.Bounds.IntersectsWith(Bounds) && c.Visible) {
// Load appearance of underlying control and redraw it on this background
Bitmap bmp = new Bitmap(c.Width, c.Height, g);
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
bmp.Dispose();
}
}
}
}
public Image Image {
get { return _image; }
set {
_image = value;
base.RecreateHandle();
}
}
private void refresher_Tick(object sender, System.EventArgs e)
{
base.RecreateHandle();
refresher.Stop();
}
}
essayez-le , et voyez par vous-même je suppose :p
ps: Je ne suis pas un gourou, alors attendez-vous à toutes sortes D'erreurs dans le C#, & VB.NET versions. lol
si vous affichez png avec transparence dans la boîte d'image, il sera automatiquement prendre en compte la transparence, de sorte que vous n'avez pas besoin de définir la couleur transparente
Les réponses ci-dessus semblent résoudre votre problème. Vous voyez en effet ce qui se cache derrière le contrôle de la boîte d'image - la forme elle-même avec backColor blanc. J'ai créé ici une fonction simple qui convertit d'abord une image de type octet (tableau) en un bitmap et ensuite en définissant des couleurs spécifiques (à partir de l'image bitmap) en transparent. Quelque chose que vous pourriez aussi bien utiliser:
using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;
public void LogoDrawTransparent(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Image myImg;
Bitmap myBitmap;
try
{
myImg = cls_convertImagesByte.GetImageFromByte(newImg);
myBitmap = new Bitmap(myImg); // @"C:\Temp\imgSwacaa.jpg");
// Get the color of a background pixel.
Color backColor = myBitmap.GetPixel(0, 0); // GetPixel(1, 1);
Color backColorGray = Color.Gray;
Color backColorGrayLight = Color.LightGray;
Color backColorWhiteSmoke = Color.WhiteSmoke;
Color backColorWhite = Color.White;
Color backColorWheat = Color.Wheat;
// Make backColor transparent for myBitmap.
myBitmap.MakeTransparent(backColor);
// OPTIONALLY, you may make any other "suspicious" back color transparent (usually gray, light gray or whitesmoke)
myBitmap.MakeTransparent(backColorGray);
myBitmap.MakeTransparent(backColorGrayLight);
myBitmap.MakeTransparent(backColorWhiteSmoke);
// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0, pictureBox1.Width, pictureBox1.Height); //myBitmap.Width, myBitmap.Height);
}
catch
{
try { pictureBox1.Image = cls_convertImagesByte.GetImageFromByte(newImg); }
catch { } //must do something
}
}
vous pouvez tirer ce func sur la peinture de la pictureBox. C'est ma classe qui est référencée dans la fonction ci-dessus:
class cls_convertImagesByte
{
public static Image GetImageFromByte(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
public static byte[] GetByteArrayFromImage(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
Merci. Chagbert