• Domingo 22 de Diciembre de 2024, 13:55

Autor Tema:  TransOCX (Frames Transparentes)  (Leído 5033 veces)

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
TransOCX (Frames Transparentes)
« en: Miércoles 10 de Marzo de 2010, 16:44 »
0
Hola a todos, me llamo Juan Fran, soy nuevo en el foro y lo primero que deseo, después de presentarme, es agradecer la existencia de este sitio de ayuda y donde se comparten
conocimietos. También quiero disculparme por si el primer tema que expongo tiene un texto demasiado largo.

Estoy cambiando la imágen gráfica de un formulario, y después de buscar sobre cómo evitar que objetos Frame se interpongan en el fondo del formulario (jpg) por no tener propiedades de transparencia o BackStyle, he encontrado el complemento (OCX) llamado "TransOCX", que convierte Frames en transparentes. El tema funciona, se trata poner el control TransOCX encima del propio Frame para que se haga transparente, y lo que pasa es que para que funcione tienes que, en vista diseño, "Enviar al fondo" todos los controles TransOCX, pero cuando vuelvo a cambiar algo en el formulario y lo vuelvo a ejecutar, vuelve a verse el fondo tapado por los colores de fondo de los frames, por lo que tengo que volver a la vista de diseño del ejercicio y volver a "Enviar al fondo" cada control TransOCX a mano, para que no interfieran los frames en el fondo del formulario.

Bueno pues he buscado y probado algunas cosas, como la propiedad ZOrder ("Transparent1.ZOrder (1)" para enviar al fondo (SendToBack)), pero no me ha funcionado, sigo teniendo que cambiar todos los TransOCX en vista de diseño cada vez que hago algún cambio en el módulo que sea del proyecto, y no digo ya el rollo que será cuando tenga 30 en vez de 5 que tengo ahora colocados. Tiene que haber algo que se pueda hacer en vista de código que sea definitivo. El "SendToBack" no me lo reconoce por la versión del VB (VB6 SP6).

Por favor, ¿existe algún truco o código para no tener que andar haciendo "Enviar al fondo" en vista de diseño cada control TransOCX cada vez que modifique el proyecto?

En la figura 1 muestro la colocación de los controles TransOCX en vista diseño en el formulario original (flechas rojas), en la figura 2 muestro el diseño que he hecho con el potochop para el fondo del formulario, y en la figura 3 se ve como queda en tiempo de ejecución la aplicación con el fondo nuevo. El cambio es radical.

Fig. 1: (por favor, poner tres 'w' antes de los nombres de las figuras y ponerlos en un navegador para verlas, ya que todavía no tengo autorización para poner enlaces en el foro)
cesol.es/Fig1.jpg

Fig. 2:
cesol.es/Fig2.jpg

Fig. 3:
cesol.es/Fig3.jpg

Las dos zonas naranjas de la Fig.3 es otra cosa que quería preguntar, ya que debe ser que al ser frames anidados dentro del frame que les rodea, ni siquiera haciendo "Enviar al fondo" en vista diseño de sus controles TransOCX respectivos, soy capaz de hacer que no se vea el color del fondo el frame original, y me tapa ciertos controles de los Frames y el fondo del formulario.

A ver si alguien me puede hechar una manilla o dar algún consejo, cualquier cometario será de agradecer.

Muchas gracias de antemano y saludos.

juanFran.

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #1 en: Jueves 11 de Marzo de 2010, 18:37 »
0
Hola.

Intenta lo siguiente:
Cuando se inicie la aplicación en el evento 'load' recorres toda la colección de controles del formulario, preguntandopor su tipo, si el control es del tipo transparente,  invocas su método 'zorder 1'
ç
algo así...

Código: Visual Basic
  1.  
  2. dim c as control
  3. on local error resume next  
  4. for each c in form1.Controls
  5.      if typename(c)= "NombreControlDeseado"  then ' el nombre de la librería, no la propiedad name del control.
  6.          c.zorder 1
  7.      end if
  8. next
  9.  
  10.  

