Logo

ClearLight
Sistema Integrado para la Administracion

Su IP: 18.97.9.170



Motivación

Las "DLL de Forma" son un concepto fundamental de nuestra "filosofía de extensibilidad". La intención básica, en las primeras versiones de ClearLight, desarrolladas en VB5, era permitir que los usuarios definieran condiciones adicionales de validación e implementaran alguno que otro efecto adicional a consecuencia de los cambios en los valores contenidos en las formas.

Al pasar el sistema a VB6, que permite la adición de controles dinámicos a las formas, las capacidades de esta herramienta se ampliaron de manera considerable.

Ejemplo:

Uno de nuestros usuarios es una cadena de perfumerías, formada por varias tiendas con una razón social única. Las compras se realizan por el almacén central, que realiza ajustes de salida para enviar mercancía a las tiendas. Al procesar los ajustes se ejecuta un script que exporta el contenido del ajuste, incluyendo información sobre la descripción y precios de los productos, que es importado en las tiendas mediante un script que se activa directamente como Script de Usuario.

Las tiendas se responsabilizan por la mercancía recibida al valor de su precio de venta al público. Pero los ajustes en ClearLight se valoran al costo de la mercancía. Hasta ahora nada que no se resuelva en el formato de impresión. Para validar el ajuste impreso, los opeadores requirieron que el valor total del ajuste, valorado al PVP de los productos, se mantuviera actualizado en pantalla a la medida que van agregando productos.

La forma Modificada para mostrar Valor a PVP La forma original de Ajuste de Inventario

La modificación intercepta el evento Load de la forma para reducir el tamaño del panel de mensajes (lblStatus), agrega dos controles a la forma y posteriormente procesa los eventos de los controles para recalcular el valor acumulado a PVP y mostrarlo en el nuevo control.

Las dos imagenes fueron capturadas durante la misma ejecución del programa. Primero se registró la DLL (frmAjuste.DLL), se activó la forma de ajustes desde el menu principal y se obtuvo la instantánea. Se cerró la forma, se de-registró la DLL, se volvió a abrir la forma y se tomó la segunda.

Ahora procederemos a una "disección" de la DLL, para terminar este articulo exponiendo el esquema formal y los mecanismos disponibles para trabajar con este recurso.

Definición:

Las DLL de usuario son bibliotecas de enlace dinámico (DLL) basadas en COM (ActiveX) que corren paralelamente a una forma de captura de datos para permitir que el usuario cambie la forma, presentación, contenido o conducta de la forma adptándola a sus necesidades específicas.

Parece obvio, pero tal vez no esté de más aclarar que esta definición tiene validez dentro de ClearLight y sus sistemas asociados.

Análisis de una DLL de Usuario:

Todas las DLLs de usuario deben implementar estas dos variables:

Public Factoria As Object
Public Form As Object

Cuando una forma de entrada de datos que soporta las DLL de usuario (todas estas fomas incluyen una referencia a una variable de tipo CusrDLL, que en el documentador se lista por lo general como «Public usrDLL As CusrDLL»), parte de su proceso de inicialización es crear una instancia de la DLL correspondiente (si ésta está definida, por supuesto), y pasarle una referencia a sí misma. Esta referencia se asigna, en la DLL, a la variable Form. La clase CusrDLL crea una instancia de CFactoria y la asign a la variable Factoria de la DLL.

Sigamos con el ejemplo:

Private Grid As MSFlexGrid
Private txTotalPVP As TextBox
Private almacenItems As Object

Estas son las declaraciones de variables para los objetos de la aplicación que utilizaremos en la DLL: «Grid» es la matriz donde se almacenan los detalles del ajuste, «txTotalPVP» una caja de texto que agregaremos a la foma para mostrar el nuevo total y «almacenItems» es una referencia al almacen que nos permite acceder a la tabla de productos (una especie de Recordset de muy alto nivel).

La función principal para el uso "estándar" de las DLL de usuario es usrEvent, y su implementación para el caso concreto que nos ocupa es la siguiente:

Public Function usrEvent(f As Object, c As Object, eventID As String) As Boolean

  Select Case UCase(eventID)

    Case "LOAD"
      Dim frm As Form
      Set frm = Form
      Set Grid = frm.Controls("flxDetalles")
      frm.Controls("lblStatus").Width = 7665

      Set txTotalPVP = frm.Controls.Add("VB.TextBox", "txTotalPVP")
      With txTotalPVP
        .ZOrder 0
        .Alignment = 1
        .Height = 315: .Width = 2055
        .Left = 8885: .Top = 5640
        .Visible = True: .TabStop = False
      End With

      Dim lbl As Label
      Set lbl = frm.Controls.Add("VB.Label", "lblTotalPVP")
      With lbl
        .Caption = "Valor PVP:"
        .Left = 7860: .Top = 5700
        .Height = 195: .Width = 765
        .ZOrder 0
        .Visible = True
      End With
      Set almacenItems = Factoria.CrearObjeto("AlmacenItemsVenta")
    Case "VALIDATECELL"
      MostrarTotales
  End Select

  usrEvent = True

