MenuItem.Popup Position

  1. 11 months ago

    Martin T

    15 Sep 2018 Pre-Release Testers Germany

    Hello,

    just a simple sample, to show you my topic. I have a canvas around which a frame is drawn and on the right side, with a width of 20 pixels, a "button".

    Now I want a popup menu to appear just below the button when you click on the drawn "button". This code, however, makes the menu appear in the wrong place. How do I calculate the coordinates correctly?

    Canvas1.MouseDown

    Return True

    Canvas1.MouseUp

    If X >= Me.Width - 20 And X <= Me.Width Then
      Dim base As New MenuItem
    
      base.Append(New MenuItem("Import"))
      base.Append(New MenuItem("Export"))
      base.Append(New MenuItem(MenuItem.TextSeparator))
      base.Append(New MenuItem("Cut"))
      base.Append(New MenuItem("Copy"))
      base.Append(New MenuItem("Paste"))
    
      Dim popup As MenuItem = base.PopUp(x, y) // Calculation
    End If

    Canvas1.Paint

    g.DrawRect(0, 0, g.Width, g.Height)
    g.FillRect(g.Width - 20, 0, 20, g.Height)
  2. Martin T

    15 Sep 2018 Pre-Release Testers Germany
    Edited 11 months ago

    It's a bit better, but not perfect. Unfortunately, the coordinates are wrong when using complex nested ContainerControls. Then the Parent value is wrong.

    Dim wLeft, wTop As Integer
    
    wLeft = Me.TrueWindow.Left + If(Me.Parent > Nil, Me.Parent.Left, 0) + Me.Left + Me.Width - 20
    wTop = Me.TrueWindow.Top + If(Me.Parent > Nil, Me.Parent.Top , 0) + Me.Top + Me.Height
    ...
    Dim popup As MenuItem = base.PopUp(wLeft, wTop)
  3. 3 months ago
  4. Sam R

    May 15 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

    You can get the current mouse position from the OS (macOS only sorry).

    Public Sub mousePositionFromOS(Extends inControl as rectControl, byRef X as integer, byRef Y as integer, flip as boolean = true)
      #if TargetMacOS then
        declare Function NSViewConvertPointFromView lib "AppKit" selector "convertPoint:fromView:" (NSViewInstance as integer, point as NSPoint, fromViewInstance as integer) as NSPoint
        declare Function NSViewWindow lib "AppKit" selector "window" (NSViewInstance as integer) as integer
        declare Function NSWIndowMouseLocationOutsideOfEventStream lib "AppKit" selector "mouseLocationOutsideOfEventStream" (NSWindowInstance as integer) as NSPoint
        
        Dim rNSPoint as NSPoint = NSViewConvertPointFromView( incontrol.handle, _
        NSWindowMouseLocationOutsideOfEventStream( NSViewWindow( inControl.handle ) ), 0 )
        X = rNSPoint.x
        Y = if( flip, inControl.height - rNSPoint.y, rNSPoint.y )
      #endif
    End Sub
    

    You'll need a NSPoint structure.

    Attributes( structureAlignment = 0 ) Structure NSPoint
      X as CGFloat
      Y as CGFloat
    End Structure

    Then in your function you do something like below.

    Dim wLeft, wTop As Integer
    
    me.mousePositionFromOS( wLeft, wTop, true )
    ...
    Dim popup As MenuItem = base.PopUp(wLeft, wTop)
  5. Edwin v

    May 18 Pre-Release Testers The Netherlands
    Edited 3 months ago

    @Sam R You can get the current mouse position from the OS (macOS only sorry).

    Public Sub mousePositionFromOS(Extends inControl as rectControl, byRef X as integer, byRef Y as integer, flip as boolean = true)
      #if TargetMacOS then
        declare Function NSViewConvertPointFromView lib "AppKit" selector "convertPoint:fromView:" (NSViewInstance as integer, point as NSPoint, fromViewInstance as integer) as NSPoint
        declare Function NSViewWindow lib "AppKit" selector "window" (NSViewInstance as integer) as integer
        declare Function NSWIndowMouseLocationOutsideOfEventStream lib "AppKit" selector "mouseLocationOutsideOfEventStream" (NSWindowInstance as integer) as NSPoint
        
        Dim rNSPoint as NSPoint = NSViewConvertPointFromView( incontrol.handle, _
        NSWindowMouseLocationOutsideOfEventStream( NSViewWindow( inControl.handle ) ), 0 )
        X = rNSPoint.x
        Y = if( flip, inControl.height - rNSPoint.y, rNSPoint.y )
      #endif
    End Sub
    

    You'll need a NSPoint structure.

    Attributes( structureAlignment = 0 ) Structure NSPoint
      X as CGFloat
      Y as CGFloat
    End Structure

    Then in your function you do something like below.
    Dim wLeft, wTop As Integer me.mousePositionFromOS( wLeft, wTop, true ) ... Dim popup As MenuItem = base.PopUp(wLeft, wTop)

    That's nice... But it would be nice to have a button aligned with another object.
    For instance, I have a label and when clicked I want a menu to popup. But I want it to be positioned right under the label, to mimic the PopupMenu control. But using a label fits the layout better.

    What I tried was iterating through the label's parent controls and add the sum of all the left-values to the left-value of the TrueWindow value. But the resulting value was too far to the right.

  6. Sam R

    May 18 Pre-Release Testers, Xojo Pro Hengchun, Pingtung, Taiwan

    http://docs.xojo.com/System.MouseX

or Sign Up to reply!