source/tpshellx/ResourceFuncs.cpp
//
// ****************************************************************************
//
// The GDI+ bitmap constructors that take an existing HICON or HBITMAP destroy
// any existing semi-transparent-alpha when the source is in 32bit ARGB format.
//
// The code below detects the alpha in a 32bit ARGB icon and uses a different
// GDI+ bitmap constructor that does preserve the alpha.
//
// If the icon is NOT in 32bit ARGB format, then fall back on the
// regular constructor which generates alpha from the icon's mask.
//
// N.B. The bitmap's pixel data is stored in the buffer that's passed in.
//
// N.B. GDI+ must already be initialized before calling this function.
The GDI+ bitmap constructors that take an existing HICON or HBITMAP destroy
any existing semi-transparent-alpha when the source is in 32bit ARGB format.

The code below detects the alpha in a 32bit ARGB icon and uses a different
GDI+ bitmap constructor that does preserve the alpha.

If the icon is NOT in 32bit ARGB format, then fall back on the
regular constructor which generates alpha from the icon's mask.




The GDI + bitmap constructors that take an existing HICON or HBITMAP destroy any existing semi - transparent - alpha when the source is in 32bit ARGB format . The code below detects the alpha in a 32bit ARGB icon and uses a different GDI + bitmap constructor that does preserve the alpha . If the icon is NOT in 32bit ARGB format then fall back on the regular constructor which generates alpha from the icon ' s mask .
Gdiplus::Bitmap * LoadMyAppIconAsBitmap (
  LPCTSTR pExeFile, BYTE * pPixelData, UINT uIconSz )
{
  HICON hIcon = NULL;
  if ( SHDefExtractIcon( pExeFile, 0, 0, &hIcon, NULL, uIconSz ) != S_OK )
  {
    return NULL;
  }
  Gdiplus::Bitmap * pBitmap = NULL;
  ICONINFO cIconInfo;
  ZeroMemory( &cIconInfo, sizeof( cIconInfo ) );
  if ( GetIconInfo( hIcon, &cIconInfo ) )
  {
    BITMAP cBitmap;
    if ( GetObject( cIconInfo.hbmColor, sizeof( cBitmap ), &cBitmap ) )
    {
      BITMAPINFO cBMI;
      ZeroMemory( &cBMI, sizeof( cBMI ) );
      cBMI.bmiHeader.biSize        = sizeof( cBMI.bmiHeader );
      cBMI.bmiHeader.biWidth       =   cBitmap.bmWidth;
      cBMI.bmiHeader.biHeight      = - cBitmap.bmHeight;
      cBMI.bmiHeader.biPlanes      = 1;
      cBMI.bmiHeader.biBitCount    = 32;
      cBMI.bmiHeader.biCompression = BI_RGB;
      if ( pPixelData )
      {
        HDC hDC = NULL;
        HDC hSC = GetDC( NULL );
        if ( hSC )
        {
          hDC = CreateCompatibleDC( hSC );
          ReleaseDC( NULL, hSC );
        }
        if ( hDC )
        {
          if ( GetDIBits(
                 hDC, cIconInfo.hbmColor,
                 0, cBitmap.bmHeight, pPixelData, &cBMI, DIB_RGB_COLORS ) )
          {
            BYTE * pPixel = pPixelData + cBitmap.bmWidth * cBitmap.bmHeight * 4;
            BYTE   bAlpha = 0;
            do
            {
              pPixel -= 4;
              bAlpha |= pPixel[3];
            } while ( pPixel > pPixelData );
            if ( bAlpha )
            {
              #if 1 
              {
                pBitmap =
                  new Gdiplus::Bitmap(
                    cBitmap.bmWidth,
                    cBitmap.bmHeight,
                    cBitmap.bmWidth * 4,
                    PixelFormat32bppARGB,
                    pPixelData );
              }
              #else 
              {
                pBitmap =
                  new Gdiplus::Bitmap(
                    cBitmap.bmWidth,
                    cBitmap.bmHeight,
                    PixelFormat32bppARGB );
                if ( pBitmap )
                {
                  Gdiplus::BitmapData cBitmapData;
                  cBitmapData.Width       = cBitmap.bmWidth,
                  cBitmapData.Height      = cBitmap.bmHeight,
                  cBitmapData.Stride      = cBitmap.bmWidth * 4;
                  cBitmapData.PixelFormat = PixelFormat32bppARGB;
                  cBitmapData.Scan0       = pPixelData;
                  cBitmapData.Reserved    = NULL;
                  Gdiplus::Rect cRect( 0, 0, cBitmap.bmWidth, cBitmap.bmHeight );
                  pBitmap->LockBits(
                    &cRect,
                    Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
                    PixelFormat32bppARGB,
                    &cBitmapData );
                  pBitmap->UnlockBits( &cBitmapData );
                }
              }
              #endif
            }
          }
          DeleteDC ( hDC );
        }
      }
    }
    DeleteObject( cIconInfo.hbmMask );
    DeleteObject( cIconInfo.hbmColor );
  }
  if ( hIcon )
  {
    if ( pBitmap == NULL )
    {
      pBitmap =
        new Gdiplus::Bitmap( hIcon );
    }
    DestroyIcon( hIcon );
    hIcon = NULL;
  }
  return pBitmap;
}
Gdiplus :: Bitmap * LoadMyAppIconAsBitmap ( LPCTSTR pExeFile , BYTE * pPixelData , UINT uIconSz ) { HICON hIcon = NULL ; if ( SHDefExtractIcon ( pExeFile , 0 , 0 , & hIcon , NULL , uIconSz ) != S_OK ) { return NULL ; } Gdiplus :: Bitmap * pBitmap = NULL ; ICONINFO cIconInfo ; ZeroMemory ( & cIconInfo , sizeof ( cIconInfo ) ) ; if ( GetIconInfo ( hIcon , & cIconInfo ) ) { BITMAP cBitmap ; if ( GetObject ( cIconInfo . hbmColor , sizeof ( cBitmap ) , & cBitmap ) ) { BITMAPINFO cBMI ; ZeroMemory ( & cBMI , sizeof ( cBMI ) ) ; cBMI . bmiHeader . biSize = sizeof ( cBMI . bmiHeader ) ; cBMI . bmiHeader . biWidth = cBitmap . bmWidth ; cBMI . bmiHeader . biHeight = - cBitmap . bmHeight ; cBMI . bmiHeader . biPlanes = 1 ; cBMI . bmiHeader . biBitCount = 32 ; cBMI . bmiHeader . biCompression = BI_RGB ; if ( pPixelData ) { HDC hDC = NULL ; HDC hSC = GetDC ( NULL ) ; if ( hSC ) { hDC = CreateCompatibleDC ( hSC ) ; ReleaseDC ( NULL , hSC ) ; } if ( hDC ) { if ( GetDIBits ( hDC , cIconInfo . hbmColor , 0 , cBitmap . bmHeight , pPixelData , & cBMI , DIB_RGB_COLORS ) ) { BYTE * pPixel = pPixelData + cBitmap . bmWidth * cBitmap . bmHeight * 4 ; BYTE bAlpha = 0 ; do { pPixel -= 4 ; bAlpha |= pPixel [ 3 ] ; } while ( pPixel > pPixelData ) ; if ( bAlpha ) { #if 1 { pBitmap = new Gdiplus :: Bitmap ( cBitmap . bmWidth , cBitmap . bmHeight , cBitmap . bmWidth * 4 , PixelFormat32bppARGB , pPixelData ) ; } #else { pBitmap = new Gdiplus :: Bitmap ( cBitmap . bmWidth , cBitmap . bmHeight , PixelFormat32bppARGB ) ; if ( pBitmap ) { Gdiplus :: BitmapData cBitmapData ; cBitmapData . Width = cBitmap . bmWidth , cBitmapData . Height = cBitmap . bmHeight , cBitmapData . Stride = cBitmap . bmWidth * 4 ; cBitmapData . PixelFormat = PixelFormat32bppARGB ; cBitmapData . Scan0 = pPixelData ; cBitmapData . Reserved = NULL ; Gdiplus :: Rect cRect ( 0 , 0 , cBitmap . bmWidth , cBitmap . bmHeight ) ; pBitmap -> LockBits ( & cRect , Gdiplus :: ImageLockModeWrite | Gdiplus :: ImageLockModeUserInputBuf , PixelFormat32bppARGB , & cBitmapData ) ; pBitmap -> UnlockBits ( & cBitmapData ) ; } } #endif } } DeleteDC ( hDC ) ; } } } DeleteObject ( cIconInfo . hbmMask ) ; DeleteObject ( cIconInfo . hbmColor ) ; } if ( hIcon ) { if ( pBitmap == NULL ) { pBitmap = new Gdiplus :: Bitmap ( hIcon ) ; } DestroyIcon ( hIcon ) ; hIcon = NULL ; } return pBitmap ; }
The GDI+ bitmap constructors that take an existing HICON or HBITMAP destroy
any existing semi-transparent-alpha when the source is in 32bit ARGB format.
The GDI + bitmap constructors that take an existing HICON or HBITMAP destroy any existing semi - transparent - alpha when the source is in 32bit ARGB format .
// Short version that links to the existing pixel data. // Long version that copies the pixel data to a new buffer.