Problem with Declares and Desktop Controls

I decided to take some time and attempt to convert my main project to start using some of the new Desktop Controls like DesktopListbox and DesktopPopUpMenu instead of the old Listbox and PopUpMenu controls.

First of all - it has been quite a bit of work. Second, I wonder if these “new” controls are really just the old ones but with different event names and method names. Is there any real advantage (other than autocomplete) to using the new controls?

But outside of that philosophical question, I have a more practical one. I have some declares that are used to get and set the sizes of PopUpMenus and PushButtons. These are now broken under the DesktopControls and it seems to revolve around that fact that in the old API, the Handle property of the control returned an integer while now the Handle property returns a Ptr. I thought it would be simple enough to use Ptr.Integer or Ptr.Int32, etc. but I get hard crashes of the app. Here is the code of the two Declares in question:

Public Function GetNSControlSize(Extends r as DesktopUIControl) As Pair
  #If TargetMacOS Then
    
    #If Target64Bit Then
      
      Declare Function getCell Lib "Cocoa" Selector "cell" ( handle As Integer ) As Integer
      Declare Function getBounds Lib "Cocoa" selector "bounds" (id As Integer) As NSRect64
      Declare Function getFrame Lib "Cocoa" selector "frame" (id As Integer) As NSRect64
      Declare Function convertRectToBacking Lib "Cocoa" selector "convertRectToBacking:" ( NSViewInstance As Integer, rect As NSRect64 ) As NSRect64
      Declare Function convertRectFromBacking Lib "Cocoa" selector "convertRectFromBacking:" ( NSViewInstance As Integer, rect As NSRect64 ) As NSRect64
      Declare Function convertSizeToBacking Lib "Cocoa" selector "convertSizeToBacking:" ( NSViewInstance As Integer, rect As NSSize64 ) As NSSize64
      
      Dim ctrl As Integer = r.Handle.Integer
      Dim cll as integer = getCell(ctrl)
      
      Dim MyRect As NSRect64 = getBounds(ctrl)
      
      Dim MyRect2 as NSRect64
      MyRect2 = convertRectFromBacking(ctrl,MyRect)
      
      Dim MySize As NSSize64 = MyRect.RSize
      Dim MySize2 as NSSize64 = convertSizeToBacking(ctrl,MySize)
      '
      Dim width As Double = MySize.width
      Dim height As Double = MySize.height
      
      // Adjust the values from what Cocoa reports - not sure why...
      If r IsA PopupMenu Then
        width = width-12
        height = height-12
      Elseif r IsA PushButton Then
        width = width-12
        height = height-12
      End If
      
      Dim p As pair = width : height
      Return p
      
    #Else
      
      Declare Function getFrame Lib "Cocoa" selector "frame" (id As ptr) As NSRect
      
      Dim ctrl As ptr=ptr(r.Handle)
      
      Dim MyRect As NSRect = getFrame(ctrl)
      
      Dim MySize As NSSize = MyRect.RSize
      
      Dim width As single = MySize.width
      Dim height As single = MySize.height
      
      Dim p As pair = width : height
      Return p
      
    #EndIf
  #EndIf
  
End Function

And

Public Sub setControlSize(Extends c as DesktopUIControl, inSize as NSControlSize)
  #If TargetMacOS Then
    Declare Function NSClassFromString Lib "Cocoa" (className As CFStringRef) As Ptr
    Declare Sub setSize Lib "Cocoa" Selector "setControlSize:" _
    ( ObjectHandle as Integer, inSize as NSControlSize )
    Declare function getCell lib "Cocoa" selector "cell" ( handle as integer ) as Integer
    
    if c isa progressBar or c isa ProgressWheel then
      setSize( c.handle.Integer, inSize )
      
    else
      setSize( getCell( c.handle.Integer ), inSize )
      
      // - Now we also update the text font to match
      Dim fontSize as Double
      
      select case inSize
      case NSControlSize.NSRegularControlSize
        declare function systemFontSize lib "Cocoa" selector "systemFontSize" _
        ( classRef as Ptr ) as Double
        fontSize = systemFontSize( NSClassFromString( "NSFont" ) )
        
      else
        // + (CGFloat)smallSystemFontSize
        declare function smallSystemFontSize lib "Cocoa" selector "smallSystemFontSize" _
        ( classRef as Ptr ) as Double
        fontSize = smallSystemFontSize( NSClassFromString( "NSFont" ) )
      end select
      
      // + (NSFont *)systemFontOfSize:(CGFloat)fontSize
      
      declare function systemFontOfSize lib "Cocoa" selector "systemFontOfSize:" _
      ( classRef as Ptr, inSize as Double ) as Ptr
      Dim ref as Ptr = systemFontOfSize( NSClassFromString( "NSFont" ), fontSize )
      
      if ref <> nil then
        // - (void)setFont:(NSFont *)fontObject
        declare sub setFont lib "Cocoa" selector "setFont:" _
        ( NSControlHandle as integer, font as Ptr )
        setFont( c.handle.Integer, ref )
      End If
      
    end if
  #else
    #pragma undefined
    
  #EndIf
End Sub

Neither of these work and they both crash as soon as you encounter any of the calls with the handle property. Would appreciate any/all suggestions…

Thanks!

If you change all your declares to have this kind of definition it should work:

Handle as ptr
id as ptr
NSSomething as ptr

That’s how declares are written on iOS and I’m pretty sure Cocoa needs the same.

OK. Thanks. I was wondering if it was that simple! :smiley:

1 Like

Also make sure to rewrite that function to return a Ptr and not an Integer

Thank you. This seems to work. Now to solve some other issues related to the new controls!

BTW: Integer and Ptr are interchangeable, but as a handle points to the starting address of a reserved space of memory (the object) Ptr is more logical.
The reason for the crashes you experienced should be that you used the Integer method of ptr, which is equivalent to ptr.Integer(0) which translates to “give me the Integer value of the first (4 or 8) bytes at the address Ptr is pointing to.”
What you needed instead was the Integer value of the Ptr itself, the address.
If you had typecast the handles from Ptr to Integer instead (and vice versa), it should have worked with the old declares.

3 Likes

Ah. OK. Interesting. Thank you. I have some Windows declares and I think that shall be useful there as well.