Su IP: 18.97.9.170
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.
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:
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.