Jump to content

GUICtrlCreateIco using GUISetBkColor for fake transparency?


Go to solution Solved by rcmaehl,

Recommended Posts

Hi all,

I'm having an issue with GUICtrlCreateIcon using the GUISetBkColor() as the color in transparent areas, instead of actual transparency. You can see this in the below code

#include <WinAPISysWin.au3>
#include <GUIConstantsEx.au3>
#include <AutoItConstants.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    GUICreate(" My GUI Icons", 400, 400)

    $BKC = _WinAPI_GetSysColor($COLOR_WINDOW)

    GUICtrlSetDefColor(0x0000FF)
    GUICtrlSetDefBKColor(0x00FF00)
    GUISetBkColor(0xFF0000)

    GUICtrlCreateLabel("", 0, 0, 100, 600)
    GUICtrlSetBkColor(-1, $BKC - 0x191919)

    GUICtrlCreateIcon("shell32.dll", 10, 20, 20)
    GUICtrlSetColor(-1, $BKC - 0x191919)
    GUICtrlSetBkColor(-1, $BKC - 0x191919)
    GUISetState(@SW_SHOW)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example

 

Is there any workaround for this bug so that the icons can have actual transparency?

I've tried:

  • Adjusting GUISetBKColor() before the controls are created and then back again after the icons are created
  • Various Ctrl and GUI Flags
  • Other icon sources (dlls, compiled exe)

 

Thanks in advance!

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Link to post
Share on other sites

Hi rcmaehl
Here is the display when I launch your script (the light grey background comes from my Windows theme, on your computer it's probably a white background) :

586603603_OPiconredbackground.png.b73103fa1f0d6b2dc1c2a58a8e3ef787.png

So you're asking how to get rid of the red background displayed behind the icon ?

I was lucky to find this thread where Yashied attached a function named _SetBkIcon()
Unfortunately his function can't be downloaded from there as it's not hosted on AutoIt. Trying some google search, I found Yashied's function inside a script from funkey.

Here is the result, based on the way you scripted it (the icon over the label) :

1070823635_Transparenticonbackground.png.d6ae5fd518ccf1b336830630b0bfb67c.png

#Include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    $hGUI = GUICreate("Icons", 200, 250)

    $BKC = _WinAPI_GetSysColor($COLOR_WINDOW) ; window background (help file)
    ; ConsoleWrite("0x" & Hex($BKC, 6) & @crlf) ; 0xE3DFE0 (light grey, my windows theme)

    GUISetBkColor(0xFF0000) ; red (Gui)

    GUICtrlSetDefColor(0x0000FF) ; blue (controls)
    GUICtrlSetDefBKColor(0x00FF00) ; green (controls)

    GUICtrlCreateLabel("test label", 0, 0, 100, 20, BitOR($SS_CENTERIMAGE, $SS_CENTER)) ; blue on green

    GUICtrlCreateLabel("", 0, 20, 100, 230)
    GUICtrlSetBkColor(-1, $BKC) ; light grey (background)

    $Icon1 = GUICtrlCreateIcon('', -1, 30, 40) ; left, top
    $Icon2 = GUICtrlCreateIcon('', -1, 20, 100)
    $Icon3 = GUICtrlCreateIcon('', -1, 25, 180)
    
    _GDIPlus_Startup()
    _SetBkIcon($Icon1, $BKC, @SystemDir & '\shell32.dll', 10, 32, 32)  ; icon #10,  width, height
    _SetBkIcon($Icon2, $BKC, @SystemDir & '\shell32.dll', 130, 48, 48)
    _SetBkIcon($Icon3, $BKC, @SystemDir & '\shell32.dll', 131, 48, 48)
    _GDIPlus_Shutdown()

    GUISetState(@SW_SHOW)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>Example

;============================================================================
Func _SetBkIcon($ControlID, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight)
    
    Local Static $STM_SETIMAGE = 0x0172
    Local $tIcon, $tID, $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon

    $tIcon = DllStructCreate('hwnd')
    $tID = DllStructCreate('hwnd')
    $hIcon = 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 ($hIcon[0] = 0) Then
        Return SetError(1, 0, 0)
    EndIf
    $hIcon = DllStructGetData($tIcon, 1)
    $tIcon = 0
    $tID = 0

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hBkIcon = DllCall($__g_hGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0)
    $hBkIcon = $hBkIcon[2]
    _GDIPlus_ImageDispose($hImage)

    GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon))
    _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID))

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_DeleteDC($hBackDC)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteObject($hBkIcon)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteObject($hIcon)

    Return SetError(0, 0, 1)
EndFunc   ;==>_SetBkIcon

Hope it helps and good luck :bye:

Edited by pixelsearch
typo
Link to post
Share on other sites
3 minutes ago, pixelsearch said:

Hope it helps and good luck :bye:

THANK YOU!!! I feel like this should be reported as a bug if it isn't already, or at least documented in help but I digress

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Link to post
Share on other sites
Posted (edited)

Reviving this thread as it seems to break on compile 😕

 

I know @funkey is still active and about. Maybe they can shed some light on a fix

 

Edited by rcmaehl

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Link to post
Share on other sites

For me the example from @pixelsearch works on x86 and x64 and compiled and not compiled. Don't know what is going wrong on your system, sorry.

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to post
Share on other sites
Just now, funkey said:

For me the example from @pixelsearch works on x86 and x64 and compiled and not compiled. Don't know what is going wrong on your system, sorry.

Maybe I just need a restart. Lots of odd autoit specific issues lately. Stdout output was getting eaten as well.

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

Link to post
Share on other sites
  • Solution
Posted (edited)

I've found my issue. The function doesn't seem to work for .exes but works fine for dlls. Fails on DllCall('user32.dll', 'int', 'PrivateExtractIcons'

I hadn't realized as I was creating the icon anyway with the original controls on my other script. I was able to fix it using the following

Func _SetBkIcon($ControlID, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight)

    Local Static $STM_SETIMAGE = 0x0172
    Local $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon

    $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hBkIcon = DllCall($__g_hGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0)
    $hBkIcon = $hBkIcon[2]
    _GDIPlus_ImageDispose($hImage)

    GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon))
    _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID))

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_DeleteDC($hBackDC)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteObject($hBkIcon)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteObject($hIcon)

    Return SetError(0, 0, 1)
EndFunc   ;==>_SetBkIcon

Edit: This didn't work for extracting the icon from the running compiled script. I fixed that using ResourcesEx

Func _SetBkSelfIcon($ControlID, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight)

    Local Static $STM_SETIMAGE = 0x0172
    Local $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon

    $hIcon =  _Resource_GetAsIcon($iIndex, "RC_DATA", $sIcon)

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hBkIcon = DllCall($__g_hGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0)
    $hBkIcon = $hBkIcon[2]
    _GDIPlus_ImageDispose($hImage)

    GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon))
    _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID))

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_DeleteDC($hBackDC)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteObject($hBkIcon)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteObject($hIcon)

    Return SetError(0, 0, 1)
EndFunc   ;==>_SetBkIcon


 

Edited by rcmaehl

My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.

My Projects

WhyNotWin11
Cisco FinesseGithubIRC UDFWindowEx UDF

 

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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...