Control position on container

Inside a canvas custom control, I need to know if the Mouse is over itself.
I find that setting a property using MouseEnter/Exit doesn’t work reliable because these events aren’t always triggered correctly. Especially when flying over the canvas real quick.

So I normally use this to check:

  Dim X As Integer = Self.MouseX
  Dim Y As Integer = Self.MouseY
  
  // Return True if the Mouse is over Me
  Return X >= Me.Left And X <= Me.Left + Me.Width And Y >= Me.Top And Y <= Me.Top + Height 

This works fine as long as the control is placed on the main window itself. However, this doesn’t work if the control is stacked on a container or canvas. In that case, Left & Top are relative to the container.

Is there a better way to do this or can I somehow find out the Left & Top relative to the Main Window dynamically?

Why not use MouseMove in the canvas ?

How? That won’t tell me if the mouse is not over the canvas.
In this case, when the Paint event is executed, I need to know if the mouse is over the canvas (or not). I also use it when the mouse button is pressed and moved out of the canvas.

This should help:

[code]Function TrueBoundary(Extends theRectControl As RectControl) As BoundaryRect

'gets the boundary of a rect control in relation to the screen and not the parent

dim theBoundary as new BoundaryRect
theBoundary.height = theRectControl.height
theBoundary.width = theRectControl.width
theBoundary.top = theRectControl.top
theBoundary.left = theRectControl.left

'loop up the containing chain
dim theWindow as window = theRectControl.window
while theWindow isa containercontrol
theBoundary.top = theBoundary.top + theWindow.top
theBoundary.left = theBoundary.left + theWindow.left
theWindow = containercontrol(theWindow).window
wend

'add values for the window
theBoundary.top = theBoundary.top + theWindow.top
theBoundary.left = theBoundary.left + theWindow.left

return theBoundary

End Function[/code]

where Boundary rect is a class with properties top, left, height, width.

[quote=237527:@Marco Hof]How? That won’t tell me if the mouse is not over the canvas.
In this case, when the Paint event is executed, I need to know if the mouse is over the canvas (or not). I also use it when the mouse button is pressed and moved out of the canvas.[/quote]

Mousemove fires as long as the mouse is over the canvas. You can also use it to compare with sel.x and y and find the relative position. But you may prefer the long declare above. Not cross platform, though…

Thanks you @Beatrix Willius!! That was exactly what I was looking for.
Had to modify it a little bit but this works:

  Dim sX As Integer = System.MouseX
  Dim sY As Integer = System.MouseY
  
  Dim cLeft, cTop, cWidth, cHeight As Integer
  cLeft = Me.Left
  cTop = Me.Top
  cWidth = Me.width
  cHeight = Me.Height
  
  // Loop up the containing chain
  Dim theWindow As Window = Me.Window
  While theWindow IsA ContainerControl
    cLeft = cLeft + theWindow.Left
    cTop = cTop + theWindow.Top
    theWindow = ContainerControl(theWindow).Window
  Wend
  
  // Add values for the window
  cTop = cTop + theWindow.Top
  cLeft = cLeft+ theWindow.Left
  
  // Return True if Mouse is over Me
  Return sX >= cLeft And sX <= cLeft + cWidth And sY >= cTop And sY <= cTop + Height Then

Thanks!

@Michel Bujardet
I tried most of it but I constantly end up with a little function like this. It’s also not tracking/flagging constantly. It’s just giving the info when needed.
You said that the above code isn’t x-plat? Why is that?

You already got a method. But the reason why you were not able to get the coordinates is because when your canvas is in a Container, self is not what you think it is. Self refers to the Container, not to the window the container is placed onto.

See http://documentation.xojo.com/index.php/Window.TrueWindow

Incidentally, TrueWindow does what the loop does in the code Beatrix Willius posted, but in one line.

The mouse coordinates wasn’t the issue. It’s was about getting the Left/Top of a control placed on a container relative to the Main Window.
I’m aware of TrueWindow but I’m not sure how I can use that to get the Left/Top positions of my canvas that’s placed on a container.

//me is a canvas laid on a ContainerControl that is placed on a window dim CanvasLeft as Integer = me.left + self.left dim CanvasTop as Integer = me.top + self.Top

[quote=237543:@Michel Bujardet] //me is a canvas laid on a ContainerControl that is placed on a window dim CanvasLeft as Integer = me.left + self.left dim CanvasTop as Integer = me.top + self.Top[/quote]
I think that’s going to have the same issue my initial function but now it tells me when it’s stacked one level. It won’t work if the control is on the Main Window or if the container is stacked on another container.

Before I went to bed last night, I tried to use TrueWindow to find the positions but I can’t seem to figure it out what you meant with that. Also, what did you mean with the Beatrix solution not being cross-platform? I don’t have other platforms to test and that worries me.

[quote=237592:@Marco Hof]I think that’s going to have the same issue my initial function but now it tells me when it’s stacked one level. It won’t work if the control is on the Main Window or if the container is stacked on another container.

Before I went to bed last night, I tried to use TrueWindow to find the positions but I can’t seem to figure it out what you meant with that. Also, what did you mean with the Beatrix solution not being cross-platform? I don’t have other platforms to test and that worries me.[/quote]

No problem with Beatrix solution. It is indeed cross platform.

What it does is just fine if you stack containers.

To use the Canvas MouseMove and TrueWindow to find its position on the window no matter how many containers were stacked :

TrueLeft = self.TrueWindow.MouseX-X TrueTop = self.TrueWindow.MouseY-Y

Of course that works only if the mouse goes over the canvas at least once.