This happens because GDI+, which is drawing the image, doesn't know that red is becoming transparent.
Therefore, it blends the borders of the image with the red background, creating reddish (but not completely red) pixels which do not become transparent.
To solve this, you'll need to make a layered window.
EDIT:
Use the following native methods:
static class NativeMethods {
public const int LayeredWindow = 0x80000;//WS_EX_LAYERED
#region Drawing
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateLayeredWindow(IntPtr handle, IntPtr screenDc, ref Point windowLocation, ref Size windowSize, IntPtr imageDc, ref Point dcLocation, int colorKey, ref BlendFunction blendInfo, UlwType type);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("User32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject(IntPtr hObject);
#endregion
}
struct BlendFunction {
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
enum UlwType : int {
None = 0,
ColorKey = 0x00000001,
Alpha = 0x00000002,
Opaque = 0x00000004
}
Override the form's CreateParams
:
protected override CreateParams CreateParams {
get {
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= NativeMethods.LayeredWindow;
return createParams;
}
}
Call the following function in OnShown
:
static Point Zero;
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults")]
void UpdateWindow() {
IntPtr screenDC = NativeMethods.GetDC(IntPtr.Zero);
IntPtr imageDC = NativeMethods.CreateCompatibleDC(screenDC);
IntPtr gdiBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try {
gdiBitmap = image.GetHbitmap(Color.FromArgb(0)); //Get a GDI handle to the image.
oldBitmap = NativeMethods.SelectObject(imageDC, gdiBitmap); //Select the image into the DC, and cache the old bitmap.
Size size = image.Size; //Get the size and location of the form, as integers.
Point location = this.Location;
BlendFunction alphaInfo = new BlendFunction { SourceConstantAlpha = 255, AlphaFormat = 1 }; //This struct provides information about the opacity of the form.
NativeMethods.UpdateLayeredWindow(Handle, screenDC, ref location, ref size, imageDC, ref Zero, 0, ref alphaInfo, UlwType.Alpha);
} finally {
NativeMethods.ReleaseDC(IntPtr.Zero, screenDC); //Release the Screen's DC.
if (gdiBitmap != IntPtr.Zero) { //If we got a GDI bitmap,
NativeMethods.SelectObject(imageDC, oldBitmap); //Select the old bitmap into the DC
NativeMethods.DeleteObject(gdiBitmap); //Delete the GDI bitmap,
}
NativeMethods.DeleteDC(imageDC); //And delete the DC.
}
Invalidate();
}