Trying to find display (screen) names

Does anyone know how to detect the names of connected screens (e.g. “Built-in Retina Display”, or “Thunderbolt Display”)? I am currently referring to them in my app as “Display 1”, “Display 2”, etc., but I’d like to present the user with something more useful. I haven’t found anything in the MBS suite with this ability. Cheers.

we have several ways.

One is to use NSScreenMBS class and then query localizedName property.

And just for reference and for those who don’t want or can’t use a Plugin:

Dim sScreenLocalizedNames() As String

#If TargetMacOS Then
  Declare Function NSClassFromString Lib "Foundation" (className As CFStringRef) As Ptr
  Declare Function getScreens Lib "AppKit" selector "screens" (ptrToNSScreenClass As Ptr) As Ptr
  Declare Function getLocalizedName Lib "AppKit" selector "localizedName" (ptrToNSScreenInstance As Ptr) As CFStringRef
  
  Declare Function NSArrayCount Lib "Foundation" selector "count" (ptrToNSArray As Ptr) As UInteger
  Declare Function NSArrayObjectAtIndex Lib "Foundation" selector "objectAtIndex:" (ptrToNSArray As Ptr, index As UInteger) As Ptr
  
  Dim ptrNSScreenClass As Ptr = NSClassFromString("NSScreen")
  Dim ptrScreensArray As Ptr = getScreens(ptrNSScreenClass)
  Dim iScreensArrayCount As UInteger = NSArrayCount(ptrScreensArray)
  
  For i As Integer = 0 To iScreensArrayCount - 1
    Dim ptrToNSScreen As Ptr = NSArrayObjectAtIndex(ptrScreensArray, i)
    sScreenLocalizedNames.Append(getLocalizedName(ptrToNSScreen))
  Next
#EndIf

Me.Text = Join(sScreenLocalizedNames, ", ")

Note: This code is just to get an idea which Declares are involved. Could need more error checking.

2 Likes

Also the function localizedName is macOS 10.15 or newer. I was looking for such a thing a couple of years ago and the amount of code required to this was a lot!

Thanks for the replies, that was exactly what I was looking for. I guess that I can live with it being Catalina and up, I’ll just default back to the old nomenclature for older systems. Cheers.

1 Like

You should use [NSObject respondsToSelector:] to figure out if it is supported, at least that is what Apple recommends you do as opposed to checking for the OS version.

#if targetMacOS and targetDesktop then
  Dim s as integer = NSWindowScreen( self.handle )
  if NSObjectRespondsToSelector( s, NSSelectorFromString( "localizedName" ) ) then
    // --- Do thing with screen name
  else
    // --- Get screen name it the old long winded way.
  end if

#elseif targetWindows then
  // --- Do Windows thang...
#endIf

Good point. Luckily this is a macOS only utility, so less to worry about. Thanks Sam.

1 Like

Not just to determine if this is running on a Mac or not, but also to determine that this function is available on a Mac.

In the recent years with Apple’s rabid pace of change, I have seen API that was only valid for one version of the OS, with it being deprecated the year after it was introduced.

1 Like

I second the check for ability, as Sam’s thought is right in removing things.

1 Like

This one uses CGDisplayMBS class and may work on older macOS versions:

Dim DisplayList() As CGDisplayMBS = CGDisplayMBS.GetActiveDisplayList()

For Each display As CGDisplayMBS In DisplayList
  
  Dim dict As Dictionary = display.Info
  Dim names As Dictionary = dict.Lookup( "DisplayProductName", Nil )
  If names <> Nil Then
    Dim name As String = names.Lookup("en_US", "?")
    MsgBox name+" "+display.PixelsWide.ToString+"x"+display.PixelsHigh.ToString
  end if
Next