Debería funcionar salvo que haya un control que realice alteraciones en el orden z.
Si esto sucediera, entonces tras cada intervención de ese suceso, se debería ejecutar una rutina que ejecute de nuevo el proceso de enviarlos al fondo.
Para el caso no tiene cuenta volver a recorrer la colección controls del formulario, basta recorrerla una vez al principio, se añaden a un objeto  dictionary y luego cuando se precise se reinvoca la función que los envía a todos al fondo. Un ejemplo... Nota que en ejemplo se usan textbox, sustituyelo por el tipo de objetos que es el control deseado.
Código: Visual Basic
  1.  
  2. ' a nivel del formulario, añade una referencia a microsoft scripting runtime
  3. Dim Trans As Scripting.Dictionary
  4.  
  5. Private Sub Form_Load()
  6.     Dim c As Control, k As Long
  7.    
  8.     Set Trans = New Scripting.Dictionary
  9.     For Each c In Form1.Controls
  10.         If TypeName(c) = "TextBox" Then ' el nombre de la librería, no la propiedad name del control.
  11.            k = k + 1
  12.             Call Trans.Add(CStr(k), c)
  13.         End If
  14.     Next
  15.     Call EnviarAlfondo
  16. End Sub
  17.  
  18. ' cada vez que se requiera se llama a este métdo, para reenciar los objetos  deseados al fondo.
  19. Private Sub EnviarAlfondo()
  20.     Dim c As Object, k As Long
  21.    
  22.     For k = 1 To Trans.Count
  23.         Set c = Trans.Item(CStr(k))
  24.         c.ZOrder 1
  25.         c.BackColor = vbRed  ' como el orden no se aprecia visualmente, cambiamos el color del fondo... sólo vale para controles con una propiedad backcolor, por supuesto, si no dará error.
  26.    Next
  27. End Sub
  28.  
  29.  

...ya nos cuentas si te funcionó o no...
«Ma non troppo»
----> ModoVacaciones = False<----

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #2 en: Viernes 12 de Marzo de 2010, 14:55 »
0
Hola de nuevo a todos y muchas gracias, Nebire, me ha parecido una respuesta de lo más competente, te lo aseguro. En cuanto pueda lo pruebo y comento resultados.

Gracias de nuevo y un saludo.

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #3 en: Martes 16 de Marzo de 2010, 10:15 »
0
Hola de nuevo, ya probé las opciones que me has dado, pero pese a la lógica aplastante de tu respuesta, de momento sigo con el mismo problema, no consigo llevar al fondo los controles "Transparent" desde el código. Debe ser que estos controles "Transparent" están limitados en cuanto a ciertas propiedades, aunque la propiedad ZOrder sale en el desplegable de opciones al dar al punto después del nombre (name) del control. He investigado más sobre este control "Transparent", como sus propiedades "ShowClient" y "ShowNonClient" porque no sé muy bien de que van, pero no he visto nada. Bueno creo que lo he hecho bien, pero por si acaso te paso los códigos que me has pasado interpretados en mi ejercicio.

Éste es el 1º:

Citar
2.Dim c as Control
3.On Local Error Resume Next  
4.For Each c In DatosSoldador.Controls ' ó Me.Controls
5.     If TypeName(c)= "Transparent"  Then
6.          c.ZOrder (1)
7.     End If
8.Next

Y el 2º:

Citar
-------------------arriba, en la declaración general

Dim Trans As Scripting.Dictionary

------------------------------------en el load
Dim c As Control, k As Long
   Set Trans = New Scripting.Dictionary
    For Each c In DatosSoldador.Controls ' ó Me.Controls
       If TypeName(c) = "Transparent" Then
            k = k + 1
           Call Trans.Add(CStr(k), c)
        End If
    Next
    Call EnviarAlfondo
-----------------------------------y el Sub EnviarAlFondo
Private Sub EnviarAlfondo()

  Dim c As Object, k As Long

    For k = 1 To Trans.Count
        Set c = Trans.Item(CStr(k))
       c.ZOrder (1)
      '  c.BackColor = vbRed  ' he comentado la línea por que efectivamente da error.
    Next
