In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.

Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.

Problema al crear un control personalizado.

Foro público de Xailer en español
Responder
Avatar de Usuario
Shadax
Mensajes: 104
Registrado: Lun Mar 14, 2011 12:32 pm

Problema al crear un control personalizado.

Mensaje por Shadax »

Estoy creando un control personalizado que muestra una etiqueta con un icono y un texto. Este icono es un bitmap al que le he establecido la transparencia de la manera tradicional (el primer pí­xel superior izquierdo indicará el color de transparencia).
El problema es que cuando intento realizar el pintado de la imagen con la función BitBlt(...) no me pinta bien la transparencia. He jugado con el dWord del último parámetro de la función pero ninguno de ellos me sirve para pintar la transparencia.
Alguna idea?
// Genero objeto y etc...
...
...
// Si el objeto no es nulo
if( hBitmap )
{
hDCBits = CreateCompatibleDC(cp.hDC);

GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
SelectObject(hDCBits, hBitmap);

BitBlt(cp.hDC, rect.left, rect.bottom / 2 - 8, Bitmap.bmWidth, Bitmap.bmHeight, hDCBits, 0, 0, SRCCOPY);

DeleteDC(hDCBits);
}
Gracias de antemano.
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5718
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Problema al crear un control personalizado.

Mensaje por jfgimenez »

Joan Ramón,
utiliza esta función, y no tendrás que preocuparte:
void XA_DrawBmpTransparent( HDC hdc, int x, int y, HBITMAP hBmp );
í‰chale un vistazo a graphics.h, que hay algunas otras funciones de
pintado de bitmaps que también te pueden ser útiles.
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
Shadax
Mensajes: 104
Registrado: Lun Mar 14, 2011 12:32 pm

Problema al crear un control personalizado.

Mensaje por Shadax »

Gracias por tu respuesta José. He estado probando y no parece funcionar correctamente.
Te pongo en situación, este es el código que estoy utilizando para crear el control:

