Clases y Controles ActiveX

 

(traducido de http://www.vbweb.co.uk/home.htm#)

 

Introducción

Una clase es como un control sin interfase. Todos los controles son algo que se coloca dentro de una  form, no así una clase. Ambos tienen métodos (procedimientos y funciones), propiedades (variables y propiedades), constantes (enums) y eventos.

Para usar un control que algún otro ha creado (y compilado en un archivo OCX) en un proyecto, hay que agregar una referencia a él chequeando en la lista de componentes (Project|Components). Luego selecciona el icono de la caja de herramientas y lo coloca en el form. Algunos controles son visibles durante la ejecución (como el text box, combo box, list etc.), otros solo son visibkles durante el diseño (como el common dialog o el Image List). Para acceder a las propiedades o métodos de un control se usan instrucciones como :

 

FormName.ControlName.Property = Value

FormName.ControlName.Method (Param1, Param2...)

 

Para usar una clase que alguien ha creado (y compilado en un archivo DLL) en un proyecto, se agrega una referencia a ella de manera similar que con los controles, pero esta vez usando (Project|References). Si la clase DLL se especificó como global, entonces sus funciones estarán disponibles tal como cualquier otra función de VB, para llamarlas se hace usando instrucciones como:

 

FunctionName (Param1, Param2...)

PropertyName = Value

 

En cambio si la clase es especificada como MultiUse, será necesario crearla con

 

Scope clsClass As New DllName.ClassName

 

Luego, para usar sus funciones y propiedades se ocupa la sintaxis

 

clsClass.Property = Value

clsClass.Method (Param1, Param2 ...)

 

 

Creando una clase

Cuando se crea una nueva clase hay varias alternativas:

 

1) Crer un nuevo proyecto ActiveX DLL project, y agregarle las clases. Esta será

 

compilada en una DLL que puede ser usada por múltiples proyectos

 

2) Solo agregar una nueva clase a su proyecto EXE, esta no puede ser usada por otros proyectos

 

Para crear un nuevo proyecto ActiveX DLL

 

1) Seleccione File|Add Project, y haga doble clickj en ActiveX DLL.

2) Una clase es agregada automáticamente al proyecto DLL

3) De un nombre al proyecto

4) Ejegir la propiedad Instancing

Private - Solo disponible dentro de este proyecto DLL (no puede ser accesada por otro proyecto)

Multiuse - Puede ser creada como  new object en otros proyectos. La clase se carga en cuanto comienza a usarse

Global Multiuse - Los métodos y propiedades pueden accesarse desde otros proyectos como cualquier función del VB (por ejemplo Msgbox). La clase se carga cuando parte el proyecto.

5) Referencciar el proyecto DLL al otro proyecto  EXE que lo ocupará. Seleccione su proyecto EXE, y haga click en Project|References. Chequee la box correspondiente a la r DLL. El proyecto EXE ahora sabrá que la DLL existe y podrá usar sus clases

 

Agregar una nueva clase a un proyecto EXE

 

1) Seleccionar Project|Add Class Module, doble click en Class Module.

Luego darle un nombre apropiado al nuevo módulo de clase

f123x - no es obviamente un buen nombre, pues no dice nada acerca de la funcionalidad de la clase

FuncionesArchivo- está algo mejor, pero todavía le falta

ClsFuncionesArchivo - bien!  Se trata de una clase (cls) que contioene funciones de archivo.

Ya estamos listos para crear métodos, propiedades y constantes, tal como aprenderemos en las secciones siguientes

 

Creando un Control

When creating a new class you have a number of options:

1) Create a new ActiveX Control project, and add controls to that. This will then be compiled into a OCX, which can then be used by multiple projects.

2) Just add a new control to your current EXE project. This will be included into your EXE, and cannot be used by other projects.

To create a new ActiveX Control project:

1) Select File|Add Project, and double click on ActiveX Control. A new project is added to your project group.

2) A control is automatically added to the ActiveX control project for you.

3) Give the project a suitable name

To add a new class to your current EXE project:

1) Select Project|Add User Control, and double click on User Control.

2) A new control is added to your project.

Then give the class a good name that means something:

f123x - not a good name. What's it for? Is it a class, control, form or a module?

Project - getting there. This control displays a project. Is it a class, control, form or a module?

ctlProject - good! This is a control (ctl) that displays a project, and will have methods and properties to allow you to use it.

