• Viernes 29 de Marzo de 2024, 03:38

Autor Tema:  Boton Dibujado en un picture. Necesito una Sugerencia  (Leído 3700 veces)

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Boton Dibujado en un picture. Necesito una Sugerencia
« en: Miércoles 4 de Agosto de 2010, 23:18 »
0
Hola amigos de solocodigo.

En esta ocasion estoy creando un "boton de comando" pero que se dibuje en un picture.

Los codigos son los siguientes:
Modulo
Código: Visual Basic
  1. Option Explicit
  2.  
  3. Public Sub Boton(PictureKE As PictureBox, Formulario As Form, Ancho As Single, Alto As Single, _
  4. PosX As Single, PosY As Single, Color_Borde As Long, Optional Color_Fondo_PictureKE As Long = vbBlack, _
  5. Optional Texto As String = "", Optional Tamaño_Letra As Integer = 9, Optional Color_Texto As Long = vbWhite, _
  6. Optional X_MOV As Single = 0, Optional Y_MOV As Single = 0, Optional Color_Fondo_Boton As Long = vbBlack, _
  7. Optional Color_Fondo_Boton2 As Long = vbYellow, _
  8. Optional Color_Texto2 As Long = vbRed, Optional Color_Fondo_Boton3 As Long = vbYellow, _
  9. Optional Color_Texto3 As Long = vbMagenta, Optional Click_Down As Boolean = False)
  10.  
  11. 'X_MOV y Y_MOV son las coordenadas del mouse, estas variables se activaran en el evento mouse move del picture, mientras
  12. 'estaran con valor = 0
  13. 'Color_Fondo_Boton2 es el color que toma el fondo del boton cuando el mouese esta sobre él
  14. 'Color_Texto2 es el color que toma el texto cuando el mouese esta sobre el boton
  15.  
  16. 'Color_Fondo_Boton3 es el color que toma el fondo del boton cuando se ejecuta Mouse Down
  17. 'Color_Texto3 es el color que toma el texto cuando se ejecuta Mouse down
  18.  
  19.  
  20. 'Click_Down es True en el momento que se ejecute el evento Mouse_Down del picture
  21. 'Click_Up es True en el momento que se ejecute el evento Mouse_Up del picture
  22.  
  23. 'acomodando el pcicture
  24. 'Call Acomodando_Picture(PictureKE, Formulario)
  25.  
  26. Dim Long_Texto As Single 'Longitud del texto
  27. Dim Alt_Texto As Single 'Altura del texto
  28. Long_Texto = PictureKE.TextWidth(Texto)
  29. Alt_Texto = PictureKE.TextHeight(Texto)
  30.  
  31.     'Cambiando el color de fondo del boton, si el mouese esta sobre el boton
  32.     If X_MOV >= PosX And X_MOV <= (PosX + Ancho) And Y_MOV >= PosY And Y_MOV <= (PosY + Alto) Then
  33.         PictureKE.Line (PosX, PosY)-(PosX + Ancho, PosY + Alto), Color_Fondo_Boton2, BF
  34.         'escribimos el texto siempre y cuando quepa dentro del boton
  35.         If Long_Texto < Ancho And Alt_Texto < Alto Then
  36.             Call Escribir_Texto_V2(PictureKE, Color_Fondo_PictureKE, Tamaño_Letra, PosX + Ancho / 2 - Long_Texto / 2, PosY + Alto / 2 - Alt_Texto / 2, Color_Texto2, Texto)
  37.         End If
  38.    
  39.     'Cambiando el color del boton si hay click
  40.     If Click_Down = True Then
  41.         PictureKE.Line (PosX, PosY)-(PosX + Ancho, PosY + Alto), Color_Fondo_Boton3, BF
  42.         'escribimos el texto siempre y cuando quepa dentro del boton
  43.         If Long_Texto < Ancho And Alt_Texto < Alto Then
  44.             Call Escribir_Texto_V2(PictureKE, Color_Fondo_PictureKE, Tamaño_Letra, PosX + Ancho / 2 - Long_Texto / 2, PosY + Alto / 2 - Alt_Texto / 2, Color_Texto3, Texto)
  45.         End If
  46.     End If
  47.    
  48.     Else
  49.         'restableciendo el fondo del boton
  50.         PictureKE.Line (PosX, PosY)-(PosX + Ancho, PosY + Alto), Color_Fondo_Boton, BF
  51.         'escribimos el texto siempre y cuando quepa dentro del boton (Boton normal)
  52.         If Long_Texto < Ancho And Alt_Texto < Alto Then
  53.             Call Escribir_Texto_V2(PictureKE, Color_Fondo_PictureKE, Tamaño_Letra, PosX + Ancho / 2 - Long_Texto / 2, PosY + Alto / 2 - Alt_Texto / 2, Color_Texto, Texto)
  54.         End If
  55.     End If
  56.    
  57.    
  58. 'dibujando el borde exterior
  59. PictureKE.Line (PosX, PosY)-(PosX + Ancho, PosY + Alto), Color_Borde, B
  60.  
  61.  
  62. End Sub
  63.  
  64. Sub Escribir_Texto_V2(PictureKE As PictureBox, Color_PictureKE As Long, TamañoLetra As Integer, _
  65. PosX As Single, PosY As Single, Color_Texto As Long, Texto As String, Optional ByRef Delta_X As Single)
  66.     Dim Delta_X_OLD As Single
  67.     Delta_X_OLD = Delta_X
  68.     'Delta_X es la coordenada X donde se termina de escribir la palabra
  69.     'Texto es la palabra escrita
  70.    
  71.     PictureKE.PSet (PosX, PosY), Color_PictureKE
  72.    
  73.    
  74.    
  75.     PictureKE.ForeColor = Color_Texto
  76.     PictureKE.FontSize = TamañoLetra
  77.     PictureKE.Print Texto;
  78.     Delta_X = PictureKE.CurrentX
  79.    
  80.     If Delta_X < Delta_X_OLD Then
  81.         Delta_X = Delta_X_OLD
  82.     End If
  83.    
  84.    
  85. End Sub
  86.  
  87. Public Sub Acomodando_Picture(PictureKE As PictureBox, Formulario As Form)
  88. 'Acomoda el picture en el form
  89. With PictureKE
  90.     .Top = 0
  91.     .Left = 0
  92.     .Width = Formulario.ScaleWidth
  93.     .Height = Formulario.ScaleHeight
  94.     .BackColor = vbBlack
  95.     .AutoRedraw = True
  96. End With
  97. End Sub
  98.  
  99.  

Y para dibujar 3 botones en el formulario, hago lo siguiente en el procedimiento Load de dicho formulario:
Código: Visual Basic
  1. Public Click_Down As Boolean
  2.  
  3. Public Ancho1 As Single, Alto1 As Single, X1 As Single, Y1 As Single
  4. Public Ancho2 As Single, Alto2 As Single, X2 As Single, Y2 As Single
  5. Public Ancho3 As Single, Alto3 As Single, X3 As Single, Y3 As Single
  6.  
  7.  
  8. Private Sub Form_Resize()
  9.    
  10. Call Acomodando_Picture(Picture1, Me)
  11.  
  12.     'Variables de tamaños de botnes
  13.     Ancho1 = Me.ScaleWidth * 0.1: Alto1 = Me.ScaleHeight * 0.05
  14.     X1 = Me.ScaleWidth * 0.1: Y1 = Me.ScaleHeight * 0.1
  15.    
  16.     Ancho2 = Me.ScaleWidth * 0.1: Alto2 = Alto1
  17.     X2 = X1 + Ancho1 * 1.5: Y2 = Y1
  18.    
  19.     Ancho3 = Me.ScaleWidth * 0.1: Alto3 = Alto1
  20.     X3 = X2 + Ancho2 * 1.5: Y3 = Y2
  21.    
  22.     Call Boton1
  23.     Call Boton2
  24.     Call Boton3
  25. End Sub
  26.  
  27. Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  28.     Click_Down = True
  29.     Call Boton1(X, Y)
  30.     Call Boton2(X, Y)
  31.     Call Boton3(X, Y)
  32.    
  33.     Call Click(X, Y)
  34. End Sub
  35.  
  36. Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  37.     Call Boton1(X, Y)
  38.     Call Boton2(X, Y)
  39.     Call Boton3(X, Y)
  40. End Sub
  41.  
  42. Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  43.     Click_Down = False
  44.     Call Boton1(X, Y)
  45.     Call Boton2(X, Y)
  46.     Call Boton3(X, Y)
  47. End Sub
  48.  
  49.  
  50. Private Sub Boton1(Optional ByRef X As Single, Optional ByRef Y As Single)
  51.     Call Boton(Picture1, Me, Ancho1, Alto1, X1, Y1, vbGreen, , "Text1", , , X, Y, , vbGreen, vbBlue, , , Click_Down)
  52. End Sub
  53.  
  54. Private Sub Boton2(Optional ByRef X As Single, Optional ByRef Y As Single)
  55.     Call Boton(Picture1, Me, Ancho2, Alto2, X2, Y2, vbGreen, , "Text2", , , X, Y, , vbGreen, vbBlue, , , Click_Down)
  56. End Sub
  57.  
  58. Private Sub Boton3(Optional ByRef X As Single, Optional ByRef Y As Single)
  59.     Call Boton(Picture1, Me, Ancho3, Alto3, X3, Y3, vbGreen, , "Text3", , , X, Y, , vbGreen, vbBlue, , , Click_Down)
  60. End Sub
  61.  
  62. Private Sub Click(X As Single, Y As Single)
  63.     If X >= X1 And X <= (X1 + Ancho1) And Y >= Y1 And Y <= (Y1 + Alto1) Then
  64.         'Click del primer boton
  65.         MsgBox ("Boton1")
  66.     ElseIf X >= X2 And X <= (X2 + Ancho2) And Y >= Y2 And Y <= (Y2 + Alto2) Then
  67.         'Click del segundo boton
  68.         MsgBox ("Boton2")
  69.     ElseIf X >= X3 And X <= (X3 + Ancho3) And Y >= Y2 And Y <= (Y3 + Alto3) Then
  70.         'Click del tercer boton
  71.         MsgBox ("Boton3")
  72.     End If
  73.    
  74. End Sub
  75.  
  76.  
  77.  

