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?
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]
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.
[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]
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.
[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.
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)