Este fichero sirve para los que no saben como empezar a hacer un ActiveX..., pero algunas de estas cosas no aparecen en la MSDN o pasa muy por encima. Meter siempre: --- UserControl_WriteProperties: Se ejecuta cuando se copia un control dentro de un formulario de Visual Basic y al guardar el formulario donde está el control, para evitar que se pierdan las propiedades. Aquí tambien se definen las propiedades que va a tener el control. Si no aparecen aquí, se ignoran.) --- UserControl_ReadProperties (Se ejecuta cuando se pega un control dentro de un formulario de Visual Basic, para evitar que se pierdan las propiedades.) Se recomienda poner: --- UserControl_InitProperties (por si los controles que forman el OCX usan imagelist) --- UserControl_Resize (por el cambio de tamaño, puedes evitar que ocurra o para que los controles que hay dentro se estiren o se encojan) Otras: --- UserControl_DragDrop (si piensas usar el drag'n drop en ese control) --- UserControl_Click (si piensas controlar los eventos click) --- UserControl_DblClick (si piensas controlar los eventos doble click) --- UserControl_MouseDown | MouseUp (similar al clic, pero sabes que boton ha pulsado) ------------------------------------------- (a) PROPIEDADES OBJETO USERCONTROL En USERCONTROL_WRITEPROPERTIES se definen las propiedades que tiene el control (da igual si son publicas o privadas). Si no aparece aqui una propiedad, no se puede usar. Se usa el metodo 'WriteProperty' del objeto PropBag En USERCONTROL_READPROPERTIES se lee el valor de las propiedades (creo que se usa cuando se copia y pega el control). Se usa el metodo 'WriteProperty' del objeto PropBag. Ejemplo para UserControl_WriteProperties: Nombre de la propiedad || \||/ \/ PropBag.WriteProperty "NodeCount_D", NodeCount_D, 0 <-- el 0 es el valor por defecto /\ /||\ || valor de la propiedad Ejemplos para UserControl_ReadProperties: Color_Nuevo = PropBag.ReadProperty("Color_Nuevo", RGB(255, 162, 29)) /\ /\ /\ /||\ /||\ /||\ || || || Propiedad Propiedad (entre comillas) Valor por defecto Set MouseIcon = PropBag.ReadProperty("MouseIcon", LoadPicture()) /\ /||\ || Hay que usar SET porque es un objeto (por lo demás es igual que el ejemplo de arriba) (b) NUEVOS EVENTOS Meter nuevos eventos: Public Event [()] Activar esos eventos (desde dentro del OCX): RaiseEvent [()] Ejemplo: Public Event GirarCarta() <-- define el evento RaiseEvent GirarCarta <-- dispara el evento (c) METER PROPIEDADES AL OBJETO USERCONTROL (c.1) Decidir nombres de propiedades y tipo de datos y crear una variable global por cada propiedad (otra opcion es meterlas todas en una estructura TYPE ... END TYPE) El tipo de dato de las propiedades puede ser casi todo: Integer, Long, String, Double, Single, Boolean, Collection, IPictureDisp (para imágenes), enumeraciones (son enteros), otros controles (Label,...), conexiones ODBC,... Los tipos definidos por el usuario (los famosos TYPE ... END TYPE) no los soporta. :( ej: (X = acceso total ; @ = solo desde dentro) Nombre Tipo dato Es un objeto Lectura Escritura ============================================================================= CodCarta String * 2 NO X X Numero String * 1 NO X @ Palo String * 1 NO X @ Enabled Boolean NO X X ValorCarta Integer NO X @ ImagenCarta IPictureDisp NO X(**) X colExtras Collection SI X X (**) este tipo lo usa la propiedad .Picture de los controles (Image, Picturebox,...) (c.2) METER CODIGO * Public Property Get: Se puede acceder al valor de una propiedad desde fuera. * Private Property Get: No se puede acceder al valor de una propiedad desde fuera. * Public Property Set: Se puede cambiar al valor de una propiedad desde fuera. (de tipo objeto, coleccion,...) * Private Property Set: No puede cambiar al valor de una propiedad desde fuera. (de tipo objeto, coleccion,...) * Public Property Let: Se puede cambiar al valor de una propiedad desde fuera. * Private Property Let: No se puede cambiar al valor de una propiedad desde fuera. - Si no aparece Property Get no se puede saber que valor tiene la propiedad. - Si no aparece Property Let (o Property Set si es un objeto) no se puede cambiar el valor de la propiedad. --- Dentro de una propiedad puedes llamar a otras SUBs y Functions. Ejemplos: '********************************************************** ' Colección usada para pasar las caracteristicas de los treeviews. ****************************************************************** Public Property Get ColeccionPropiedades() As Collection 'colcoleccionpropiedades es una varaible global Set ColeccionPropiedades = colColeccionPropiedades End Property Public Property Set ColeccionPropiedades(colPropiedades As Collection) Set colColeccionPropiedades = colPropiedades End Property '-- devuelve el nodo seleccionado del lado izquierdo Public Property Get NodoSelecIzqdo() As Node Set TreeviewIzqdo = tvwIzqda.SelectedItem End Property '--- tipo de treeview creado en el lado derecho Public Property Get IDSecreto_Dcha() As enuTreeview IDSecreto_Dcha = intIDSecreto_Dcha End Property '-- no se puede cambiar desde fuera del ACTIVEX -- Private Property Let IDSecreto_Dcha(strNuevoID As enuTreeview) Select Case strNuevoID Case dtw_Trabajos, dtw_TrabajosSelec, dtw_ProcesosTrabajos, _ dtw_ListaManual, dtw_Contratos, dtw_GestionTrabajos_Lista, _ dtw_GestionTrabajos_Contratos ' = (0,...,6) intIDSecreto_Izqda = strNuevoID Case dtw_Menus ' = 666 Err.Raise 380 'errores provocados Case Else 'cualquier otro nº Err.Raise 380 'errores provocados End Select End Property '-- puntero del raton --- Public Property Get MousePointer() As MousePointerConstants MousePointer = bytMousePointer End Property Public Property Let MousePointer(bytPuntero As MousePointerConstants) Select Case bytPuntero Case 0 To 15, 99: bytMousePointer = bytPuntero img_Carta.MousePointer = bytMousePointer Case Else: Err.Raise 380 'El valor de la propiedad no es válido End Select End Property '--- parte de atras de las cartas Public Property Get BackCard() As enuBackCard BackCard = bytBackcard End Property Public Property Let BackCard(bytID_backcard As enuBackCard) Select Case (bytID_backcard) Case enu_Default, enu_Blue, enu_Red: bytBackcard = bytID_backcard PropertyChanged 'se informa a VB que la propiedad ha cambiado de valor If (blnAlReves) Then Call Cambiar_Imagen End If Case Else: Err.Raise 380 'El valor de la propiedad no es válido End Select End Property (c) METER METODOS AL OBJETO USERCONTROL Los metodos solo son PUBLIC SUB y PUBLIC FUNCTION definidas dentro del control (solo cuentan las del .CTL, no valen las que están en los .BAS) Ejemplo: 'palo usado como pinte (sirve para juegos como el tute) Public Sub SetPinte(ByVal strPalo_Pinte As String) 'quita espacios y comprueba el primer caracter strPalo_Pinte = Left(Trim(UCase(strPalo_Pinte)), 1) Select Case (strPalo_Pinte) Case "O", "C", "E", "B": strPaloPinte = strPalo_Pinte Case Else: strPaloPinte = "" End Select End Sub (d) INCLUIR LA VENTANA 'ACERCA DE...' Y OTROS EXTRAS Primero añade esto a tu ActiveX (en el fichero .CTL) Public Sub About() Load frmAbout frmAbout.Show vbModal End Sub Crea un formulario frmAbout que incluya el nombre del control, version y quien lo ha hecho. Vete al menú HERRAMIENTAS y elige ATRIBUTOS DEL PROCEDIMIENTO. En el campo Nombre, elige About (asi es como se llama la sub que llama al formulario) Haz clic en Avanzados. En el campo 'ID del procedimiento' elige ABOUTBOX. Haz clic en Aplicar y despues en Aceptar. Nota 1: Aqui puedes poner un pequeño comentario (en el campo Descripción) a las propiedades y métodos que has creado. Ese comentario aparece en la ventana propiedades y en el examinador de objetos. Nota 2: Cuando insertes tu OCX en el formulario, veras la propiedad '(Acerca de...)' al lado de la propiedad 'Nombre'. Si pinchas en ella, saldrá tu ventana. (e) ULTIMOS DETALLES La imagen que aparece en la barra de herramientas se mete en la propiedad TOOLBOXBITMAP del UserControl. Debe tener formato .BMP . Sus dimensiones son 16 pixels ancho x 15 pixels alto. Ya solo te queda compilar y probar que todo funciona... ;)