8 de diciembre de 2013

Los tesoros de Tamar


Tamar E. Granor Quienes conocen a Tamar E. Granor, seguramente la conocen por sus amplios conocimientos y experiencia como desarrolladora, conferenciante y autora de libros y artículos sobre Visual FoxPro. Ella tiene en su sitio web un gran tesoro para cualquier desarrollador VFP: Cientos de artículos y documentos técnicos de sesiones de conferencias y charlas, con ejemplos incluídos, para descargar libremente!!!

Para quienes no la conocen, Tamar E. Granor es propietaria de Tomorrow's Solutions, LLC, una consultora y desarrolladora de numerosas aplicaciones para grandes y pequeñas empresas, y también para organizaciones sin ánimo de lucro, ubicada en Pensilvania, Estados Unidos de América.

Ella trabaja desde 1988 con FoxBase, FoxPro y principalmente con Visual FoxPro. Tamar es autora y co-autora de muchos libros (entre los mas destacados: Hacker’s Guide to Visual FoxProMicrosoft Office Automation with Visual FoxPro y Taming Visual FoxPro’s SQL) y cientos de artículos acerca de Visual FoxPro. También es habitual oradora en numerosas conferencias y grupos de usuarios. FueMicrosoft Visual FoxPro Most Valuable Professional (Profesional Mas Valioso de Microsoft Visual FoxPro) desde el año 1993 hasta el año 2010. En 2007 recibió el Visual FoxPro Community Lifetime Achievement Award (Premio a la Trayectoria de Comunidad Visual FoxPro). Tamar es también socia de Geek Gatherings patrocinadora de las conferencias anuales Southwest Fox y Southwest Xbase++.

Los Tesoros de Tamar se encuentran en el sitio Web de su empresa, en el ítem Publications.

Los enlaces directos para descargar libremente sus publicaciones son:
Todas las publicaciones están en Inglés, pero si aun no dominan este idioma, es una buena excusa para aprender, al menos los términos técnicos, y aprovechar toda la información que fue escribiendo Tamar en su larga carrera. Aparte también estan para descargar los ejemplos en código VFP de las distintas sesiones publicadas.

Gracias Tamar por tu gran generosidad con la comunidad de Visual FoxPro.

A aprovechar este tesoro para nuestro Zorro.!!!

6 de diciembre de 2013

Control separador para Visual FoxPro

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