/*
* Xailer source code:
*
* TipLabel.prg
* Clase TTipLabel()
*
* Copyright 2007 Jose F. Gimenez
* Copyright 2007 Xailer.com
* All rights reserved
*
*/
#include "Xailer.ch"
#DEFINE tmCUSTOM 'tmCUSTOM'
#DEFINE tmINFO 'tmINFO'
#DEFINE tmWARNING 'tmWARNING'
#DEFINE tmERROR 'tmERROR'
#DEFINE tmQUESTION 'tmQUESTION'
CLASS TTipLabel FROM XTipLabel
ENDCLASS
//--------------------------------------------------------------------------
CLASS XTipLabel FROM TLabel
PUBLISHED:
PROPERTY nWidth INIT 150
PROPERTY nHeight INIT 32
PROPERTY lTransparent INIT .F.
PROPERTY nVAlignment INIT vaCENTER
PROPERTY nClrText INIT clBlack
PROPERTY nClrPane INIT 0xCCF9FF
PROPERTY oIcon WRITE METHOD SetIcon EDITOR PE_Icon AS TIcon
PROPERTY oBitmap WRITE METHOD SetBitmap EDITOR PE_Picture AS TBitmap
PROPERTY cTipMode INIT tmINFO WRITE METHOD SetTipMode VALUES tmCUSTOM, tmINFO, tmWARNING, tmERROR, tmQUESTION
PROPERTY nBorderStyle INIT bvFLAT
PROPERTY oFont INIT TFont():Create( "Arial", 10, 0, 400 )
PROPERTY nVAlignment INIT vaCENTER
PROPERTY cText INIT "-"
PROPERTY lParentFont INIT .F.
PUBLIC:
PROPERTY lAutoSize INIT .F.
METHOD Create( oParent ) CONSTRUCTOR
RESERVED:
METHOD Free()
METHOD SetIcon( oIcon )
METHOD SetBitmap( cBitmap )
METHOD SetTipMode( cMode )
METHOD WMPaint()
METHOD WMEraseBkgnd() INLINE 1
ENDCLASS
//--------------------------------------------------------------------------
METHOD Create( oParent ) CLASS XTipLabel
Super:Create( oParent )
::Adjust()
::SetTipMode()
RETURN Self
//--------------------------------------------------------------------------
METHOD Free() CLASS XTipLabel
IF ::FoIcon != Nil
::FoIcon:Destroy()
ENDIF
RETURN Super:Free()
//--------------------------------------------------------------------------
METHOD SetIcon( oIcon ) CLASS XTipLabel
// ELIMINO EL POSIBLE ICONO QUE EXISTA
IF ::FoIcon != Nil
::FoIcon:Destroy()
::FoIcon := Nil
ENDIF
// ELIMINO LA POSIBLE IMAGEN QUE EXISTA
IF ::FoBitmap != Nil
::FoBitmap:Destroy()
::FoBitmap := Nil
ENDIF
// ESTABLEZCO EL ICONO
IF ! Empty( oIcon )
IF ValType( oIcon ) != "O"
oIcon := TIcon():Create( oIcon )
ENDIF
::FoIcon := oIcon
ENDIF
::Refresh()
RETURN Nil
//--------------------------------------------------------------------------
METHOD SetBitmap( cBitmap ) CLASS XTipLabel
// ELIMINO LA POSIBLE IMAGEN QUE EXISTA
IF ::FoBitmap != Nil
::FoBitmap:Destroy()
::FoBitmap := Nil
ENDIF
// ELIMINO EL POSIBLE ICONO QUE EXISTA
IF ::FoIcon != Nil
::FoIcon:Destroy()
::FoIcon := Nil
ENDIF
// ESTABLEZCO LA IMAGEN SELECCIONADA
IF cBitmap != Nil
IF ValType( cBitmap ) != "O"
::FoBitmap := TPicture():Load( cBitmap )
ENDIF
ENDIF
::Refresh()
RETURN Nil
//--------------------------------------------------------------------------
METHOD SetTipMode( cMode ) CLASS XTipLabel
LOCAL cTipMode := Nil
DEFAULT cMode TO ::cTipMode
DO CASE
CASE cMode == tmINFO
cTipMode := "TipINFO"
CASE cMode == tmWARNING
cTipMode := "TipWARNING"
CASE cMode == tmERROR
cTipMode := "TipERROR"
CASE cMode == tmQUESTION
cTipMode := "TipQUESTION"
OTHERWISE
cTipMode := Nil
ENDCASE
::FcTipMode := cMode
::SetBitmap( cTipMode )
RETURN Nil
//--------------------------------------------------------------------------
#pragma BEGINDUMP
#include "windows.h"
#include "xailer.h"
#include "constants.ch"
//--------------------------------------------------------------------------
HB_FUNC_STATIC( XTIPLABEL_WMPAINT )
{
PHB_ITEM Self = hb_stackSelfItem();
HWND hWnd = GetHandleOf( Self ), hParent;
CONTROLPAINT cp;
RECT rect;
UINT nMargin;
HICON hIcon;
HBITMAP hBitmap;
int nMargenVariable = 22;
HDC hDCBits;
BITMAP Bitmap;
if ( XA_ControlBeginPaint( Self, hWnd, &cp, (HDC) hb_parnl( 1 ) ) )
{
GetClientRect( hWnd, &rect );
// DIBUJAR EL RECTíNGULO
XA_DrawControlBackground( Self, cp.hDC, &rect );
// ESPACIADO INTERNO
rect.left += 8;
rect.right -= 8;
// PINTAR LA CADENA DE TEXTO
switch(XA_ObjGetL( Self, "nAlignment" ))
{
case DT_LEFT: // IZQUIERDA
{
rect.left += nMargenVariable;
XA_DrawControlText( Self, cp.hDC, &rect, XA_ObjGetL( Self, "lMultiline" ) ? DT_WORDBREAK : ( XA_ObjGetL( Self, "lAutoSize" ) ? 0 : DT_WORD_ELLIPSIS ) );
rect.left -= nMargenVariable;
break;
}
case DT_RIGHT: // DERECHA
{
XA_DrawControlText( Self, cp.hDC, &rect, XA_ObjGetL( Self, "lMultiline" ) ? DT_WORDBREAK : ( XA_ObjGetL( Self, "lAutoSize" ) ? 0 : DT_RIGHT ) );
break;
}
case DT_CENTER: // CENTRO
{
XA_DrawControlText( Self, cp.hDC, &rect, XA_ObjGetL( Self, "lMultiline" ) ? DT_WORDBREAK : ( XA_ObjGetL( Self, "lAutoSize" ) ? 0 : DT_VCENTER ) );
break;
}
}
// OBTIENE SI SE LE HA ESTABLECIDO UN ICONO
hIcon = (HICON) GetHandleOf( XA_ObjGetItem( Self, "oIcon" ) );
// OBTIENE SI SE LE HA ESTABLECIDO UN BITMAP PERSONALIZADO
hBitmap = (HBITMAP) GetHandleOf( XA_ObjGetItem( Self, "oBitmap" ) );
// SI EXISTE ICONO, LO PINTA
if( hIcon )
{
DrawIconEx( cp.hDC, rect.left, rect.bottom / 2 - 8, hIcon, 16, 16, 0, NULL, DI_NORMAL );
}
// SI EXISTE BITMAP, LO PINTA. PRIMA EL BITMAP AL ICONO EN CASO QUE EXISTAN AMBOS
if( hBitmap )
{
// GENERO EL Device Contest, NECESARIO PARA PINTAR LA IMAGEN
hDCBits = CreateCompatibleDC(cp.hDC);
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
SelectObject(hDCBits, hBitmap);
// PINTO LA IMAGEN
//BitBlt(cp.hDC, rect.left, rect.bottom / 2 - 8, Bitmap.bmWidth, Bitmap.bmHeight, hDCBits, 0, 0, SRCCOPY);
XA_DrawBmpTransparent( cp.hDC, rect.left, rect.bottom / 2 - 8, hBitmap );
// ME CARGO hDCBits ( Device Contest )
DeleteDC(hDCBits);
}
}
XA_ControlEndPaint( Self, hWnd, &cp );
hb_retnl( 0 );
}
//--------------------------------------------------------------------------
#pragma ENDDUMP

