Jump to content

GDIplus alpha channel


james3mg
 Share

Recommended Posts

Hello all...I have a feeling that others have likely already run across this problem, but I've searched the forums for a few days, a few ways, and can't find anything referencing it. Please feel free to point me to an existing topic if you know of one.

What I'm trying to do is to use the GDIplus functions to create translucent (or semi-transparent) shapes in my GUI. I thought GDIplus was the best candidate because of the alpha channel portion of all the color definitions for pens and brushes. However, what I find is that reducing the alpha on a pen or brush does appear to blend the color with the GUI background color as expected, but it doesn't blend with anything else...that is, it doesn't allow objects/colors/lines/etc to "show through" what should be translucent.

Here is a script to show what I mean:

#include <ButtonConstants.au3>
#include <GdiPlus.au3>
_GDIPlus_Startup()

Global $hGUI=GUICreate("Alpha test",400,400)
$ContextMenu=GUICtrlCreateContextMenu()
$SavePicture=GUICtrlCreateMenuItem("Save picture",$ContextMenu)

$button=GUICtrlCreateButton("A test button- I thought this should ""show through"" anything with less than full alpha",50,100,300,40,$BS_MULTILINE)

$hGraphic=_GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBMP=_GDIPlus_BitmapCreateFromGraphics(400,400,$hGraphic)
$hImage=_GDIPlus_ImageGetGraphicsContext($hBMP)

For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR(0xFF000000-((0xFF000000/15)*$i),0xFF0000),1)
    _GDIPlus_GraphicsDrawLine($hImage,0,200-$i,400,200-$i,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,0,199+$i,400,199+$i,$hPen)
    _GDIPlus_PenDispose($hPen)
Next
For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR(0xFF000000-((0xFF000000/15)*$i),0x0000FF),1)
    _GDIPlus_GraphicsDrawLine($hImage,200-$i,0,200-$i,400,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,199+$i,0,199+$i,400,$hPen)
    _GDIPlus_PenDispose($hPen)
Next

_GDIPlus_GraphicsDispose($hImage)
GUISetState()
Do
    _GDIPlus_GraphicsDrawImageRect($hGraphic,$hBMP,0,0,400,400)
    $msg=GUIGetMsg()
    If $msg<0 Then ContinueLoop
    If $msg=$SavePicture Then
        $SaveFile=FileSaveDialog("Save image as...","","png image (*.png)|jpg image (*.jpg)|gif image (*.gif)",18,"Output.png")
        If NOT @error Then _GDIPlus_ImageSaveToFile($hBMP, $SaveFile)
    EndIf
    sleep(15)
Until $msg = -3
As you can see, I reduce the alpha channel of the lines as they move away from center, and they appear as intended where they're just over the GUI. However, where they cross each other or another control, they paint right over each other instead of blending and allowing them to be seen "through".

Do I not understand how the alpha channel is supposed to work, or am I using it the wrong way, or is this a known problem?

Thanks for your input! :mellow:

Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

I don't know whether it is possible to combine buttons with GDI+ so that the buttons are semi transparent with GDI+ elements! You can use a backround pic and draw semi transparent lines over it!

#include <ButtonConstants.au3>
#include <GdiPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()

Global $hGUI=GUICreate("Alpha test",400,400)
GUISetBkColor(0)
$ContextMenu=GUICtrlCreateContextMenu()
$SavePicture=GUICtrlCreateMenuItem("Save picture",$ContextMenu)
$button=GUICtrlCreateButton("A test button- I thought this should ""show through"" anything with less than full alpha",50,100,300,40,$BS_MULTILINE)
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState()

$hGraphic=_GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBMP=_GDIPlus_BitmapCreateFromGraphics(400,400,$hGraphic)
$hImage=_GDIPlus_ImageGetGraphicsContext($hBMP)

For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR(0x80000000-((0x80000000/15)*$i),0x800000),1)
    _GDIPlus_GraphicsDrawLine($hImage,0,200-$i,400,200-$i,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,0,199+$i,400,199+$i,$hPen)
    _GDIPlus_PenDispose($hPen)
Next
For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR(0x80000000-((0x80000000/15)*$i),0x0000FF),1)
    _GDIPlus_GraphicsDrawLine($hImage,200-$i,0,200-$i,400,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,199+$i,0,199+$i,400,$hPen)
    _GDIPlus_PenDispose($hPen)
Next

_GDIPlus_GraphicsDispose($hImage)

_GDIPlus_GraphicsDrawImageRect($hGraphic,$hBMP,0,0,400,400)
Do
    $msg=GUIGetMsg()
    If $msg<0 Then ContinueLoop
    If $msg=$SavePicture Then
    $SaveFile=FileSaveDialog("Save image as...","","png image (*.png)|jpg image (*.jpg)|gif image (*.gif)",18,"Output.png")
    If NOT @error Then _GDIPlus_ImageSaveToFile($hBMP, $SaveFile)
    EndIf
    sleep(15)