A new icon on the toolbox has been added. Select your EXE project and add the control to a form. If the new icon is disabled, close both the form window and the code window of your Control. When you switch back to the EXE project, the icon will have been enabled.

 

Variables y Propiedades

 

Variables

Para usar una variable dentro de un control, simplemente debe declararse de la manera normal. Si necesita accesarla por el container (por ejemplo la form donde esta puesto el control) se debe crear una propiedad como se describe a continuación

 

Definiendo propiedades

Al usar un control tal como el textbox, hay un número de propiedades que se pueden ajustar. Algunas son propiedades estandar que tienen todos los controles tales como left, width, tag, y name. Otras son únicas a ese control (y a veces usadas por otros controles), tales como Text, Enabled, Locked o Multiline. Para darle una propiedad a un control o a una clase hay tres formas que (en orden de sencilles) son:

 

1) Usar el ActiveX Control wizard (clickear en  Project|Add User Control|VB ActiveX Control Wizard)

2) Simplemente declarar una variable public, como:

Public Enabled As Boolean

3) Crer un procedure Property Enabled_Let and Property Enabled_Get

 

Para el principiante, la opción 1 es, sin duda la más conveniente

 

El segundo método también es simple, pero crea una propiedad que solo puede asignarse en tiempo de ejecución. También permite al proyecto que usa el control (llamado el cliente) cambiar el valor de enabled sin su conocimiento.. Si la propiedad no requiere validadción y no necesita cambiar ottras propiedades(y, por lo tanto no interesa si el cliente cambia o no) bien podría usarse éste método. De otra manera debera usarse la instrucción Property Como muestra el siguiente ejemplo

 

Dim m_BackColor As Long '// private variable that stores the value of BackColor.
'// the back color property. This is called when the client requests the value of BackColor
Public Property Get BackColor() As Long
BackColor = m_BackColor '// return the private variable
End Property

'// this is called when the client requests to change the value of BackColor.
Public Property Let BackColor(ByVal New_BackColor As Long)
'// if the property is read only (ie the client cannot change its value), you do not need this procedure.
'// before you assign the new value, you could check to see if it is empty, or a valid colour etc.

m_BackColor = New_BackColor '// set the private variable to the new value
PropertyChanged "BackColor" '// property has changed
End Property

 

Mapeando propiedades de un control a otro

 

Si quiere que la propiedad de un control mapee a la propiedad de otro directamente (por ejemplo si el control tiene una textbox y cuando el usuario cambia la propiedad text se requiere cambiar la propiedad textbox.text) entonces hay que hacer lo siguiente

 

'// the back color property. This is called when the client requests the value of BackColor
Public Property Get Text() As String
BackColor = txtMain.Text '// return the textbox.text property
End Property

'// this is called when the client requests to change the value of BackColor.
Public Property Let Text(ByVal Text As String)
'// if the property is read only (ie the client cannot change its value), you do not need this procedure.

'// before you assign the new value, you could check to see if it is empty etc:
'// If New_Text = Empty Then Exit Property

txtMain.Text = New_Text '// set the textbox.text property to the new value
PropertyChanged "Text" '// property has changed
End Property

 

Especificar cuando las propiedades pueden ser asignadas y leídas

 

Si quiere que una propiedad sea read-only en la etapa de diseño, hay que chequear la propoiedad Ambient.UserMode. Es falso en teimpo de diseño y verdadero en tiempo de ejecución

 

Dim m_vFile As Variant
Public Property Get vFile() As Variant
'// we are happy for the client to read vFile at both run time and design time
vFile = m_vFile
End Property

Public Property Let vFile(ByVal New_vFile As Variant)
'// only allowed to set value at run time
'// raise an error if we try to set it at design time.
If Ambient.UserMode = False Then Err.Raise 382
m_vFile = New_vFile
PropertyChanged "vFile"
End Property

 

Así si solo quiere leer y asignar una propiedad en tiempo de diseño, hay que insertar:

 
If Ambient.UserMode = False Then Err.Raise 387
into both the Property Let and Property Get procedures, and likewise, if you only want to be able to read and set a property at run time, then you insert
If Ambient.UserMode Then Err.Raise 387
into both the Property Let and Property Get procedures.

 

Especificando valores por default a propiedades

 

La manera más fácil de hacer esto es crear una consatante como se muestra a continuaciçon:

 

 Const m_def_Text = "Default Value" '// default value of Text property

 

