Jump to content

CreateIconIndirect()


Recommended Posts

I can not get a combination of icons. CreateIconIndirect() function does not take the icon mask, or that I am doing something wrong? Please run my example and by all see.

Thanks.

#Include <Constants.au3>
#Include <GDIPlus.au3>
#Include <StaticConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPI.au3>

GUICreate('Test', 180, 260)

GUICtrlCreateLabel(' - Back Icon', 80, 18, 100, 16)
GUICtrlCreateLabel(' - Front Icon', 80, 70, 100, 16)
GUICtrlCreateLabel(' - Result Bitmap', 80, 122, 100, 16)
GUICtrlCreateLabel(' - Result Mask', 80, 174, 100, 16)
GUICtrlCreateLabel(' - Result Icon ???', 80, 226, 100, 16)

$Back = GUICtrlCreateIcon('shell32.dll', -42, 34, 10, 32, 32)
$Front = GUICtrlCreateIcon('shell32.dll', -29, 34, 62, 32, 32)
$Bmp = GUICtrlCreatePic('', 34, 114, 32, 32)
$Mask = GUICtrlCreatePic('', 34, 166, 32, 32)
$Result = GUICtrlCreateIcon('', 0, 34, 218, 32, 32)

_SetHIcon($Result, _CombineIcon('shell32.dll', -42, 'shell32.dll', -29, 32, 32))

GUISetState()

do
until GUIGetMsg() = -3

func _CombineIcon($sIconBack, $iIndexBack, $sIconFront, $iIndexFront, $iWidth, $iHeight)
    
    const $STM_SETIMAGE = 0x0172
    
    local $hDC, $hBackDC, $hFrontDC, $hBackSv, $hFrontSv, $sBackInfo, $sFrontInfo, $hBackIcon, $hFrontIcon, $hResultIcon, $hBitmap, $hImage
    
    $hBackIcon = _WinAPI_PrivateExtractIcon($sIconBack, $iIndexBack, $iWidth, $iHeight)
    $hFrontIcon = _WinAPI_PrivateExtractIcon($sIconFront, $iIndexFront, $iWidth, $iHeight)
    
    $sBackInfo = DllStructCreate('byte fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')
    DllCall('user32.dll', 'int', 'GetIconInfo', 'hwnd', $hBackIcon, 'ptr', DllStructGetPtr($sBackInfo))
    $sFrontInfo = DllStructCreate('byte fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')
    DllCall('user32.dll', 'int', 'GetIconInfo', 'hwnd', $hFrontIcon, 'ptr', DllStructGetPtr($sFrontInfo))
    
    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBackSv = _WinAPI_SelectObject($hBackDC, DllStructGetData($sBackInfo, 'hbmColor'))
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hFrontIcon, 0, 0, 0, 0, $DI_NORMAL)
    _WinAPI_SelectObject($hBackDC, DllStructGetData($sBackInfo, 'hbmMask'))
    $hFrontDC = _WinAPI_CreateCompatibleDC($hDC)
    $hFrontSv = _WinAPI_SelectObject($hFrontDC, DllStructGetData($sFrontInfo, 'hbmMask'))
    _WinAPI_BitBlt($hBackDC, 0, 0, $iWidth, $iHeight, $hFrontDC, 0, 0, $SRCAND)

    _GDIPlus_Startup()

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP(DllStructGetData($sBackInfo, 'hbmColor'))
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _WinAPI_DeleteObject($hImage)
    _WinAPI_DeleteObject(DllStructGetData($sBackInfo, 'hbmColor'))
    DllStructSetData($sBackInfo, 'hbmColor', $hBitmap)
    
    _SetHImage($Bmp, $hBitmap) ; For test only

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP(DllStructGetData($sBackInfo, 'hbmMask'))
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _WinAPI_DeleteObject($hImage)
    _WinAPI_DeleteObject(DllStructGetData($sBackInfo, 'hbmMask'))
    DllStructSetData($sBackInfo, 'hbmMask', $hBitmap)
    
    _SetHImage($Mask, $hBitmap) ; For test only
    
    _GDIPlus_Shutdown()

    $hResultIcon = _WinAPI_CreateIconIndirect($sBackInfo)

    _WinAPI_SelectObject($hFrontDC, $hFrontSv)
    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hFrontDC)
    _WinAPI_DeleteDC($hBackDC)
    _WinAPI_DeleteObject($hFrontIcon)
    _WinAPI_DeleteObject($hBackIcon)
    
    return $hResultIcon
endfunc; _SetCombineBkIcon

#Region Additional Function (Do not pay attention to this)

func _SetHIcon($hWnd, $hIcon)
    
    const $STM_SETIMAGE = 0x0172
    
    local $Style

    if not IsHWnd($hWnd) then
        $hWnd = GUICtrlGetHandle($hWnd)
    endif
    
    if $hWnd = 0 then
        return SetError(1, 0, 0)
    endif
    
    $Style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE)
    if @error then
        return SetError(1, 0, 0)
    endif
    _WinAPI_SetWindowLong($hWnd, $GWL_STYLE, BitOR($Style, Hex($SS_ICON)))
    if @error then
        return SetError(1, 0, 0)
    endif
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_ICON, 0))
    _SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_ICON, $hIcon)
    if @error then
        return SetError(1, 0, 0)
    endif
    return 1
endfunc; _SetHIcon

func _SetHImage($hWnd, $hBitmap)
    
    const $STM_SETIMAGE = 0x0172
    
    local $Style

    if not IsHWnd($hWnd) then
        $hWnd = GUICtrlGetHandle($hWnd)
    endif
    
    if $hWnd = 0 then
        return SetError(1, 0, 0)
    endif
    
    $Style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE)
    if @error then
        return SetError(1, 0, 0)
    endif
    _WinAPI_SetWindowLong($hWnd, $GWL_STYLE, BitOR($Style, Hex($SS_BITMAP)))
    if @error then
        return SetError(1, 0, 0)
    endif
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, 0))
    _SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap)
    if @error then
        return SetError(1, 0, 0)
    endif
    return 1