Until $msg = -3

UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Well, the issue wasn't trying to get the button translucent, the button was just to show that I couldn't get the GDIplus lines to be translucent over other lines OR over other GUI elements.

I went through your script and compared it to my original script, and analyzing each change you did and thinking about the implications made me realize my problem. I'd been BitOR'ing a fraction of 0xFF000000 with the color that I wanted the lines to really be, intending that it would be a smooth gradient down in the alpha channel, leaving the color intact. When I saw you using a different alpha starting point though, it made me realize I never stopped to calculate what the result of my attempt to subtract 1/15 of 0xFF000000 from 0xFF000000 WAS. It's not 0xEE000000 as I'd intended, but rather 0xFF111112. So the alpha was staying quite solid, and the actual RGB colors were actually being affected, instead of the other way around.

So I think I've got some parenthesees issues in there somewhere.

Edit: Seems that maybe 0xFF000000 is too high a number for AutoIt or something, as a plain old ConsoleWrite(0xFF000000/15) spits out -1118481.06666667, not 285212672 :mellow:

Edit2: Yep, it's an AutoIt limitation. I thought it would work, since 0xFFFFFFFF only takes 32 bits to render, but I forgot about the fact that they're signed integers...according to the Help File, it only supports hex numbers from -0x80000000 to 0x7FFFFFFF. 0xFF000000 is certainly larger than that, so that's why it doesn't work.

At any rate, I confirmed GDIplus alpha actually DOES work the way I'd intended with the following script:

#include <ButtonConstants.au3>
#include <GdiPlus.au3>
_GDIPlus_Startup()

Global $hGUI=GUICreate("Alpha test",400,400)
$ContextMenu=GUICtrlCreateContextMenu()
$SavePicture=GUICtrlCreateMenuItem("Save picture",$ContextMenu)

$button=GUICtrlCreateButton("A test button- I thought this should ""show through"" anything with less than full alpha",50,100,300,40,$BS_MULTILINE)

$hGraphic=_GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBMP=_GDIPlus_BitmapCreateFromGraphics(400,400,$hGraphic)
$hImage=_GDIPlus_ImageGetGraphicsContext($hBMP)

For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR("0x"&StringRight(Hex($i,1),1)&StringRight(Hex($i,1),1)&"000000",0xFF0000),1)
    _GDIPlus_GraphicsDrawLine($hImage,0,200-$i,400,200-$i,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,0,199+$i,400,199+$i,$hPen)
    _GDIPlus_PenDispose($hPen)
Next
For $i=1 To 15
    $hPen=_GDIPlus_PenCreate(BitOR("0x"&StringRight(Hex($i,1),1)&StringRight(Hex($i,1),1)&"000000",0x0000FF),1)
    _GDIPlus_GraphicsDrawLine($hImage,200-$i,0,200-$i,400,$hPen)
    _GDIPlus_GraphicsDrawLine($hImage,199+$i,0,199+$i,400,$hPen)
    _GDIPlus_PenDispose($hPen)
Next

_GDIPlus_GraphicsDispose($hImage)
GUISetState()
_GDIPlus_GraphicsDrawImageRect($hGraphic,$hBMP,0,0,400,400)
Do
    $msg=GUIGetMsg()
    If $msg<0 Then ContinueLoop
    If $msg=$SavePicture Then
        $SaveFile=FileSaveDialog("Save image as...","","png image (*.png)|jpg image (*.jpg)|gif image (*.gif)",18,"Output.png")
        If NOT @error Then _GDIPlus_ImageSaveToFile($hBMP, $SaveFile)
    EndIf
    sleep(15)
Until $msg = -3
(the only difference between this one and my original script is a little bit more ... "manual" ... creation of the alpha channel of the pen definition, as well as removing the _GDIPlus_GraphicsDrawImageRect() from the do...until loop.

One final thought- copied your removal of _GDIPlus_GraphicsDrawImageRect() from the Do...Until loop, because as it constantly redrew the image over itself, the alpha slowly faded to solid...which makes sense as I think about it. The reason I had it IN the loop, is that if I cover or minimize the GUI with my code, then restore or uncover the window, the graphic is still visible. With your way, the "canvas" gets wiped clean and the drawing is gone. If there's a better way than my way to get the graphic to stick around, I'd love to hear it! :(

Thanks so much for helping me out and also for being my sounding board- sometimes you've just gotta put it out there before you can find your mistakes!

Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

...

Edit2: Yep, it's an AutoIt limitation. I thought it would work, since 0xFFFFFFFF only takes 32 bits to render, but I forgot about the fact that they're signed integers...according to the Help File, it only supports hex numbers from -0x80000000 to 0x7FFFFFFF. 0xFF000000 is certainly larger than that, so that's why it doesn't work.

...

Just have in mind that 0xFFFFFFFF is splitted into

0x[alpha channel value as byte][red as byte][green as byte][blue as byte]. So I think internaly only RGB values will be used for color calculation.

Regards,

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

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...