Y este es el resultado final, utilizando XA_DrawBmpTransparent:

Como se puede apreciar, no me dibuja correctamente la imagen que debiera pintar.
Utilizando BitBlt, funciona correctamente pero no me permite
el uso de transparencias:

¿Alguna idea?
Gracias por todo y un saludo.
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5718
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Problema al crear un control personalizado.

Mensaje por jfgimenez »

Joan Ramón,
el problema es que estás cargando la imagen con la clase TPicture, y
entonces, para dibujarla tienes que usar el método Paint() de esta clase.
Si vas a usar las funciones de pintado de bitmaps de Xailer, o incluso
las funciones originales del API, tendrás que cargar la imagen con
LoadImage(), XA_LoadImage() o con la clase TBitmap. Las dos funciones
primeras te devuelven directamente el handle del bitmap, que tendrás que
liberar después con DeleteObject().
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
Shadax
Mensajes: 104
Registrado: Lun Mar 14, 2011 12:32 pm

Problema al crear un control personalizado.

Mensaje por Shadax »

Ok, ayer tuve tiempo para probar y finalmente he podido realizar el pintado correctamente. He corregido algunas cosas que me habí­a dejado,
añadida alguna propiedad y finalmente he pintado el bitmap transparente utilizando:
BOOL TransparentBlt(
__in HDC hdcDest,
__in int xoriginDest,
__in int yoriginDest,
__in int wDest,
__in int hDest,
__in HDC hdcSrc,
__in int xoriginSrc,
__in int yoriginSrc,
__in int wSrc,
__in int hSrc,
__in UINT crTransparent
);
Muy útil la funcion.
Me surge una duda adicional y es:
Tengo una propiedad publicada, como puede verse en el código, que es "cTipMode" cuyos valores pueden ser "tmINFO", "tmWARNING"... La cosa
es que lo que quiero es que los #DEFINE quedasen así­:
#DEFINE tmCUSTOM 0
#DEFINE tmINFO 1
#DEFINE tmWARNING 2
#DEFINE tmERROR 3
#DEFINE tmQUESTION 4
y que en el diseñador de objetos se desplegase la lista con los defines establecidos (tmCUSTOM, tmINFO, tmWARNING...). ¿Tenéis algún enlace o algo documentando esto?
===========
EDIT
===========
He estado probando el control, compilando la dll e insertándolo mediante el diseñador de informes de Xailer. Me encuentro con que me da el error de que no reconoce la clase TBitmap.
He utilizado esto para la carga del bitmap:

