Artículo original: Splitter Class for Visual FoxPro
http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,cbfe9ce7-8b19-4374-8c52-132a853ef7b3.aspx
Autor: Craig Boyd
Traducido por: Ana María Bisbé York
Muchos lenguajes tienen algún tipo de control separador (splitter), ¿porqué Visual FoxPro no? Para ser justos, he visto algunas clases dando vueltas de tiempo en tiempo; pero pensé que podría intentar echar una mano en esto. Estaba convencido en que no sería muy difícil y Visual FoxPro no me ha defraudado. Más abajo aparece el enlace para la descarga de la biblioteca de clases en la que he colocado mi separador (basada en shape) y un formulario de ejemplo que muestra cómo se utiliza la clase (he tomado una imagen de la pantalla para que pueda ver el aspecto que tiene). Ahora, si desea intentar utilizar esta clase fuera puede que tenga algunos problemas para descargarla. He creado además un ejemplo de ejecución cortar y pegar que podrá encontrar justo a continuación de la imagen de la pantalla. Este control separador está diseñado para trabajar con Visual FoxPro 9.0. Si está utilizando versiones previas entonces, necesitará modificar / eliminar algunas cosas.
Descarga de Splitter.vcx y formulario de ejemplo (8 KB aprox.): http://www.sweetpotatosoftware.com/files/splitter.zip
*!* Corte y pegue este código a un archivo prg y ejecútelo para ver
*!* y tratar de trabajar con un ejemplo de la clase splitter
PUBLIC oform1
oform1=NEWOBJECT("form1")
oform1.SHOW
RETURN
************************************
DEFINE CLASS form1 AS FORM
************************************
DOCREATE = .T.
CAPTION = "Ejemplo de Separador"
NAME = "Form1"
MDIFORM = .T.
AUTOCENTER = .T.
ADD OBJECT text1 AS TEXTBOX WITH ;
Anchor = 11, ;
HEIGHT = 29, ;
LEFT = 0, ;
TOP = 0, ;
WIDTH = 375, ;
NAME = "Text1"
ADD OBJECT edit1 AS EDITBOX WITH ;
Anchor = 7, ;
HEIGHT = 217, ;
LEFT = 0, ;
TOP = 33, ;
WIDTH = 184, ;
NAME = "Edit1"
ADD OBJECT edit2 AS EDITBOX WITH ;
Anchor = 15, ;
HEIGHT = 217, ;
LEFT = 188, ;
TOP = 33, ;
WIDTH = 187, ;
NAME = "Edit2"
ADD OBJECT splitter1 AS splitter WITH ;
TOP = 32, ;
LEFT = 183, ;
HEIGHT = 219, ;
WIDTH = 6, ;
Anchor = 7, ;
NAME = "Splitter1"
ADD OBJECT splitter2 AS splitter WITH ;
TOP = 28, ;
LEFT = 0, ;
HEIGHT = 6, ;
WIDTH = 376, ;
Anchor = 10, ;
vertical = .F., ;
minimumsize = 29, ;
NAME = "Splitter2"
PROCEDURE INIT
THIS.text1.VALUE = "Visual FoxPro Rocks!"
THIS.Edit1.VALUE = "Visual FoxPro es una herramienta de desarrollo extremadamente " + ;
"versátil. No sólo le permite al desarrollador crear buenas aplicaciones centradas " + ;
"en datos, permite además, extender el lenguaje actual con nuevas clases, bibliotecas " + ;
"de código, y ganchos. Si es un desarrollador Visual FoxPro tan ávido como yo " + ;
"esto es bueno para usted. Y si no, entonces le invito a que tome Visual FoxPro " + ;
"y lo intente. No se arrepentirá"
THIS.Edit2.VALUE = "Este es un ejemplo de una clase de control separador para " + ;
"utilizar en formularios Visual FoxPro 9.0. " + ;
"Esto es Visual FoxPro puro, no hay ActiveX adicionales o dependencias a DLL " + ;
"que le preocupen durante la distribución de su aplicación. Para verlo en " + ;
"acción, mueva los separadores horizontal y vertical de un lado a otro dentro " + ;
"de este formulario. Además, al redimensionar el formulario puede ver que va " + ;
"a funcionar la nueva propiedad Anchors de Visual FoxPro 9.0."
ENDPROC
ENDDEFINE
************************************
DEFINE CLASS splitter AS SHAPE
************************************
HEIGHT = 182
WIDTH = 8
MOUSEPOINTER = 9
SPECIALEFFECT = 0
STYLE = 0
NAME = "splitter"
mousedownat = 0 && Hace seguimiento de los movimientos del ratón
&& y permite que la clase ignore los movimientos
&& causados al redimensionar el formulario
vertical = .T. && Hacer = .F. para splitter horizontal
minimumsize = 40 && Esto es cuán pequeño (en pixels) pueden
&& ser los paneles cuando se mueve el splitter
PROCEDURE MOUSELEAVE
LPARAMETERS nButton, nShift, nXCoord, nYCoord
THIS.mousedownat = 0
ENDPROC
PROCEDURE MOVE
LPARAMETERS nLeft, nTop, nWidth, nHeight
*!* Si desea mover el splitter en tiempo de ejecución y hacer que mueva los otros controles
*!* entonces haga que mousedownat != 0 y llame al método move del spiltter
*!* recuerde restablecer mousedownat = 0 cuando ha terminado de mover el splitter
LOCAL loControl, llLockScreenWas, lnMovement, llIsSplitter, lcUniqueTag, lnMarginOfError, lnAnchorWas
IF THIS.MouseDownAt == 0
DODEFAULT(m.nLeft, m.nTop, m.nWidth, m.nHeight)
RETURN
ENDIF
m.loControl = NULL
*!* La siguiente etiqueta puede ser colocada en controles que no desea MOVER
m.lcUniqueTag = "DoN't_MoVe_SpLiT" && Es algo que garantiza muy bien de que sea único
THIS.TAG = m.lcUniqueTag
m.llLockScreenWas = THISFORM.LOCKSCREEN && En este caso la pantalla está bloqueada
THISFORM.LOCKSCREEN = .T.
m.lnMovementLeft = m.nLeft - THIS.LEFT
m.lnMovementTop = m.nTop - THIS.TOP
FOR EACH m.loControl IN THIS.PARENT.CONTROLS
IF m.loControl.TAG = lcUniqueTag && Es el control splitter, entonces regresamos al inicio del lazo
LOOP
ENDIF
IF PEMSTATUS(m.loControl,"Anchor",5)
m.lnAnchorWas = m.loControl.Anchor
m.loControl.Anchor = 0
m.llIsSplitter = m.loControl.CLASS = "Splitter"
IF THIS.vertical && Vertical Splitter
lnMarginOfError = INT(THIS.WIDTH/2) && En este caso el desarrollador lleva el splitter demasiado cerca
IF m.loControl.LEFT <= THIS.LEFT && El control está a la izquierda del splitter
IF (m.loControl.LEFT + m.loControl.WIDTH) <= (THIS.LEFT + lnMarginOfError) AND !m.llIsSplitter
m.loControl.WIDTH = MAX(m.loControl.WIDTH + m.lnMovementLeft, 0)
ENDIF
ELSE && El control está a la derecha del splitter
IF !m.llIsSplitter
m.loControl.WIDTH = MAX(m.loControl.WIDTH - m.lnMovementLeft, 0)
ENDIF
m.loControl.LEFT = m.loControl.LEFT + m.lnMovementLeft
ENDIF
ELSE && Horizontal Splitter
lnMarginOfError = INT(THIS.TOP/2) && En este caso el desarrollador lleva el splitter demasiado cerca
IF m.loControl.TOP <= THIS.TOP && El control está encima del splitter
IF (m.loControl.TOP + m.loControl.HEIGHT) <= (THIS.TOP + lnMarginOfError) AND !m.llIsSplitter
m.loControl.HEIGHT = MAX(m.loControl.HEIGHT + m.lnMovementTop, 0)
ENDIF
ELSE && El control está debajo del splitter
IF !m.llIsSplitter
m.loControl.HEIGHT = MAX(m.loControl.HEIGHT - m.lnMovementTop, 0)
ENDIF
m.loControl.TOP = m.loControl.TOP + m.lnMovementTop
ENDIF
ENDIF
m.loControl.Anchor = m.lnAnchorWas
ENDIF
NEXT
m.lnAnchorWas = THIS.Anchor
THIS.Anchor = 0
DODEFAULT(m.nLeft, m.nTop, m.nWidth, m.nHeight) && Finalmente mueve el splitter
THIS.Anchor = m.lnAnchorWas
THISFORM.LOCKSCREEN = m.llLockScreenWas
THIS.TAG = ""
ENDPROC
PROCEDURE MOUSEMOVE
LPARAMETERS nButton, nShift, nXCoord, nYCoord
LOCAL lnMovement
IF m.nButton = 1 AND !(THIS.mousedownat == 0)
IF THIS.vertical
IF m.nXCoord != THIS.mousedownat
m.lnMovement = m.nXCoord - THIS.mousedownat
IF BETWEEN(THIS.LEFT + m.lnMovement, THIS.minimumsize, THIS.PARENT.WIDTH - THIS.WIDTH - THIS.minimumsize)
THIS.MOVE(THIS.LEFT + m.lnMovement, THIS.TOP, THIS.WIDTH, THIS.HEIGHT)
THIS.mousedownat = m.nXCoord
ENDIF
ENDIF
ELSE && Horizontal
IF m.nYCoord != THIS.mousedownat
m.lnMovement = m.nYCoord - THIS.mousedownat
IF BETWEEN(THIS.TOP + m.lnMovement, THIS.minimumsize, THIS.PARENT.HEIGHT - THIS.HEIGHT - THIS.minimumsize)
THIS.MOVE(THIS.LEFT, THIS.TOP + m.lnMovement, THIS.WIDTH, THIS.HEIGHT)
THIS.mousedownat = m.nYCoord
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROCEDURE MOUSEDOWN
LPARAMETERS nButton, nShift, nXCoord, nYCoord
IF THIS.vertical
THIS.mousedownat = nXCoord
ELSE
THIS.mousedownat = nYCoord
ENDIF
ENDPROC
PROCEDURE INIT
IF !THIS.vertical
THIS.MOUSEPOINTER = 7 && NS
ENDIF
ENDPROC
PROCEDURE MOUSEUP
LPARAMETERS nButton, nShift, nXCoord, nYCoord
THIS.mousedownat = 0
ENDPROC
ENDDEFINE