Como resultado se visualiza los "botones" dibujados en el picture, asi:

En el codigo pueden ver que cuando el mouse pasa por encima del boton, este cambia de color, lo mismo cuando se ejecuta el evento Mouse_Down del picture.

Mi pregunta es la siguiente:
Hay alguna manera de hacer esto sin que se coloque tanto codigo en el Form_Load ?
Necesito sugerencias.


Un saludo y de verdad, muchas gracias.


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #1 en: Jueves 5 de Agosto de 2010, 21:01 »
0
Creando un control OCX.
Ahora estoy de vacaciones así que sólo me pao de tanto en tanto por el foro ni puedo dedicarle tiempo.
Para finales de agosto regreso, si no tienes mucha prisa para entonces te pongo un ejemplo...
«Ma non troppo»
----> ModoVacaciones = False<----

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #2 en: Jueves 5 de Agosto de 2010, 21:37 »
0
Cita de: "Nebire"
Creando un control OCX.
Ahora estoy de vacaciones así que sólo me pao de tanto en tanto por el foro ni puedo dedicarle tiempo.
Para finales de agosto regreso, si no tienes mucha prisa para entonces te pongo un ejemplo...
Perfecto... disfruta de las vacaciones amigo...  ^_^   :good:


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #3 en: Sábado 4 de Septiembre de 2010, 05:01 »
0
Bueno una vez acabadas las vacaciones, como te señale, vamos a construir un control de usuario.

Como es largo (de explicar) lo haré en partes.
En esta primera parte vamos a describir todo lo necesario para poder desarollar los proyectos y crear los archivos necesarios para crear el control y probarlo. ncluyendo la primera prueba del control, sin código alguno, listo para la siguiente parte en que iré exponiendo código y las razones de qué, cómo, cuándo y porqué de cada cosa.

______________________________
Para empezar es conveniente saber que un control deusaurio se crea cuando necesitamos exponer una interfaz de usuario, es decir algo gráfico. Desde este punto de vista estos controles deberían mejor llamarse 'control gráfico de usuario' frente a las clases que podrían llamarse 'control no gráfico de usuario', como el orden de suceso de las cosas fueron de una manera cada cosa se llamó como en su momento se consideró oportuno. También es importante señalar que quien ya ha trabajado con clases encontrará bastante asequible trabajar con controles de usuario.

Ahora crearemos todos los archivos y proyectos que necesitamos para empezar, se creará un proyecto para elcontrol y un proyecto para probarlo y ambos proyectos serán controlados por lo que en el entorno VB se llama 'grupo de proyectos' . Así abramos el entorno de desarrollo y elegimos eltipo de proyecto 'control Activex'.  Ahora cambiamos el nombre del proyecto (para no perdernos en explicaciones conviene que le des el mismo nombre que sugiero, luego en tu desarrollo dale el nombre que prefieras, éste nombre elegido es por comodidad en la didáctica, nada más) desde 'proyecto1' a 'PryBoton'. Ahora igualmente cambiamos el nombre del control de usuario desde 'UserControl1' a 'CtlBoton'. finalmente le damos al botón guardar para guardar el proyecto, la ruta elígela como prefieras yo sugiero algo como: 'C:Mis proyectoscontrolesBotón simple'.

Una vez creado el proyecto del control, podremos cerrar el entorno y volverlo a abrir o bien desde el menú 'archivo' elegir 'crear nuevo proyecto', ahora elegimos un proyecto de tipo 'exe estándar'. Igualmente que con el anterior a este proyecto le renombramos desde 'proyecto1' a 'Probar_ctlBoton' . el nombre del formulario no importa. Ahora guardamos el proyecto, la ruta será la misma que elegimos para el control pero creamos una carpeta llamada 'pruebas' y lo guardamos dentro de esa carpeta ('C:Mis proyectoscontrolesBotón simplePruebas'). Este proyecto está destinado a probar el control mientras lo estamos diseñando e incluso para probarlo una vez hayamos compilado el control.