IF ! Empty( cBitmap )
IF ValType( cBitmap ) != "O"
::FoBitmap := TBitmap():New( cBitmap )
ENDIF
ENDIF

Sin utilizar el diseñador, ví­a código está funcionando correctamente.
===========
Gracias por la ayuda y tu tiempo José !!!
Avatar de Usuario
jfgimenez
Site Admin
Mensajes: 5718
Registrado: Lun Abr 06, 2015 8:48 pm
Contactar:

Problema al crear un control personalizado.

Mensaje por jfgimenez »

Joan Ramón,
> Me surge una duda adicional y es:
>
> Tengo una propiedad publicada, como puede verse en el
> código, que es "cTipMode" cuyos valores pueden ser
> "tmINFO", "tmWARNING"... La cosa
> es que lo que quiero es que los #DEFINE quedasen así­:
>
> #DEFINE tmCUSTOM 0
> #DEFINE tmINFO 1
> #DEFINE tmWARNING 2
> #DEFINE tmERROR 3
> #DEFINE tmQUESTION 4
>
> y que en el diseñador de objetos se desplegase la lista con
> los defines establecidos (tmCUSTOM, tmINFO, tmWARNING...).
En vez de #define, tienes que utilizar #xtranslate, así­:
#xtranslate tmCUSTOM => 0
y después, en la propiedad, tienes que utilizar la cláusula VALUES, así­:
PROPERTY nTipMode INIT tmINFO VALUES tmCUSTOM, tmINFO,
tmWARNING, tmERROR, tmQUESTION
esto es todo. Pero fí­jate que he cambiado cTipMode por nTipMode, para
recalcar que ahora es de tipo numérico y no de cadena.
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info
José F. Giménez
[Equipo de Xailer / Xailer team]
http://www.xailer.com
http://www.xailer.info
Avatar de Usuario
Shadax
Mensajes: 104
Registrado: Lun Mar 14, 2011 12:32 pm

Problema al crear un control personalizado.

Mensaje por Shadax »

José, he estado probando el control; Compilando la dll e insertándolo mediante el diseñador de informes de Xailer. Me encuentro con que me da el error de que no reconoce la clase TBitmap.
He utilizado esto en el control para la carga del bitmap:

IF ! Empty( cBitmap )
IF ValType( cBitmap ) != "O"
::FoBitmap := TBitmap():New( cBitmap )
ENDIF
ENDIF

Sin utilizar el diseñador, ví­a código está funcionando correctamente, pero cuando lo quiero insertar con el diseñador, revienta.
Gracias nuevamente por todo.
********
EDIT
********
He probado a utilizar el TPicture():Create( cBitmap ) y me está funcionando perfectamente ahora.
Gracias y un saludo.
Responder