Programación General > Visual Basic 6.0 e inferiores

 TransOCX (Frames Transparentes)

<< < (2/2)

juanfosaiz:
Por supuesto.

...cesol.es/TransOCX/TRANS11A.zip

Gracias de nuevo.

Nebire:
He hecho un pequeño proyecto de prueba, y la causa queda clara... la propiedad zorder no interviene para nada, da igual el orden Z

El control enmascara el contenedor con el contenido gráfico del contenedor padre. Esto es lo que hace el control, y lo hace bien.
El problema está en lo que tú asumes que hace, pero que no hace. Me explico.

Tu tienes una ventana que tiene una imagen de fondo,  tienes un control lamémosle frame1, y dentro de este otroframe, llamémosle frame2. Bien cuando se establece la propiedad autofindcontrol (o se cambia cualquier otra propiedad) internamente el control invoca a crear la máscara, esta se crea con el contenido gráfico (el ORIGINAL) del contendor padre donde está alojado el control transpar... Veamos, le toca el turno al frame1, crea una máscara con el contenido gráfico del formulario ... ahora le toca el turno al frame2 crea una máscara con el contenido gráfico del frame1, pero el contenido gráfico del frame1 no es lo que visualmente 'se ve', lo que se ve es el resultado del contenido gráfico y la máscara, así si el frame1 tuviera un fondo rojo, el frame2 crea una máscara para ese contenido gráfico (en la practica una cantidad de bytes cuyo contenido es el byte RED, rojo).

Dicho de otro modo, el control notiene capacidad de anidamiento. al control le falta 'un hervor', para que fuera más útil. La propiedad autofindcontrol, localiza el contenedor padre, si tuviera una propiedad que realizara la función como señala el nombre ContainerMask, entonces permitíría asignar el contenedor del que crear la máscara, así para el frame2 en vez de enmascarar contenido del frame1 podríamos decirle:
frame2.autofindcontrol=false
set frame2.ContainerMask = Me (el formulario)
Entonces daría un resultado correcto. como no tiene una propiedad similar, entonces la solución pasa por colocar el contenido gráfico directamente tú sobre el contenedor, para que así el contenedor  anidado, tome dicho contenido para enmascarar...

Hay un problema, los controles frame, no implementan una interfaz que es la que proporciona el método paintpicture (no tiene propiedad hDC)...
Por tanto tu solución pasa por una entre varias alternativas, en vez de usar frames, utiliza controles picture, y un label para emular el control frame, o bien crea un usercontrol que imite un frame pero que tenga propiedad picture.

Te envío una copia del proyecto que he realizado para probarlo... en el mismo verás la solución aplicada sobre un picture...
El proyecto inicialmente recoge 3 imágenes, que las va alternando para que se vea como enmascara el contenido. Observarás como cuando se hace un resize, se realiza... también debe suceder cada vez que cambie el contenido gráfico (es decir la imagen del formulario), para verificar bien esto se ha provisto  2 botones "demostración" . Pulsa preferiblemente el botón 'Demostracion2', par aalternar lasimágenes y siguiendolo paso a paso ver como se va actualizando. ... si tienes dudas pregunta.
Tal vez debas modificar la referencia del control transpar (para localizar el componenete) ... ya que yo lo tenía localizado sin registrar en la misma carpeta del proyecto... búscalo si te lo pide...

p.d.: antes de ejecutar el proyecto, elimina la línea (del procedimiento Form_Load)  me.show o bien carga en diseño una imagen en el formulario... olvidé limpiar las líneas extras... ya que quité la imagen, para que el proyecto apenas pesara, cargándolas desde windows, al empaquetarlo...

juanfosaiz:
Muchas gracias por las aclaraciones, Nebire. Al final supongo que seguiré tu consejo de quitar los frames e imitarlos con labels y paint pictures, va a ser un poco 'rollo' pero qué se leva a hacer (jeje)... Pero antes registraré el control y 'a ver qué tal', ya que yo también lo tengo localizado en otra carpeta.

 También miraré con atención tu ejercicio de prueba, me resulta bastante interesante, tanto para éste como para futuros proyectos.

 Muchas gracias por todo y un saludo.