Para que ambos proyecto trabajen juntos ambos deben estar dentro de un grupo de proyectos, así ahora vamos al menú 'archivo' y elegimos 'añadir proyecto' y desde la ficha 'recientes' elegimos el proyecto 'pryBoton' (o bien lo localizamos desde la ficha existente, también podríamos haber creado en este momento el proyecto del botón) y lo abrimos. Si nos fijamos bien en el cuadro de herramientas se nos ha añadido el icono para el control que hemos añadido (más adelante se indicará como proporcionar un icono personalizado para el control). Seleccionamos dicho icono del control (veremos que el tooltip del icono señala el tipo de control que es (ctlBoton) . Bien pués ahora pongamos una instancia del control en el formulario del proyecto de prueba.
Ahora pulsamos el botón de guardar proyecto, el archivo del grupo de proyectos 'grupo1.vbg' (vb-Group ) lo guardamos también donde el proyecto de prueba, no es necesario cambiarle el nombre. Si ahora cerramos el entorno cuando volvamos a abrir el entorno ahora buscaremos abrir el archivo de proyectos, 'grupo1.vbg', ya que si sólo abrimos uno de los proyectos se abrirán sólo los archivos concerniente a ese proyecto, este archivo de 'grupo' es el que vincula 2 o más proyectos entre sí. Mas adelante se darán las indicaciones oportunas a la hora de compilar el control.

Bien ahora ya tenemos todo listo para empezar. Vayamos al control de usaurio y abramos el control, sobre las propiedades del control busquemos la propiedad backcolor cambiémosla por cualquier color que no sea gris... rojo, negro va bien. Si apartamos la ventana del control lo suficiente para ver el formulario veremos que el control aparece 'rayado', esto es indicativo de que el control está en 'modo diseño' . Cerremos la ventana del control (la ventana no el proyecto) veremos que inmediatamente nuestro control en el formulario cambia, no sólo desaparece el rayado sino que ahora aparece del color que le elegimos para el fondo, se dice que ahora el control está en 'modo de ejecución'. Esto es importante tenerlo en cuenta, ya que un poyecto de vb estaba en ejecución cuando pulsábamos f5 y aquí aún no lo hemos pulsado.

Podemos proceder, pero primero damos al botón paa guardar todos los cambios operados (yo en mis opciones de vb tengo por defecto que cuando ejecute un proyecto me pida si se guardan o no los cambios así, yo no necesito pulsar el botón, pero hay que acostumbrarse a guardar los cambios antes de ejecutar (el proyecto deprueba). Pulsemos la tecla F5 y veremos nuestro control en ejecución, aunque de momento no hace nada, sin embargo se ve y (en mi caso aparece rojo).

Ya estamos listos para empezar a diseñar nuestro botón. Esta es la primera parte, los preparativos iniciales, realmente lleva más tiempo explicarlo que hacerlo... y bastante más si además se tiene que teclear las indicaciones así que ruego paciencia.

Mañana empezaremos a diseñar el botón y explicaremos el ciclo de vida de un control de usuario.
«Ma non troppo»
----> ModoVacaciones = False<----

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #4 en: Sábado 4 de Septiembre de 2010, 05:07 »
0
Estare en primera fila siguiendo este pequeño curso que preparas para mi.  B)
Ufff, no sabes cuanto te lo agradezco !!

Leyendoooo  y aprendiendo mas ^_^
Y claro que tendré paciencia, creo que soy el que la pide amigo !!!


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #5 en: Domingo 5 de Septiembre de 2010, 06:35 »
0
Bueno, vamos por la siguiente parte.

Ya hemos creado los archivos necesarios del proyecto, por tanto ahora abrimos el entorno desde el archivo Group1.vbg que como señalé es el que mantiene unido ambos proyectos el del control y el de prueba.

Este tramo inicial podía haberla añadido al final de la parte de ayer , pero bueno....
 
Hay que señalar que cuando hay un grupo de proyectos, sólo uno es el 'proyecto inicial', el que se va a ejecutar cuando se arranque el proyecto para su ejecución, en este caso el proyecto inicial es el de prueba ya que el del control actúa como secundario dentro del proyecto de prueba... justo cuando se inicializa el formulario (cuando se carga los controles ya deben haberse cargado, de hecho se carga justo cuando el último control constituyende del formulario se ha cargado) se invoca la carga de todos y cada uno de los controles que lo integran. Para hacer la prueba vayamos al código del formulario y escojamos el procedimiento de evento del formulario initialize, este sería su código :
Código: Visual Basic
  1.  
  2. Private Sub Form_Initialize()
  3.     MsgBox "Formulario inicializando"
  4. End Sub
  5.  
  6.  
Acto seguido vamos a la ventana de código del control, también en su procedimiento de evento initialize.... este sería su código:
Código: Visual Basic
  1.  
  2. Private Sub UserControl_Initialize()
  3.     MsgBox "Control inicializando"
  4. End Sub
  5.  
  6.  

Para verificar lo que se ha dicho finalmente exponemos código en el load del formulario:
Código: Visual Basic
  1.  
  2. Private Sub Form_Load()
  3.     MsgBox "formulario inicializado  y cargando..."
  4. End Sub
  5.  
  6.  

Ahora ejecutamos paso a paso el grupo de proyectos (tecla F8).. veremos que vamos al procedimiento initialize del formulario, luego al initialize del control y finalmente al load del formulario.

Para el diseño del control esto no tiene mucha importancia, pero es precisamente lo que nos ayudará a entender la cascadade sucesos de arranque del control. Si se piensa bien el evento initialize del formulario ocurre una sola vez, en cambio el evento load del formulario puede ocurrir varias veces durante la vida del mismo, esto mismo sucede con el control, aunque más adelante se detallará esta cuestión. Ahora lo que nos importa es saber si el proyecto de inicio fue exitosamente el de prueba. si fue el del control debemos ir al 'explorador de proyectos' (CTRL + R)  y fijarnos cualo de los dos proyectos aparece en negrita, eso marca el proyecto inicial, si es necesario, por tanto pulsamos click sobre el proyecto de prueba y sobre el menú emergente pulsamos en 'establecer como inicial'.

Ya borramos todo el código introducido anteriormente y guardamos el proyecto. Ahora empezamos realmente esta 2ª parte.
____________________________________-
Cuando vamos a crear un control, previamente es conveniente hacer una descripción sobre un papel de que funcionalidad es la que esperamos que tenga, evidentemente siempre en medio del proyecto podremos hacer añadidos y de hecho los haremos a propósito para ver como afecta los añadidos a última hora. Sin embargo cuanto mejor tengamos explicitado  lo que queremos que haga en mejores condiciones estaremos para proveer lo que precisa...

Vamos pués a proceder a dar una somera descripción de lo que pretendemos crear... es habitual que la razón por la que queramos construir un control es que determinado existente no tenga tal o cual característica/s por lo que nuestro modelo podría ser una copia en cierto modo similar a otro ya existente pero con algunos cambios.... por ejemplo, a mi nunca me gustó que los botones de microsoft no tuvieran una propiedad 'forecolor', por narices siempre es negro (se puede cambiar empleando APIs, pero no hay una propiedad), si queremos cambiar el color del fondo debemos cambiar la propiedad estilo a 'graphical', sólo entonces toma el color que hayamos designado a la propiedad backcolor, ese comportamiento también nos parece 'idiota', otra cuestión es que por ejemplo admite una imagen, pero se pega al tamaño real, también debe estar establecido estilo a graphical (Command1.style=1: Command1.picture= loadpicture(ruta...)) . Para colmo incluso creando una imagen justo a la medida del botón, si es oscurapor abajo nos 'tapa' el texto del botón... en fin como puede sentirse, hay razones que ya justifican nuestro botón y ya de entrada tenemos unas descripciones de lo que tiene que ser...

El control debe poder cambiar el color del fondo, el color del texto, alinear el texto horizontalmente, admitir una imagen ajustada en todo momento al fondo, tener capacidad para un icono alineado siempre a la izquierda y poseer un borde perimetral que de momento no definimos como se comportará (podría ser fijo o que se hunda al pulsar y se eleve al soltar), debe tener algunas propiedades típicas, activo (enabled), font, etc...

Es una descripción pequeña, pero para empezar a contruirlo nos vale, luego a medida que vayamos diseñando y probando terminaremos de definir tal vez nuevas propiedades o cambios de funcionalidad... esto debe entenderse como algo lógico y razonable, tampoco es estrictamente necesario tener una descripción exhaustiva del mismo, siendo como es para nosotros... A medida que uno se familiariza creando controles bastantes ideas de la descripción están ya en la cabeza y no necesitamos tener que plasmarlas por escrito, en cambio si conviene dejar escrito esas funcionalidades específicas que pretendíamos para el control ya que si no, cabe la posibilidad de que tras algún tiempo sin retomar el proyecto se nos haya olvidado por completo la misma, la funcionalidad que lo haría diferente de otros modelos previos que ya hayamos realizado, por ejemplo puede que este nuevo botón se deba a que queramos unir varios botones en línea y columna formando una tabla y por ello queramos redefinir la forma en que se dibuja el relieve de los mismos... o podríamos querer en un nuevo botón que tenga una pequeña animación cuando se pasa el ratón por encima, o simplemente añadir un sonido cuando se oprime y suelta elbotón... estas 2 últimas funcionalidades las utilñizaremos como un añadido de última hora cuando se dé al control por terminado...

El mejor sitio para dejar escrito la funcionalidad (las ideas de como debe operar) es usar un archivo de texto en la misma carpeta que el control, así siempre estará disponible.

Por tanto empezaremos definiendo propiedades bastante conocidas: Backcolor, forecolor, enabled, Text... pero a mi particularmente me gusta usar el español que es mi idioma, por tanto todas las propiedades y demás se reflejarán en lo posible en español... hay una razón más o menos poderosa para dejarlo en inglés, que ya para el final se indicará si no me olvido, y si me olvido me lo recordais (me refiero al final de la elaboración del control).

Las propiedades pueden usarse tanto en clases como en formularios y por supuesto en los controles que es donde más lo vemos. Las propiedades son un trío de funciones realmente pero que el entorno de VB lo enmascara como si fueran algo distinto de funciones, de hecho podríamos olvidar las propiedades y tratarlas como funciones pero nos perderíamos ciertas funcionalidades del entorno, como mostrar los valores de las propiedades del control en la 'Ventana de propiedades'.

Las propiedades como digo son un trío, una devuelve un valor y las otras 2 entregan un valor. de estas 2 una se utiliza cuando se usa un tipo de datos genérico y la otra cuando se usa como tipo de datos un objeto.
A continuación iremos poniendo código y explicando...
Código: Visual Basic
  1.  
  2. Public Property Get ColorTapiz() As OLE_COLOR
  3.      ColorTapiz = UserControl.BackColor
  4. End Property
  5.     Public Property Let ColorTapiz(ByVal ct As OLE_COLOR)
  6.         If ct <> UserControl.BackColor Then
  7.             UserControl.BackColor = ct
  8.             UserControl.PropertyChanged "ColorTapiz"
  9.             ' añadidos posteriores
  10.         End If
  11.     End Property
  12.  
  13.  
Acabamos de definir la propiedad ColorTapiz (colorFondo, BackColor) para el control, analicemos cada parte...
GET: es como una función, devuelve un valor, se usaría así en el formulario: dim X as long: x= CtlBoton1.Colortapiz : msgbox x
Public: porque queremos que esta propiedad sea legible, si quisiéramos que no se pudiera leer pondríamos private y sería una propiedad sin derecho a lectura.
LET: es la asignación de la propiedad, puede verse que es como una función tiene un parámetro que es por donde se recibe el valor, a dicho parámetro le hemos lamado, ct (abreviatura de Colortapiz, yo suelo usar esta convención), este parámetro no es visible desde fuera, luego no importa el nombre que se le dé. Let también se declaró public, si lo hubiéramos declarado private la propiedad estaría privada de escritura, es decir sólo podría invocarse para ser leída pero nunca podría escribirse.
Más adelante se mostrará que es posible dar más de un parámetro a las propiedades, sin embargo debe quedar claro que 1º no es obligatorio el par de procedimientos de la propiedad, puede usarse sólo el get y no aparecer el let, o al revés. 2º si aparecen ambos deben ser congruentes en el tipo de datos y en la cantidad de parámetros, veremos que siempre LET tiene un parámetro más que GET, 3º en las propiedades del control (en el formulario) sólo aparece una propiedad si aparecen ambos métodos y también ambos son públicos, si uno de los 2 es privado no aparece en las propiedades del control. (conviene que luego se pruebe a cambiarlos a private uno de ellos y se verá como deja de aparecer).

La propiedad almacena un color que a fin de cuentas es un tipo de datos long, porqué lo hemos declarado del tipo OLE_COLOR ?, porque cuando se declara de esa manera el entorno de VB nos despliega una 'página de propiedades'  para elegir visualmente el color, si utilizamos un tipo de datos long, desde el entorno sólo podríamos introducir valores numéricos desde el teclado. Los controles pueden poseer páginas de propiedades que es casi un pequeño mundo lo mismo que los controles pero que una vez conocidos los controles son más sencillos de conocer, el uso de páginas de propiedades para los controles facilita al programador poder cambiar cómodamente algunas propiedades incluso a varios controles a la vez, la contrapartida es que diseñar una página de propiedades nos lleva más tiempo y hace al control más pesado (el control una vez compilado pesa más)... si al final hay ganas podríamos crear una sencilla página de propiedades.

 Véase que usando una propiedad en vez de 2 funciones, ambos métodos se llaman iguales, usando funciones por necesidad cada uno debería tener un nombre distinto)... Ahora ponemos un ejemplo de como se asigna la propiedad del control en el formulario.... Dim x as long : x= 1234567: CtlBoton1.ColorTapiz = x .Aquí escritura y antes dimos un ejemplo de lectura de la propiedad. Antes de seguir, podemos probar ya esta nueva propiedad, para ello debemos ir al formulario y pulsar en el control, en las propiedades del control veremos que aparece la propiedad ColorTapiz y podemos ver como tiene el color que le asignamos (el tipo Ole_color hace que el entorno nos muestre el color visualmente en vez de un número y podemos cambiar el color y ver como el cambio se refleja en el control...por ejemplo cambíalo a azul... IMPORTANTE: si el control en el formulario aparece 'rayado diagonalmente', tal como se dijo ayer es porque está en modo diseño, para poder probarlo en el formulario es preciso ponerlo en modo ejecución, y para ponerlo en modo ejecución tenemos que cerrar la ventana del control (no la de código si no la de la interfaz del control)... esto no lo voy a repetir más veces, debe quedar claro YA.

Sólo nos queda describir el código introducido en los métodos de la propiedad ColorTapiz... para el get le decimos que colortapiz es igual a un valor que el propio control ya mantiene una variable... (Cada contenedor provee determinada funcionalidad, disponible para los objetos insertados en él y los contenedores del entorno de VB proveen propiedades como Backcolor,y algunas otras que se irán describiendo, al objeto Usercontrol, nuestra instancia. Por tanto la línea 'ColorTapiz = UserControl.BackColor' le está diciendo que  entregue la propiedad almacenada en la variable Backcolor que provee ya el control.
En cuanto al código de la asignación LET, lo primero que hacemos es verificar si el color recibido es el mismo, y sólo si es distinto se lo asignamos a la propiedad backcolor del usercontrol. La razón de esto es doble por un lado más adelante tenemos que añadir funcionalidad al final del código de este método, dicho código queremos que sólo se ejecute si realmente el color asignado cambió si no estaremos ejecutando cosas para que quede todo como estaba antes. La otra razón es que ahora el valor del color se guarda en la propiedad backcolor del control (en el que hemos delegado), pero si (cambiamos el color del tapiz a azul como se sugirió más arriba al probar y cerramos el entorno y volvemos a abrirlo, volverá a ser rojo, es decir el cambio no se ha mantenido, justo para eso está la siguiente línea: PropertyChanged "ColorTapiz", esta línea le  dice al entorno que esta propiedad ha cambiado, sin embargo esta línea no trabaja sola sino que trabaja en conjunto con 2 métodos del control, uno se encarga de guardar a fichero el cambio registrado (cuando le demos al botón de guardar cambios en el proyecto), y la otra funcionalidad se encargará de volver a leer el valor cambiado cuando arranquemos el proyecto, o se ponga en modo de ejecución el proyecto.

La última línea de código del método LET es una línea comentada, más adelante tenemos que introducir código ya que el cambio del color del fondo, implica que nos borrará el resto del contenido gráfico del control, por lo que se añadirá una línea que salte a una función que vuelva a dibujar todo lo que teníamos y que se ha borrado. Como ese método aún no lo tenemos, dejamos una línea comentándolo.

Justo ahora describiremos estos métodos que ayudan a almacenar de forma permanente las propiedades y que permiten luego al ejecutarlo volver a leer ese valor guardado y lo dejamos por hoy, mañana iremos más rápido con las siguientes propiedades una vez que hemos comprendido de forma general acerca de las propiedades, faltan detallesque se irán presentando según surjan los casos.

Para probar que el color no permanece, vayamos al modo ejecución y cambiemos el color del fondo... y acto segudio pulsemos la tecla F5, veremos que aparecerá el formulario pero con el color que le asignamos en la propiedad backcolor de la ventana de propiedades de la interfaz del control.

Ahora añadamos este código al control (abajo del todo):
Código: Visual Basic
  1.  
  2. Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  3.     With PropBag
  4.         .WriteProperty "ColorTapiz", UserControl.BackColor, Ambient.BackColor
  5.    
  6.     End With
  7. End Sub
  8.  
  9. Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  10.     With PropBag
  11.         UserControl.BackColor = .ReadProperty "ColorTapiz", Ambient.BackColor
  12.        
  13.     End With
  14. End Sub
  15.  
  16.  
Estos métodos pueden localizarse en la ventana de código del control sobre la lista de procedimientos del control (usarcontrol), por tanto elparámetro éste de propbag, lo provee el entorno de VB, este es un objeto interno de VB cuya funcionalidad procede de una interfaz cuyo objetivo es precisamente la de almacenar y recuperar valores de propiedades que se han asignado durante el diseño (impronta), es algo así como si compras un vehículo, cuando se fabrica es metal y debe ser pintado para evitar que se oxide, aunque a los vehículos se los elige el color y se piden se nosenvía cuando la fábrica dispone de una demanda suficiente de ese color para cambiar los tambores de pinturas en el proceso en cadena, por ejemplo para pintar 200 vehículos seguidios de ese color. sin embargo aquí en VB es como si todos salieran con una capa antióxido gris (que en el entorno se llama  Ambient.Backcolor y que es el contenedor quien decide ese color, de hecho es el color del contenedor, es como si la fábrica fuera azul por defecto todos los vehículos salieran azules), luego para asignar el color que actualmente hay guardado el objeto Propbag (Bolsa de propiedades) le dice asigna a la variable (Usercontrol.Backcolor) leyendo en las propiedades guardadas ( .Readproperties) el valor de la propiedad ColorTapiz  que se guardó bajo ese mismo nombre en el fichero, y si no se encuentra en el fichero un valor guardado tomamos el valor almacenado en usercontrol.backcolor actualmente.

Es decir el método readproperties se compone de 3 partes la asignación (usercontrol.Backcolor =), la invocación  del método del objeto pararecuperar el valor (propbag.Readproperties), pero que como usamos with, nos ahorramos escribir en cada línea el nombre del objeto), y los parámetros que necesita esta invocación, que al caso son 2, el nombre de la propiedad guardada y un valor que se asigna por defecto si tal propiedad no se encuentra: UserControl.BackColor = .ReadProperty ("ColorTapiz", Ambient.BackColor) igualmente en vez de poner por defecto el color del contenedor podríamos poner un color específico, por ejemplo: .ReadProperty( "ColorTapiz", vbBlue) o incluso un valor numérico: .ReadProperty ("ColorTapiz", 234567)

El método readproperties ocurre 1 única vez (realmente es un evento que se dispara para el usercontrol) y es cuando el control entra en modo de ejecución, una vez leídas las propiedades ya no se vuelve a invocar dicho método.

Writeproperties, es el método que usa el control para que se guarden las propiedades y ocurre también una sola vez, justo antes de que el control sea descargado de memoria. Esto sólo sucede mientras la 'aplicación cliente' está en diseño, es decir el control está en modo de ejecución, ya que en modo diseño lo que se guarda es el valor de la propiedad que nosostros le dimos en la ventana de propiedades del control, pero ese no es accesible a nosotros. Es decir nosotros hemos diseñado que cada vez que un cliente utilice el control éste aparecerá cuando se cargue por primera vez la instancia el color rojo, sin embargo el cliente querrá y podrá cambiar  que cuando su aplicación se ejecute el control aparecerá con el color que él eligió, es ese valor el que nosotros guardamos en writeproperties, los cambios que el cliente introduce cuando está diseñando la aplicación.

Este método consta de un parámetro más que el método readproperties del objeto propertybag: guarda a fichero (writeporperties) una propiedad con el nombre "ColorTapiz", cuyo valor actual está en la variable: Usercontrol.Backcolor (la variable que actalmente contiene su valor) y si el valor no se encuentra o no es válido entonces asigna éste por defecto (Ambient.Backcolor, el del contenedor donde se halleel control). Igualmente que para readproperties podría asignar un valor directo, como vbBlue ó 56789. Conviene en cualquier caso que en ambos sitios el color asignado por defecto sea el mismo en ambos casos

Bien ahora que ya hemos descrito como se logra que las propiedades permanezcan entre sesiones, podemos volver al formulario cambiar el color a uno que no hayamos usado (por ejemplo un violeta) y guardar el proyecto para que ocurra un evento writeproperties y efectivamente se guarden, luego pulsamos la tecla F5, con lo que ahora se crea el control (recordemos el evento initialize que probamos al principio de esta parte) y luego se invoca el evento readproperties, que asigna las propiedades que hemos guardado. en el evento initialize el color será rojo, pero ahora tras el readproperties será el que le dimos la última vez (violeta)...
Y finalmente por hoy ya que hemos guardado el color violeta para esta instancia veamos como al añadir una nueva instancia del control al formulario el color del fondo de éste es el rojo. Ahora debería quedar claro que valores son los que se guardan en writeproperties y se leen con readproperties Y también debería quedar claro el significado del método propertychanged.
También podemos probar a cambiar la propiedad del control por código, no sólo desde la ventana de propiedades de los objetos del formulario. Por ejemplo añade un botón microsoft y escribe código, para que cuando se pulse cambie nuestro control de color o nos diga el color actual.

Después hacer todas las pruebas que queramos, conviene dejar sólo una instancia del control (del que estamos diseñando) en el formulario para no liarnos cuando mañana continuemos...

Mañana ahondaremos en las propiedades y crearemos bastantes más ahora que se ha explicado como crearlas. También mañana explicaremos como se soportan propiedades que ni siquiera existen, backcolor lo posee el usercontrol y enabled, por lo que en estos caso podemos delegar en elas aunque como hemos visto podemos cambiarle el nombre por el camino...

No lo he revisado ya que sale un tocho largo y me llevaría más tiempo, espero que no se me haya escapado ningún gazapo...
«Ma non troppo»
----> ModoVacaciones = False<----

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #6 en: Lunes 6 de Septiembre de 2010, 08:59 »
0
Si alguien no se ha acabado de enterar muy bien de las propiedades puede abrir el grupo de proyectos ir al código que escribimos seleccionar la palabra property 1 pulsar la tecla F1 que nos lleva a la ayuda, naturalmente se explicará bien incluso mejor que yo el significado y declaración de la propiedad aunque todo el intríngulis de las propiedades no aparece... pero entre la ayuda y mis indicaciones creo que todo el mundo podría saciar sus dudas.

En el apartado de ayer se explicó gran parte de las propiedades y también se explicó la persistencia (preservación) de los valores de las propiedades. Hoy avanzaremos con más propiedades de nuestro control y se indicarán más detalles acerca de las propiedades a medida que surja cada caso.

Quedamos en que íbamos a requerir determinadas propiedades: ColorTapiz (BackColor), ColorTexto (ForeColor), el propio Texto del botón (Caption o Text), alinear el texto, un Icono,  una Imagen autoajustable al botón... pués hoy procederemos con el código para estas propiedades y de fondo otras característica sobre el Usercontrol...

El código para la propiedad ColorTexto (ForeColor)
Código: Visual Basic
  1.  
  2. Public Property Get ColorTexto() As OLE_COLOR
  3.      ColorTexto = UserControl.ForeColor
  4. End Property
  5.     Public Property Let ColorTexto(ByVal ct As OLE_COLOR)
  6.         If ct <> UserControl.ForeColor Then
  7.             UserControl.ForeColor = ct
  8.             UserControl.PropertyChanged "ColorTexto"
  9.             ' añadidos posteriores
  10.         End If
  11.     End Property
  12.  
  13.  
Vemos que prácticamente podemos copiar el código del Backcolor y hacer manualmente los cambios (de hecho yo lo he hecho así). ColorTexto es lo que nos va a permitir cambiar el color al texto que se escribe en el botón, de momento no hemos realizado la propiedad texto, por lo que aparece también la línea comentada 'añadidos posteriores. Lo dicho ayer sobre Usercontrol.BackColor  es aplicable también sobre Usercontrol.ForeColor, es una propiedad también sobre la que delegamos ya que la 'plantilla' que se nos presenta del contrl la trae, estas propiedades sobre las que podemos delegar pueden verse sobre la ventana depropiedades de la ventana de la interfaz del control. Igualmente si por defecto deseamos que la aplicación cliente tenga nada más cargar una instancia en un formulario un color determinado es en esa ventana donde debemos designarlo. Yo lo dejo en negro.

Debe quedar claro desde ya que todas las propiedades que vayamos a añadir y que el control posee delegaremos sobre ellas, salvo  que la funcionalidad sea totalmente distinta a la que realiza la plantilla... si surge un caso así ya se explicará.

Es conveniente (no obligatorio) que cada vez que añadimos una propiedad hagamos los propio para su persistencia, añadiendo las entradas correspondientes en los métodos Readproperties y Writeproperties... Yo copio una entrada anterior, pego y luego la modifico... entonces ya tendremos esto:
Código: Visual Basic
  1.  
  2. Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  3.     With PropBag
  4.         UserControl.BackColor = .ReadProperty("ColorTapiz", Ambient.BackColor)
  5.         UserControl.ForeColor = .ReadProperty("ColorTexto", Ambient.ForeColor)
  6.        
  7.     End With
  8. End Sub
  9.  
  10. Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  11.     With PropBag
  12.         .WriteProperty "ColorTapiz", UserControl.BackColor, Ambient.BackColor
  13.         .WriteProperty "ColorTexto", UserControl.ForeColor, Ambient.ForeColor
  14.        
  15.     End With
  16. End Sub
  17.  
  18.  
Es decir ayer pusimos la del color tapiz ahora metemos la del color texto.... en lo sucesivo sólo pondré la línea concreta como recordatorio, ya vosotros sabeis donde debe añadirse (a continuación de la anterior y dejamos una nueva línea para la siguiente entrada... bueno esto al gusto).

Ahora vamos con la siguiente propiedad; Texto. Vemos que el control no tienen una propiedad Text ni Caption, esto significa que no podemos delegar en ella sino que la tenemos que contruir completamente. Al hacerlo se entenderá fácilmente su lógica y se explicará como se le cede su primer valor.
Código: Visual Basic
  1.  
  2. ' esta línea de código debe ir arriba del todo, por encima de cualquier declaración de propiedades y funciones...
  3. Private p_Texto As String   ' el texto del botón se almacena en esta variable internamente.
  4.  
  5. ' esta línea podemos ponerla a continuación (debajo de) la propiedad ColorTexto.
  6. Public Property Get Texto() As String
  7.     Texto = p_Texto
  8. End Property
  9.     Public Property Let Texto(ByVal t As String)
  10.         If t <> p_Texto Then
  11.             p_Texto = t
  12.             PropertyChanged "Texto"
  13.             ' añadidos posteriores
  14.         End If
  15.     End Property
  16.  
  17.  
Como se puede ver, el valor de la propiedad realmente la almacenamos en una variable (p_Texto) declarada privada, por tanto  no es accesible desde fuera y debe verse como lógicamente la hemos declarado de tipo string. Surge una pregunta lógica de parte del aprendiz, porqué no guardamos directamente la propiedad sobre la variable p_Texto ?. De hecho podríamos hacerlo, pero entonces si tenemos algo como esto:
Código: Visual Basic
  1.  
  2. public TextoBoton as string
  3.  
  4.  
...Es realmente una propiedad con todas las de la ley, pero presenta unos inconvenientes para determinadas situaciones: 1º Si utilizamos una propiedad así, no hay forma de saber cuando el cliente ha cambiado su valor, por tanto tampoco sabemos cuando debe actualizarse lo que deba actualizarse.
2º Si necesitamos garantizar que el valor que introduce el cliente (el cliente en este caso es el programador que utiliza el control compilado) cumpla ciertos requisitos no tenemos forma de hacerlo porque como se indicó antes no sabemos cuando se introduce un nuevo valor.

Al expresarse las propiedades en forma de 2 funciones, una que entrega el valor y otra que lo recibe, la que lo recibe cuenta con 2 notificaciones, a) que se recibe un valor, B) si lo deseamos podemos comprobar si ese valor es distinto del actual, es decir si cambia de valor. Hasta ahora si os fijais en el código de las 3 propiedades que llevamos hasta el momento, en los 3 casos hemos verificado si el valor que se introduce es distinto del actual, ya se explicó ayer porque hacemos esa comprobación, no siempre la haremos como severá más adelante, básicamente cada vez que una comprobación se amás engorrosa o conlleve más tiempo que hacer las operaciones que un cambio supone.

