public static void SelectBitmapIntoLayerWindow(Form win, Bitmap bitmap, byte opacity) { // 判断位图是否包含Alpha通道 if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) { throw new ApplicationException("必须是带Alpha通道的32位位图"); } // 获取设备上下文DC IntPtr screenDc = Win32.GetDC(IntPtr.Zero); IntPtr memDc = Win32.CreateCompatibleDC(screenDc); IntPtr hBitmap = IntPtr.Zero; IntPtr hOldBitmap = IntPtr.Zero; try { // 获取插入到设备上下文位图的句柄 hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); hOldBitmap = Win32.SelectObject(memDc, hBitmap); // 设置层叠窗口更新的参数 Size newSize = new Size(bitmap.Width, bitmap.Height); // 设置窗口同位图大小 Point sourceLocation = new Point(0, 0); Point newLocation = new Point(win.Left, win.Top); BlendFunction blend = new BlendFunction(); blend.BlendOp = (byte)BlendOp.AC_SRC_OVER; // 仅支持32位位图 blend.BlendFlags = 0; // 总是 0 blend.SourceConstantAlpha = opacity; // 像素的Alpha通道值 blend.AlphaFormat = (byte)BlendOp.AC_SRC_ALPHA; // 仅支持含Alpha通道的位置 // 更新层叠窗口 Win32.UpdateLayeredWindow(win.Handle, screenDc, ref newLocation, ref newSize, memDc, ref sourceLocation, 0, ref blend, (int)ULWPara.ULW_ALPHA); } finally { // 释放设备上下文 Win32.ReleaseDC(IntPtr.Zero, screenDc); if (hBitmap != IntPtr.Zero) { Win32.SelectObject(memDc, hOldBitmap); Win32.DeleteObject(hBitmap); // 删除GDI+位图 } Win32.DeleteDC(memDc); } }
/// <summary> /// 使用AlphaBlend API绘制带Alpha通道的半透明图片 /// </summary> /// <param name="gx">Destination graphics</param> /// <param name="image">The image to draw</param> /// <param name="transparency">transparent factor</param> /// <param name="x">X Location</param> /// <param name="y">Y Location</param> public static void DrawAlpha(this Graphics gx, Bitmap image, byte transparency, int x, int y) { using (Graphics gxSrc = Graphics.FromImage(image)) { IntPtr hdcDst = gx.GetHdc(); IntPtr hdcSrc = gxSrc.GetHdc(); BlendFunction blendFunction = new BlendFunction(); blendFunction.BlendOp = (byte)BlendOperation.AC_SRC_OVER; // Only supported blend operation blendFunction.BlendFlags = (byte)BlendFlags.Zero; // Documentation says put 0 here blendFunction.SourceConstantAlpha = transparency; // Constant alpha factor blendFunction.AlphaFormat = (byte)0; // Don't look for per pixel alpha Win32.AlphaBlend(hdcDst, x, y, image.Width, image.Height, hdcSrc, 0, 0, image.Width, image.Height, blendFunction); gx.ReleaseHdc(hdcDst); // Required cleanup to GetHdc() gxSrc.ReleaseHdc(hdcSrc); // Required cleanup to GetHdc() } }
extern public static Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);
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);