Sign in to follow this  
Followers 0
Lucid

Change Opactiy of GDI+ Bitmap

7 posts in this topic

I'm having problems getting my brain to work, and I can't find anything to help me get moving on the web - so I was hoping someone here could nudge me in the right direction.

I'm trying to be able to change the opacity of a bitmap using GDI+ (the source files are all .PNG). So at times it's fully opaque, and others it's faded out. Below is a sample bit of code. How can I get the bitmap to look semi-transparent? Thanks!

 

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <GUIConstants.au3>
#include <ColorConstantS.au3>
#include <WinAPIGdi.au3>
#include <WindowsConstants.au3>

AutoItSetOption("MustDeclareVars", 1)

_GDIPlus_Startup()

Local $hGUI = GUICreate("test", 400, 300, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetBkColor(0x000000, $hGUI)

Local $hImage = _GDIPlus_ImageLoadFromFile("AnyPNGFile.png")
Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
Local $iHeight = _GDIPlus_ImageGetHeight($hImage)
Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

; how can I dynamically change the opacity of the bitmap?

Local $hPicCtrl = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)
_SetBitmapToCtrl($hPicCtrl, $hBitmap)
GUICtrlSetState ($hPicCtrl, $GUI_SHOW)
GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            Exit
    EndSwitch
WEnd


Func _SetBitmapToCtrl($CtrlId, $hBitmap)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local Const $SS_BITMAP = 0xE
    Local Const $GWL_STYLE = -16
    Local $hWnd = GUICtrlGetHandle($CtrlId)
    If $hWnd = 0 Then Return SetError(1, 0, 0)
      ; set SS_BITMAP style to control
    Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE)
    If @error Then Return SetError(2, 0, 0)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP))
    If @error Then Return SetError(3, 0, 0)
        Local $oldBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBitmap)
    If @error Then Return SetError(4, 0, 0)
    If $oldBmp[0] <> 0 Then _WinAPI_DeleteObject($oldBmp[0])
    Return 1
EndFunc

 

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

Try this:

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>

AutoItSetOption("MustDeclareVars", 1)

_GDIPlus_Startup()

Global $hImage = _GDIPlus_ImageLoadFromFile("c:\Program Files (x86)\AutoIt3\Examples\GUI\Torus.png")
Global $iWidth = _GDIPlus_ImageGetWidth($hImage)
Global $iHeight = _GDIPlus_ImageGetHeight($hImage)

Global $hGUI = GUICreate("test", $iWidth, $iHeight, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetState(@SW_SHOW, $hGUI)

Global $hBitmap_Transparent = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
Global $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap_Transparent)
Global $hAttribute_Transparent = _GDIPlus_AttributeCreateTransparentBitmap($hImage)
_GDIPlus_GraphicsDrawImageRectRect($hGfx, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hAttribute_Transparent)

Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Transparent)
_WinAPI_BitmapDisplayTransparentInGUI($hHBitmap, $hGUI)


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_ImageAttributesDispose($hAttribute_Transparent)
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_ImageDispose($hBitmap_Transparent)
            _GDIPlus_ImageDispose($hImage)
            _WinAPI_DeleteObject($hHBitmap)
            _GDIPlus_Shutdown()
            Exit
    EndSwitch
WEnd

Func _GDIPlus_AttributeCreateTransparentBitmap($hImage, $fTransparency = 0.25)
    Local Const $hAttribute_Alpha = _GDIPlus_ImageAttributesCreate()
    $fTransparency = $fTransparency > 1 ? 1 : $fTransparency < 0 ? 0 : $fTransparency
    Local $tColorMatrix = _GDIPlus_ColorMatrixCreateTranslate(0, 0, 0, $fTransparency * -1)
    Local Const $pColorMatrix = DllStructGetPtr($tColorMatrix)
    _GDIPlus_ImageAttributesSetColorMatrix($hAttribute_Alpha, 0, True, $pColorMatrix)
    Return $hAttribute_Alpha
EndFunc

Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $bReleaseGDI = True)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Sorry for not being clear. I'm looking to be able to alter the transparency of the image, but keep the background of the GUI visible.

So in UEZ's example, if I add "GUISetBkColor(0x000000, $hGUI)" I don't see the black background I'd expect to see. I've been trying to work my way through the code and understand what it's doing, but I'm coming up with a few blanks. How can I have a semi-transparent image on top of the GUI, but still be able to see the GUI background?

Thanks!

Share this post


Link to post
Share on other sites

Here the modfied version:

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WindowsConstants.au3>

AutoItSetOption("MustDeclareVars", 1)

_GDIPlus_Startup()

Global $hImage = _GDIPlus_ImageLoadFromFile("c:\Program Files (x86)\AutoIt3\Examples\GUI\Torus.png")
Global $iWidth = _GDIPlus_ImageGetWidth($hImage)
Global $iHeight = _GDIPlus_ImageGetHeight($hImage)

Global $hGUI = GUICreate("test", $iWidth, $iHeight)
GUISetBkColor(0)
GUISetState(@SW_SHOW, $hGUI)

Global $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hAttribute_Transparent = _GDIPlus_AttributeCreateTransparentBitmap($hImage)

_GDIPlus_GraphicsDrawImageRectRect($hGfx, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth, $iHeight, $hAttribute_Transparent)



While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_ImageAttributesDispose($hAttribute_Transparent)
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_ImageDispose($hImage)
            _GDIPlus_Shutdown()
            Exit
    EndSwitch
WEnd

Func _GDIPlus_AttributeCreateTransparentBitmap($hImage, $fTransparency = 0.25)
    Local Const $hAttribute_Alpha = _GDIPlus_ImageAttributesCreate()
    $fTransparency = $fTransparency > 1 ? 1 : $fTransparency < 0 ? 0 : $fTransparency
    Local $tColorMatrix = _GDIPlus_ColorMatrixCreateTranslate(0, 0, 0, $fTransparency * -1)
    Local Const $pColorMatrix = DllStructGetPtr($tColorMatrix)
    _GDIPlus_ImageAttributesSetColorMatrix($hAttribute_Alpha, 0, True, $pColorMatrix)
    Return $hAttribute_Alpha
EndFunc

 


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Thanks for the speedy reply UEZ!

I guess I'm not being clear. So what I'm trying to figure out how to do is to make an image semi-transparent on top of the background of the GUI (so you can see the background through the semi-transparent image). In the included pics, you can see that the red Torus ring is 100% in the one, but in the other the ring is like 55% transparent and the blue background shows through. How can I accomplish this with GDI+ using a PNG file?

Thanks! And sorry for not being clear enough in my first post.

 

flat.jpg

transparent.jpg

Share this post


Link to post
Share on other sites

Nevermind! Totally my fault - got a number in the wrong spot in my test. Thanks UEZ! I think I'm able to move forward and try understanding/adapting your code.

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  
Followers 0