I have a custom control which opens a context menu at the controls location. The custom control (canvas) may be nested or even just placed in a window.
I thought instead of calculation every container’s top/lef it might be easier to use a declare.
Is there an easy way to get the x,y of the canvas ?
screen position is not x.left or x.top.
The other thing is if the control is embedded in a container it only get’s the origins relating to the embedded container.
I am basically looking for a declare. I think I’ll go for NSWindow “convertRectToScreen:”
Not a Declare and maybe not 100% perfect but I’m currently using this extend:
Function scrnPosTopLeft(Extends cvs As Canvas) As Integer()
// Returns Actual Screen Positions
Dim cTop, cLeft As Integer
cTop = cvs.Top
cLeft = cvs.Left
// Loop up
Dim mWindow As Window = cvs.Window
While mWindow IsA ContainerControl
cTop = cTop + mWindow.Top
cLeft = cLeft + mWindow.Left
mWindow = ContainerControl(mWindow).Window
Wend
// Add
cTop = cTop + mWindow.Top
cLeft = cLeft+ mWindow.Left
// What Screen are we on?
Dim thisScreen As Integer
For i As Integer = 0 To ScreenCount - 1
If cLeft >= Screen(i).Left And cLeft < Screen(i).Left + Screen(i).Width And cTop >= Screen(i).Top And cTop < Screen(i).Top + Screen(i).Height Then
thisScreen = i
Exit for i
End If
Next
// Adjust for active Screen
If cLeft >= Screen(thisScreen).Left Then
cLeft = cLeft - Screen(thisScreen).Left
End If
If cTop >= Screen(thisScreen).Top Then
cTop = cTop - Screen(thisScreen).Top
End If
Dim topLeft() As Integer = Array(cTop, cLeft)
Return topLeft
End Function
[code]Function MouseDown(X As Integer, Y As Integer) As Boolean
dim trueleft, trueTop as integer
TrueLeft = self.TrueWindow.MouseX-X
TrueTop = self.TrueWindow.MouseY-Y
system.DebugLog str(trueleft)+" "+str(truetop)
End Function
[/code]
I was peeking and poking with some declares and got it almost right but wasn’t able to get the correct x,y
if you move the window to a different screen.
Thanks for all suggestion.
It’s true the most reliable and easiest way is for my problem is to use x,y from mouseDown
and System.MouseX/Y as I’ll have a contextmenu open on a mouseDown event so basically Michal’s way with some
adjustments so that the selected menuitem is centered (assuming OSX)
[code]Declare Function menu Lib “Cocoa” Selector “menu” (NSMenuItem As Ptr) As Ptr
Dim NSMenuItemPtr As Ptr = Ptr(result.Handle(MenuItem.HandleType.CocoaNSMenuItem)) // The NSMenuItem
Dim NSMenuPtr As Ptr = menu(NSMenuItemPtr) // The XOJMenu, a subclass of NSMenu[/code]
[quote=240481:@Eli Ott][code]Declare Function menu Lib “Cocoa” Selector “menu” (NSMenuItem As Ptr) As Ptr
Dim NSMenuItemPtr As Ptr = Ptr(result.Handle(MenuItem.HandleType.CocoaNSMenuItem)) // The NSMenuItem
Dim NSMenuPtr As Ptr = menu(NSMenuItemPtr) // The XOJMenu, a subclass of NSMenu[/code][/quote]
Thanks Eli. Getting the NSMenu from the popup result answers the question.
I have spent some time to understand the NSMenu/NSMenuItem since I wanted to write a custom popup
control which behaves like the OSX popup button. There are two options for the custom control in terms of the menu location:
for a pulldown menu: opens the menu beneath the control less 5 pixel
for a popup: center the selected item within the control
[code]Private Sub handlePopUp()
if self.captions.Ubound>-1 then
// some declares
declare function menu Lib CocoaLib selector “menu” (obj_id as Ptr) as Ptr
declare sub setMinimumWidth Lib CocoaLib selector “setMinimumWidth:” (obj_id as Ptr, v as CGFloat)
declare function popUpMenuPositioningItem lib CocoaLib selector “popUpMenuPositioningItem:atLocation:inView:” _
(obj_id as Ptr, item as Ptr, location as NSPoint, view as Ptr) as Boolean
declare function indexOfItem Lib CocoaLib selector “indexOfItem:” (obj_id as Ptr, m as ptr) as integer
declare function highlightedItem lib CocoaLib selector “highlightedItem” (obj_id as Ptr) as Ptr
declare function size Lib CocoaLib selector “size” (obj_id as Ptr) as NSSize
// get the xojo menuitem
dim base as MenuItem=self.makePopup()
dim firstItem as ptr = ptr(base.Item(0).Handle(MenuItem.HandleType.CocoaNSMenuItem))
dim menuRef as ptr = menu( firstItem )
// stretch menu width to the control
setMinimumWidth(menuRef, self.Width)
// Note: NSMakePoint is a convenience method
// Note to calculate the menuitem height for the centered selection, we use size() declare that returns the total height/width of the menu divided by the menuitem count that equals 18 or 19 pixel.
dim hasSelection as Boolean
select case self.ButtonType
case CustomButton1.Type.PopUp
hasSelection = popUpMenuPositioningItem(menuRef, _
ptr(base.Item(self.mlistIndex).Handle(MenuItem.HandleType.CocoaNSMenuItem)), _
NSMakePoint(0, ((size(menuRef).height/base.Count-1)+me.Height)/2 ), _
ptr(me.handle) )
case CustomButton1.Type.PullDown
hasSelection = popUpMenuPositioningItem(menuRef, nil, NSMakePoint(0,-5), ptr(me.handle))
end select
if hasSelection then
dim hitItem as ptr = highlightedItem(menuRef)
if hitItem<>nil then
self.mlistIndex=indexOfItem( menuRef, hitItem )
self.caption = self.captions(self.mlistIndex)
end if
end if