End Function

Las rutinas para el manejo de los eventos de los controles contenidos en las formas de entrada de datos de ClearLight solicitan de la DLL, si está presente, una confirmación para procesar el evento. Para ello laman a la función usrEvent, pasándole los argumentos siguientes:

f: Una referencia a la forma. Lo normal es que siempre sea igual al valor de la variable Form.

c: Una referencia al control que origina el evento. Si el control es un FlexGrid, normalmente no se refiere al Grid sino al objeto que se le superpone para permitir la entrada de datos en las celdas.

eventId: una cadena (String) que contiene la identificacion del evento. Pulse aquí para obtener información detallada.

El único evento que debemos interceptar es ValidateCell, que es donde se producen los cambios en el contenido del ajuste que pueden alterar su valor a PVP. Dentro de la DLL implementamos la función MostrarTotales, responsable de esa actualización, que se listará mas adelante.

Pero tambien debemos "preparar el entorno" para la operación. Por eso fue necesario agregar código para el evento Load. En esencia, se reduce el ancho del control lblStatus para darel cabida a dos nuevos controles: txTotalPVP una caja de texto donde mostraremos el totl a PVP, y lblTotalPVP, que simplemente sirve de titulo a txTotalPVP. Como MostrarTotales debe acceder a los productos y servicios para obtener los PVP de los productos asociados a los códigos de inventario,  creamos de entrada una referencia al almacen de productos (AlmacenItemsVenta). Igualmente, MostrarTotales va a recorrer el grid que contiene los detalles. Obtener la referencia es cuestión de fracciones de segundo, pero es mejor obtener la referencia ahora y usarla cada vez que resulte necesario despues.

Y la función que actualiza el total es esta:

Private Sub MostrarTotales()
Dim Acum As Currency
Dim itemVenta As Object, i As Integer

  For i = 1 To Grid.Rows - 1
    Set itemVenta = almacenItems.itemVenta(Grid.TextMatrix(i, 0))
    If Not itemVenta Is Nothing Then
      Dim Cantidad As Double
      Cantidad = CDbl(Grid.TextMatrix(i, 1))
      Acum = Acum + Cantidad * itemVenta.PrecioConIVA(INDICE_PRECIO) * _
                         itemVenta.FactorPresentacion(Grid.TextMatrix(i, 2))
    End If
  Next
  txTotalPVP.Text = Format(Acum, "Currency")
End Sub

Los requisitos formales para construir una DLL de usuario son los siguientes:

  1. El nombre del proyecto debe ser igual al nombre de la forma (en nuestro caso es frmAjuste, porque ese es el nombre de las formas de ajuste de inventario en ClearLight).
  2. Deben declarar las variables públicas Factoria y Form, ambas "As Object".
  3. Deben implementar la función usrEvent, con la siguiente firma (o prototipo): 
          Public Function usrEvent(f As Object, c As Object, eventID As String) As Boolean

El resto de la forma puede construirse utilizando todos los recursos del lenguaje que se necesiten, sin ningún tipo de restricción.

Tambien es posible construir manejadores de eventos a la manera "normal" de Visual Basic. Supongamos, por ejemplo, que queremos que la descripción de los ajustes se escriba siempre en letras mayúsculas. En lo personal, no soy muy amigo de ejecutar validaciones ni cambios a nivel de caracteres individuales, pero en este caso es una manera efectiva de lograr el objetivo.

En primer lugar, declaramos un control de tipo TextBox que va a generar eventos:

Private WithEvents txDescripcion As TextBox

Luego, en la inicializacion de la forma (Load) agregamos una linea que asocie el control de la forma anfitriona (txDescripcion) con el control que queremos manejar en la DLL:

Set txDescripcion = Form.txDescripcion

Por último, escribimos la rutina de manejo del evento:

Private Sub txDescripcion_KeyPress(KeyAscii As Integer)
  KeyAscii = Asc(UCase(Chr(KeyAscii)))
End Sub

Y eso es todo.

Conclusión:

Las DLL de usuario son un mecanismo eficiente, adaptable y simple para modificr la apariencia y conducta de las formas de entrada de datos de ClearLight. Para utilizarlas, basta con saber lo que se quiere (siempre es lo mas dificil) y tener conocimientos intermedios de programacion con Visual Basic 6.

Comentario adicional:

Desde el 7 de noviembre del 2007, es posible implementar código para los eventos publicados por el formulario desde posExt.vbs.