Transparencia en controles definidos por el usuario

Post Reply
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Transparencia en controles definidos por el usuario

Post by Marcelo Via Giglio »

Holas,
estoy definiendo algunos controles, y no se como puedo hacerlos transparentes, por ejemplo he probado que el control sea una simple linea, pero igual el area del control no que da transparente, el :ltransparent := .T. no tiene efecto, o tengo que hacerlo de otra manera.

El control lo estoy derivando de la clase Tcontrol

alguna idea?

saludos

Marcelo
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Marcelo,

Estas usando temas de XP ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Post by Marcelo Via Giglio »

Antonio,

no, no estoy utilizando temas de XP

saludos

Marcelo
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Prueba a asignarle un brush "NULL" al control:

<oControl>:SetBrush( TBrush():New( "NULL" ) )

Eso hará que se dibuje transparente
regards, saludos

Antonio Linares
www.fivetechsoft.com
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Post by Marcelo Via Giglio »

Gracias Antonio,

pero aun no funciono, te dejo el codigo es super sencillo

Code: Select all

#include "fivewin.ch"

FUNCTION main()
   LOCAL oDlg, ofig1, ofig2, s1

   DEFINE WINDOW oDlg FROM 10,10 TO 40,60

   SetGridSize( 5, 5 )

   @ 15,15 say s1 PROMPT "HOLA" of odlg COLOR CLR_RED SIZE 100,20 DESIGN
   s1:lTransparent := .T.

   ofig1 := tfig():new(1,1,25,25, oDlg )
   ofig1:setBrush( tbrush():new("NULL"))

   ofig2 := tfig():new(25,25,45,55, oDlg )
   ofig2:setBrush( tbrush():new("NULL"))

   ACTIVATE WINDOW oDLg

   RETURN( NIL )

//----------------------------------------------------------------------------//

CLASS Tfig FROM TControl

   CLASSDATA lRegistered AS LOGICAL

   METHOD New( nRow, nCol, nHeight, nWidth, oWnd ) CONSTRUCTOR
   METHOD Display() INLINE ::BeginPaint(), ::Paint(), ::EndPaint(), 0
   METHOD Initiate( hDlg ) INLINE Super:Initiate( hDlg )
   METHOD Paint()

ENDCLASS

//----------------------------------------------------------------------------//
METHOD New( nRow, nCol, nHeight, nWidth, oWnd ) CLASS tfig

   ::nTop      := nRow
   ::nLeft     := nCol
   ::nBottom   := ::nTop  + nHeight
   ::nRight    := ::nLeft + nWidth

   ::oWnd      := oWnd
   ::nStyle  = nOr( WS_CHILD, WS_VISIBLE, WS_TABSTOP, WS_CLIPSIBLINGS )

   ::lCaptured   := .F.
   ::lDrag       := .T.
   ::lDesign     := .T.
   ::lUpdate     := .T.
   ::lRegistered := .f.
   ::ltransparent := .T.

   ::Register()
   ::Create()
   ::oWnd:AddControl( Self )
   ::CheckDots()

return SELF

//----------------------------------------------------------------------------//
METHOD Paint() CLASS tfig
   LOCAL hBrush, hOldBrush

   moveTo( ::hDC, 1, 1 )
   LineTo( ::hDC, ::nWidth, ::nHeight )

return Super:Paint()
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Marcelo,

Tu ejemplo parece funcionar correctamente en Vista:
Image
regards, saludos

Antonio Linares
www.fivetechsoft.com
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Post by Marcelo Via Giglio »

Antonio,

no me queda claro la idea de transparencia, si te das cuenta, el SAY no permite que se vea parte de la linea, asi mismo, cuando sobrepones las lineas, en funcion del orden de creacion claro esta, el area del control (linea) se sobrepone a la otra, en ese sentido no podria formar una cruz (+) con dos de estos controles, salvo que sus diemsiones sean de 1 pixel, habra la forma de hacerlo?, no se si esta clara mi pregunta.

Desde ya muchas gracias por tu tiempo

saludos

Marcelo
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Marcelo,

Lo que quieres hacer al algo más complicado de lo que parece.

Cada control es responsable de dibujar su propia imagen. El brush se utiliza para borrar la superficie del control antes de dibujar en él lo que sea.

Cuando queremos que sea transparente, se trata de que el fondo no se borre y en su lugar se copie la imagen que haya debajo del control. Pero, si existe otro control debajo (para formar una X por ejemplo) hay que combinar las imágenes de ambos.

El método EraseBkGnd() (Erase background) lo podemos declarar virtual, para que no se borre nada:

METHOD EraseBkGnd() VIRTUAL

Y en el método Paint() copiaríamos la imagen que hay debajo:

Code: Select all

METHOD Paint() CLASS tfig 
   ... copiar la imagen que hay debajo del control al hDC de este control...
   moveTo( ::hDC, 1, 1 ) 
   LineTo( ::hDC, ::nWidth, ::nHeight ) 
return nil
La función para copiar desde un hDC a otro hDC es BitBlt(). Sigo...
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Marcelo,

Aqui te pongo un ejemplo que debería funcionar bien, pero no lo hace. De todas formas debemos estar muy cerca:

Code: Select all

#include "fivewin.ch" 