Luego, asignar el siguiente código al control (presumiendo que ya tiene una variable llamada m_Text variable, una constante m_def_Text y una propiedad Text):

 

Private Sub UserControl_InitProperties()
m_Text = m_def_Text '// set Text property to default value
End Sub

 

Luego, necesitará especificar m_def_Text en los procedures WriteProperties y ReadProperties .

 

Si desea tener una propiedad que default al nombre del control (como la propiedad caption del control label), entonces la cosa es algo diferente. Primero, no puede poner una constante parea el valor default, pues no sabrá el nombre del control (ej. Control1, Control2 etc) hasta el tiempo de ejecución. Tpor lo tanto declara una variable llamada  m_def_propertyname, y coloca su valor en el procedure UserControl_Initialize

 

Private m_def_Text As String
Private Sub UserControl_Initialize()
m_def_Text = UserControl.Name '// set its default value to the name of the control
End Sub

 

Grabando y leyendo propiedades

 

Si ya ha agregado el control a la form, colocado algunas propiedades y luego cerrado la ventana de diseño estas propiedades se perderán. Cuando vuelva a abrir esa ventana y mire las propiedades del control encontrará que ninguna se ha grabado. Para grabarlas necesita usar dos procedures

 

'// Load property values from storage
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

End Sub

'// Write property values to storage
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

End Sub

 

Para cada propiedad es necesario grabar su valor en el evento WriteProperties, y leerla en el evento ReadProperties. Esto se hace llamando los métodos  PropBag.WriteProperty y PropBack.ReadProperty, que tienen la siguiente sintaxis:

 

ReadProperty(Name As String, [DefaultValue]) '// a function - returns the property value

WriteProperty(Name As String, Value, [DefaultValue]) '// a sub

So, as an example, the following code allows VB to read and write the Text property:

'// Load property values from storage
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
'// fill the private variable (m_Text) with the value of Text. You can specify a default value, in this case the constant m_def_Text
'// first param: Property Name
'// second optional param: Default Value
m_Text = PropBag.ReadProperty("Text", m_def_Text)
End Sub

'// Write property values to storage
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
'// save the private m_Text variable. You can specify a default value, in this case m_def_Text
'// first param: Property Name
'// second param: Property Value
'// third optional param: Default Value
Call PropBag.WriteProperty("Text", m_Text, m_def_Text)
End Sub

 

Escondiendo propiedades en tiempo de diseño

En algunos casos, como la propiedad TextRTF del control RichTextBox puede que no desee que la propiedad se muestre en tiempo de diseño. Para esto seleccione Procedure Attributes en el menu Tools. Seleccione la propiedad de los nombres que se despliegan, haga click en Advanced, y chequee Don't show in Property Browser

 

Métodos (Procedures y Functions)

Los Métodos son básicamente los procedures y functions públicos de un control. Si desea hacer un método para su control (que el cliente pueda llamar) simplemente declárelo como public. Los procedures y fuctions privatdos no están disponibles para el cliente (principio de la encapsulación)

.

'// Public Refresh method
Public Sub Refresh()
UserControl.Refresh
txtMain.Refresh
End Sub

'// Private update method
Private Function Update(txtText As TextBox)
'// update text box
End Function

 

 

Constantes y Enums

Habrá notado que no se puede tener una constante pública en un user control o módulo de clase. También habrá notado que muchos parámetros en otros controles vienen con una lista de posibles valores, como vbCritical para la propiedad Icon de la función Msgbox . Para hacer esto en VB, se usa la instrucción Enum. Esta es la única manera posible de crear constantes públicas. Aquí va un ejemplo

 

Public Enum ShowDialogConstants
SDC_ShowOpen = 0
SDC_ShowSave = 1
SDC_ShowPageSetup = 2
End Enum

 

La asignación de valores es opcional, para usar esto en un parámetro, se especifican como ShowDialogConstants en lugar de las usuales As Long etc. Luego, cuando el usuario del control encuentra ese parámetro de la función, tendrá una lista de las posibles constantes

 

Public Sub ShowDialog(vMethod As ShowDialogConstants)
Select Case vMethod
Case SCD_ShowOpen
'// show open
Case 1 '// the specified numbers can be used too
'// show save
...
End Sub

 

 

Agregando Descripciones

Puede agregar una descripción a una propiedad o método seleccionando Procedure Attributes en el menú Tools .