Jump to content
Sign in to follow this  

How to convert a hIcon to a 32-bit hBitmap

Recommended Posts


I have created a menu, with items links to some files.

And I want to add icons for these menu items.

I found _GUICtrlMenu_SetItemBmp() function to do this, and it needs hBitmap

But i use _WinAPI_PrivateExtractIcon() to get an icon, which returns an icon handle.

So I needs to convert hicon to hbitmap so that i can add it to my menu item.

And i got _GdipCreateBitmapFromHICON() in a previous thread, it did create a bitmap, but the alpha transparent information is disappeared.

I have found something on the web but not in autoit code.


And this, I wrote a au3 version MI_GetBitmapFromIcon32Bit() but not works.

Func GetBitmapFromIcon32Bit($hIcon, $iWidth=0, $iHeight=0)
    Local $aIcon = _WinAPI_GetIconInfo($hIcon)
;       $aIcon[0] - True on success, otherwise False
;       $aIcon[1] - True specifies an icon, False specifies a cursor
;       $aIcon[2] - Specifies the X coordinate of a cursor's hot spot
;       $aIcon[3] - Specifies the Y coordinate of a cursor's hot spot
;       $aIcon[4] - Specifies the icon bitmask bitmap
;       $aIcon[5] - Handle to the icon color bitmap
    Local $hbmMask  = $aIcon[4] ; used to generate alpha data (if necessary)
    Local $hbmColor = $aIcon[5] ; used to measure the icon

    if $iWidth = 0 or $iHeight = 0 then ; get size from bitmap
        Local $tBitmap = DllStructCreate("int bmType;int bmWidth;int bmHeight;int bmWidthBytes;ushort bmPlanes;ushort bmBitsPixel;ptr bmBits")
        if not $hbmColor or not _WinAPI_GetObject($hbmColor, 24, DllStructGetPtr($tBitmap)) then return 0
        $iWidth  = DllStructGetData($tBitmap,"bmWidth")
        $iHeight = DllStructGetData($tBitmap,"bmHeight")
        $tBitmap = 0 ; free struct

    ; Create a device context compatible with the screen.
    Local $hdcDest = _WinAPI_CreateCompatibleDC(0)
    if $hdcDest then
;       Local $tBitmapInfo = DllStructCreate("dword Size;long Width;long Height;ushort Planes;ushort BitCount;dword Compression;dword SizeImage;long XPelsPerMeter;long YPelsPerMeter;dword ClrUsed;dword ClrImportant;dword RGBQuad")
        Local $tBitmapInfo = DllStructCreate($tagBITMAPINFO)
        ; Create a 32-bit bitmap to draw the icon onto.
        ; Set parameters for 32-bit bitmap. May also be used to retrieve bitmap data from the icon's mask bitmap.
        DllStructSetData($tBitmapInfo, "Size"    , DllStructGetSize($tBitmapInfo) - 4) ;40)
        DllStructSetData($tBitmapInfo, "Width"   , $iWidth)
        DllStructSetData($tBitmapInfo, "Height"  , $iHeight)
        DllStructSetData($tBitmapInfo, "Planes"  , 1)
        DllStructSetData($tBitmapInfo, "BitCount", 32) ; 32-bit bitmap

        Local $pBits

        Local $hBitmap = CreateDIBSection($hdcDest, DllStructGetPtr($tBitmapInfo), 0, $pBits, 0, 0)
        if $hBitmap then
            ; SelectObject -- use hdcDest to draw onto bm
            Local $hBitmapOld = _WinAPI_SelectObject($hdcDest, $hBitmap)
            if $hBitmapOld then
                ; Draw the icon onto the 32-bit bitmap.
                _WinAPI_DrawIconEx($hdcDest, 0, 0, $hIcon)
                _WinAPI_SelectObject($hdcDest, $hBitmapOld)

            Local $pBitsEnd = $pBits + $iWidth*$iHeight
            ; Check for alpha data.
            Local $fHasAlpha = false
            for $pThisPixel = $pBits to $pBitsEnd-1
                if BitAND(Ptr($pThisPixel), 0xFF000000) then
                    $fHasAlpha = true

            if not $fHasAlpha then
                ; Ensure the mask is the right size.