Hemos creado la propiedad texto, pero sabemos que cuando se declara una variable antes de usarse su valor es el que VB asigna por defecto, en el caso de los números (byte, long,etc...) siempre valen 0 y en el caso de los tipo string valen "" es decir una cadena vacía. Naturalmente nosotros podemos querer que ya de entrada cuando se cree una instancia sobre el formulario del cliente éste texto (y en general casi todaslas propiedades), tenga ya un valor concreto y determinado por nuestro interés, etc... bien esto se llama inicialización de variables y nos interesa que sólo ocurra una vez, justo cuando se ha creado la instancia, luego ya sabemos que writepoprties guardará el valor  y que readproperties lo recuperará, además si el cliente cambia el valor entonces el que se guardará y luego se leerá será ese valor y no el que nosotros inicialmente le dimos, para que este funcionamiento sea así, por tanto este valor debe ejecutarse una sola vez, justodurante la creación por primera vez de la instancia. es preciso saber que el evento initialice ciertamente crea la instancia, sin embargo cuando se pasa al modo ejecución se destruye y es vuelta a crear es decir  se  vuelve a ejecutar initialize, parece pués un buen sitio para colocar ese código, pero claro si  se carga y descarga 10 veces el formulario, también 10 veces se ejecuta initialize y por tanto 10 veces le estamos asignando nuestro valor 'de capricho' siendo que luego 10 veces también se ejecutará el readproperties... no sería más útil que sólo se ejecutara 1 única vez ?.... pués esto es precisamente lo que hace un procedimiento del usercontrol.... ponemos el código (puede encontrarse el método en la lista de procediemientos de eventos cuando en la lista de la izquierda tenemos seleccionado el usercontrol, si tenemos seleccionado general, aparecerán las propiedades y funciones que vayamos creando ):

