Get System HighlightColor for ListBox row BG in Cocoa

Hi, I’m looking for code to get the correct highlight color for a listbox row when the window is active and inactive. Until now I have been able to use the following code (copied from a REALBasic forum/list) for carbon builds:

[code]Declare function GetThemeBrushAsColor lib “Carbon” (inBrush as Integer, inDepth as Integer, inColorDev as Integer, outColor as ptr) as Integer

  Dim oc as MemoryBlock = new MemoryBlock(6)
  
  If GetThemeBrushAsColor(-5, 32, 1, oc) <> 0 then
    ActiveColor =  HighlightColor
  else
    ActiveColor = RGB(oc.byte(0), oc.byte(2), oc.byte(4))
  end if
  
  If GetThemeBrushAsColor(-4, 32, 1, oc) <> 0 then
    InActiveColor = DarkBevelColor
  else
    InActiveColor =  RGB(oc.byte(0), oc.byte(2), oc.byte(4))
  end if
  [/code]

When I use this code for cocoa builds in OS X 10.9.5 the Active color is a little bit light while the inactive color is good. However when I run the app in OS X 10.10.1 the highlight color is completely wrong (not sure what the inactive was doing).

Looking at another post I saw reference to Christian’s ‘NSColorMBS.highlightColor’. I tried this but it seems to return white when the system highlight color is set to blue.

Does anyone have a way to get these two colours for Cocoa?

with a color picker I get &c0550CF and &cCACACA

OSX 10.10.2

Thanks Alex, I may use that in the mean time but I’d rather get these colors from OS X if the user changes the Highlight color in the system prefs

Here’s a bit of code that I think will do what you’re after. It depends on macoslib to get the NSCalibratedRGBColorSpace constant, but that could be replaced with calls to CFBundle/NSBundle or dlopen and dlsym.

One thing worth noting is that a Xojo color is incapable of representing all possible NSColor values. For example, some system colors are patterns and just extracting the red, green, and blue components loses information. Also, not all NSColors even can have their RGB components fetched.

[code]Private Function ProperHighlightColor(active as Boolean) As Color
#if TargetMacOS
Declare Function NSClassFromString Lib “Foundation” ( name As CFStringRef ) As Ptr
Declare Function alternateSelectedControlColor Lib “AppKit” Selector “alternateSelectedControlColor” ( obj As Ptr ) As Ptr
Declare Function secondarySelectedControlColor Lib “AppKit” Selector “secondarySelectedControlColor” ( obj As Ptr ) As Ptr
Declare Function colorUsingColorSpaceName Lib “AppKit” Selector “colorUsingColorSpaceName:” (obj As Ptr, name As Ptr) As Ptr
#If Target32Bit
Declare Function redComponent Lib “AppKit” Selector “redComponent” (obj As Ptr) As Single
Declare Function greenComponent Lib “AppKit” Selector “greenComponent” (obj As Ptr) As Single
Declare Function blueComponent Lib “AppKit” Selector “blueComponent” (obj As Ptr) As Single
#else
Declare Function redComponent Lib “AppKit” Selector “redComponent” (obj As Ptr) As Double
Declare Function greenComponent Lib “AppKit” Selector “greenComponent” (obj As Ptr) As Double
Declare Function blueComponent Lib “AppKit” Selector “blueComponent” (obj As Ptr) As Double
#Endif

Static NSColor As Ptr = NSClassFromString("NSColor")
Static NSCalibratedRGBColorSpace As Ptr
If NSCalibratedRGBColorSpace = Nil Then
  Dim bundle As CFBundle = CFBundle.NewCFBundleFromID("com.apple.AppKit")
  NSCalibratedRGBColorSpace = bundle.DataPointerNotRetained("NSCalibratedRGBColorSpace").Ptr(0)
End If

Dim theColor As Ptr
If active Then
  theColor = alternateSelectedControlColor(NSColor)
Else
  theColor = secondarySelectedControlColor(NSColor)
End If

Dim rgbColor As Ptr = colorUsingColorSpaceName(theColor, NSCalibratedRGBColorSpace)
If rgbColor <> Nil Then
  Dim red As Integer = redComponent(rgbColor) * 255.0
  Dim green As Integer = greenComponent(rgbColor) * 255.0
  Dim blue As Integer = blueComponent(rgbColor) * 255.0
  Return RGB(red, green, blue)
Else
  Return HighlightColor
End If

#else
return HighlightColor
#endif
End Function[/code]

Yeah, hardcoding color values is typically a bad idea unless there truly is no supported way to get the information.

Thanks Joe - your code works a treat. Tested my Cocoa app on OS X 10.7.5, 10.9.5 and 10.10.1. All good for active and inactive color and all follow the color set in the system preferences.

Regards,

Mark

and same using plugin:

[code]Function ProperHighlightColor(active as Boolean) As Color
#if TargetCocoa
Dim theColor As NSColorMBS
If active Then
theColor = NSColorMBS.alternateSelectedControlColor
Else
theColor = NSColorMBS.secondarySelectedControlColor
End If

Dim rgbColor As NSColorMBS = theColor.colorUsingColorSpaceName(NSColorSpaceMBS.NSCalibratedRGBColorSpace)
If rgbColor <> Nil Then
  Dim red   As Integer = rgbColor.redComponent   * 255.0
  Dim green As Integer = rgbColor.greenComponent * 255.0
  Dim blue  As Integer = rgbColor.blueComponent  * 255.0
  Return RGB(red, green, blue)
Else
  Return HighlightColor
End If

#else
return HighlightColor
#endif
End Function
[/code]

That was for my customers who don’t love macoslib so much :slight_smile:

This begs the question of why this is not a shared Xplatform method on the listbox in the framework?

Almost everyone who does anything interesting with the listbox needs to paint the selection highlight themselves sometimes…

I believe way back when ( Maybe as far back as REALBugs for those that remember that app) I put in a feature request… don’t know if it is in the current system anymore… After I got declares that worked some years back I stopped worrying about it… But apparently, if I read the posts here correctly, in 10.10 (I’m still on 10.9) those declares no longer give the right color.

  • Karen

[quote=163380:@Karen Atkocius]This begs the question of why this is not a shared Xplatform method on the listbox in the framework?

Almost everyone who does anything interesting with the listbox needs to paint the selection highlight themselves sometimes…

I believe way back when ( Maybe as far back as REALBugs for those that remember that app) I put in a feature request… don’t know if it is in the current system anymore… After I got declares that worked some years back I stopped worrying about it… But apparently, if I read the posts here correctly, in 10.10 (I’m still on 10.9) those declares no longer give the right color.

  • Karen[/quote]

I am even surprised that works at all in a cocoa build, as the OP seems to indicate, since they are Carbon declares.

A quick search in the Mac Developer Library does not even show any result for GetThemeBrushAsColor.

Many thanks Christian for the cocoa code. Tested my Cocoa app on OS X 10.7.5, 10.9.5 and 10.10.1 - All good for active and inactive color. Rather use this than have to carry MacOSLib in my project.

Regards,

Mark

GetThemeBrushAsColor is old and deprecated, but still exists.

It would be nice if a future Xojo version has a property on the listbox (like web edition) to automatic get the behavior. (and still be able to overwrite in events)