For background please see: =/library/en-us/gdi/bitmaps_3b3m.aspWhen you call GetHBITMAP and the bitmap has an alpha channel,you will get a bluish tint in the areas where the bitmap is transparent.Your bitmap has a Format32bppARGB. It requires special handling.This is by design. See the above link for an explanation.If you first convert the bitmap to Format32bppPARGB and then callGetHBITMAP, you image will display without a bluish tint.Keep in mind that the original design of the GDI Bitmap did not includean alpha channel. You can see this by examining the BITMAPINFOHEADER.Microsoft later introduced the BITMAPV5HEADER which allows foran alpha channel.In Gdiplus, all bitmaps are 32bpp. If you don't do anythingbut simply load and draw an image then everything comes outOk! Gdiplus handles all of the conversions to allow drawingon a GDI context behind the scenes.In my test case, I use the GDI functions to display the HBITMAPS.You will get the same results if you simply use the Gdiplus GraphicsAPI.Below is a test case that demonstrates the above:Save as Form1.csusing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;using System.Runtime.InteropServices;namespace hbitmap /// /// Summary description for Form1. /// public class Form1 : System.Windows.Forms.Form public const int transparent = 1; public const int opaque = 2; public const int AC_SRC_ALPHA = 1; private System.Windows.Forms.MainMenu mainMenu1; private System.Windows.Forms.MenuItem menuItemDraw; private System.Windows.Forms.MenuItem menuItemOpaque; private System.Windows.Forms.MenuItem menuItemBitmap3; private System.Windows.Forms.MenuItem menuItemFormat32bppARGB; private System.Windows.Forms.MenuItem menuItemFormat32bppPARGB; public const int AC_SRC_OVER = 0; public struct BLENDFUNCTION public byte BlendOp; public byte BlendFlags; public byte SourceConstantAlpha; public byte AlphaFormat; ; public enum TernaryRasterOperations SRCCOPY = 0x00CC0020, // dest = source SRCPAINT = 0x00EE0086, // dest = source OR dest SRCAND = 0x008800C6, // dest = source AND dest SRCINVERT = 0x00660046, // dest = source XOR dest SRCERASE = 0x00440328, // dest = source AND (NOT dest) NOTSRCCOPY = 0x00330008, // dest = (NOT source) NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest) MERGECOPY = 0x00C000CA, // dest = (source AND pattern) MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest PATCOPY = 0x00F00021, // dest = pattern PATPAINT = 0x00FB0A09, // dest = DPSnoo PATINVERT = 0x005A0049, // dest = pattern XOR dest DSTINVERT = 0x00550009, // dest = (NOT dest) BLACKNESS = 0x00000042, // dest = BLACK WHITENESS = 0x00FF0062, // dest = WHITE ; [DllImport("Msimg32.dll")] public static extern bool AlphaBlend( IntPtr hdcDest, // handle to destination DC int nXOriginDest, // x-coord of upper-left corner int nYOriginDest, // y-coord of upper-left corner int nWidthDest, // destination width int nHeightDest, // destination height IntPtr hdcSrc, // handle to source DC int nXOriginSrc, // x-coord of upper-left corner int nYOriginSrc, // y-coord of upper-left corner int nWidthSrc, // source width int nHeightSrc, // source height BLENDFUNCTION blendFunction // alpha-blending function ); [DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); [DllImport("gdi32.dll")] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hBitmap); [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop ); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC( IntPtr hdc ); [DllImport("gdi32.dll")] public static extern bool DeleteDC( IntPtr hdc ); [DllImport("gdi32.dll")] public static extern int SetBkMode( IntPtr hdc, int iBkMode ); [DllImport("gdi32.dll")] public static extern int SetBkColor( IntPtr hdc, int crColor ); [DllImport("gdi32.dll")] public static extern int SetTextColor( IntPtr hdc, int crColor ); [DllImport("user32.dll")] public static extern IntPtr GetDC( IntPtr hWnd ); [DllImport("user32.dll")] public static extern bool ReleaseDC( IntPtr hWnd, IntPtr hdc ); Bitmap bm; IntPtr hBitmap; IntPtr hMemDC; IntPtr hOldBitmap; bool bOpaque; /// /// /// Required designer variable. /// private System.ComponentModel.Container components = null; public Form1() // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) if( disposing ) if (components != null) components.Dispose(); base.Dispose( disposing ); #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() this.mainMenu1 = new System.Windows.Forms.MainMenu(); this.menuItemDraw = new System.Windows.Forms.MenuItem(); this.menuItemOpaque = new System.Windows.Forms.MenuItem(); this.menuItemBitmap3 = new System.Windows.Forms.MenuItem(); this.menuItemFormat32bppARGB = new System.Windows.Forms.MenuItem(); this.menuItemFormat32bppPARGB = new System.Windows.Forms.MenuItem(); // // mainMenu1 // this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] this.menuItemBitmap3, this.menuItemDraw); // // menuItemDraw // this.menuItemDraw.Index = 1; this.menuItemDraw.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] this.menuItemOpaque); this.menuItemDraw.Text = "Draw"; // // menuItemOpaque // this.menuItemOpaque.Checked = true; this.menuItemOpaque.Index = 0; this.menuItemOpaque.Text = "Opaque"; this.menuItemOpaque.Click += new System.EventHandler(this.menuItemOpaque_Click); // // menuItemBitmap3 // this.menuItemBitmap3.Index = 0; this.menuItemBitmap3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] this.menuItemFormat32bppARGB, this.menuItemFormat32bppPARGB); this.menuItemBitmap3.Text = "Bitmap"; // // menuItemFormat32bppARGB // this.menuItemFormat32bppARGB.Checked = true; this.menuItemFormat32bppARGB.Index = 0; this.menuItemFormat32bppARGB.Text = "Format32bppARGB"; this.menuItemFormat32bppARGB.Click += new System.EventHandler(this.menuItemFormat32bppARGB_Click); // // menuItemFormat32bppPARGB // this.menuItemFormat32bppPARGB.Index = 1; this.menuItemFormat32bppPARGB.Text = "Format32bppPARGB"; this.menuItemFormat32bppPARGB.Click += new System.EventHandler(this.menuItemFormat32bppPARGB_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(292, 266); this.Menu = this.mainMenu1; this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint); this.Leave += new System.EventHandler(this.Form1_Leave); #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() Application.Run(new Form1()); private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) // Do something with hBitmap. IntPtr hdc = e.Graphics.GetHdc(); if ( this.bOpaque ) BitBlt(hdc, 0, 0, bm.Width, bm.Height, hMemDC, 0, 0, TernaryRasterOperations.SRCCOPY); else BLENDFUNCTION bf; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 0xFF; bf.AlphaFormat = AC_SRC_ALPHA; AlphaBlend(hdc, 0, 0, bm.Width, bm.Height, hMemDC, 0, 0, bm.Width, bm.Height, bf ); e.Graphics.ReleaseHdc(hdc); private void Form1_Load(object sender, System.EventArgs e) this.bOpaque = true; this.BackColor = Color.White; this.bm = new Bitmap("c:\\temp\\PP0N6A08.png"); SelectObject(this.hMemDC, this.hOldBitmap ); DeleteObject(this.hBitmap); DeleteDC(this.hMemDC); this.hBitmap = bm.GetHbitmap(this.bm.GetPixel(0,0)); IntPtr hDC = GetDC( (IntPtr)null ); this.hMemDC = CreateCompatibleDC(hDC); ReleaseDC( (IntPtr)null, hDC ); this.hOldBitmap = SelectObject(hMemDC, hBitmap ); private void Form1_Leave(object sender, System.EventArgs e) this.bm.Dispose(); SelectObject(this.hMemDC, this.hOldBitmap ); DeleteDC(this.hMemDC); DeleteObject(this.hBitmap); private void menuItemOpaque_Click(object sender, System.EventArgs e) bOpaque = !bOpaque; if ( bOpaque ) menuItemOpaque.Checked = true; Form1.ActiveForm.Invalidate(); else menuItemOpaque.Checked = false; Form1.ActiveForm.Invalidate(); private void menuItemFormat32bppARGB_Click(object sender, System.EventArgs e) menuItemFormat32bppPARGB.Checked = !menuItemFormat32bppPARGB.Checked; menuItemFormat32bppARGB.Checked = true; bm.Dispose(); this.bm = new Bitmap("c:\\temp\\PP0N6A08.png"); SelectObject(this.hMemDC, this.hOldBitmap ); DeleteObject(this.hBitmap); DeleteDC(this.hMemDC); this.hBitmap = bm.GetHbitmap(this.bm.GetPixel(0,0)); IntPtr hDC = GetDC( (IntPtr)null ); this.hMemDC = CreateCompatibleDC(hDC); ReleaseDC( (IntPtr)null, hDC ); this.hOldBitmap = SelectObject(hMemDC, hBitmap ); Form1.ActiveForm.Invalidate(); private void menuItemFormat32bppPARGB_Click(object sender, System.EventArgs e) menuItemFormat32bppARGB.Checked = !menuItemFormat32bppARGB.Checked; menuItemFormat32bppPARGB.Checked = true; bm.Dispose(); Bitmap temp = new Bitmap("c:\\temp\\PP0N6A08.png"); this.bm = new Bitmap( temp.Width, temp.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb ); Graphics g = Graphics.FromImage( bm ); g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; Rectangle rect = new Rectangle(0,0,temp.Width, temp.Height); g.DrawImage( temp, rect ); g.Dispose(); temp.Dispose(); SelectObject(this.hMemDC, this.hOldBitmap ); DeleteObject(this.hBitmap); DeleteDC(this.hMemDC); this.hBitmap = bm.GetHbitmap(this.bm.GetPixel(0,0)); IntPtr hDC = GetDC( (IntPtr)null ); this.hMemDC = CreateCompatibleDC(hDC); ReleaseDC( (IntPtr)null, hDC ); this.hOldBitmap = SelectObject(hMemDC, hBitmap ); Form1.ActiveForm.Invalidate(); I got the .png image from the PNG test image suite here:
the procedure entry point alphablend msimg32 dll
2ff7e9595c
Comments