Transparent images with C# WinForms
Solution 1:
I was in a similar situation a couple of days ago. You can create a transparent control to host your image.
using System;
using System.Windows.Forms;
using System.Drawing;
public class TransparentControl : Control
{
private readonly Timer refresher;
private Image _image;
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
refresher = new Timer();
refresher.Tick += TimerOnTick;
refresher.Interval = 50;
refresher.Enabled = true;
refresher.Start();
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
protected override void OnPaint(PaintEventArgs e)
{
if (_image != null)
{
e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do not paint background
}
//Hack
public void Redraw()
{
RecreateHandle();
}
private void TimerOnTick(object source, EventArgs e)
{
RecreateHandle();
refresher.Stop();
}
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
RecreateHandle();
}
}
}
Solution 2:
PictureBox has 2 layers of images: BackgroundImage and Image, that you can use independently of each other including drawing and clearing.
Solution 3:
Put the big/bottom image on a PictureBox
, then add a handler to the OnPaint
event and use one of the e.Graphics.DrawImage()
overloads. You can load the image using Image.FromFile()
.
The small/top image will have to have an alpha channel and be transparent in the background for the overlay to work. You should be able to ensure this pretty easily in Photoshop or something similar. Make sure you save in a format that supports the alpha channel, such as PNG.
Solution 4:
The vb.net code (All credits to Leon Tayson):
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Public Class TransparentControl
Inherits Control
Private ReadOnly Local_Timer As Timer
Private Local_Image As Image
Public Sub New()
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
BackColor = Color.Transparent
Local_Timer = New Timer
With Local_Timer
.Interval = 50
.Enabled = True
.Start()
End With
AddHandler Local_Timer.Tick, AddressOf TimerOnClick
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams
cp = MyBase.CreateParams
cp.ExStyle = &H20
Return cp
End Get
End Property
Protected Overrides Sub OnMove(ByVal e As System.EventArgs)
MyBase.OnMove(e)
RecreateHandle()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
If Local_Image IsNot Nothing Then _
e.Graphics.DrawImage(Local_Image, New Rectangle(0, 0, (Width / 2) - (Local_Image.Width / 2), (Height / 2) - (Local_Image.Height / 2)))
End Sub
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
' DO NOT PAINT BACKGROUND
End Sub
''' <summary>
''' Hack
''' </summary>
''' <remarks></remarks>
Public Sub ReDraw()
RecreateHandle()
End Sub
Private Sub TimerOnClick(ByVal sender As Object, ByVal e As System.EventArgs)
RecreateHandle()
Local_Timer.Stop()
End Sub
Public Property Image As Image
Get
Return Local_Image
End Get
Set(ByVal value As Image)
Local_Image = value
RecreateHandle()
End Set
End Property
End Class
Solution 5:
A list of similar posts is referenced at the bottom of this reply.
This reply addresses pictureBoxes and Winforms (in the other posts below, several reiterate that WPF solves this well already)
- Create Winform
- Create x2 pictureBoxes
- foreground_pictureBox // picture box 'in front' of 'background'
- background_pictureBox // picture box 'behind' the 'foreground'
- Add the 'paint' event for each pictureBox
- select object in the 'designer'
- choose the 'properties' tab (or right-click and choose from popup menu)
- select the events button (small lightning bolt)
- double-click in the empty field to the right of the 'paint' event
- Add the following code to the main form's 'load' function (if not already added, use the approach in step 3 and select 'on load' rather than 'paint')
=
private void cFeedback_Form_Load(object sender, EventArgs e)
{
...
// Ensure that it is setup with transparent background
foreground_pictureBox.BackColor = Color.Transparent;
// Assign it's 'background'
foreground_pictureBox.Parent = background_pictureBox;
...
}
5 . In the 'paint' call for the 'background_pictureBox':
=
private void background_pictureBox_Paint(object sender, PaintEventArgs e)
{
...foreground_pictureBox_Paint(sender, e);
}
6 . Within the 'foreground_pictureBox_Paint' call, add in whatever graphics calls you want to be displayed in the foreground.
This topic repeats itself in several posts it seems:
how-to-make-picturebox-transparent
c-sharp-picturebox-transparent-background-doesnt-seem-to-work
make-overlapping-picturebox-transparent-in-c-net
a-picturebox-problem