Page 1 of 1

Transparent Window Background Image

Posted: Fri Jul 20, 2012 10:01 am
by IdeasVacuum
Well, this has proven to be very tricky. I have set a Window to be transparent where a region is blue. There is an ImageGadget the same size as the Window. Any part of the image that is pure blue should be transparent, and it is.

Yet there is a snag........ bit depth.

WindowsXP 32bit: If the image is 32bits, the Window is see-through but you can still hold left-mouse down in the transparent region and move the window without any issue (exactly what I need, perfect). If the image is 24bits, the Window is see-through but too see-through - the mouse picks whatever there is underneath the window in the transparent region.

Windows 7 (32bit exe on Win 7 64bit): Both 32bit and 24bit images are "too see-through" as described above.

Test Code:

Code: Select all

#BackBlue = 16711680 ;RGB(0,0,255)

Enumeration
#Win
#ImageGdt
#BtnExit
EndEnumeration

iFlags.i = #PB_Window_BorderLess|#PB_Window_Invisible|#PB_Window_ScreenCentered

  If OpenWindow(#Win, 0, 0, 400, 400, "Transparent Win",iFlags)

                  SetWindowLongPtr_(WindowID(#Win), #GWL_EXSTYLE, #WS_EX_LAYERED | #WS_EX_TOPMOST)
        SetLayeredWindowAttributes_(WindowID(#Win),#BackBlue,0,#LWA_COLORKEY)

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                    iImage.i = CreateImage(#PB_Any, 400, 400, 32) ;<<<< Change to 24bit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        If StartDrawing(ImageOutput(iImage))
        
                        DrawingMode(#PB_2DDrawing_Default)
                                Box(0,0,400,400,#BackBlue)
                                Box(20,20,360,360,RGB(0,0,0))
                                Box(50,50,300,300,#BackBlue)
                        StopDrawing()

                        ImageGadget(#ImageGdt,0,0,400,400,ImageID(iImage))
                      DisableGadget(#ImageGdt,#True)
        EndIf

        ButtonGadget(#BtnExit,10,10,50,30,"Exit")

          HideWindow(#Win,#False)
        StickyWindow(#Win,#True)

           iQuit.i = #False
        iEventID.i = 0

        Repeat

                        iEventID = WaitWindowEvent(1)
                 Select iEventID

                         Case #WM_LBUTTONDOWN

                              SendMessage_(WindowID(#Win), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)

                         Case #WM_RBUTTONDOWN : iQuit = #True

                         Case #PB_Event_Gadget

                              If (EventGadget() = #BtnExit) : iQuit = #True : EndIf
                 EndSelect

        Until iQuit = #True
  EndIf

  FreeImage(iImage)
  End
Is there a simple remedy?

Re: Transparent Window Background Image

Posted: Fri Jul 20, 2012 12:19 pm
by Lord
IdeasVacuum wrote:..
Windows 7 (32bit exe on Win 7 64bit): Both 32bit and 24bit images are "too see-through" as described above.
...

.. and on Win7 64Bit exe works too.

Nice!

Re: Transparent Window Background Image

Posted: Fri Jul 20, 2012 3:06 pm
by RASHAD
Hi IdeasVacuum

I faced that problem before between SetLayeredWindowAttributes and Windows XP
Next is what I did to overcome that problem
Hope it will satisfy you

Code: Select all

#BackBlue = 16711680 ;RGB(0,0,255)

Enumeration
#Win
#Win0
#ImageGdt
#BtnExit
#String
EndEnumeration

iFlags.i = #PB_Window_BorderLess|#PB_Window_ScreenCentered

 

  OpenWindow(#Win, 0, 0, 400, 400, "Transparent Win",iFlags)

                  SetWindowLongPtr_(WindowID(#Win), #GWL_EXSTYLE, #WS_EX_LAYERED )
        SetLayeredWindowAttributes_(WindowID(#Win),#BackBlue , 0, #LWA_COLORKEY)

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                    iImage.i = CreateImage(#PB_Any, 400, 400, 24) ;<<<< Change to 24bit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        If StartDrawing(ImageOutput(iImage))
       
                        DrawingMode(#PB_2DDrawing_Default)
                                Box(0,0,400,400,#BackBlue)
                                Box(20,20,360,360,RGB(0,0,0))
                                Box(50,50,300,300,#BackBlue)
                        StopDrawing()

                        ImageGadget(#ImageGdt,0,0,400,400,ImageID(iImage))
                      DisableGadget(#ImageGdt,#True)
        EndIf

        ButtonGadget(#BtnExit,10,10,50,30,"Exit")

          ;HideWindow(#Win,#False)
        StickyWindow(#Win,#True)

           iQuit.i = #False
        iEventID.i = 0
        OpenWindow(#Win0, 0, 0, 300, 300, "Transparent Win",iFlags)
        SetWindowLongPtr_(WindowID(#Win0), #GWL_EXSTYLE, #WS_EX_LAYERED)
        SetLayeredWindowAttributes_(WindowID(#Win0),0,1,#LWA_ALPHA)
        
       
        Repeat

                        iEventID = WaitWindowEvent(1)
                 Select iEventID
                 
                         Case #WM_MOVE;,#WM_SIZE
                              ResizeWindow(#Win0,WindowX(#Win)+50,WindowY(#Win)+50,300,300)

                         Case #WM_LBUTTONDOWN
                              SendMessage_(WindowID(#Win), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)

                         Case #WM_RBUTTONDOWN : iQuit = #True

                         Case #PB_Event_Gadget

                              If (EventGadget() = #BtnExit) : iQuit = #True : EndIf
                 EndSelect

        Until iQuit = #True


  FreeImage(iImage)
  End

Re: Transparent Window Background Image

Posted: Fri Jul 20, 2012 8:38 pm
by IdeasVacuum
Hi Rashad

That works really well! How on earth did you work out that it would? :?

Re: Transparent Window Background Image

Posted: Mon Jul 23, 2012 3:39 am
by IdeasVacuum
Oh dear - back to square one!

First issue is that if a background image is more complex (only some regions being the key colour), the 2nd Window method does not work. I also see 'flashing' when the mouse cursor is swiped across the window - in fact, it seems to reveal that Win7 redraws windows more often than XP does - don't know, just my impression.

However, even if it did work, it has an unacceptable issue of it's own - the task bar tells the User that there are 2 windows :?

Re: Transparent Window Background Image

Posted: Mon Jul 23, 2012 7:34 am
by Bisonte
Hide it with :

Code: Select all

EnableExplicit

Procedure HideFromTaskBar(hWnd.l, Flag.l)
  Protected TBL.ITaskbarList
  CoInitialize_(0)
  If CoCreateInstance_(?CLSID_TaskBarList, 0, 1, ?IID_ITaskBarList, @TBL) = #S_OK
    TBL\HrInit()
    If Flag
      TBL\DeleteTab(hWnd)
    Else
      TBL\AddTab(hWnd)
    EndIf
    TBL\Release()
  EndIf
  CoUninitialize_()
 
  DataSection
    CLSID_TaskBarList:
    Data.l $56FDF344
    Data.w $FD6D, $11D0
    Data.b $95, $8A, $00, $60, $97, $C9, $A0, $90
    IID_ITaskBarList:
    Data.l $56FDF342
    Data.w $FD6D, $11D0
    Data.b $95, $8A, $00, $60, $97, $C9, $A0, $90
  EndDataSection
EndProcedure

If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  
  HideFromTaskBar(WindowID(0),1)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Source : http://www.rsbasic.de/winapi-library/

Re: Transparent Window Background Image

Posted: Mon Jul 23, 2012 9:41 am
by TI-994A
Hi IdeasVacuum. Here's a simple way to hide the second window from the taskbar, by initially making it invisible, adding the #WS_EX_TOOLWINDOW style, and then unhiding it. However, it's only been tested with WinXP:

Code: Select all

...
 ...
  OpenWindow(#Win0, 0, 0, 300, 300, "Transparent Win",iFlags | #PB_Window_Invisible)
  SetWindowLongPtr_(WindowID(#Win0), #GWL_EXSTYLE, #WS_EX_LAYERED | #WS_EX_TOOLWINDOW)
  SetLayeredWindowAttributes_(WindowID(#Win0),0,1,#LWA_ALPHA)
  HideWindow(#Win0, 0)
 ...
...

Re: Transparent Window Background Image

Posted: Mon Jul 23, 2012 11:00 am
by RASHAD
Hi IdeasVacuum :)

1- Flashing issue resolved
2- Second window in TaskBar resolved
3- Added another way to catch any border less window
SendMessage_(WindowID(#Win),#WM_SYSCOMMAND, #SC_DRAGMOVE, 0)

Hope you like it

Are you using an image other than the one you posted ?
Code #1

Code: Select all

#BackBlue = 16711680 ;RGB(0,0,255)

Enumeration
#Win
#Win0
#ImageGdt
#BtnExit
EndEnumeration

#SC_DRAGMOVE = $F012

iFlags.i = #PB_Window_BorderLess|#PB_Window_ScreenCentered


  OpenWindow(#Win, 0, 0, 400, 400, "Transparent Win",iFlags)
                  SetWindowLongPtr_(WindowID(#Win), #GWL_EXSTYLE, #WS_EX_LAYERED )
        SetLayeredWindowAttributes_(WindowID(#Win),#BackBlue , 0, #LWA_COLORKEY)

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                    iImage.i = CreateImage(#PB_Any, 400, 400, 24) ;<<<< Change to 24bit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        If StartDrawing(ImageOutput(iImage))
       
                        DrawingMode(#PB_2DDrawing_Default)
                                Box(0,0,400,400,#BackBlue)
                                Box(20,20,360,360,RGB(0,0,0))
                                Box(50,50,300,300,#BackBlue)
                        StopDrawing()

                        ImageGadget(#ImageGdt,0,0,400,400,ImageID(iImage))
                      DisableGadget(#ImageGdt,#True)
        EndIf

        ButtonGadget(#BtnExit,10,10,50,30,"Exit")

          ;HideWindow(#Win,#False)
        StickyWindow(#Win,#True)

           iQuit.i = #False
        iEventID.i = 0
        If OSVersion() < #PB_OS_Windows_Vista
            OpenWindow(#Win0, 0, 0, 300, 300, "",iFlags)
            SetWindowLongPtr_(WindowID(#Win0), #GWL_EXSTYLE, #WS_EX_LAYERED)
            SetLayeredWindowAttributes_(WindowID(#Win0),0,1,#LWA_ALPHA)
    
            SetWindowLongPtr_(WindowID(#Win0),#GWL_HWNDPARENT,WindowID(#Win))
        EndIf
        
       
        Repeat

                        iEventID = WaitWindowEvent(1)
                 Select iEventID
;                  
                         Case #WM_MOVE;#WM_SIZE
                              If OSVersion() < #PB_OS_Windows_Vista
                                  ResizeWindow(#Win0,WindowX(#Win)+50,WindowY(#Win)+50,300,300)
                              EndIf

                         Case #WM_LBUTTONDOWN
                              SendMessage_(WindowID(#Win),#WM_SYSCOMMAND, #SC_DRAGMOVE, 0)
                              ;SendMessage_(WindowID(#Win), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)                       

                         Case #WM_RBUTTONDOWN : iQuit = #True

                         Case #PB_Event_Gadget

                              If (EventGadget() = #BtnExit) : iQuit = #True : EndIf
                 EndSelect

        Until iQuit = #True


  FreeImage(iImage)
  End

Think of it the other way around
See which one is better

Code #2

Code: Select all

#BackBlue = 16711680 ;RGB(0,0,255)

Enumeration
#Win
#Win0
#ImageGdt
#BtnExit
EndEnumeration

#SC_DRAGMOVE = $F012

iFlags.i = #PB_Window_BorderLess|#PB_Window_ScreenCentered|#PB_Window_Invisible

            OpenWindow(#Win0, 0, 0, 400, 400, "",iFlags)
            SetWindowLongPtr_(WindowID(#Win0), #GWL_EXSTYLE, #WS_EX_LAYERED)
            SetLayeredWindowAttributes_(WindowID(#Win0),0,1,#LWA_ALPHA)
            
            
  OpenWindow(#Win, 0, 0, 400, 400, "Transparent Win",#WS_POPUP|iFlags,WindowID(#Win0))
                  SetWindowLongPtr_(WindowID(#Win), #GWL_EXSTYLE, #WS_EX_LAYERED )
        SetLayeredWindowAttributes_(WindowID(#Win),#BackBlue , 0, #LWA_COLORKEY)
                  SetWindowLongPtr_(WindowID(#Win0),#GWL_HWNDPARENT,WindowID(#Win))
                  
 ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                    iImage.i = CreateImage(#PB_Any, 400, 400, 24) ;<<<< Change to 24bit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        If StartDrawing(ImageOutput(iImage))
       
                        DrawingMode(#PB_2DDrawing_Default)
                                Box(0,0,400,400,#BackBlue)
                                Box(20,20,360,360,RGB(0,0,0))
                                Box(50,50,300,300,#BackBlue)
                        StopDrawing()

                        ImageGadget(#ImageGdt,0,0,400,400,ImageID(iImage))
                      DisableGadget(#ImageGdt,#True)
        EndIf

        ButtonGadget(#BtnExit,10,10,50,30,"Exit")
        HideWindow(#Win,0)
        HideWindow(#Win0,0)
      
        Repeat

                        iEventID = WaitWindowEvent(1)
                 Select iEventID
;                  
                         Case #WM_MOVE;#WM_SIZE
                                  MoveWindow_(WindowID(#Win0),WindowX(#Win),WindowY(#Win),400,400,1)

                         Case #WM_LBUTTONDOWN
                              SendMessage_(WindowID(#Win),#WM_SYSCOMMAND, #SC_DRAGMOVE, 0)
                              ;SendMessage_(WindowID(#Win), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)                       

                         Case #WM_RBUTTONDOWN : iQuit = #True

                         Case #PB_Event_Gadget

                              If (EventGadget() = #BtnExit) : iQuit = #True : EndIf
                 EndSelect

        Until iQuit = #True


  FreeImage(iImage)
  End
EDIT: Snippet #2 modified
You can use any skinned image, all the transparent regions are active now

Good luck

Re: Transparent Window Background Image

Posted: Tue Jul 24, 2012 4:03 pm
by IdeasVacuum
Hi Rashad

Thank you for having another look at the issue. The new solution brings a new problem (each Window has it's own cursor and there is cursor flashing on mouse move/hover) but, unfortunately, the original problem is still there! I'm going to go back to basics and try another approach but otherwise I think I'll simply disable transparency as an option on Win7. It has always worked fine on XP.

off topic: It is actually sunny in the UK today! 8)

Re: Transparent Window Background Image

Posted: Thu Jul 26, 2012 3:58 am
by RASHAD
Works great with XP & Windows 7 :mrgreen:
Very flexible

Code: Select all

#SC_DRAGMOVE = $F012

Procedure AlphaImageWindow(WindowID, ImageID, Alpha)
  Protected Image_HDC, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
  Protected xx, yy, x, y, Red, Green, Blue, AlphaChannel
  Protected Dim Grate.f($FF)
  For x = 0 To $FF
    Grate(x) = x / $FF
  Next
   
  Image_HDC = CreateCompatibleDC_(#Null)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
   
  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
   
  xx = Image_Bitmap\bmWidth - 1
  yy = Image_Bitmap\bmHeight - 1
  Protected Dim Image.l(xx, yy)
   
  GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
  For x = 0 To xx
    For y = 0 To yy
      Color = Image(x, y)
      AlphaChannel = Color >> 24 & $FF
      If AlphaChannel < $FF
        Red = (Color & $FF) * Grate(AlphaChannel)
        Green = (Color >> 8 & $FF) * Grate(AlphaChannel)
        Blue = (Color >> 16 & $FF) * Grate(AlphaChannel)
        Image(x, y) = Red | Green << 8 | Blue << 16 | AlphaChannel << 24
      EndIf
    Next
  Next
   
  SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
  Blend\AlphaFormat = 1
  Blend\BlendOp = 0
  Blend\BlendFlags = 0
  Blend\SourceConstantAlpha = Alpha
  UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
     
  SelectObject_(Image_HDC, Image_Ancienne)
  DeleteDC_(Image_HDC)
  
EndProcedure

CreateImage(0, 400, 400,32)
StartDrawing(ImageOutput(0))         
   DrawingMode(#PB_2DDrawing_Default )
   Box(0,0,400,400,RGBA(255,255,255,1))
   Box(20,20,360,360,RGB(0, 0, 255))
   Box(40,40,320,320,RGB(255, 0, 0))
   DrawingMode(#PB_2DDrawing_Gradient)
   GradientColor(0.2, $00FF00)
   GradientColor(0.8, $00FF00)
   LinearGradient(0, 0, 200, 200)
   RoundBox(0,0,50,30,2,2)
   DrawingMode(#PB_2DDrawing_Outlined)
   RoundBox(0,0,50,30,2,2,RGB(0, 0, 0))
   DrawingMode(#PB_2DDrawing_Transparent)
   DrawText(10,7,"EXIT",$05FAE8)
   DrawingMode(#PB_2DDrawing_AlphaChannel)
   Box(60,60,280,280,RGBA(250,250,250,1))
   Box(50,0,350,20,RGBA(250,250,250,1))
   Box(0,380,400,20,RGBA(250,250,250,1))
   Box(0,30,20,350,RGBA(250,250,250,1))
   Box(380,20,20,360,RGBA(250,250,250,1))
StopDrawing()

CreateImage(1, 400, 400,32)
StartDrawing(ImageOutput(1))
   DrawingMode(#PB_2DDrawing_Default )
   Box(0,0,400,400,RGBA(255,255,255,1))
   Box(20,20,360,360,RGB(0, 0, 255))
   Box(40,40,320,320,RGB(255, 0, 0))
   DrawingMode(#PB_2DDrawing_Gradient)
   GradientColor(0.2, $00FFFF)
   GradientColor(0.8, $FFFF00)
   LinearGradient(0, 0, 200, 200)
   RoundBox(0,0,50,30,2,2)
   DrawingMode(#PB_2DDrawing_Outlined)
   RoundBox(0,0,50,30,2,2,RGB(0, 0, 0))
   DrawingMode(#PB_2DDrawing_Transparent)
   DrawText(10,7,"EXIT",$170DFE)         
   DrawingMode(#PB_2DDrawing_AlphaChannel)
   Box(60,60,280,280,RGBA(250,250,250,1))
   Box(50,0,350,20,RGBA(250,250,250,1))
   Box(0,380,400,20,RGBA(250,250,250,1))
   Box(0,30,20,350,RGBA(250,250,250,1))
   Box(380,20,20,360,RGBA(250,250,250,1))
StopDrawing()  


  OpenWindow(0, 0, 0, 400, 400, "Layered Window", #PB_Window_BorderLess | #PB_Window_ScreenCentered | #PB_Window_Invisible)
  SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)  
  AlphaImageWindow(WindowID(0), ImageID(0), 255)
  
  HideWindow(0, 0)

  Repeat
    Select WaitWindowEvent()
      Case #WM_MOUSEMOVE
            If WindowMouseX(0)>2 And WindowMouseX(0)<48 And WindowMouseY(0)>2 And WindowMouseY(0)<28
                AlphaImageWindow(WindowID(0), ImageID(1), 255)
            Else
                AlphaImageWindow(WindowID(0), ImageID(0), 255)
            EndIf
            
      Case #WM_LBUTTONDOWN
            If WindowMouseX(0)>0 And WindowMouseX(0)<50 And WindowMouseY(0)>0 And WindowMouseY(0)<30
                Quit = 1
            Else
                SendMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_DRAGMOVE, 0)
            EndIf

    EndSelect
  Until Quit = 1
End


Re: Transparent Window Background Image

Posted: Thu Jul 26, 2012 1:48 pm
by electrochrisso
This one works real good RASHAD, no tearing when I move the window around, well done! :)

Re: Transparent Window Background Image

Posted: Thu Jul 26, 2012 11:16 pm
by IdeasVacuum
Hi Rashad

Thanks again - you are a glutton for punishment! :mrgreen:

Your sample works really well. I ripped chunks out of it to make it closer to my product code (the exit button for example). However, at the moment, I can't get it to work with any images (32bit png images). If using CatchImage, PB doesn't like it - if I use LoadImage (which my app will not be able to use) PB is happy but the image is not displayed (or it is displayed but I only see the black of the host image that the required image is drawn on, not sure which because I don't understand your code). I'm working on another project at the moment so I don't have time to investigate - at the end of the day, I can live without transparency on Win7 anyway - given that the original method works so nicely on XP, I thought the solution for Win7 would be a tiny change. Wrong!

Re: Transparent Window Background Image

Posted: Sat Jul 28, 2012 1:20 pm
by RASHAD