Page 1 of 1

Reposicionar controles en una oDlg automaticamente.

PostPosted: Mon Sep 01, 2008 1:34 am
by FranciscoA
Utilizo un dialog desde recursos que contiene botones en la parte superior, seguido de un listbox y algunos botones mas debajo del listbox.

He logrado situar correctamente el listbox cuando se maximiza la hacer dobleclick en barra del caption, pero solo situa correctamente los botones de arriba, los de abajo se pierden entre las lineas del oLbx. Esto último ya lo he solucionado de manera un poco artesanal y funciona perfectamente, pero lo que trato de hacer es automatizar este proceso para lo cual he logrado todo, menos cambiar de posición los controles. (botones de abajo)

Me da el siguiente error:
Error description: Error BASE/1132 Bound error: array access
Args:
[ 1] = A { ... }
[ 2] = N 1

Stack Calls
===========
Called from: \WCONT\wcont.prg => POSICIONAR(196)

El codigo es el siguiente:

aObjetos :={oCuadra,oBusca,oImpri,oDesc,oDeb,oHab}
oDlg:bResized = {|| posicionar(aObjetos }
Activate dialog oDlg

//colocar controles en nuevas coordenadas
Function Posicionar(aObjetos)
local n:=0

for n:=1 to len(aObjetos)
aObjetos[n]:Move( aLinPos[n],aColPos[n] ) //esta es la linea 196
next

¿Se pueden manipular los controles (oButton1...) de este manera?
¿Qué estoy haciendo mal?

Gracias de antemano, y saludos a todos.

Re: Reposicionar controles en una oDlg automaticamente.

PostPosted: Mon Sep 01, 2008 4:46 am
by FranciscoA
Ya lo solucioné.

Parece que hay un pequeño bug en la clase tDialog, con el codeblock bInit, ya que con este me daba el error, pero usando ON INIT trabaja perfectamente. Después de estudiar el manual de la clase opté por utilizar oDlg:bStart = {||...} por cuestión de elegancia en el código, en vista de que este modo trabaja, también, perfectamente.

//Este da el error
oDlg:bInit = {|| aColCtrls:=ColPosCtrl(oDlg,oLbx,aObjetos),aLinCtrls:=LinPosCtrl(oDlg,oLbx,aObjetos) }

//Estos trabajan bien
oDlg:bStart = {|| aColCtrls:=ColPosCtrl(oDlg,oLbx,aObjetos),aLinCtrls:=LinPosCtrl(oDlg,oLbx,aObjetos) }

ACTIVATE DIALOG oDlg CENTERED ;
/ON INIT ( aColCtrls:=ColPosCtrl(oDlg,oLbx,aObjetos),aLinCtrls:=LinPosCtrl(oDlg,oLbx,aObjetos) )

PostPosted: Mon Sep 01, 2008 7:44 am
by Antonio Linares
Francisco,

Bien! :-)

> ¿Se pueden manipular los controles (oButton1...) de este manera?

Si

PostPosted: Mon Sep 01, 2008 6:19 pm
by FranciscoA
Antonio Linares wrote:Francisco,

Bien! :-)

> ¿Se pueden manipular los controles (oButton1...) de este manera?

Si


Gracias por contestar, Antonio.
Aquí dejo el código ejemplo por si alguien tiene la misma necesidad que tuve, y desea emplearlo. El ejemplo es para redimensionar el oLbx y colocar debidamente los controles debajo del mismo.

//------------------------------
FUNCTION Grabar(lImportados)
LOCAL oDlg, oLbx, ..., ...
local aColCtrls, aLinCtrls, aObjetos, aLinColCtrls:={}
local nAltoIniDlg:=0,nAnchoIniDlg:=0, nAltoIniLbx:=0,nAnchoIniLbx:=0

Tu codigo...
//
//

aObjetos :={oLbx,oCuadra,oBusca,oImpri,oSay1,oBmp,oCalc,oDesc,oDeb,oHab} //los controles mover

oDlg:bStart = {|| nAltoIniDlg:=oDlg:nHeight,nAnchoIniDlg:=oDlg:nWidth,nAltoIniLbx:=oLbx:nHeight,nAnchoIniLbx:=oLbx:nWidth, aLinColCtrls:=LinColCtrl(aObjetos), aLinCtrls:=aLinColCtrls[1], aColCtrls:=aLinColCtrls[2] }
oDlg:bResized = {|| Posicionar(oDlg,oLbx,aObjetos,nAltoIniDlg,nAnchoIniDlg,nAltoIniLbx,nAnchoIniLbx,aLinCtrls,aColCtrls) } //Cambiar posicion
oDlg:bPainted = {|| Degrade2C( oDlg:hWnd, oDlg:hDC, aColores ) }

ACTIVATE DIALOG oDlg CENTERED

oFont:End()
oFont1:End()

RETURN NIL

//--------------------------------------
//Conocer posicion origen de los controles deseados
Function LinColCtrl(aObjetos)
local n:= 0, aLinPos:={}, aColPos:={}

for n:=1 to len(aObjetos)
aadd( aLinPos, aObjetos[n]:nTop )
aadd( aColPos, aObjetos[n]:nLeft)
next
Return {aLinPos,aColPos}

//------------------------------------------------------------------------
Function Posicionar(oDlg,oLbx,aObjetos,nAltoIniDlg,nAnchoIniDlg,nAltoIniLbx,nAnchoIniLbx,aLinCtrls,aColCtrls)
local n:=0, nNvasLineas:=0,nNvasColumn:=0

//Conocer diferencia del tamaño que adquiere el oDlg (Resize)
nNvasLineas:= oDlg:nHeight - nAltoIniDlg
nNvasColumn:= oDlg:nWidth - nAnchoIniDlg

//colocar controles deseados en nuevas coordenadas
//Si es un listbox, cambia alto y ancho, a diferencia de los demas.
for n:=1 to len(aObjetos)
if upper(aObjetos[n]:ClassName()) == 'TWBROWSE' // Si es un listbox
oLbx:nWidth := nAnchoIniLbx + nNvasColumn
oLbx:nHeight:= nAltoIniLbx + nNvasLineas
else
aObjetos[n]:Move( aLinCtrls[n]+nNvasLineas, aColCtrls[n] )
endif
next

oDlg:Refresh()
SysRefresh()
RETURN NIL

Saludos