There should be a way to correctly show the alpha channel of a BackgroundImage(32bpp) on a transparent Form by invoking user32/gdi32.dll. I want to show the borders of a white logo with glowing borders(blurred) in a transparent Form window.
In the past I only called user32.dll parameters to control the opacity of images in a transparent Form window, but my solution didn't support most alpha channel values of a .png image.
Now I included a new solution using Layered Windows in the code below, but it has no effect on the BackgroundImage. I assume what I tried yet to reference my BackgroundImage with the layered window code is not a valid method?
using System;
using System.IO;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace BgImage32bppbgra
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// controlled by LayeredWindows? // this.TransparencyKey = System.Drawing.SystemColors.Control;
this.BackgroundImage = Image.FromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"bgIMG1\bgIMG1.png"));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.ShowInTaskbar = false;
this.Load += BgImage32bppbgra_Load;
}
void BgImage32bppbgra_Load(object sender, EventArgs e)
{
this.Size = this.BackgroundImage.Size;
this.TopMost = true;
}
/// --- Control Format32bppArgb transparent alpha channel with LayeredWindows ULW_ALPHA Blend
protected override CreateParams CreateParams
{
get
{
// Add WS_EX_LAYERED extended style
CreateParams createParams = base.CreateParams;
if (!DesignMode)
createParams.ExStyle |= WS_EX_LAYERED;
return createParams;
}
}
public void BG(Bitmap BackgroundImage)
{
BG(BackgroundImage, 255);
}
public void BG(Bitmap BackgroundImage, int opacity)
{
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr hOldBitmap = IntPtr.Zero;
try
{
// Get handle to the new bitmap.
hBitmap = BackgroundImage.GetHbitmap(Color.FromArgb(0));
hOldBitmap = SelectObject(memDc, hBitmap);
// params for layered window update
Size newSize = new Size(BackgroundImage.Width, BackgroundImage.Height);
Point sourceLocation = new Point(0, 0);
Point newLocation = new Point(this.Left, this.Top);
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = (byte)opacity;
blend.AlphaFormat = AC_SRC_ALPHA;
// layered window update
UpdateLayeredWindow(this.Handle, screenDc, ref newLocation, ref newSize, memDc, ref sourceLocation, 0, ref blend, ULW_ALPHA);
// this.Handle = Handle to the layered window
// screenDc = Handle to the screen DC
// ref newLocation = New screen position of the layered window
// ref newSize = New size of the layered window
// memDc = Handle to the layered window surface DC
// ref sourceLocation = Location of the layer in the DC
// 0 = Color key of the layered window
// ref blend = Transparency of the layered window
// ULW_ALPHA = Use blend as the blend function
}
finally
{
// release context
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
SelectObject(memDc, hOldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
}
const Int32 WS_EX_LAYERED = 0x80000;
const Int32 HTCAPTION = 0x02;
const Int32 WM_NCHITTEST = 0x84;
const Int32 ULW_ALPHA = 0x02;
const byte AC_SRC_OVER = 0x00;
const byte AC_SRC_ALPHA = 0x01;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
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", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteObject(IntPtr hObject);
}
}