How to get Screen Top, Left of a control (that may be embedded in a container control)?

How do you get the real Screen Top and Left positions of a control that may be nested in one or more container controls? Each .Left and .Top is relative to the containing controls and I have not found a good way to loop through the tree adding them all up to come up with a final .Left and .Top value for a given control.

My end goal is to have a Top and Left value for a popup selector window closely tied to the control itself.

I may have hit on something. Had we tried this?

I put this code in a Pushbutton embedded in ContainterControl1.ContainerControl2.ContainerControl3.

  dim relativeLeft as integer = me.Left
  dim relativeTop as integer = me.Top
  
  dim w as Window = me.Window
  while w isa Window
    if w isa ContainerControl then
      relativeLeft = relativeLeft + w.Left
      relativeTop = relativeTop + w.Top
      w = ContainerControl(w).Window
    else
      w = nil
    end if
  wend

That gives you left, top relative to TrueWindow. From there, it’s just a matter of adding wnd.Left, wnd.Top to get the Screen coordinates.

Heh … Apple used to have Global To Local and local to Global which we in screen coordinates but served much the same purpose

Thanks Kem,

What I came up with your code is:

  dim b as REALbasic.Rect = picker.Bounds
  b.Left = Self.TrueWindow.Left
  b.Top = Self.TrueWindow.Top + Me.Height
  
  dim w as Window = me.Window
  while w isa Window
    if w isa ContainerControl then
      b.Left = b.Left + w.Left
      b.Top = b.Top + w.Top
      w = ContainerControl(w).Window
    else
      w = nil
    end if
  wend

  picker.Bounds = b

picker is a Window, Me in this case is a canvas that is drawn right next to a text field to give the appearance of a popup picker button. This works when the widget is in a container, in nested container and also while in a container placed into a tab panel.

this is what worked for me.
I had some controls just in a window, but others in a container control in a window
this version seems to work for either, where “ME” is the control in question

Dim relativeLeft As Integer = Me.Left Dim relativeTop As Integer = Me.Top Dim w As Window = Me.Window While w IsA Window relativeLeft = relativeLeft + w.Left relativeTop = relativeTop + w.Top If w IsA ContainerControl Then w = ContainerControl(w).Window Else w = Nil End If Wend