7
votes

I am trying to design a semi transparent screen as Adobe Photoshop's and visual studios semi transparent welcome splash screen while opening the Application. I set FormBorderStyle to none, And I place a picturebox on it and I added a png image to it, I Set picturebox color to transparent, But I am not able to set Form's back color as transparent. Below are exmples:

Photo shop start up splash screen

Visual studio start up splash screen

and when I set form's Back Color as transparent, it shows me error

Property Not Valid. Control does not support transparent background colors.

I already tried couple of code samples as shown below:

    public Splash_Screen()
{
    this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    InitializeComponent();
    this.BackColor = Color.Red;
    BackColor = Color.Transparent;
}

and

    public Splash_Screen()
{
    this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    InitializeComponent();
}

But nothings works for me.. Any suggestions?

2
Hi @BenVoigt , Thanks for this valuable comment, This might be an alternative for me to design a not rectangular form, But I have a question, it may sounds like a dumb questions, but it will be good if you justify where do I implement the code provided by you in above link?Ahmed Syed
The form's OnLoad method would be a good place.Ben Voigt

2 Answers

11
votes

You set your semi transparent background image to BackgroundImage property of the form. Then set a BackColor to your form, and set the TransparencyKey property of the form to the same color you set for your forms BackColor. Then remove the borders of the form by changing FormBorderStyle property of the form to None. That will do it.

2
votes

This question is old, but I decided to chime in because it's the first result for "transparent splash screen C#", and Tolga's solution can produce strange borders with the color of the TransparencyKey around some edges of the image. This is more evident if it has lines anti-aliased with semitransparent pixels.

I copied this code from here. Unfortunately, neither I nor the poster know the original author.

I've also made some modifications to support changing the form's opacity.

Splash.cs:

class Splash : Form {
    private float _opacity = 1.0f;
    public Bitmap BackgroundBitmap;

    public new float Opacity {
        get {
            return _opacity;
        }
        set {
            _opacity = value;
            SelectBitmap(BackgroundBitmap);
        }
    }

    public Splash(Bitmap bitmap) {
        // Window settings   
        this.TopMost = true;
        this.ShowInTaskbar = false;
        this.Size = bitmap.Size;
        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        // Must be called before setting bitmap   
        this.BackgroundBitmap = bitmap;
        this.SelectBitmap(BackgroundBitmap);
        this.BackColor = Color.Red;
    }

    // Sets the current bitmap
    public void SelectBitmap(Bitmap bitmap) {
        // Does this bitmap contain an alpha channel?   
        if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) {
            throw new ApplicationException("The bitmap must be 32bpp with alpha-channel.");
        }
        // Get device contexts   
        IntPtr screenDc = APIHelp.GetDC(IntPtr.Zero);
        IntPtr memDc = APIHelp.CreateCompatibleDC(screenDc);
        IntPtr hBitmap = IntPtr.Zero;
        IntPtr hOldBitmap = IntPtr.Zero;
        try {
            // Get handle to the new bitmap and select it into the current device context      
            hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
            hOldBitmap = APIHelp.SelectObject(memDc, hBitmap);
            // Set parameters for layered window update      
            APIHelp.Size newSize = new APIHelp.Size(bitmap.Width, bitmap.Height);
            // Size window to match bitmap      
            APIHelp.Point sourceLocation = new APIHelp.Point(0, 0);
            APIHelp.Point newLocation = new APIHelp.Point(this.Left, this.Top);
            // Same as this window      
            APIHelp.BLENDFUNCTION blend = new APIHelp.BLENDFUNCTION();
            blend.BlendOp = APIHelp.AC_SRC_OVER;
            // Only works with a 32bpp bitmap      
            blend.BlendFlags = 0; // Always 0   
            blend.SourceConstantAlpha = (byte)(Opacity * 255); // Set to 255 for per-pixel alpha values
            blend.AlphaFormat = APIHelp.AC_SRC_ALPHA;
            // Only works when the bitmap contains an alpha channel      
            // Update the window      
            APIHelp.UpdateLayeredWindow(Handle, screenDc, ref newLocation, ref newSize, memDc, ref sourceLocation, 0, ref blend, APIHelp.ULW_ALPHA);
        } finally {
            // Release device context      
            APIHelp.ReleaseDC(IntPtr.Zero, screenDc);
            if (hBitmap != IntPtr.Zero) {
                APIHelp.SelectObject(memDc, hOldBitmap);
                APIHelp.DeleteObject(hBitmap);
                // Remove bitmap resources      
            }
            APIHelp.DeleteDC(memDc);
        }
    }

    protected override CreateParams CreateParams {
        get {
            // Add the layered extended style (WS_EX_LAYERED) to this window      
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= APIHelp.WS_EX_LAYERED;
            return createParams;
        }
    }

    // Let Windows drag this window for us (thinks its hitting the title bar of the window)
    protected override void WndProc(ref Message message) {
        if (message.Msg == APIHelp.WM_NCHITTEST) {
            // Tell Windows that the user is on the title bar (caption)      
            message.Result = (IntPtr)APIHelp.HTCAPTION;
        } else {
            base.WndProc(ref message);
        }
    }
}

APIHelp.cs:

// Class to assist with Win32 API calls
class APIHelp { 
    public const Int32 WS_EX_LAYERED = 0x80000;
    public const Int32 HTCAPTION = 0x02;
    public const Int32 WM_NCHITTEST = 0x84;
    public const Int32 ULW_ALPHA = 0x02;
    public const byte AC_SRC_OVER = 0x00;
    public const byte AC_SRC_ALPHA = 0x01;

    public enum Bool {
        False = 0, True = 1
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Point {
        public Int32 x;
        public Int32 y;
        public Point(Int32 x, Int32 y) {
            this.x = x;
            this.y = y;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Size {
        public Int32 cx;
        public Int32 cy;
        public Size(Int32 cx, Int32 cy) {
            this.cx = cx;
            this.cy = cy;
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct ARGB {
        public byte Blue;
        public byte Green;
        public byte Red;
        public byte Alpha;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct BLENDFUNCTION {
        public byte BlendOp;
        public byte BlendFlags;
        public byte SourceConstantAlpha;
        public byte AlphaFormat;
    }

    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern IntPtr CreateCompatibleDC(IntPtr hDC);

    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll", ExactSpelling = true)]
    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern Bool DeleteDC(IntPtr hdc);

    [DllImport("gdi32.dll", ExactSpelling = true)]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);

    [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern Bool DeleteObject(IntPtr hObject);
}