Por tanto en la lista izquierda seleccionamos usercontrol y en la lista derecha desplegamos hasta encontrar 'InitProperties'
Código: Visual Basic
  1.  
  2. Private Sub UserControl_InitProperties()
  3.     p_Texto = UserControl.Extender.Name
  4. End Sub
  5.  
  6.  
En este código hemos asignado el valor que tomará justo cuando el cliente inserta una instancia del control, sólo en esa ocasión ocurre el evento initproperties, por tanto en efecto se ejecutauna sola vez, aunque siempre sucede (cuando sucede) justo después del evento initialize (que de momento no lo tenemos presente, porque de momento no le hemos asignado código).
Hay nuevamente que recordar que hemos añadido una línea comentada, que está destinada a poner algó de código más adelante, de momento podemos cambiar el valor del texto, pero en nuestro botón no aparece el texto, esa línea comentada es justo donde le indicaremos cuando dónde y cómo dibujarse, pero esto loharemos cuando tengamos más elementos de juicio para dibujarlo, concretamente cuando decidamos como funcionará el alineamiento, ya que pensamos también incluir un icono, es lógico que el texto no quede cubierto por dicho icono... justo cuando describamos esas 2 propiedades pasaremos a dibujar el texto, porque ya tendremos definido todos los elementos que afectan al texto.