End Sub

Con lo que sea, de verdad te doy las gracias por ayudarme, por lo menos lo estamos intentando.

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #4 en: Martes 16 de Marzo de 2010, 22:35 »
0
Puedes subir el control a algún sitio donde pueda descargarlo y probarlo ?.
Dado que no es un control de VB si falla es necesario verificar el propio control...
«Ma non troppo»
----> ModoVacaciones = False<----

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #5 en: Miércoles 17 de Marzo de 2010, 08:23 »
0
Por supuesto.

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

Gracias de nuevo.

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #6 en: Miércoles 17 de Marzo de 2010, 18:01 »
0
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...
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.
«Ma non troppo»
----> ModoVacaciones = False<----

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #7 en: Jueves 18 de Marzo de 2010, 13:21 »
0
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

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #8 en: Jueves 18 de Marzo de 2010, 17:25 »
0
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
  1.  
  2. Private Sub Form_Resize()
  3.     MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."
  4.     Stop  ' pulsa la TECLA F8 para continuar, paso a paso
  5.     With Picture1
  6.         Tr(7).ShowClient = True  ' desactivamos, para que luego al activarlo 'lea' el nuevo contenido que enmascarar
  7.         Call .PaintPicture(Me.Picture, 0, 0, , , .Left, .Top, .Width, .Height, vbSrcCopy) ' pegamos un nuevo contenido gráfico
  8.         Tr(7).ShowClient = False  ' ahora al activarlo crea una máscara para el contenido gráfico, que ahora coincide con el del fondo.
  9.     End With
  10. End Sub
  11.  
  12.  

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
  1.  
  2. Private Sub Form_Resize()
  3.     MsgBox "ejecuta paso a paso estas instruccciones, teniendo a la vista el formulario en ejecución..."
  4.     Stop  ' pulsa la TECLA F8 para continuar, paso a paso
  5.  
  6.     Set Frame5(0).Container = Me         ' al mudarlo al formulario, enmascara con el contenido gráfico del mismo,
  7.     Set Frame5(0).Container = Frame2  ' al mudarlo de nuevo al frame del que procede, nuevamente se vuelve a enmascaras, con su contenido gráfico.
  8. End Sub
  9.  
  10.  

...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
  1.  
  2. Private Sub Form_Resize()
  3.      Call Desanidar(Frame5(0))
  4. End Sub
  5.  
  6. Private Sub DesAnidar(ByRef f As Frame)
  7.     Dim x As Single, y As Single
  8.     x = f.Left + f.Container.Left
  9.     y = f.Top + f.Container.Top
  10.     Set f.Container = Me
  11.     f.Move x, y
  12.     f.ZOrder 0
  13. End Sub
  14.  
  15. Private Sub ReAnidar(ByRef f As Frame, ByRef O As Control)
  16.     Dim x As Single, y As Single
  17.     x = f.Left - O.Left
  18.     y = f.Top - O.Top
  19.     Set f.Container = O
  20.     f.Move x, y
  21.     f.ZOrder 0
  22. End Sub
  23.  
  24. ' oculta o muestra el frame2, al hacerlo arrastra con ello también al que tiene anidado...
  25. ' 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.
  26. Private Sub Check3_Click()
  27.     If Check3.Value = 1 Then
  28.         Frame2.Visible = True
  29.         Call Desanidar(Frame5(0))
  30.     Else
  31.         Call Reanidar(Frame5(0), Frame2)
  32.         Frame2.Visible = False
  33.     End If
  34. End Sub
  35.  
  36.  
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...
«Ma non troppo»
----> ModoVacaciones = False<----

juanfosaiz

  • Nuevo Miembro
  • *
  • Mensajes: 6
    • Ver Perfil
Re: TransOCX (Frames Transparentes)
« Respuesta #9 en: Lunes 22 de Marzo de 2010, 10:04 »
0
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.