/// <summary> /// Updates the layered window. /// </summary> /// <param name="b">The image to uses as the window background</param> /// <param name="form">The form containing any controls to draw</param> /// <param name="x">The x position</param> /// <param name="y">The y position</param> /// <param name="opacity">The opacity</param> public static void UpdateLayeredWindow(Bitmap b, Form form, int x, int y, byte opacity) { if (b.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) throw new ApplicationException("The bitmap must be 32ppp with alpha-channel."); Bitmap bitmap = new Bitmap(b); using (bitmap) { // The idea of this is very simple, // 1. Create a compatible DC with screen; // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC; // 3. Call the UpdateLayeredWindow. IntPtr screenDc = Win32.GetDC(IntPtr.Zero); IntPtr memDc = Win32.CreateCompatibleDC(screenDc); IntPtr hBitmap = IntPtr.Zero; IntPtr oldBitmap = IntPtr.Zero; try { Graphics g = Graphics.FromImage(bitmap); using (g) { foreach (Control ctrl in form.Controls) { if (ctrl is PictureBox) { PictureBox pb = (PictureBox)ctrl; if(pb.Image != null) g.DrawImage(pb.Image, ctrl.Bounds); } else if (ctrl is Label) { // text looks crappy if we use the DrawControlToBitmap method, so we have to do it manually Label el = (Label)ctrl; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //g.PixelOffsetMode = PixelOffsetMode.HighQuality; //g.CompositingQuality = CompositingQuality.HighQuality; //g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; if (el is ExpandingLabel) g.TextRenderingHint = ((ExpandingLabel)el).TextRenderingHint; SolidBrush brush = new SolidBrush(el.ForeColor); using (brush) { g.DrawString(el.Text, el.Font, brush, new RectangleF(el.Bounds.X, el.Bounds.Y, el.Bounds.Width, el.Bounds.Height), System.Drawing.StringFormat.GenericTypographic); } } else { DrawControlToBitmap(ctrl, bitmap, ctrl.Bounds); //ctrl.DrawToBitmap leaks memory, so we use our own version } } } hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap oldBitmap = Win32.SelectObject(memDc, hBitmap); Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height); Win32.Point pointSource = new Win32.Point(0, 0); Win32.Point topPos = new Win32.Point(x, y); Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION(); blend.BlendOp = Win32.AC_SRC_OVER; blend.BlendFlags = 0; blend.SourceConstantAlpha = opacity; blend.AlphaFormat = Win32.AC_SRC_ALPHA; Win32.UpdateLayeredWindow(form.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA); } finally { Win32.ReleaseDC(IntPtr.Zero, screenDc); if (hBitmap != IntPtr.Zero) { Win32.SelectObject(memDc, oldBitmap); Win32.DeleteObject(hBitmap); } Win32.DeleteDC(memDc); } } }
/// <summary> /// Updates the layered window. /// </summary> /// <param name="b">The image to uses as the window background</param> /// <param name="form">The form containing any controls to draw</param> /// <param name="x">The x position</param> /// <param name="y">The y position</param> /// <param name="opacity">The opacity</param> public static void UpdateLayeredWindow(Bitmap b, Form form, int x, int y, byte opacity) { if (b.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) { throw new ApplicationException("The bitmap must be 32ppp with alpha-channel."); } Bitmap bitmap = new Bitmap(b); using (bitmap) { // The idea of this is very simple, // 1. Create a compatible DC with screen; // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC; // 3. Call the UpdateLayeredWindow. IntPtr screenDc = Win32.GetDC(IntPtr.Zero); IntPtr memDc = Win32.CreateCompatibleDC(screenDc); IntPtr hBitmap = IntPtr.Zero; IntPtr oldBitmap = IntPtr.Zero; try { Graphics g = Graphics.FromImage(bitmap); using (g) { foreach (Control ctrl in form.Controls) { if (ctrl is PictureBox) { PictureBox pb = (PictureBox)ctrl; if (pb.Image != null) { g.DrawImage(pb.Image, ctrl.Bounds); } } else if (ctrl is Label) { // text looks crappy if we use the DrawControlToBitmap method, so we have to do it manually Label el = (Label)ctrl; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //g.PixelOffsetMode = PixelOffsetMode.HighQuality; //g.CompositingQuality = CompositingQuality.HighQuality; //g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; if (el is ExpandingLabel) { g.TextRenderingHint = ((ExpandingLabel)el).TextRenderingHint; } SolidBrush brush = new SolidBrush(el.ForeColor); using (brush) { g.DrawString(el.Text, el.Font, brush, new RectangleF(el.Bounds.X, el.Bounds.Y, el.Bounds.Width, el.Bounds.Height), System.Drawing.StringFormat.GenericTypographic); } } else { DrawControlToBitmap(ctrl, bitmap, ctrl.Bounds); //ctrl.DrawToBitmap leaks memory, so we use our own version } } } hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap oldBitmap = Win32.SelectObject(memDc, hBitmap); Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height); Win32.Point pointSource = new Win32.Point(0, 0); Win32.Point topPos = new Win32.Point(x, y); Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION(); blend.BlendOp = Win32.AC_SRC_OVER; blend.BlendFlags = 0; blend.SourceConstantAlpha = opacity; blend.AlphaFormat = Win32.AC_SRC_ALPHA; Win32.UpdateLayeredWindow(form.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA); } finally { Win32.ReleaseDC(IntPtr.Zero, screenDc); if (hBitmap != IntPtr.Zero) { Win32.SelectObject(memDc, oldBitmap); Win32.DeleteObject(hBitmap); } Win32.DeleteDC(memDc); } } }