- Сообщения
- 5,379
- Репутация
- 2,724
Наконец-то я нашел "нормальный" способ сделать это. Проблема - сохранить прозрачность у объединенной иконки + разная глубина цвета у входных иконок. Здесь я убил сразу всех зайцев... Эта функция будет присутствовать в библиотеке WinAPEx, начиная с версии 3.2.
И еще небольшое дополнение. Эта функция устанавливает прозрачность (делает бледнее) для указанной иконки.
Код:
#Include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Global Const $STM_SETIMAGE = 0x0172
Global $hIcon, $hOverlay, $hResult
; Create icon with overlay mask (48x48)
$hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 1, 48, 48)
If _WinAPI_GetVersion() >= '6.0' Then
$hOverlay = _WinAPI_ShellExtractIcon(@SystemDir & '\imageres.dll', 154, 48, 48)
Else
$hOverlay = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 29, 48, 48)
EndIf
$hResult = _WinAPI_AddIconOverlay($hIcon, $hOverlay)
_WinAPI_DestroyIcon($hIcon)
_WinAPI_DestroyIcon($hOverlay)
; Create GUI
GUICreate('MyGUI', 128, 128)
GUICtrlCreateIcon('', 0, 40, 40, 32, 32)
GUICtrlSendMsg(-1, $STM_SETIMAGE, 1, $hResult)
GUISetState()
Do
Until GUIGetMsg() = -3
; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_AddIconOverlay
; Description....: Creates an icon by merging the source icon and overlay mask.
; Syntax.........: _WinAPI_AddIconOverlay ( $hIcon, $hOverlay )
; Parameters.....: $hIcon - Handle to the source icon.
; $hOverlay - Handle to the icon to use as an overlay mask.
; Return values..: Success - Handle to the newly created icon.
; Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: The source icon and overlay mask must be the same size but can have different bit depth. When you are finished
; using the icon, destroy it using the _WinAPI_DestroyIcon() function.
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================
Func _WinAPI_AddIconOverlay($hIcon, $hOverlay)
Local $tSIZE, $Ret, $hIL, $hResult = 0
$tSIZE = _WinAPI_GetIconDimension($hIcon)
If @error Then
Return SetError(1, 0, 0)
EndIf
$hIL = DllCall('comctl32.dll', 'ptr', 'ImageList_Create', 'int', DllStructGetData($tSIZE, 1), 'int', DllStructGetData($tSIZE, 1), 'uint', 0x0021, 'int', 2, 'int', 2)
If (@error) Or (Not $hIL[0]) Then
Return SetError(2, 0, 0)
EndIf
Do
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_ReplaceIcon', 'ptr', $hIL[0], 'int', -1, 'ptr', $hIcon)
If (@error) Or ($Ret[0] = -1) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_ReplaceIcon', 'ptr', $hIL[0], 'int', -1, 'ptr', $hOverlay)
If (@error) Or ($Ret[0] = -1) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'int', 'ImageList_SetOverlayImage', 'ptr', $hIL[0], 'int', 1, 'int', 1)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$Ret = DllCall('comctl32.dll', 'ptr', 'ImageList_GetIcon', 'ptr', $hIL[0], 'int', 0, 'uint', 0x00000100)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$hResult = $Ret[0]
Until 1
DllCall('comctl32.dll', 'int', 'ImageList_Destroy', 'ptr', $hIL[0])
If Not $hResult Then
Return SetError(3, 0, 0)
EndIf
Return $hResult
EndFunc ;==>_WinAPI_AddIconOverlay
И еще небольшое дополнение. Эта функция устанавливает прозрачность (делает бледнее) для указанной иконки.
Код:
#Include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Global Const $STM_SETIMAGE = 0x0172
Global $hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 1, 32, 32)
GUICreate('MyGUI', 262, 108)
For $i = 0 To 3
GUICtrlCreateIcon('', 0, 30 + 58 * $i, 38, 32, 32)
GUICtrlSendMsg(-1, $STM_SETIMAGE, 1, _WinAPI_AddIconTransparency($hIcon, 100 - 25 * $i))
Next
_WinAPI_DestroyIcon($hIcon)
GUISetState()
Do
Until GUIGetMsg() = -3
; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_AddIconTransparency
; Description....: Adds a transparency to the specified 32 bits-per-pixel icon.
; Syntax.........: _WinAPI_AddIconTransparency ( $hIcon [, $iPercent [, $fDelete]] )
; Parameters.....: $hIcon - Handle to the icon.
; $iPercent - A value (in percent) that specifies how much to decrease the values of the alpha channel for the specified icon.
; $fDelete - Specifies whether deletes an icon after the function is successful, valid values:
; |TRUE - Icon will be deleted if the function succeeds.
; |FALSE - Don't delete, you must release the icon when you are finished using it. (Default)
; Return values..: Success - Handle to the newly created icon.
; Failure - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: This function only works with 32 bits-per-pixel (RGB + Alpha) icons. When you are finished using the icon,
; destroy it using the _WinAPI_DestroyIcon() function.
; Related........:
; Link...........: None
; Example........: Yes
; ===============================================================================================================================
Func _WinAPI_AddIconTransparency($hIcon, $iPercent = 50, $fDelete = 0)
Local $tICONINFO, $tBITMAP, $W, $H, $Ret, $iByte, $tBits, $pBits, $hBitmap[2], $hResult = 0
$tICONINFO = DllStructCreate($tagICONINFO)
$Ret = DllCall('user32.dll', 'int', 'GetIconInfo', 'ptr', $hIcon, 'ptr', DllStructGetPtr($tICONINFO))
If (@error) Or (Not $Ret[0]) Then
Return SetError(1, 0, 0)
EndIf
For $i = 0 To 1
$hBitmap[$i] = DllStructGetData($tICONINFO, $i + 4)
Next
Do
$tBITMAP = DllStructCreate($tagBITMAP)
If Not _WinAPI_GetObject($hBitmap[1], DllStructGetSize($tBITMAP), DllStructGetPtr($tBITMAP)) Then
ExitLoop
EndIf
$W = DllStructGetData($tBITMAP, 'bmWidth')
$H = DllStructGetData($tBITMAP, 'bmHeight')
$iByte = $W * $H * 4
$tBits = DllStructCreate('byte[' & $iByte & ']')
$pBits = DllStructGetPtr($tBits)
If _WinAPI_GetBitmapBits($hBitmap[1], $iByte, $pBits) <> $iByte Then
ExitLoop
EndIf
For $i = 1 To $iByte Step 4
DllStructSetData($tBits, 1, DllStructGetData($tBits, 1, $i + 3) * $iPercent / 100, $i + 3)
Next
_WinAPI_DeleteObject($hBitmap[1])
$hBitmap[1] = _WinAPI_CreateBitmap($W, $H, 1, 32, $pBits)
If $hBitmap[1] Then
$hResult = _WinAPI_CreateIconIndirect($hBitmap[1], $hBitmap[0])
EndIf
Until 1
For $i = 0 To 1
If $hBitmap[$i] Then
_WinAPI_DeleteObject($hBitmap[$i])
EndIf
Next
If Not $hResult Then
Return SetError(1, 0, 0)
EndIf
If $fDelete Then
_WinAPI_DestroyIcon($hIcon)
EndIf
Return $hResult
EndFunc ;==>_WinAPI_AddIconTransparency