Ahora comentamos la línea de código: p_Texto = UserControl.Extender.Name
Podríamos haber puesto p_Texto = "Viva Yo y mi botón", y eso sería lo que siempre saldría cuando un cliente pusiera una nueva instancia del control sobre un formulario. Sin embargo lo lógico (y que estamos acostumbrado) es que cuando creamos un boton de microsoft , éste se llama Command1 y si ponemos otro este se llama Command2 y el nombre es precisamente el texto que contiene el botón. Esto es coherente y en esa coherencia nos movemos. Entonces que significa la parte derecha de la igualdad de p_Texto ?. Bien digamos que mientras se crea el control, VB crea y mantiene unas propiedades siempre vinculadas a cada control, esas propiedades están almacenadas en un objeto llamado VbControlExtender y de la que el usercontrol mantiene una instancia a través de la propiedad extender. Para curiosos decir que estas propiedades son aquellas que son propias e intrínsecas del control PERO DE las que el contenedor, realiza un seguimiento.

Ayer hablamos de otro objeto que es una propiedad del usercontrol Ambient. Conviene no confundir uno con otro. Extender, Por ejemplo además del nombre del control, mantiene la propiedad de posición  Left, Top y de tamaño Width y Height... si quereis saber con exactitud cuantas y cuales son las propiedades alojadas en el objeto extender, ir al formulario, seleccionad el control en el formulario y mirad las propiedades que tiene el control en la ventana de propiedades, si está en modo ejecución, pués son todas excepto las que nostros hemos creado hasta el momento, y si el control está en modo diseño (rayado) todas esas propiedades nosotros no las hemos creado, es el propio VB quien se encarga de crearlas para cada control y son aquellas que los contenedores deben tener acceso...  al contenedor no le importa ni necesita saber si yo tengo una propiedad llamada Icono ó Realte ó AlineaciónTexto... pero si necesita saber la posición del control, para saber si está parcialmente tapado o no, igual que la propiedad visible, etc... Hay también que decir que algunas de estas propiedades son de sólo lectura...
Podemos por tanto decir que un control se compone de 4 tipos de propiedades:
1 - Las que trae la propia plantilla del usercontrol (BackColor, Forecolor, Font, Picture, etc...) estas podemos usarlas o no, son opcionales no estamos obligados a usarlas si no las necesitamos.
2 - Las que se proveen a través de la propiedad Extender (del objeto VBControlExtender del que el usercontrol tiene una instancia accesible a través de la propiedad Extender) estas son obligadas y por tanto las provee el propio VB, como ya dije, Left, Top TooltipText, Name, Tag... ).
3 - Las que provee el contenedor y que tenemos acceso a ellas a través de la propiedad Ambient (del objeto AmbientProperties, como ), estas son todas de sólo lectura para el control.
4 - Y finalmente las que nosotros implementamos, ColorTapiz, ColorTexto, Texto, AlineacionTexto, Icono...

Tanto extender como Ambient no sólo proveen propiedades sino también funciones y eventos.

Finalmente, como hemos hecho con las otras propiedades, nos aseguramos de su  persistencia en el tiempo:
Código: Visual Basic
  1.  
  2. ' en el evento readproperties
  3. p_Texto = .ReadProperty("Texto", UserControl.Extender.Name)
  4.  
  5. ' en el evento writeproperties
  6. .WriteProperty "Texto",p_Texto, UserControl.Extender.Name
  7.  
  8.  
En lo sucesivo  ya no se comentará donde irá cada línea de persistencia de la propiedad... nos debe quedar claro donde corresponde cada una. Si pondré cada línea para que no se nos olvide...

Ahora deberíamos avanzar con una propiedad relacionada directamente con el texto AlineacionTexto:
Código: Visual Basic
  1.  
  2. ' declaramos la variable que contendrá el valor.
  3. Private p_Alineacion As TiposDeAlineacion  'AlignmentConstants  ' Guarda el valor de alineación del texto.
  4.  
  5. ' Creamos una enumeración para los valores posibles. Este código debe ir arriba del todo, incluso por encima de la declaración de variables.
  6. Public Enum TiposDeAlineacion
  7.     ALINEACION_IZQUIERDA = 0
  8.     ALINEACION_CENTRADA = 1
  9.     ALINEACION_DERECHA = 2
  10. End Enum
  11.  
  12. '  la declaración de la propiedad, la pondremos debajo de la última declaración de propiedad que pusimos
  13. Public Property Get AlineacionTexto() As TiposDeAlineacion
  14.     AlineacionTexto = p_Alineacion
  15. End Property
  16.     Public Property Let AlineacionTexto(ByVal at As TiposDeAlineacion)
  17.         If at <> p_Alineacion Then
  18.             p_Alineacion = at
  19.             PropertyChanged "AlineacionTexto"
  20.             ' añadidos posteriores
  21.         End If
  22.     End Property
  23.  
  24. ' el establcecimiento inicial de la propiedad dentro del evento initproperties, que ahora va quedando así...
  25. Private Sub UserControl_InitProperties()
  26.     p_Texto = UserControl.Extender.Name
  27.     p_Alineacion = ALINEACION_IZQUIERDA
  28.    
  29. End Sub
  30.  
  31. ' y finalmente el código de persistencia, cada línea donde corresponde ya debeis saber cual en cual...
  32.         p_Alineacion = .ReadProperty("AlineacionTexto", TiposDeAlineacion.ALINEACION_IZQUIERDA)
  33.         .WriteProperty "AlineacionTexto", p_Alineacion, TiposDeAlineacion.ALINEACION_IZQUIERDA
  34.  
  35.  