endfunc; _SetHImage

func _WinAPI_CreateIconIndirect($tICONINFO)
    
    local $Ret = DllCall('user32.dll', 'int', 'CreateIconIndirect', 'ptr', DllStructGetPtr($tICONINFO))
    
    if (@error) or ($Ret[0] = 0) or ($Ret[0] = Ptr(0)) then
        return SetError(1, 0, 0)
    endif
    return SetError(0, 0, $Ret[0])
endfunc; _WinAPI_CreateIconIndirect

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)
    endif
    
    $hIcon = DllStructGetData($tIcon, 1)
    
    if ($hIcon = Ptr(0)) or (not IsPtr($hIcon)) then
        return SetError(1, 0, 0)
    endif
    return SetError(0, 0, $hIcon)
endfunc; _WinAPI_PrivateExtractIcon

#EndRegion Additional Function (Do not pay attention to this)

CreateIconIndirect.au3

Link to comment
Share on other sites

I prepared a more simple example. Look in the comments.

#Include <WinAPI.au3>

local $Form, $sBackInfo, $sFrontInfo, $hBackIcon, $hFrontIcon, $hResultIcon

$Form = GUICreate('', 100, 100)
GUISetState()

; Get icons
$hBackIcon = _WinAPI_PrivateExtractIcon('shell32.dll', 0, 32, 32)
$hFrontIcon = _WinAPI_PrivateExtractIcon('shell32.dll', 28, 32, 32)

; Get information about icons
$sBackInfo = DllStructCreate('byte fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')
DllCall('user32.dll', 'int', 'GetIconInfo', 'hwnd', $hBackIcon, 'ptr', DllStructGetPtr($sBackInfo))
$sFrontInfo = DllStructCreate('byte fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')
DllCall('user32.dll', 'int', 'GetIconInfo', 'hwnd', $hFrontIcon, 'ptr', DllStructGetPtr($sFrontInfo))

; Specifying the bottom icon mask from the top icon
DllStructSetData($sBackInfo, 'hbmMask', DllStructGetData($sFrontInfo, 'hbmMask'))
;DllStructSetData($sBackInfo, 'hbmColor', DllStructGetData($sFrontInfo, 'hbmColor'))

; Create a new icon
$hResultIcon = _WinAPI_CreateIconIndirect($sBackInfo)

; Results obtained in the bottom icon in the original form
; Why?
_WinAPI_DrawIcon(_WinAPI_GetDC($Form), 34, 34, $hResultIcon)

do
until GUIGetMsg() = -3

#Region Additional Function (Do not pay attention to this)

func _WinAPI_CreateIconIndirect($tICONINFO)
    
    local $Ret = DllCall('user32.dll', 'int', 'CreateIconIndirect', 'ptr', DllStructGetPtr($tICONINFO))
    
    if (@error) or ($Ret[0] = 0) or ($Ret[0] = Ptr(0)) then
        return SetError(1, 0, 0)
    endif
    return SetError(0, 0, $Ret[0])
endfunc; _WinAPI_CreateIconIndirect

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)
    endif
    
    $hIcon = DllStructGetData($tIcon, 1)
    
    if ($hIcon = Ptr(0)) or (not IsPtr($hIcon)) then
        return SetError(1, 0, 0)
    endif
    return SetError(0, 0, $hIcon)
endfunc; _WinAPI_PrivateExtractIcon

#EndRegion Additional Function (Do not pay attention to this)
Link to comment
Share on other sites

I'm not sure what you're trying to achieve here; are you trying to superimpose one icon on to another? If so, I don't think you're quite on the right lines here as you're replacing the bitmap mask from one with a mask from another one. In addition, a BOOL in the Win32 API is actually an int and not a byte:

$sBackInfo = DllStructCreate('int fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')oÝ÷ Ømnëm)äÊ·õÖÞmëmz»hr·µæ¦zj+È0×kk趢{(Ú"µ©Ý¶§µ©"az·¬º[Hz0¶¬É÷öÛaz¸ ×(uæîµÚ²Øb²ÈhÃZ·*.ßÚÞ¶¼¢hv®¶­seõväôG&t6öâõväôvWDD2b33c´f÷&ÒÂ3BÂ3BÂb33c¶&6´6öâ¥õväôG&t6öâõväôvWDD2b33c´f÷&ÒÂ3BÂ3BÂb33c¶g&öçD6öâ

WBD

Link to comment
Share on other sites

I just want to understand why, when I change the mask of the two icons to each other, nothing happens.

I'm not sure what you're trying to achieve here; are you trying to superimpose one icon on to another? If so, I don't think you're quite on the right lines here as you're replacing the bitmap mask from one with a mask from another one. In addition, a BOOL in the Win32 API is actually an int and not a byte:

$sBackInfo = DllStructCreate('int fIcon;dword xHotspot;dword yHotspot;ptr hbmMask;ptr hbmColor')oÝ÷ Ûú®¢×z·²¢æ«z¸ Öî¶+]¡ë'¢×!jx¶«zË¥¶«¨µéÚ
How you are going to do?
Link to comment
Share on other sites

From Googling around, I think you have a couple of alternatives. See the following pages for some ideas:

http://www.codeguru.com/forum/archive/inde...p/t-168770.html

http://social.microsoft.com/Forums/en-US/v...d-5697aa2a29d6/

I'd be inclined down the ImageList route but it's your call. Don't forget that you'll need to call InitCommonControls if you're going to use an image list.

Regards,

WBD

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...