FUNCTION main() 
   LOCAL oDlg, ofig1, ofig2, s1 

   DEFINE WINDOW oDlg FROM 10,10 TO 40,60 COLOR "W/G"

   SetGridSize( 5, 5 ) 

   @ 15,15 say s1 PROMPT "HOLA" of odlg COLOR CLR_RED SIZE 100,20 DESIGN 
   s1:lTransparent := .T. 

   ofig1 := tfig():new(1,1,25,25, oDlg ) 

   ofig2 := tfig():new(25,25,45,55, oDlg ) 

   ACTIVATE WINDOW oDLg 

   RETURN( NIL ) 

//----------------------------------------------------------------------------// 

CLASS Tfig FROM TControl 

   CLASSDATA lRegistered AS LOGICAL 

   METHOD New( nRow, nCol, nHeight, nWidth, oWnd ) CONSTRUCTOR 
   METHOD Display() INLINE ::BeginPaint(), ::Paint(), ::EndPaint(), 0 
   METHOD Initiate( hDlg ) INLINE Super:Initiate( hDlg ) 
   METHOD Paint() 
   METHOD EraseBkGnd() VIRTUAL

ENDCLASS 

//----------------------------------------------------------------------------// 
METHOD New( nRow, nCol, nHeight, nWidth, oWnd ) CLASS tfig 

   ::nTop      := nRow 
   ::nLeft     := nCol 
   ::nBottom   := ::nTop  + nHeight 
   ::nRight    := ::nLeft + nWidth 

   ::oWnd      := oWnd 
   ::nStyle  = nOr( WS_CHILD, WS_VISIBLE, WS_TABSTOP, WS_CLIPSIBLINGS ) 

   ::lCaptured   := .F. 
   ::lDrag       := .T. 
   ::lDesign     := .T. 
   ::lUpdate     := .T. 
   ::lRegistered := .f. 
   // ::ltransparent := .T. 

   ::Register() 
   ::Create() 
   ::oWnd:AddControl( Self ) 
   ::CheckDots() 

return SELF 

//----------------------------------------------------------------------------// 

METHOD Paint() CLASS tfig 

   ParentImage( ::hWnd, ::hDC )
   moveTo( ::hDC, 1, 1 ) 
   LineTo( ::hDC, ::nWidth, ::nHeight ) 

return nil

//----------------------------------------------------------------------------// 

#pragma BEGINDUMP

#include <hbapi.h>
#include <windows.h>

HB_FUNC( PARENTIMAGE ) // hControl, hDC
{
   HWND hWnd = ( HWND ) hb_parnl( 1 );
   HDC hDC = ( HDC ) hb_parnl( 2 );
   HDC hDcParent = GetDCEx( GetParent( hWnd ), NULL, DCX_PARENTCLIP	);
   RECT rct;
   POINT pt;

   GetWindowRect( hWnd, &rct );
   pt.y = rct.top;
   pt.x = rct.left;
   ScreenToClient( GetParent( hWnd ), &pt );

   BitBlt( hDC, 0, 0, rct.right - rct.left, rct.bottom - rct.top, hDcParent,
           pt.x, pt.y, SRCCOPY );

   ReleaseDC( GetParent( hWnd ), hDcParent );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Post by Marcelo Via Giglio »

Antonio,

gracias, por lo visto es mas complicado de lo que pense, mas aun cuando hay may de dos controles sobrepuestos, la solucion para este caso particular de figuras geometricas seria utilizar algo como hizo Paco Garcia tiempo atras, buscare el fuente que es para 16 bits

Muchas gracias por tu tiempo, sin embargo, le echo mano a tu ejemplo y veo que sale

un abrazo

Marcelo
R.F.
Posts: 840
Joined: Thu Oct 13, 2005 7:05 pm

Post by R.F. »

Marcelo y Antonio:

¿ Y no seria mas facil hacerlo por el BKMode ?

En el proceso de pintado de controles, bastaría con cambiar el SetBkMode del contexto de dispositivo, por ejemplo:

hDc := oDlg:GetDC()
SetBkMode(hDc, 1) // no recuerdo si la transparencia es 0 o 1

Y a continuación pintar, con un TextOut() por ejemplo, se pintaría transparentado con el fondo

El caso es que creo que Marcelo quiere pintar DEPUES de hacer control, lo cual si que está complicado con el SAY de FiveWin, porque ese hereda del LABEL API de Windows, ignoro si el LABEL internamente cambia el BKMode, sería mas facil que se hiciera su propio SAY mandando llamar al BKmode haciendolo transparente y luego pintando el texto.
Saludos
R.F.
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

René,

Gracias por la sugerencia, pero no cambia la situación. El problema no es al pintar la línea sino que el fondo que hay debajo del control (no de la línea) sea visible.

Usando temas se consigue copiando el fondo del padre, que es lo mismo que hace la función en C que le he mostrado, pero por alguna causa, no lo está haciendo bien
regards, saludos

Antonio Linares
www.fivetechsoft.com
Marcelo Via Giglio
Posts: 1033
Joined: Fri Oct 07, 2005 3:33 pm
Location: Cochabamba - Bolivia

Post by Marcelo Via Giglio »

Rene,

gracias por contestar, ya probe antes con el SetBkMode(hDc, 1) y todo lo demas que pude averiguar y por eso pregunte en el foro.

Actualmente tengo corriendo en 32 bits un paint que creo lo hizo Paco Garcia, ya que estoy con tiempito, lo que deseo hacer es un generador de codigo para la clase tprint, veremos que sale, aun falta mucho :-)

saludos

Marcelo
Post Reply