Transparent images with C# WinForms
Asked Answered
M

6

26

I am working on a Windows Forms application in VS 2008, and I want to display one image over the top of another, with the top image being a gif or something with transparent parts.

Basically I have a big image and I want to put a little image on top if it, so that they kinda appear as one image to the user.

I've been trying to use a picturebox, but this doesn't seem to have worked, any suggestions?

Meanie answered 27/12, 2008 at 18:30 Comment(2)
Duplicate question answered here (same applies to C#)- #394926 #392757Davis
Link to duplicate answer is brokenDairyman
I
28

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();
        }
    }
}
Incontrollable answered 12/1, 2009 at 7:26 Comment(10)
Whats the Hack for I don't see Redraw called internally. When does it need to be called?Camlet
as you can see, it's Public. IIRC, i encountered a bug when resizing the form of an anchored TransparentControl. I think it disappears from the form, so I put that Redraw method to be called from the form's resize.Incontrollable
works great. The only problem I faced is that unlike the PictureBox, I couldnt set this to auto-resize or stretch. Other than that, it works like a charm. Thanks Leon!Methodical
What's the timer/Refresh for?Idioplasm
Set ControlFlags.ResizeRedraw.Better
The Redraw() hack was just what I needed!Braithwaite
@Slaks I think you mean: SetStyle(ControlStyles.ResizeRedraw, true);Clavier
This TransparentControl code was a disaster for me, it wouldn't even paint the image I'd set, it would paint some other part of the UI, at random. Probably because my UI is hidden while repainting... not sure. But unusable for meMonoxide
Excelent! But unfortunately, when a control refreshes under the image, it makes the piece of the image that is immediately above it disappear (talking about the z-axis here)Ermentrude
Normally you would use Invalidate() to repaint the image. RecreateHandle() is kind of overkill.Anode
C
7

PictureBox has 2 layers of images: BackgroundImage and Image, that you can use independently of each other including drawing and clearing.

Clasping answered 14/10, 2011 at 12:17 Comment(0)
T
4

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.

Thematic answered 27/12, 2008 at 19:9 Comment(0)
W
3

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
Wen answered 20/8, 2012 at 17:32 Comment(1)
how I use this ?Hungary
V
2

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)

  1. Create Winform
  2. Create x2 pictureBoxes
    • foreground_pictureBox // picture box 'in front' of 'background'
    • background_pictureBox // picture box 'behind' the 'foreground'
  3. 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
  4. 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

Venepuncture answered 26/2, 2014 at 15:32 Comment(0)
I
0

I've always found that I've had to composite the images myself, using a single picturebox or control. Having two pictureboxes with transparent parts has never worked for me.

Interstellar answered 28/12, 2008 at 20:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.