Ahora comentamos el código... Vemos que esta propiedad tampoc  delega el en objeto usercontrol, por lo que hemos declarado una variable para contener su valor  (yo a las variables de apoyo a la propiedades siempre les doy un nombre como p_nombrepropiedad , aunque no suelo poner el nombre de la propiedad completa, aldecidir un nombre de propiedad debe pensarse que debe resultar intuitivo al cliente su significado, por lo que no demos escatimar letras, si pusieramos alineación, el cliente podría tener dudas si se refiere al icono, o al control, pero con alineacionTexto, no da lugar a confusión, como internamente el cleinte no tiene acceso y sólo tengo una propiedad que tenga alineación, en la variable privada no me complico, un sencillo comentario al final de cada declaración, nos puede ayudar a recordar para qué se usa.

Se puede ver que hemos creado una enumeración para los 3 valores de la alineación, realmente vb, tiene una enumeración equivalente llamada AlignmentConstants, pero henmos desistido de usarla por 3 razones:
1º Nos sirve de excusa para aprender a usar enumeraciones como tipo de datos para cuando necesitemos variables.
2º La enumeración de windows no es correlativa de derecha a izquierda, nosotros tenemos izquierda, centro, derecha, con valores 0,1 y 2. Vb usa izquierda, derecha y centro que al menos a mi me parece  menos coherente.
3º Mantenemos en mente que estamos creando nuestro control en español (que se jodan los estadounidenses  :devil:  :devil:  :devil: así les damos algo de su propia medicina ... es broma).

En vez de una enumeración realmente para la declaración de la variable podríamos haber usado un tipo de datos byte, pero si usamos la enumeración mientras escribamos código el intellisense, nos ayudará sugiriéndono cual delos valores usar, con ello adelantamos al escribir y tampoco nos obliga a memorizar, esto limita en algo un posible error por ese problema de no haber recordado bien el valor... De modo consecuente, también se ha optado por usar el tipo de datos enumeración para la propiedad, porque así en la ventana de propiedades cuando el cliente decida cambiar el valor se despliega una lista precisamente exponiendo los nombres que les hemos dado a nuestras constantes de alineación.

Respecto de la alineación, nosotros sólo realizaremos una alineación horizontal, queda como ejercicio para el interesado cambiarlo por una alineación también vertical. A este respecto VB tiene otra enumeración AlignConstant, que usa valores semejantes a los anteriores pero que además añade top y bottom.

El código de la propiedad no está realmente bien terminado, si el lector es avispado hace rato que debería estar rondándole en la cabeza lo que vamos a describir a continuación...
Puesto que la alineación sólo tiene 3 posibilidades, que le impide al cliente introducir un valor de por ejemplo 25 ?. Realmente si así lo hiciera ahoraese valor sería introducido y si nuestro cálculo de reposicionamiento del texto estuviera ya listo, nos arrojaría un error, nos falta por tanto un 'hervor' en el código de la asignación de la propiedad.
Ese hervor es controlar que valor se introduce, y al efecto sólo debemos permitir que se introduzca uno de los 3 valoresposibles. Hay 2 formas (coherentes) de resolver esto, si el control es para nosotros, (como lo es) lo solucionaremos de una manera 'llana y sencilla' porque conocemos los detalles y sabemos que entenderemos laforma de funcionar que le vamos a dar, ahora bien si el control fuera un encargo de una empresa, lo que deberíamos hacer realmente es marcar un error cuando se introdujera un valor incorrecto, con ello el cleinte sabría que ha introducido un valor noadmitido y se supone que acabaría por 'conocer' bien el control. Pondremos ambos ejemplos de código.

' el código para un encargo de empresa:
Código: Visual Basic
  1.  
  2. Public Property Let AlineacionTexto(ByVal at As TiposDeAlineacion)
  3.         If at <> p_Alineacion Then
  4.            If (at < 0) or (at > 2) Then
  5.                Raise Error(380) ' el error 380 tiene asignado el significado de: Se ha asignado a una propiedad un valor incorrecto
  6.            else
  7.                 p_Alineacion = at
  8.                 PropertyChanged "AlineacionTexto"
  9.                 ' añadidos posteriores
  10.             End If
  11.         End If
  12.     End Property
  13.  
  14.  

El código, más inteligente, para gente más inteligente:
Código: Visual Basic
  1.  
  2. Public Property Let AlineacionTexto(ByVal at As TiposDeAlineacion)
  3.         If at <> p_Alineacion Then
  4.             If at < 0 Then
  5.                 at = 0 'ALINEACION_IZQUIERDA
  6.            ElseIf at > 2 Then
  7.                 at = 2 ' ALINEACION_DERECHA
  8.            end if
  9.  
  10.             p_Alineacion = at
  11.             PropertyChanged "AlineacionTexto"
  12.             ' añadidos posteriores
  13.        End If
  14.     End Property
  15.  
  16.  

En este caso hemos optado por no señalar un error, sino que cualquier valor por encima de 2 lo hacemos igual a 2 y cualquier valor menor que 0 lo hacemos = a 0. Cyuando el cliente está en modo de diseño y escribe una propiedad, se pasa el valor al procedimiento de propiedad, lapropiedad actúa, como no marcamos error, el valor queda correctamente almacenado en la variable p_Alineacion,pero partimos de que el cliente introdujo por ejemplo un valor de 37, entonces qué ocurre ?. a continuación (estando en diseño como hemos dicho),  el entorno de vb una vez termina el procedimiento let realiza una llamada (de forma transparente) al procedimiento get, para actualizar el valor en la ventana de propiedades, con lo que en efecto al leer el valor de p_Alineacion, le entregará el valor 2 que sustituirá al 37 que introdujo el cliente.

Todavía podría decir que a la propiedad alineacionTexto le falta un hervor más, pero en este caso no se aplica del todo, así que lo dejamos para más adelante cuando una propiedad lo justifique y si vamos terminando el control y no ha sucedido pués aprovechando esta propiedad locomentaríamos y dejaríamos puerta libre para que qien qiera lo aplicara o no.

Sobre la propiedad alineación sólo nos resta decir que al igual que las propiedades anteriores hemosdejado un comentario como recordatorio de que ahí va algo de código, que mañana cuando por fin pongamos el código para los gráficos se añada el código faltante en estas propiedades.

Ahora vamos a añadir una propiedad Font, para que nuestro cliente pueda decidir que tipo de letra se pone al texto del botón, este es el sitio adecuado para introducirlo (la posición).
Código: Visual Basic
  1.  
  2. ' el código de la propiedad fuente (Font)
  3. Public Property Get Fuente() As IFontDisp
  4.     Set Fuente = UserControl.Font
  5. End Property
  6.     Public Property Set Fuente(ByRef f As IFontDisp)
  7.         Set UserControl.Font = f
  8.          PropertyChanged "Fuente"
  9.         ' añadidos posteriores
  10.     End Property
  11.  
  12.  
  13.  
  14.  
Comentamos el código para esta propiedad. Esta propiedad es una propiedad de ambiente, por lo que también el usercontrol la contiene, por tanto delegamos en ella para contenerla. Ayer hablamos de que había 3 procedmientos de propiedad y que uno de ellos era para cuando el tipo de datos era un objeto. Este es el caso presente, Font es un objeto, por tanto no puede usarse 'property let' sino que deb usarse 'property Set', véase igualmente como la asignación de objeto utiliza Set para almacenarlo en la variable, el procedmiento Get, igualmente debe usarse un set y el cliente necesariamente deberá alamcenar este objeto en una variable que él designe como objeto sino obtendrá un error.
Luego hemos usado la interfaz Ifontdisp, del mismo modo y razón por la que usamos OLE_COLOR para las propiedades de color, ya que así VB presenta el cuadro de diálogo para que el cliente elija la fuente deseada así como sus propiedades (size, Bold, etc...)
Podríamos dividir la asignación de fuente en cada una delas propiedades del objeto, por ejemplo FontSize por un lado y fontName por otro, FontBold,etc... esto sólo interesa si por ejemplo queremos limitar al usuario de una de dichas características, aunque también en lapropiedad Fuente que hemos declarado, podríamos incluir código para hacer lo mismo, es cuestión de gustos, yo prefiero poner una sola propiedad fuente  en vez de varias, que llenen la ventana de propiedades... Finalmente hemos elegido pasar el dato por referencia y no por valor, aunque realmente VB hace una copia de la fuente, ya que si no un cambio originaría un cambio de donde procede, es decir el contenedor.

Ahora como ya habeis aprendido, a asignar un valor por defecto para la propiedad y también darle persistencia:
Código: Visual Basic
  1.  
  2. Private Sub UserControl_InitProperties()
  3.     p_Texto = UserControl.Extender.Name
  4.     p_Alineacion = ALINEACION_IZQUIERDA
  5.     Set UserControl.Font = Ambient.Font         ' no es estrictamente necesario, ya que esto sucede automáticamente
  6.    
  7. End Sub
  8.  
  9. ' persistencia:
  10.         Set UserControl.Font = .ReadProperty("Fuente", UserControl.Ambient.Font)
  11.         .WriteProperty "Fuente", UserControl.Font, UserControl.Ambient.Font
  12.  
  13.  


 A continuación, crearemos una propiedad icono y damos por terminado esta parte de hoy.
 
Código: Visual Basic
  1.  
  2. ' en la sección de declaración de variables....
  3. Private p_Icono As IPictureDisp ' icono que se presenta alineado enla izquierda
  4.  
  5. ' debajo de todas las propiedades hasta el momento....
  6. Public Property Get Icono() As IPictureDisp
  7.     Set Icono = p_Icono
  8. End Property
  9.     Public Property Set Icono(ByRef i As IPictureDisp)
  10.         Set p_Icono = i
  11.         PropertyChanged "Icono"
  12.         ' añadidos posteriores
  13.     End Property
  14.  
  15. ' persistencia.
  16.         Set p_Icono = .ReadProperty("Icono", Nothing)
  17.         .WriteProperty "Icono", p_Icono, Nothing
  18.  
  19.  
Esta propiedad es fácil y rápido de comentar... al como pasó para el color y la fuente usamos un tipo de datos que nos mostrará una ventana de propiedades como cuadro de diálogo para localizar y elegir la imagen deseada que se usará como icono. Hay que señalar que por defecto el icono es... ninguno, es decir si el cliente no elige un icono, no dibujamos nada. Por ello en el evento initproperties no le asignamos nada, ya es nothing...

Ahora guardar todo y podeis probar los añadidos realizados, claro que al ejecutar de momento sólo nos resulta tangible el colorTapiz ya que de momento no hacemos nada gráfico...

Mañana nos centramos en graficar todo lo que tenemos hasta ahora y que se pueda plasmar en el control. Veremos que alinear el texto tiene consecuencias según exista o no un icono, así mismo decidiremos un margen entre el control y el icono, ya que todavía nos falta una propiedad que realice un relieve sobre el contorno del control...
« última modificación: Lunes 6 de Septiembre de 2010, 22:46 por Nebire »
«Ma non troppo»
----> ModoVacaciones = False<----

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #7 en: Lunes 6 de Septiembre de 2010, 14:38 »
0
Volviste de las vacaciones con todas las baterias puestas (espero que sigas asi por mucho mas tiempo)  :lol:  
(aun te sigo leyendo, con tu explicacion se me vienen muchas ideas a la cabeza, pero no me apresuraré, esperaré ver el final de tu artículo antes de hacer cualquier cosa)...

Espero mas de tu valiosa explicacion.  :good:


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #8 en: Lunes 6 de Septiembre de 2010, 22:35 »
0
Bueno, hoy ya repasando lo de ayer (aparte de la ortografía, porque en el teclado me falla, sobre todo la tecla de espacio) observo que seme escapó un error, lo corrijo allí, pero lo señalo aquí por si alguien ya lo copió, para que sea consciente del cambio...

Donde aparece:
Código: Visual Basic
  1.  
  2. Public Property Let AlineacionTexto(ByVal at As TiposDeAlineacion)
  3.         If at <> p_Alineacion Then
  4.             If at < 0 Then
  5.                 at = 0 'ALINEACION_IZQUIERDA
  6.             ElseIf at > 2 Then
  7.                 at = 2 ' ALINEACION_DERECHA
  8.             Else
  9.                 p_Alineacion = at
  10.                 PropertyChanged "AlineacionTexto"
  11.                 ' añadidos posteriores
  12.             End If
  13.         Else
  14.             Raise Error(380)
  15.         End If
  16.     End Property
  17.  
  18.  
Debe sustituirse por:
Código: Visual Basic
  1.  
  2. Public Property Let AlineacionTexto(ByVal at As TiposDeAlineacion)
  3.         If at <> p_Alineacion Then
  4.             If at < 0 Then
  5.                 at = 0 'ALINEACION_IZQUIERDA
  6.             ElseIf at > 2 Then
  7.                 at = 2 ' ALINEACION_DERECHA
  8.             end if
  9.  
  10.             p_Alineacion = at
  11.             PropertyChanged "AlineacionTexto"
  12.             ' añadidos posteriores
  13.         End If
  14.     End Property
  15.  
  16.  

Puede verse que el bloque de decisión If...elseif, no puede finaliza con un else... sino que tras garantizar un valor aceptable (corrigiendo los valores fuera de ambos extremos) las líneas de código siguiente se aplican para todos los casos...
También a causa del copia-pega, del que partí para modificarlo, sobra la provocación de fallo: Else : Raise Error(380)

Este es el tipo de errores que cuando probamos un control vemos que su comportamiento no es como se esperaba y debemos buscar donde está el origen de la causa, a veces sólo con leerlo de nuevo, el error se ve claramente.

-------------
Nilson, aunque te guardes las preguntas para más adelante, convendría que las fueras haciendo y las guardaras en texto, para que no se te olvide y también conviene que el código lo vayas redactando a la par que yo me explico para que puedas ir probando...

Más tarde expondré la siguiente parte, ahora tengo algunas cosas pendientes que hacer...
«Ma non troppo»
----> ModoVacaciones = False<----

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #9 en: Martes 7 de Septiembre de 2010, 04:04 »
0
Citar
también conviene que el código lo vayas redactando a la par que yo me explico para que puedas ir probando...
Me parece bien.
Pero te pedire que pares 1 día para ir probando. Mañana no publiques nada para que me de tiempo de alcanzarte  ^_^ ....
El día de mañana probare todas las cosas minuciomente para luego hacerte las preguntas que me asalten.

Eres muy valioso Nebire, ya impresionaste a mi novia que también te lee  :lol:


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #10 en: Martes 7 de Septiembre de 2010, 07:13 »
0
Como el título no  acompaña y dado que saldrá una guía he decido abrir un nuevo hilo, pasar allí los mensajes y continuar desde allí...

La siguiente parte del tutorial la puedes ver ya allí.

Este es el hilo: viewtopic.php?f=143&t=44068

Las preguntas y respuestas las llevamos aquí y cuando finalice el turorial las copiamos las trasladamos allí, de modo que un mensaje tras otro sean la guía facilitando con ello a otros el poder leerlo seguido sin tener que ir buceando entre mensajes...
«Ma non troppo»
----> ModoVacaciones = False<----

Jimbenit

  • Miembro MUY activo
  • ***
  • Mensajes: 269
  • Nacionalidad: co
    • Ver Perfil
    • http://ingenieriacivil.foroactivo.com
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #11 en: Martes 7 de Septiembre de 2010, 15:07 »
0
Me parece perfecto que hagas un nuevo hilo con la explicacion completa, asi será mas fácil en la busqueda, ayudando mejor a todos y no solo a mi  :good:  :good:

Aunque considero que un hilo asi, debería quedar como fijo, ya que es un tutorial muy util diferente a los que encuentras normalmente en otras páginas. Ojala el MOD de la sección lo coloque como fijo, me hubiese gustado que tu fueras un MOD  :lol: ... asi colocar el tema como fijo seria mas sencillo.

Bueno, a estudiar !!, necesito aprender bien este tema  ^_^


Yo quiero mucho a Toph ---> Mi Web]http://ingenieriacivil.foroactivo.com[/url]

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: Boton Dibujado en un picture. Necesito una Sugerencia
« Respuesta #12 en: Sábado 18 de Septiembre de 2010, 17:32 »
0
Aunque a la guía no le quedan muchas partes, ya, para darlo por terminado, puedes ir exponiendo tus dudas AQUI, así las voy respondiendo sobre la marcha... eso sí no te adelantes a cuestiones aún no expuestas, pregunta ´de momento sólo lo que hay escrito.

Estoy procurando extenderme bastante en explicaciones a fin de que no vayan quedando cosas oscuras... pero obviamente 'lo que se ve', depende de 'donde se encuentra uno' y por ello es natural que unos lo vean todo despejado y otros a través de ramas...
«Ma non troppo»
----> ModoVacaciones = False<----