Transparent image over MDI gadget over all windows

Just starting out? Need help? Post your questions and find answers here.
User avatar
marcoagpinto
Addict
Addict
Posts: 1076
Joined: Sun Mar 10, 2013 3:01 pm
Location: Portugal
Contact:

Transparent image over MDI gadget over all windows

Post by marcoagpinto »

Heya,

I have a button to display on my MDI gadget on Windows 11 which I want to appear over everything.

My best attempt was to create a window and then an image gadget inside it, but it gets an opaque area around the edges of the image.

Is there a way of fixing it? Maybe other way of achieving this?

Image

Thanks!
User avatar
marcoagpinto
Addict
Addict
Posts: 1076
Joined: Sun Mar 10, 2013 3:01 pm
Location: Portugal
Contact:

Re: Transparent image over MDI gadget over all windows

Post by marcoagpinto »

ChatGPT fixed it!!!!:

Code: Select all

EnableExplicit
UsePNGImageDecoder()

OpenWindow(0, 100, 100, 900, 600, "MDI host", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
MDIGadget(0, 0, 0, 900, 600, 0, 0)

; --- overlay window (borderless + transparent background)
Define.i w = 900, h = 600, overlay = 1, img
img = LoadImage(#PB_Any, "overlay.png")           ; make sure this file exists
OpenWindow(overlay, 100, 100, w, h, "", #PB_Window_BorderLess | #PB_Window_Invisible)
SetWindowColor(overlay, RGB(255, 0, 255))         ; choose a color NOT used in your image
ImageGadget(1, 0, 0, w, h, ImageID(img), #PB_Image_BorderLess)

; make everything in the window that is RGB(255,0,255) fully transparent
SetWindowLongPtr_(WindowID(overlay), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(overlay), #GWL_EXSTYLE) | #WS_EX_LAYERED | #WS_EX_TRANSPARENT)
SetLayeredWindowAttributes_(WindowID(overlay), RGB(255, 0, 255), 0, #LWA_COLORKEY)

; float on top of the MDI host
SetWindowPos_(WindowID(overlay), #HWND_TOPMOST, 100, 100, w, h, #SWP_SHOWWINDOW)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
User avatar
marcoagpinto
Addict
Addict
Posts: 1076
Joined: Sun Mar 10, 2013 3:01 pm
Location: Portugal
Contact:

Re: Transparent image over MDI gadget over all windows

Post by marcoagpinto »

and how do I do so that the windows I open having as parent the main window appear over this image?
Got it — you want your other windows (dialogs/tool windows you open from the main window) to appear above the overlay image.

Easiest fix: don’t make the overlay TOPMOST. Keep it a transparent, borderless window, but use #HWND_TOP (not #HWND_TOPMOST) and add #WS_EX_NOACTIVATE. Then any normal window you open (parented/owned by the main window) will rise above the overlay when it’s shown/activated.

Here’s the minimal tweak from the earlier snippet:

Code: Select all

; ... after OpenWindow(0) and MDIGadget(...)

; overlay window (transparent, click-through, NON-topmost)
OpenWindow(1, 100, 100, w, h, "", #PB_Window_BorderLess | #PB_Window_Invisible)
SetWindowColor(1, RGB(255,0,255))
ImageGadget(1, 0, 0, w, h, ImageID(img), #PB_Image_BorderLess)

; transparent background + no-activate so it never steals focus
Protected ex = GetWindowLongPtr_(WindowID(1), #GWL_EXSTYLE)
SetWindowLongPtr_(WindowID(1), #GWL_EXSTYLE, ex | #WS_EX_LAYERED | #WS_EX_TRANSPARENT | #WS_EX_NOACTIVATE)
SetLayeredWindowAttributes_(WindowID(1), RGB(255,0,255), 0, #LWA_COLORKEY)

; put it above the MDI host, but NOT topmost
SetWindowPos_(WindowID(1), #HWND_TOP, 100, 100, w, h, #SWP_SHOWWINDOW)
Now when you open another window, it’ll show over the image:

Code: Select all

; any normal top-level window you open will be above the overlay
OpenWindow(2, 160, 160, 320, 200, "Child/Dialog", #PB_Window_SystemMenu | #PB_Window_Tool)
; (optional) ensure it’s on top of non-topmost windows right away:
SetWindowPos_(WindowID(2), #HWND_TOP, 0,0,0,0, #SWP_NOMOVE|#SWP_NOSIZE|#SWP_SHOWWINDOW)
Why this works

By removing TOPMOST, the overlay stays above the MDI host but below any currently active normal windows.

#WS_EX_NOACTIVATE ensures the overlay never grabs focus (so your dialogs naturally come to the front).

You still keep the transparent background via the color key, so the overlay window itself isn’t opaque.

If you prefer your dialogs to always sit above everything the moment they’re created, keep that one-line SetWindowPos with #HWND_TOP on creation.

GPT SAID THIS AND IT WORKS!
Fred
Administrator
Administrator
Posts: 18344
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Transparent image over MDI gadget over all windows

Post by Fred »

We could close these forums soon :lol:
User avatar
marcoagpinto
Addict
Addict
Posts: 1076
Joined: Sun Mar 10, 2013 3:01 pm
Location: Portugal
Contact:

Re: Transparent image over MDI gadget over all windows

Post by marcoagpinto »

Fred wrote: Thu Oct 09, 2025 4:12 pm We could close these forums soon :lol:
@Fred

At least I found the answer without giving work to anyone and still posted here the snippet for other users who want to do the same I did in their apps.
dcr3
Enthusiast
Enthusiast
Posts: 188
Joined: Fri Aug 04, 2017 11:03 pm

Re: Transparent image over MDI gadget over all windows

Post by dcr3 »

Interesting :!:

Which PB Version has,this #PB_Image_BorderLess.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 676
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Transparent image over MDI gadget over all windows

Post by minimy »

Fred wrote: Thu Oct 09, 2025 4:12 pm We could close these forums soon :lol:
Nooo, please!! :lol:
I ask chatgpt and say: 'fred dont close the forums...' :mrgreen:

dcr3 wrote: Thu Oct 09, 2025 8:53 pm Interesting :!:

Which PB Version has,this #PB_Image_BorderLess.
I think 5.x or bigger. With 6.x sure.

marcoagpinto may be this can help you.
Your method use a blend like simple chroma key (pixelated) no antialias.
I found this in my archive. With this method you have the window with alpha blend.

Code: Select all

  Procedure   imagePNGaWin(win.l, img.i, alfa.a=255)
    ;modo de capa para la ventana
    SetWindowLong_(WindowID(win), #GWL_EXSTYLE, GetWindowLong_(WindowID(win), #GWL_EXSTYLE) | #WS_EX_LAYERED)
  
    Protected.i WindowID= WindowID(win)
    Protected.i ImageID=ImageID(img)
  ;   Protected.a Alpha= alfa
    Protected   Image_HDC, Image_Bitmap.BITMAP
    Protected   Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
    Protected xx, yy, x, y, rojo, verde, azul, canalAlfa
     
    ; Précalculo
    Protected  Dim alfa.f(255)
    For x = 0 To 255
      alfa(x) = x / 255
    Next
     
    ; Carga del HDC
    Image_HDC = CreateCompatibleDC_(#Null)
    Image_Ancienne = SelectObject_(Image_HDC, ImageID)
     
    ; Dimension de la imagen
    GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
    Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
    Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
    Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
    Image_BitmapInfo\bmiHeader\biPlanes = 1
    Image_BitmapInfo\bmiHeader\biBitCount = 32
     
    ; Zona de memoria de la imagen
    xx = Image_Bitmap\bmWidth - 1
    yy = Image_Bitmap\bmHeight - 1
    Protected Dim Image.l(xx, yy)
     
     ; Copia la imagen en memoria
    GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
     
    ; Modificacion de la imagen en la memoria
    For x = 0 To xx
      For y = 0 To yy
       colorRGB = Image(x, y)
       canalAlfa = colorRGB >> 24 & 255
        If canalAlfa < 255
          rojo= (colorRGB & 255) * alfa(canalAlfa)
          verde=(colorRGB >> 8 & 255) * alfa(canalAlfa)
          azul= (colorRGB >> 16 & 255) * alfa(canalAlfa)
          Image(x, y) = rojo | verde << 8 | azul << 16 | canalAlfa << 24
        EndIf
      Next
    Next
     
    ; Transferencia de la memoria a la imagen
    SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
     
    ; Imagenn convertida en skin de la ventana
    Blend\SourceConstantAlpha = alfa  ; nivel de transparencia
    Blend\AlphaFormat = 1             ; activación del canal alpha
    Blend\BlendOp = 0
    Blend\BlendFlags = 0
    UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
     
    ; Formacion del HDC
    SelectObject_(Image_HDC, Image_Ancienne)
    DeleteDC_(Image_HDC)
  EndProcedure
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply