Crea tu propio ImageWell con Canvas

La creación de controles gráficos personalizados ya se ha abordado en anteriores entradas. En este caso me centraré en mostrar lo sencillo que resulta emular el comportamiento del ImageWell suministrado de serie como parte del Framework de Xojo. ¿Qué ventajas nos puede aportar? Entre otras cosas, evitaremos así un bug que está presente y que impide mostrar como imagen asignada del ImageWell cualquiera de las asignadas y cuyo tamaño ajustemos proporcionalmente (esto es que se muestre completa en la superficie del control). También nos servirá para ver como podemos habilitar y detectar la capacidad de que el usuario arrastre y suelte sobre el control un archivo de imagen.

Detectar archivos soltados sobre el control

Como de costumbre, comenzaremos añadiendo una nueva clase al proyecto. Puedes utilizar el Panel Inspector para añadir un nombre descriptivo (en el ejemplo utilizaré MyCanvas), asignando como clase superior Canvas, de modo que podamos heredar todas las propiedades, eventos y métodos de dicha clase.

Para que cualquiera de las instancias basadas en la recién creada clase puedan detectar el soltado de archivos JPEG, de modo que podamos tratarlos posteriormente, añadiremos el Evento Open e incluiremos la siguiente línea:

Me.AcceptFileDrop("img/jpeg")

En el caso de que quisiéramos aceptar otras extensiones de archivos gráficos, de entre los soportados por Xojo, bastaría con editar un File Type Set y utilizarlo como asignación de la anterior línea.

Tratar archivos soltados

El siguiente paso consiste en implementar el evento DropObject (cuya signatura completa es DropObject(obj As DragItem, action As Integer). Este es el evento que se disparará cuando el usuario suelte un archivo en los límites del control. Eso sí, hemos de verificar que se trata de un archivo de imagen, algo fácil de hacer. En el caso de que así sea, cargaremos el contenido del archivo como Picture y lo asignaremos a una propiedad del mismo tipo. Por tanto, aprovecha y añade ahora una propiedad a la clase (en el ejemplo image As Picture).

El código a añadir en el evento, por tanto, será el siguiente:

If obj.FolderItemAvailable Then
  image = Picture.Open(obj.FolderItem)
  Invalidate  
End If

¿Por qué Invalidate? Bien, acabamos de recibir una nueva imagen… de modo que tendremos que actualizar el estado gráfico de la instancia. Esto es lo que conseguimos mediante esta instrucción que fuerza el redibujado del control cuando sea posible.

Propiedades adicionales: Color de borde, tamaño de línea, color…

Las instancias creadas a partir de la clase han de indicar de algún modo que están presentes en el diseño de la ventana donde se vayan a utilizar. En nuestro caso nos limitaremos a hacerlo rellenando el fondo con un color específico, así como dibujando el borde del control con el color y tamaño de línea que deseemos. Para ello, añadiremos otra serie de propiedades a la clase:

  • backGroundColor As Color = &cdddddd
  • borderColor As Color = &c000000
  • penSize as Integer = 2

Redibujar el control

El último paso consiste en redibujar el control. Aquí es donde crearemos el aspecto propiamente dicho, no sólo rellenando el color de fondo y el borde con los colores asignados, sino también encajando y redimensionando (de ser necesario) la imagen soltada del control para que se vea correctamente. Esto es lo que logramos con el siguiente código:

//Rellenamos el fondo con el color indicado
g.ForeColor = backgroundColor
g.FillRect(0,0,Me.Width,Me.Height)

//Si hay una imagen válida, la dibujamos
If image <> Nil Then 

  Dim Height, Width As Integer

  Dim sourcey, sourcex As Integer = 0 

  If image.Height > image.Width Then

    Height = Me.Height
    Width = (Me.Height * image.Width) / image.Height

    sourcey = (Me.Width - Width) / 2

  Else

    Width = Me.Width
    Height = (Me.Width * image.Height) / image.Width

    sourcex = (Me.Height - Height) /2

  End If

  g.DrawPicture(image,sourcey,sourcex,Width,Height,0,0,image.Width,image.Height)

End If

//dibujamos el borde del control
g.PenWidth = penSize
g.PenHeight = penSize

g.ForeColor = borderColor

g.DrawRect(0,0,Me.Width,Me.Height)

Como puedes ver el código se explica por sí solo. No es nada complicado.

Si quieres, puedes sacar provecho del Inspector Behavior de modo que las propiedades añadidas al control puedan asignarse utilizando el Panel Inspector. De este modo, cuando añadamos nuevas instancias al diseño de las ventanas en el Editor de Diseño, sólo tendremos que utilizar el Panel Inspector para indicar el color de fondo, color de borde y grosor de línea que deseemos. Puedes leer como utilizar el Inspector Behaviour en tus clases en esta entrada.

Ahora ya sólo queda que arrastres la recién creada clase a la ventana donde desees incorporar dicha capacidad, ¡y listo! Verás como cuando sueltes archivos de imágenes JPEG sobre el control este se encargará de mostrarlas centradas sobre la superficie disponible.

En la imagen de ejemplo puedes ver como queda la misma imagen cuando se arrastra sobre un ImageWell (arriba) y sobre una instancia de la clase que hemos creado en este tutorial.

Javier Rodriguez

Consultor, desarrollador y formador con más de 25 años de experiencia. Reconocido experto en el mundo Apple, autor de varios libros sobre tecnología. Si tienes un proyecto o necesitas ayuda, ¡ponte en contacto conmigo!

Etiquetado con: ,

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*