Get default window background color for transparency, all OS

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Get default window background color for transparency, all OS

Post by Keya »

I couldnt really find an existing all-OS version of this but the jigsaw pieces were all there to put together, so thanks to all the dozens of people who've contributed to the dozens of background-color threads!

Tested in Windows XP+7+10, Mac (El Capitan), and Linux Mint, but it'd be good to check if it works on all KDE/Gnome/Xfce Linuxii because there had been problems in the past in regards to this (but using a different api to the one im calling) http://www.purebasic.fr/english/viewtop ... 04&start=2

This demo simply has a Canvas gadget which defaults to flat white and doesn't seem to natively support transparency, so it changes that to the default window background and writes a DrawText() with that background color to achieve transparency like a simple Label/Text gadget would
Image

Code: Select all

Procedure GetWindowBackgroundColor(hwnd=0) ;hwnd only used in Linux, ignored in Win/Mac
  CompilerSelect #PB_Compiler_OS
      
    CompilerCase #PB_OS_Windows  
      Protected color = GetSysColor_(#COLOR_WINDOW)
      If color = $FFFFFF Or color=0: color = GetSysColor_(#COLOR_BTNFACE): EndIf
      ProcedureReturn color
      
    CompilerCase #PB_OS_Linux   ;thanks to uwekel http://www.purebasic.fr/english/viewtopic.php?p=405822
      Protected *style.GtkStyle, *color.GdkColor
      *style = gtk_widget_get_style_(hwnd) ;GadgetID(Gadget))
      *color = *style\bg[0]                ;0=#GtkStateNormal
      ProcedureReturn RGB(*color\red >> 8, *color\green >> 8, *color\blue >> 8)
      
    CompilerCase #PB_OS_MacOS   ;thanks to wilbert http://purebasic.fr/english/viewtopic.php?f=19&t=55719&p=497009
      Protected.i color, Rect.NSRect, Image, NSColor = CocoaMessage(#Null, #Null, "NSColor windowBackgroundColor")
      If NSColor
        Rect\size\width = 1
        Rect\size\height = 1
        Image = CreateImage(#PB_Any, 1, 1)
        StartDrawing(ImageOutput(Image))
        CocoaMessage(#Null, NSColor, "drawSwatchInRect:@", @Rect)
        color = Point(0, 0)
        StopDrawing()
        FreeImage(Image)
        ProcedureReturn color
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure  




;##### SIMPLE DEMO #####

#Dlg1 = 0
#Canvas1 = 1
OpenWindow(#Dlg1, 0, 0, 400, 100, "Window Background Color", #PB_Window_SystemMenu | #PB_Window_ScreenCentered |  #PB_Window_Invisible)
CanvasGadget(#Canvas1, 20, 24, 360, 60, #PB_Canvas_Border)
Define bgcolor = GetWindowBackgroundColor(WindowID(#Dlg1))
HideWindow(#Dlg1, 0) ;(proof that it also works with hidden window, as we would hope!)
SetWindowTitle(#Dlg1, GetWindowTitle(#Dlg1) + " = " + Hex(bgcolor,#PB_Long))

If StartDrawing(CanvasOutput(#Canvas1))
  Box(0,0,GadgetWidth(#Canvas1), GadgetHeight(#Canvas1), bgcolor)                 ;fill the canvas with the background color
  DrawText(2,10, "Background should be same color as outer", RGB(0,0,0), bgcolor) ;text should now have 'transparent' backround
  StopDrawing()
EndIf

Repeat
  Define event.i = WaitWindowEvent()
Until event = #PB_Event_CloseWindow
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Get default window background color for transparency, al

Post by Shardik »

Thank you for evaluating the already posted OS-specific codes and combining them into one cross-platform example. I have tested your example successfully with PB 5.43 x86 on these operating systems:

Linux (with both GTK2 and GTK3)
- Fedora 23 x86 with Gnome 3
- Kubuntu 14.04 x86 with KDE
- Linux Mint 18 x86 "Sarah" with Cinnamon
- Lubuntu 16.04 x86 with LXDE
- Ubuntu 16.04 x86 with Unity
- Xubuntu 16.04 x86 with Xfce

MacOS
- 10.6.8 (Snow Leopard) with PB 5.43 x86 and x64

Windows
- Windows XP SP3 x86
- Windows 7 SP1 x86
- Windows 8.1 x64

The only problem I found during testing was with Fedora 23 using subsystem GTK2 where the compilation stopped reporting that mixing GTK2 and GTK3 functions is not possible.

I have put a link to your code example into my link list of cross-platform API codes!
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Get default window background color for transparency, al

Post by Keya »

Shardik thanks heaps for running those tests! excellent to hear it ran on such a variety! :) and im guessing the one it failed to compile on still would've been able to run the executable from another build ok
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Get default window background color for transparency, al

Post by Keya »

this probably isn't usually required but i needed to add a check to ensure the detected color is actually a shade of grey

Code: Select all

;Determine if a color is grey
;Supports off-grey tolerance, eg. with RGB 50 50 53 a tolerance of 3 is ok but not 2.
;Tolerance is based on the max distance between r&g g&b b&r.
;It generally should be <20, down to 0 for exact greys where r,g,b must be all equal.
;Also supports a tolerance of minimum black and maximum white levels,
;eg. to disallow shades that are too close to black or white for your liking.

Macro MAX(a,b)
 (((Not a<=b)-1)&b)|(((Not b<a)-1)&a)
EndMacro

Procedure IsGrey(r,g,b, tolerance, minblack, maxwhite)
  Protected deltaRG, deltaGB, deltaBR, rc=0
  deltaRG = Abs(r-g)
  deltaGB = Abs(g-b)
  deltaBR = Abs(b-r)  
  If MAX(MAX(deltaRG,deltaGB),MAX(deltaGB,deltaBR)) <= tolerance
    Select (r+g+b)/3 ;average level, 0-255
      Case minblack To maxwhite: rc=1
    EndSelect
  EndIf
  ProcedureReturn rc
EndProcedure

Debug IsGrey(50,50,50, 0, $00,$FF) ;yes
Debug IsGrey(50,50,51, 1, $00,$FF) ;yes
Debug IsGrey(50,50,52, 1, $00,$FF) ;no: +2 is greater than the tolerance of 1
Debug IsGrey(50,50,52, 2, $00,$FF) ;yes
Debug IsGrey(0,0,0,    0, $01,$FE) ;no: black (000000) and white (FFFFFF) disallowed
Debug IsGrey(1,1,1,    0, $01,$FE) ;yes
User avatar
_aNdy_
User
User
Posts: 40
Joined: Fri Jun 17, 2016 12:06 am
Contact:

Re: Get default window background color for transparency, al

Post by _aNdy_ »

Just made use of this to tidy up an editor gadget in a new application I'm working on. The editor gadget is being used to display information about different loaded/saved files and looks much nicer in window bg colour rather than white or other.

Thanks for the code!
User avatar
oakvalley
User
User
Posts: 76
Joined: Sun Aug 08, 2004 6:34 pm
Location: Norway
Contact:

Re: Get default window background color for transparency, al

Post by oakvalley »

I've always used

Code: Select all

 StartDrawing(WindowOutput(0))
        win_back_color=Point(0,0)
   StopDrawing()
To set background color of editor gadget (or others) to same as window color :-)
Regards Stone Oakvalley
Currently @ PB 5.70
mestnyi
Addict
Addict
Posts: 1000
Joined: Mon Nov 25, 2013 6:41 am

Re: Get default window background color for transparency, al

Post by mestnyi »

oakvalley wrote:I've always used

Code: Select all

 StartDrawing(WindowOutput(0))
        win_back_color=Point(0,0)
   StopDrawing()
To set background color of editor gadget (or others) to same as window color :-)
This does not work on mac os.
in mac os i think it will be better

Code: Select all

Procedure GetWindowBackgroundColor()
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_MacOS   
      Protected.i NSColor = CocoaMessage(#Null, #Null, "NSColor windowBackgroundColor")
      
      If NSColor
        Protected.cgfloat red, green, blue, alpha
        Protected nscolorspace = CocoaMessage(0, nscolor, "colorUsingColorSpaceName:$", @"NSCalibratedRGBColorSpace")
        
        If nscolorspace
          CocoaMessage(@red, nscolorspace, "redComponent")
          CocoaMessage(@green, nscolorspace, "greenComponent")
          CocoaMessage(@blue, nscolorspace, "blueComponent")
          CocoaMessage(@alpha, nscolorspace, "alphaComponent")
          ProcedureReturn RGBA(red * 260.0, green * 260.0, blue * 260.0, alpha * 260.0)
        EndIf
      Else
        ProcedureReturn -1
      EndIf
      
  CompilerEndSelect
EndProcedure 
BarryG
Addict
Addict
Posts: 3322
Joined: Thu Apr 18, 2019 8:17 am

Re: Get default window background color for transparency, al

Post by BarryG »

Keya wrote:

Code: Select all

If color = $FFFFFF Or color=0: color = GetSysColor_(#COLOR_BTNFACE): EndIf
Why don't you accept black or white when the window is black or white?
Post Reply