Pegar un PictureBox en otro

Fecha: 28/Ene/2004 (27-01-2004)
Autor: Carles Tricuera tricuera@bsab.com


Tuve que desarrollar un aplicativo que a partir de un fichero de base de datos Access (.mdb), acababa dibujando un organigrama. Dado que el tamaño de dicho organigrama era imprevisible debido a que dependía de ciertas selecciones previas del usuario, me lo monté todo en un control "PictureBox" aprovechando los métodos gráficos de éste. Hasta ahí, ningún problema; éstos surgieron a la hora de querer incluir en algún lugar de la imagen final, un logotipo.
Si añadía un control "Image" u otro control "Picture" en el inicial (los controles picture son contenedores) con la imagen del logotipo previamente cargada, me encontraba con que por pantalla se mostraban tanto los controles contenidos como los elementos creados por métodos gráficos pero a la hora de imprimir los resultados o guardarlos en un fichero de imagen (BMP, JPG, etc.) solo se reflejaban los gráficos; los controles eran como sino existieran.
Probé con las diversas funciones de las que dispone la API y que hacen referencia a los contextos de dispositivo y conseguí imprimir y guardar gráficos y controles a la vez pero sólo los que se encuentran visibles en la pantalla; los que quedaban fuera de los límites de esta eran ignorados por lo que las funciones API, pese a su potencia tampoco me solucionaron el problema.

Al final "se me encendió la bombilla"

Algún sabio dijo: "Lo más rápido, seguro y eficaz es siempre lo más sencillo" y es curioso comprobar lo cierta que resulta la cita sobre todo en el mundo de la informática.
Se me ocurrió que si cargaba el logotipo en un pequeño PictureBox invisible, leía sus pixeles con el método Point y los pintaba sobre el Picture de destino con el método Pset, la cosa podría funcionar. Y así fue; el problema quedaba resuelto con un par de bucles FOR NEXT anidados.

El poco código necesario es el siguente:


  Dim DatoPixel As Long, X As Integer, Y As Integer, DestinoX As Integer, DestinoY As Integer

  ' Los valores de DestinoX y DestinoY pueden ser cualquier coordenada en pixels
  ' que esten dentro de los límites del picture de destino.
  
  DestinoX = 50: DestinoY = 100


  ' Nos aseguramos de interpretar las medidas i coordenadas en "pixeles"
  
  Origen.ScaleMode = 3 ' "Origen" es el picture que contiene la imagen que queremos "pegar"
  Destino.ScaleMode = 3 ' "Destino" es el picture en el cual queremos "pegar" el origen
  
  
  '"escaneamos" la imagen de origen que vamos a "pegar" en destino"
  
  For X = 0 To Origen.ScaleWidth - 1
    For Y = 0 To Origen.ScaleHeight - 1
      DatoPixel = Origen.Point(X, Y)  'leemos el color del pixel de origen
      Destino.PSet (DestinoX + X, DestinoY + Y), DatoPixel  'pintamos el pixel leido, en Destino
     Next
  Next

Este método es particularmente eficaz cuando la imagen de origen es de reducidas dimensiones. En imágenes extensas, los bucles pueden tomarse su tiempo pero en general las imágenes o porciones de imagen que se "pegan" en otras no acostumbran a ser muy grandes.
Si lo que queremos "pegar" es solo una porción de la imagen de origen, no tenemos más que "jugar" con los valores de inicio y final de las variables X e Y de los bucles; además, podemos hacer que un color o colores determinados de la imagen de origen sean transparentes simplemente con no pintarlos en destino.

Formulario de ejemplo.

En el pequeño ejemplo que adjunto se incluyen los procedimientos para "hacer" colores transparentes así como para "salvaguardar" el área donde se "pegará" la imagen de origen para poder hacer "marcha atrás" si es necesario.

Nada más. Espero que todo ello os resulte de utilidad.


ir al índice

El formulario de ejemplo: tricu_PegarPictureBoxEnOtro.zip - 202 Kb.