Page 1 of 2

Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 1:56 am
by OgreVorbis
I've found many posts regarding this by searching, but none of them seem to do what I'm looking for.
Currently, I'm using SetLayeredWindowAttributes with LWA_COLORKEY. This only allows me to have a certain color be fully transparent. What I want to do is display a PNG with an alpha channel in a boarderless window and have the alpha parts be partially transparent. In simpler terms, I want to display a transparent PNG exactly as it should look. There are no controls on the form other than an image gadget currently.
There's also the LWA_ALPHA option, but apparently that just makes the whole window partially transparent. My goal is something like the program called Rainmeter.

Side question: If I'm able to achieve this, does drawing on the alpha PNG with 2D drawing functions void the alpha channel? Cause I want to draw extra stuff on top of the PNG programmatically. The extra stuff does not need to be transparent though.

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 5:36 am
by BarryG
What do you mean? I display transparent PNGs with its alpha channel transparent all the time. Is that what you mean? You still need #LWA_COLORKEY to make the window transparent, but the color used for that doesn't have to match the alpha channel of the PNG. Just load the PNG and show it on the transparent window, like this:

Code: Select all

UsePNGImageDecoder()
LoadImage(0,"My_Transparent_PNG_Image.png")

OpenWindow(0,200,65,400,300,"test",#PB_Window_BorderLess)
StickyWindow(0,1)

hWnd=WindowID(0)
SetWindowColor(0,#Blue) ; Color used by #LWA_COLORKEY below (not the PNG's alpha channel).
SetWindowLongPtr_(hWnd,#GWL_EXSTYLE,GetWindowLongPtr_(hWnd,#GWL_EXSTYLE)|#WS_EX_LAYERED)
SetLayeredWindowAttributes_(hWnd,#Blue,0,#LWA_COLORKEY)

ImageGadget(0,10,10,0,0,ImageID(0))

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 7:31 am
by OgreVorbis
BarryG wrote: Sat Mar 05, 2022 5:36 am What do you mean? I display transparent PNGs with its alpha channel transparent all the time. Is that what you mean? You still need #LWA_COLORKEY to make the window transparent, but the color used for that doesn't have to match the alpha channel of the PNG. Just load the PNG and show it on the transparent window, like this:
I tried that with one of my PNGs and it doesn't work. It's only fully transparent or not transparent. As I said, it needs to be partially transparent. Could you please upload the PNG you used for the test because it's not working for me. Maybe there is something wrong with my PNG file. It's made with paint.net and displays proper transparency in other image programs.

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 7:44 am
by BarryG
I don't know if uploading it somewhere will re-encode the PNG, so I put it in a zip file here:

https://drive.google.com/file/d/1kYhEIw ... sp=sharing

Run it with my test code above, and this is how it appears on my desktop:

Image

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 7:57 am
by OgreVorbis
BarryG wrote: Sat Mar 05, 2022 7:44 am
Run it with my test code above, and this is how it appears on my desktop:
You must not understand the question. What you are showing me has already been done.
The problem is it doesn't work with PARTIAL transparency. Open that image in paint.net or equivalent software and apply a transparency level of 128 for example, you will see it is NOT transparent.

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 8:14 am
by BarryG
OgreVorbis wrote: Sat Mar 05, 2022 7:57 amYou must not understand the question.
Sorry!

Re: Transparent PNG alpha channel window

Posted: Sat Mar 05, 2022 8:49 am
by chi
Search for "UpdateLayeredWindow"

Re: Transparent PNG alpha channel window

Posted: Mon Mar 07, 2022 6:52 am
by netmaestro
Try this out:

Code: Select all

; Requires PB 5.10 or newer

Declare PreMultiply(image)

CreateImage(0,64,64,32,#PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(0))
AddPathBox(0,0,64,64)
VectorSourceColor(RGBA(255,0,0,128))
FillPath()
AddPathBox(16,16,32,32)
VectorSourceColor(RGBA(0,0,255,255))
FillPath()
StopVectorDrawing()

;PreMultiply(0) ; Only use this if the image is brought in with UsePngImageDecoder()

OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)

hDC = StartDrawing(ImageOutput(0)) 
  With sz.SIZE
    \cx = ImageWidth(0)
    \cy = ImageHeight(0)
  EndWith
  With BlendMode.BLENDFUNCTION 
    \SourceConstantAlpha = 255 
    \AlphaFormat = 1
  EndWith
  UpdateLayeredWindow_(WindowID(0),0,0,@sz,hDC,@ContextOffset.POINT,0,@BlendMode,2)
StopDrawing() 

Repeat
  ev=WaitWindowEvent()
  Select ev
    Case #WM_LBUTTONDOWN
      SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    Case #PB_Event_RightClick
      CloseWindow(0)
      End
    EndSelect
Until ev = #PB_Event_CloseWindow

Procedure PreMultiply(image)
  StartDrawing(ImageOutput(image))
    DrawingMode(#PB_2DDrawing_AllChannels)
    For j=0 To ImageHeight(image)-1
      For i=0 To ImageWidth(image)-1
        color = Point(i,j)
        Plot(i,j, RGBA(Red(color)   & $FF * Alpha(color) & $FF / $FF,
                       Green(color) & $FF * Alpha(color) & $FF / $FF,
                       Blue(color)  & $FF * Alpha(color) & $FF / $FF,
                       Alpha(color)))
      Next
    Next
  StopDrawing()
EndProcedure

Re: Transparent PNG alpha channel window

Posted: Thu May 05, 2022 12:37 pm
by punak
@netmaestro : thanks for your codes, I think these codes have the potential to make aero glass windows. :D now i want to create a frosted glass window. what changes should be made to the code for this purpose?

like this :
Image

i use this image:
https://www.pngkit.com/view/u2t4r5y3e6u ... ffect-png/

and this codes

Code: Select all

Enumeration 
  #GlassWin
  #ControlsWin
  #AeroGlassImg
  #CalendarGadget
EndEnumeration

Declare PreMultiply(image)
Define ev, hdc, sz.SIZE, BlendMode.BLENDFUNCTION, ContextOffset.POINT

UsePNGImageDecoder()
LoadImage(#AeroGlassImg,"a.png")

Procedure ControlsWinCB()
  ResizeWindow(#ControlsWin,WindowX(#GlassWin), WindowY(#GlassWin), WindowWidth(#GlassWin), WindowHeight(#GlassWin))
EndProcedure

PreMultiply(#AeroGlassImg) 

OpenWindow(#GlassWin,0,0,ImageWidth(#AeroGlassImg),ImageHeight(#AeroGlassImg),"",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
SetWindowLongPtr_(WindowID(#GlassWin), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(#GlassWin), #GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)
StickyWindow(#GlassWin, #True) 


hDC = StartDrawing(ImageOutput(#AeroGlassImg)) 
With sz
  \cx = ImageWidth(#AeroGlassImg)
  \cy = ImageHeight(#AeroGlassImg)
EndWith
With BlendMode 
  \SourceConstantAlpha = 255 
  \AlphaFormat = 1
EndWith

UpdateLayeredWindow_(WindowID(#GlassWin),0,0,@sz,hDC,@ContextOffset,0,@BlendMode,2)
StopDrawing()

OpenWindow(#ControlsWin, WindowX(#GlassWin), WindowY(#GlassWin), WindowWidth(#GlassWin), WindowHeight(#GlassWin), "", #PB_Window_BorderLess|#PB_Window_Invisible,WindowID(#GlassWin))
SetWindowColor(#ControlsWin, #Green)
SetWindowLong_(WindowID(#ControlsWin), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(#ControlsWin), #Green, 255, #LWA_COLORKEY) 

CalendarGadget(#CalendarGadget,100,100,250,200)
HideWindow(#ControlsWin, #False) 

BindEvent(#PB_Event_MoveWindow,@ControlsWinCB())
SetActiveWindow(#GlassWin)  

Repeat
  ev=WaitWindowEvent()
  Select ev
    Case #WM_LBUTTONDOWN
      SendMessage_(WindowID(#GlassWin), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    Case #PB_Event_RightClick
      CloseWindow(#ControlsWin)
      CloseWindow(#GlassWin)
      End
  EndSelect
Until ev = #PB_Event_CloseWindow

Procedure PreMultiply(image)
  StartDrawing(ImageOutput(image))
  DrawingMode(#PB_2DDrawing_AllChannels)
  For j=0 To ImageHeight(image)-1
    For i=0 To ImageWidth(image)-1
      color = Point(i,j)
      Plot(i,j, RGBA(Red(color)   & $FF * Alpha(color) & $FF / $FF,
                     Green(color) & $FF * Alpha(color) & $FF / $FF,
                     Blue(color)  & $FF * Alpha(color) & $FF / $FF,
                     Alpha(color)))
    Next
  Next
  StopDrawing()
EndProcedure

Re: Transparent PNG alpha channel window

Posted: Thu May 05, 2022 6:50 pm
by netmaestro
I am working on a demo code for you, should be ready sometime in the next day or so. In the meantime, here's the basic method in a nutshell:

1. Create a transparent image of the desired dimensions
2. Draw a white box to it with an alpha value of around 140 (or whatever looks good to you). A slight tint might be desirable, up to you.
3. Decide where on the screen you want your frosted glass
4. Take a screenshot of this rectangle
5. Apply a gaussian blur to the screenshot
6. Create an output image same size
7. Draw the blurred image on it
8. Draw the alpha image on it
9. Render the output image to the screen

The result will be a rectangle with a frosted glass appearance, with contents under the glass looking somewhat blurry. If you draw a bathroom or something this could go over top of it in case anyone goes in there. Anyway look for some demo code in the next day or two.

As I am almost criminally lazy I'm going to wait until Keya isn't looking and steal his blur code from:

https://www.purebasic.fr/english/viewtopic.php?p=577063

Because he did an excellent job and I'm tired of reinventing wheels.

Re: Transparent PNG alpha channel window

Posted: Fri May 06, 2022 1:37 pm
by punak
@netmaestro : thank you for your effort, I can't wait... :D

Re: Transparent PNG alpha channel window

Posted: Fri May 06, 2022 3:44 pm
by acreis
Me too

Re: Transparent PNG alpha channel window

Posted: Sat May 07, 2022 6:58 am
by BarryG
+1

Re: Transparent PNG alpha channel window

Posted: Mon May 09, 2022 4:22 pm
by netmaestro
I'm still fighting to achieve this. I've been on it all weekend with only limited success. There are two basic problems: 1) How to achieve faster performance for the blur and 2) How to grab a screenshot beneath my own window without including my window in it. Microsoft made a perfect solution in Vista with the DwmEnableBlurBehindWindow function (dwmapi.dll) and screenshots of it working look excellent. But while the API runs successfully it no longer blurs the area behind the window starting with Windows 8 because they changed the way windows are drawn. If anyone is able to assist with either of these two issues, your input would be very welcome. I'm not giving up on this.

Re: Transparent PNG alpha channel window

Posted: Mon May 09, 2022 10:14 pm
by netmaestro
Okay I have a couple of ideas. On the blur speed, I've submitted Keya's blur code to wilbert, if he can't speed it up no one can. On screenshotting the area under my window without including my window I can remove the whole client area using SetWindowRgn_() and my client area bits can't interfere with anything if they aren't there. Starting to look hopeful now.