Nebire:
Se me olvidó decirte que hay un par de líneas en el código de ejemplo que realmente no son necesarias, pero que se incluyeron para que se viera paso a paso como sucede

las líneas son las que están a ambos lados de paintpicture, las ...Tr(7).ShowClient , las puedes quedar comentadas.

--- Código: Visual Basic --- Private Sub Form_Resize()    MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."    Stop  ' pulsa la TECLA F8 para continuar, paso a paso    With Picture1        Tr(7).ShowClient = True  ' desactivamos, para que luego al activarlo 'lea' el nuevo contenido que enmascarar        Call .PaintPicture(Me.Picture, 0, 0, , , .Left, .Top, .Width, .Height, vbSrcCopy) ' pegamos un nuevo contenido gráfico        Tr(7).ShowClient = False  ' ahora al activarlo crea una máscara para el contenido gráfico, que ahora coincide con el del fondo.    End WithEnd Sub  
Hay también otra forma de verificar como el control asume la máscara del contenedor... cambiándolo de contenedor, prueba este ejemplo haciendo los cambios oportunos.

--- Código: Visual Basic --- Private Sub Form_Resize()    MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."    Stop  ' pulsa la TECLA F8 para continuar, paso a paso     Set Frame5(0).Container = Me         ' al mudarlo al formulario, enmascara con el contenido gráfico del mismo,    Set Frame5(0).Container = Frame2  ' al mudarlo de nuevo al frame del que procede, nuevamente se vuelve a enmascaras, con su contenido gráfico.End Sub  
...y una solución algo más simple aún a base de unas líneas extras respecto del código que tengas actualmente, saca los frames de dentro del frame, es decir que el contendor sea el formulario, sin anidamiento, pero sitúalos en la posición actual y el que hasta ahora el contenedor envíalo alplano z del fondo. Con esto consifues lo que necesitas visualmente, sólo deberás tener en cuenta otros detalles, como por ejemplo cuando tengas que ocultar lo que antes era el frame padre..., haz la operación inversa, calculas o guardas la posición que toca dentro del frame anidado y le devuelves como contenedor el original
ejemplo, en el evento resize del  formulario llamas a esta función :

--- Código: Visual Basic --- Private Sub Form_Resize()     Call Desanidar(Frame5(0))End Sub Private Sub DesAnidar(ByRef f As Frame)    Dim x As Single, y As Single    x = f.Left + f.Container.Left    y = f.Top + f.Container.Top    Set f.Container = Me    f.Move x, y    f.ZOrder 0End Sub Private Sub ReAnidar(ByRef f As Frame, ByRef O As Control)    Dim x As Single, y As Single    x = f.Left - O.Left    y = f.Top - O.Top    Set f.Container = O    f.Move x, y    f.ZOrder 0End Sub ' oculta o muestra el frame2, al hacerlo arrastra con ello también al que tiene anidado... ' OJO: usar un check no  es muy bueno (se pone sólo como ejemplo) porque al hacer resize lo desanidamos, y por tanto puede no corresponderse con el estado del check... lo que movería el frame afectado a unas cordenadas incorrectas. Private Sub Check3_Click()    If Check3.Value = 1 Then        Frame2.Visible = True        Call Desanidar(Frame5(0))    Else        Call Reanidar(Frame5(0), Frame2)        Frame2.Visible = False    End IfEnd Sub  Este último método creo que es más cómodo para ti, porque lo diseñas completamente como tu quieres, y en ejecución posiblemente sólo necesites  hacerlo (desanidar) una vez...

juanfosaiz:
Hola a todos y gracias de nuevo, Nebire. Bueno, lo primero decirte que el ejercicio de muestra me aclara más dudas de las que yo pensaba (...), y muy buenas las ideas que expones, la de cambio de contenedor y la del desanidamiento de frames (éstas incluso me sirven para otras aplicaciones que tengo pendientes).

Muchas gracias de nuevo y saludos cordiales.

Navegación

[0] Índice de Mensajes

[*] Página Anterior

Ir a la versión completa