;               $hbmMask = DllCall("CopyImage", "uint", $hbmMask, "uint", 0, "int", $iWidth, "int", $iHeight, "uint", BitOR(4,8))
                Local $pMaskBits
                if _WinAPI_GetDIBits($hdcDest, $hbmMask, 0, $iHeight, $pMaskBits, DllStructGetPtr($tBitmapInfo), 0) then
                    ; Use icon mask to generate alpha data.
                    Local $pThisMaskPixel = $pMaskBits
                    for $pThisPixel = $pBits to $pBitsEnd-1
                        if Ptr($pThisMaskPixel) then
                            Ptr($pThisPixel) = 0
                            Ptr($pThisPixel) = BitOR(Ptr($pThisPixel), 0xFF000000)
                    ; Make the bitmap entirely opaque.
                    for $pThisPixel = $pBits to $pBitsEnd-1
                        Ptr($pThisPixel) = BitOR(Ptr($pThisPixel), 0xFF000000)

        ; Done using the device context.

    if $hbmColor then _WinAPI_DeleteObject($hbmColor)
    if $hbmMask  then _WinAPI_DeleteObject($hbmMask)
    return $hBitmap

Func CreateDIBSection ($hdc, $pbmi, $iUsage, ByRef $ppvBits, $hSection, $dwOffset)
    Local $aRes = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
                                                'ptr',   $hdc,      _ ; // handle to DC
                                                'ptr',   $pbmi,     _ ; // bitmap data
                                                'uint',  $iUsage,   _ ; // data type indicator
                                                'ptr*',  $ppvBits,  _ ; // bit values
                                                'ptr',   $hSection, _ ; // handle to file mapping object
                                                'dword', $dwOffset )  ; // offset to bitmap bit values
    Local $cbSize = DllStructGetData (DllStructCreate ($tagBITMAPINFOHEADER, $pbmi), 'SizeImage')
    $ppvBits = DllStructCreate ('uint[' & $cbSize / 4 & ']', $aRes[4])
    Return $aRes[0]
Edited by rexx

Share this post

Link to post
Share on other sites

Try this.

#Include <GUIConstantsEx.au3>
#Include <GUIMenu.au3>
#Include <Constants.au3>
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)

Global $hMenu, $hForm, $hFile = 1000, $idNew, $idExit

$hForm = GUICreate('Menu', 400, 300)

$hFile = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem ($hFile, 0, ' &Favorites', $idNew)
_GUICtrlMenu_InsertMenuItem ($hFile, 1, '', 0)
_GUICtrlMenu_InsertMenuItem($hFile, 2, ' E&xit', $idExit)
$hMenu = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, '&File', 0, $hFile)
_GUICtrlMenu_SetMenu($hForm, $hMenu)
_GUICtrlMenu_SetItemBmp($hFile, 0, _CreateBitmapFromIcon(_WinAPI_GetSysColor($COLOR_MENU), @SystemDir & '\shell32.dll', 43, 16, 16))
_GUICtrlMenu_SetItemBmp($hFile, 2, _CreateBitmapFromIcon(_WinAPI_GetSysColor($COLOR_MENU), @SystemDir & '\shell32.dll', 27, 16, 16))



Func _CreateBitmapFromIcon($iBackground, $sIcon, $iIndex, $iWidth, $iHeight)

    Local $hDC, $hBackDC, $hBackSv, $hIcon, $hBitmap
    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    $hIcon = _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    If Not @error Then
        _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    Return $hBitmap
EndFunc   ;==>_CreateBitmapFromIcon

Func _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)

    Local $hIcon, $tIcon = DllStructCreate('hwnd'), $tID = DllStructCreate('hwnd')
    Local $Ret = DllCall('user32.dll', 'int', 'PrivateExtractIcons', 'str', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr', DllStructGetPtr($tIcon), 'ptr', DllStructGetPtr($tID), 'int', 1, 'int', 0)

    If (@error) Or ($Ret[0] = 0) Then
        Return SetError(1, 0, 0)
    $hIcon = DllStructGetData($tIcon, 1)
    If ($hIcon = Ptr(0)) Or (Not IsPtr($hIcon)) Then
        Return SetError(1, 0, 0)
    Return $hIcon
EndFunc   ;==>_WinAPI_PrivateExtractIcon
Edited by Yashied

Share this post

Link to post
Share on other sites

It works!!

Thank you very much!! =D

Edited by rexx

Share this post

Link to post
Share on other sites

Mmmm, I'm filing this one away :)

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  


Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.