2

I've got a PictureBox, which can be moved vertically. The image displayed in the PictureBox is a transparent GIF, so when viewed in an image viewer, it has no background.

The problem is that when I move the PictureBox in the application, the PictureBox's background moves around too strangely - almost as if the PictureBox has a background itself.

Before:

enter image description here

After (while moving):

enter image description here

Some code:

path = "C:\\note.gif";
note.Image = Image.FromFile(path);
note.Visible = true;
note.BackColor = Color.Transparent;
panel.Controls.Add(note);

I've also tried making the picturebox double buffered, but that doesn't work either.

Jason Down
  • 21,731
  • 12
  • 83
  • 117
Dot NET
  • 4,891
  • 13
  • 55
  • 98
  • What happens if you replace your GIF with a PNG that has transparency set? – ChrisF Dec 31 '11 at 13:58
  • Tried PNG before GIF, same exact scenario unfortunately. – Dot NET Dec 31 '11 at 14:00
  • Does calling `note.Invalidate();` after moving it help? Or `panel.Invalidate();`? – LarsTech Dec 31 '11 at 15:34
  • 2
    Fundamentally, your approach is flawed because using a picture box control for every musical note is not the best approach. Ideally, you should be doing all of the drawing in your panel, and handling the mouse down events to select the notes based on coordinates. All drawing happens in the panel. When you move a note, you redraw the whole thing again. – LarsTech Dec 31 '11 at 16:12
  • Unfortunately, the PictureBox is a strict requirement. Believe me, if it wasn't I'd use something else - it caused so many problems along the way. – Dot NET Dec 31 '11 at 16:43

2 Answers2

4

While WinForms is poorly suited to transparency in usercontrols, it is possible. See this article here. In it the author suggests deriving from Panel rather then UserControl and overridding the OnPaintBackground method to do nothing. this will stop your background from being drawn

protected override void OnPaintBackground(PaintEventArgs pevent)
{
    //do nothing
}

protected override void OnMove(EventArgs e)
{
    RecreateHandle();
}

// Override the CreateParams property:
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle = 0x00000020; //WS_EX_TRANSPARENT
        return cp;
    }
}

Finally, overriding the OnPaint function you can draw your picturebox.

protected override void OnPaint(PaintEventArgs e)
{
    Graphics g = e.Graphics;

    //Do your drawing here
}

Using this you could create a custom picturebox with transparency, although note you will get flicker and blurring if you move it around the screen in real-time.

Using this and similar techniques we managed to get a WinForms app, Premex XPort to render with a similar branding to their website. This involved multiple transparent controls, painting hacks and all sorts to get it to display correctly.

In conclusion, the reason why Winforms does this poorly is in Win32 based technologies one control owns one pixel on the screen. There is no way to truly composite pixels with transparency as you would expect in HTML or WPF. Later Windows technologies (WPF) do this particularly well so if you really wish to make heavy use of transparency in your app I would suggest moving to this platform, at least in part (WPF can be hosted within WinForms and vice versa).

Best regards,

Dr. Andrew Burnett-Thompson
  • 20,980
  • 8
  • 88
  • 178
2

Win32 controls are not truly transparent.

Your choices are:

  • Change to WPF
  • Use PictureBox.Region to clip the control's unwanted ("transparent") areas
  • See if there are 3rd party controls which'll do what you want
John Arlen
  • 6,539
  • 2
  • 33
  • 42
  • So basically what you're saying is that there's no way to solve this with WinForms? Other than PictureBox.Region which isn't viable at all as I've got loads of different types of PictureBoxes – Dot NET Dec 31 '11 at 15:42
  • 1
    @Sean `no way` is stretching it a bit, but it just isn't worth the effort, and the result will always look phony - Windows Forms, unlike WPF, was not created with those concerns in mind. Now, I don't know *why* using a WinForms `PictureBox` is a requirement, but if this were a real-world project I'd advise you to **pick the right tools for the job**. – Adam Dec 31 '11 at 17:58
  • It's a project for university - that's why it's a requirement :) If it were a real world project it would be more practical. – Dot NET Jan 01 '12 at 01:42
  • I call bunk on this answer. I was doing TRUE transparent controls using the Windows API in VB6, albeit it has never been supported natively. Can also be done in Delphi (win32 controls), and so on. You can also do this (an excellent example) in current version on the entire form http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C ). Perhaps someone can adjust that to work on controls by giving the controls a handle since M$ has so kindly removed the handles. – Kraang Prime Jul 21 '14 at 14:29
  • @SanuelJackson Not sure your answer makes sense. You call bunk with no evidence to the contrary. A hack from 10 years ago and an unsupported claim admitting that it's not supported natively anyway. If there were true (ie supported) transparency it would be easy to demonstrate. – PandaWood Dec 15 '14 at 04:24