MenuItem.Popup Position

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?

[h]Canvas1.MouseDown[/h]

Return True

[h]Canvas1.MouseUp[/h]

[code]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[/code]

[h]Canvas1.Paint[/h]

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

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

[code]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)[/code]

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

[code]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

[/code]
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.

[code]Dim wLeft, wTop As Integer

me.mousePositionFromOS( wLeft, wTop, true )

Dim popup As MenuItem = base.PopUp(wLeft, wTop)[/code]

[quote=436637:@Sam Rowlands]You can get the current mouse position from the OS (macOS only sorry).

[code]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

[/code]
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.

[code]Dim wLeft, wTop As Integer

me.mousePositionFromOS( wLeft, wTop, true )

Dim popup As MenuItem = base.PopUp(wLeft, wTop)[/code][/quote]

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.

http://documentation.xojo.com/api/os/system.html#system-mousex