Leandro. Aquí tienes un ejemplo en un TDIALOG
Como te explicaba en el código anterior, debes implementarlo para todos los casos posibles (yo desconozco sobre que objetos quieres posicionar tu objeto de referencia)
Para calcular la posición vertical/horizontal absoluta, debes incluir los distintos tipos de clases en los que se va a anidar.
Prueba este ejemplo en un Dialogo. (tal vez falta ajustar algún pixel, porque como te decía en mi versión los diálogos no se calculan igual que las ventanas)
- Code: Select all Expand view RUN
STATIC FUNCTION PRUEBA_DIALOGO()
LOCAL oWnd
LOCAL oMenu
LOCAL N:=1
MENU oMenu
MENUITEM "&Sistema"
MENU
MENUITEM "&Especificar impresora" ACTION PrinterSetup()
SEPARATOR
MENUITEM "&Salir" ACTION oWnd:End()
ENDMENU
ENDMENU
DEFINE WINDOW oWnd MDI FROM 100,100 TO 600,1200 PIXEL TITLE "TEST POSICION DIALOGO" COLOR CLR_BLACK, CLR_GRAY MENU oMenu
ACTIVATE WINDOW oWnd MAXIMIZED ON INIT CreaChild(oWnd)
RETURN(NIL)
static function CreaChild(oWnd)
local oWndChild
LOCAL oBtn
DEFINE DIALOG oWndChild TITLE "Dialogo" FROM 200,500 TO 600,1000 PIXEL OF oWnd
@25,10 BUTTON oBtn PROMPT "CREA" SIZE 100,20 OF oWndChild PIXEL ACTION Prueba2(oBtn)
ACTIVATE DIALOG oWndChild
RETURN(NIL)
///////////////////////////////////////////////////////////////////////////////
static function prueba2(oBtn)
local odlg
LOCAL oWnd:=oBtn:oWnd
LOCAL nVerticalPos:=oBtn:nTop
LOCAL nAjustar:=CuantoAjustar(oWnd)
LOCAL nNTOP, nNLEFT, nNBOTTOM, nNRIGHT
nnTop:=nVerticalPos+nAjustar+30 // al crear el dialogo se me sube siempre 30, los añado
nnLeft:=GetRight(oBtn)
nnBottom:=nVerticalPos+nAjustar+30+100 //100 es el tamaño del dialogo, pon tu el tuyo
nnRight:=nnLeft+100 // 100 idem
DEFINE DIALOG oDlg FROM nnTop, nnLeft TO nnBottom, nnRight TITLE "oDLG POSICIONADO" PIXEL OF oWnd
IF oDlg:nBottom>GetSysMetrics(1)-40-30 // pongo 40 barra inferior de windows y 30 de ajuste manual
ACTIVATE DIALOG oDlg CENTER // aqui puedes utilizar aPos := GetCoors( FindWindow( "Shell_TrayWnd", "" ) )
ELSE // para saber donde esta la barra de windows
ACTIVATE DIALOG oDlg
ENDIF
return(nil)
///////////////////////////////////////////////////////////////////////////////
STATIC FUNCTION CuantoAjustar(oWnd)
local nAjuste:=0
local oDlg
local n:=1
local nLocalAjuste:=0
local aRect
DO WHILE .T.
IF oWnd:ClassName()="TMDIFRAME"
EXIT
ENDIF
// aqui tienes que desarrollar mas posibles casos TDIALOG, ETC...
// Yo he hecho el TGROUP y el TMDICHILD
IF oWnd:ClassName()="TGROUP"
nAjuste:=nAjuste+oWnd:nTop
ENDIF
IF oWnd:ClassName()="TDIALOG"
aRect := GetCoors( oWnd:hWnd )
nAjuste:=nAjuste+aRect[1] +43 // 43 DEL FRAME DEL DIALOGO, también en MDICHILD pero lo calculo con el falso dialogo (que también me da 43)
ENDIF
IF oWnd:ClassName()="TMDICHILD"
nLocalAjuste:=0
DEFINE DIALOG oDlg FROM 100,100 TO 200,200 TITLE "Cuanto tengo que ajustar" PIXEL OF OWND
ACTIVATE DIALOG oDlg ON INIT (nLocalAjuste:=100-oDlg:nTop, oDlg:End() )
nAjuste:=nAjuste+nLocalAjuste
aRect := GetCoors( oWnd:hWnd ) // esto me dice donde esta ahora la ventana
nAjuste:=nAjuste+aRect[1]
ENDIF
oWnd:=oWnd:oWnd
ENDDO
RETURN(nAjuste)
////////////////////////////////////////////////////////////////////////////
STATIC FUNCTION GetRight(objeto) // Devuelve el punto derecha absoluto del objeto pasado, en este caso un boton, prueba con un get
LOCAL oWnd:=objeto:oWnd
LOCAL nRight:=0
LOCAL aRect
DO WHILE .T.
IF oWnd:ClassName()="NIL"
EXIT
ENDIF
// aqui tienes que desarrollar mas posibles casos TDIALOG, ETC...
// Yo he hecho el TGROUP, TMDICHILD Y TMDIFRAME (ahora el TDIALOG)
IF oWnd:ClassName()="TGROUP"
nRight:=nRight+oWnd:nLeft
ENDIF
IF oWnd:ClassName()="TMDICHILD" .or. oWnd:ClassName()="TMDIFRAME" .OR. oWnd:ClassName()="TDIALOG"
aRect := GetCoors( oWnd:hWnd )
nRight:=nRight+aRect[2]
ENDIF
oWnd:=oWnd:oWnd
ENDDO
nRight:=nRight+objeto:nLeft+objeto:nWidth+13
return(nRight)