May 082009
 

Editor de Skins para Formularios:

Este es el editor anteriormente mencionado, bien no voy a dar muchos detalles por el momento, después voy a crear una pagina donde voy a dar una explicación más detallada.
En el link de descarga van a encontrar un archivo .zip con el ejecutable, este no tiene dependencias por lo tanto no requiere instalación.

Skins para Formularios (Editor)

May 082009
 

Módulo ClsSkinner:

Este es un módulo clase llamado ClsSkinner, el cual sirve para cambiar el aspecto de nuestros formularios, no necesita ningún OCX o DLL y su implementación es muy sencilla, los skin los carga desde unos archivos de extensión «.Skin» los cuales también se puede guardar en archivos de recursos para luego ser implementados.
En esta versión sólo cambia el aspecto de los formularios y barra de menús, para los PopUpMenú solamente le he implementado la opción de cambiarle el color de fondo, también se les puede aplicar a formularios MDI y a todas las ventanas dentro de la instancia de nuestra aplicación que posean bordes.
Para la próxima versión (si Dios quiere), tengo pensado implementárselo a los controles, pero bien es una idea  muy a futuro.Estas son algunas capturas de muestra, en el ejemplo que voy a poner a continuación existen estos dieciséis Skins en los cuales he utilizado partes de otros programas similares (pagos y de código cerrado), estos skin los pueden crear ustedes mismos con un editor que es exclusivo para este módulo clase.

Skins para Formularios

 Publicado por a las 12:29  Tagged with:
May 072009
 

Se trata de dos proyectos para enviar capturas de una webcam a través de los Socket, es decir, podrás enviar capturas de una webcam por internet en una conexión Cliente-Servidor, ambos trabajan con la clase CSocket y no dependen del Winsock.ocx, las capturas son comprimidas a .JPG con la clase cJpeg y no dependen de GDI+, si ejecuta el servidor éste se ejecutará de manera oculta, por lo que sólo podrán cerrarlo con el Cliente desde el administrador de tareas, el Cliente cuenta con dos opciones para elegir el tamaño y calidad de la captura (mientras más bajos sean estos valores más rápido será la transferencia), también posee una barra de progreso que muestra el envió de cada captura.

Webcam

 Publicado por a las 23:34  Tagged with:
May 042009
 

Este es un módulo bas que sirve para que nuestra aplicación se inicie junto con Windows, no es nada novedoso, modifica las claves del registro mediante Apis.
Cuenta con dos funciones:
SetAutoRun: Con un parámetro Boolean, si éste es verdadero ancla nuestra aplicación al inicio, de lo contrario la quita, la función debería retornarnos un valor verdadero si es que todo salió bien.
IsAutoRun: Devuelve «true» si nuestra aplicación ya está en el inicio

Option Explicit

Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As String, ByVal cbData As Long) As Long
Private Declare Function RegDeleteKey& Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String)
Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long
Private Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
Private Declare Function RegDeleteValue& Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String)

Private Const RAMA_RUN_WINDOWS As String = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const HKEY_CURRENT_USER = &H80000001
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const HKEY_USERS = &H80000003
Private Const REG_SZ As Long = 1
Private Const KEY_ALL_ACCESS = &H3F

Public Function SetAutoRun(Value As Boolean) As Boolean 
    Dim Path          As String
    Dim Handle        As Long 
    Path = Chr(34) & App.Path & "\" & App.EXEName & ".exe" & Chr(34) 
    RegOpenKeyEx HKEY_CURRENT_USER, RAMA_RUN_WINDOWS, 0, KEY_ALL_ACCESS, Handle
    If Value Then
        SetAutoRun = RegSetValueExString(Handle, App.Title, 0&, REG_SZ, Path, Len(Path)) = 0
    Else
        SetAutoRun = RegDeleteValue(Handle, App.Title) = 0
    End If
    RegCloseKey Handle 
End Function

Public Function IsAutoRun() As Boolean 
    Dim Path          As String
    Dim Handle        As Long
    Dim Data          As String
    Dim cch           As Long 
    Path = Chr(34) & App.Path & "\" & App.EXEName & ".exe" & Chr(34) 
    RegOpenKeyEx HKEY_CURRENT_USER, RAMA_RUN_WINDOWS, 0, KEY_ALL_ACCESS, Handle
    RegQueryValueExNULL Handle, App.Title, 0&, 0&, 0&, cch

    If cch > 0 Then
        Data = String(cch - 1, 0)
        RegQueryValueExString Handle, App.Title, 0&, 0&, Data, cch
        IsAutoRun = Path = Data
    End If 
    RegCloseKey Handle 

End Function

May 042009
 

Este es un módulo con una función para implementar los diferentes gráficos de la Api Google Char en Visual Basic, quizás no tenga mucho sentido ya que dependemos de una conexión a internet y descargamos la imágen desde una web, lo cual ya requiere de un cierto tiempo, pero bueno siempre puede llegar a ser útil en estos casos.
Junto al proyecto de descarga hay cinco ejemplos muy sencillos y un editor en Flash que nos podrá ayudar mucho, primeramente a entender esta api y luego cómo manejar sus parámetros.
Para saber más acerca de cómo utilizar esta api pueden visitar esta Web, donde explica en detalle cada uno de los parámetros.
Los gráficos a continuación son directamente generados por Google Char.

Grafico de linea

Grafico de linea

Grafico de linea

 Publicado por a las 22:46  Tagged with:
May 012009
 

Esta es una función simple para dibujar puntos sobre un Formulario, Picture Box o hdc, la función es rápida.

Draw Grip

Option Explicit

'=========GDI32 Api========
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function SetRect Lib "user32.dll" (ByRef lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function GetDCBrushColor Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetBkColor Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function SetPixelV Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreatePatternBrush Lib "gdi32.dll" (ByVal hBitmap As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GdiTransparentBlt Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal crTransparent As Long) As Boolean

'============User32 Api===========
Private Declare Function FillRect Lib "user32.dll" (ByVal hdc As Long, ByRef lpRect As RECT, ByVal hBrush As Long) As Long

'============Estructura Rect========
Private Type RECT
    Left                        As Long
    Top                         As Long
    Right                       As Long
    Bottom                      As Long
End Type

Public Function ShiftColor(ByVal clr As Long, ByVal d As Long) As Long
  Dim R As Long, B As Long, G As Long
    R = (clr And &HFF) + d
    G = ((clr \ &H100) Mod &H100) + d
    B = ((clr \ &H10000) Mod &H100) + d
    
    If (d > 0) Then
        If (R > &HFF) Then R = &HFF
        If (G > &HFF) Then G = &HFF
        If (B > &HFF) Then B = &HFF
    ElseIf (d < 0) Then
        If (R < 0) Then R = 0
        If (G < 0) Then G = 0
        If (B < 0) Then B = 0
    End If
    ShiftColor = R + &H100& * G + &H10000 * B
End Function

Public Sub DrawGrip(DestDC As Long, DestX As Long, DestY As Long, DestWidth As Long, DestHeight As Long)
    Dim DC                      As Long
    Dim hDCMemory               As Long
    Dim hBmp                    As Long
    Dim hOldBmp                 As Long
    Dim hBrush                  As Long
    Dim Rec                     As RECT
    Dim lOriginalColor          As Long
    Dim clrHighLight            As Long
    Dim clrShadow               As Long

    lOriginalColor = GetBkColor(DestDC)
    clrHighLight = ShiftColor(lOriginalColor, &H40)
    clrShadow = ShiftColor(lOriginalColor, -&H40)
    
    DC = GetDC(0)
    hDCMemory = CreateCompatibleDC(0)
    hBmp = CreateCompatibleBitmap(DC, 6, 6)
    hOldBmp = SelectObject(hDCMemory, hBmp)
          
    hBrush = CreateSolidBrush(lOriginalColor)
    SetRect Rec, 0, 0, 6, 6
    FillRect hDCMemory, Rec, hBrush
    DeleteObject hBrush
    
    SetPixelV hDCMemory, 2, 1, clrShadow
    SetPixelV hDCMemory, 1, 2, clrShadow
    SetPixelV hDCMemory, 2, 2, clrShadow
    
    SetPixelV hDCMemory, 0, 0, clrHighLight
    SetPixelV hDCMemory, 1, 0, clrHighLight
    SetPixelV hDCMemory, 0, 1, clrHighLight
    SetPixelV hDCMemory, 1, 1, clrHighLight
    
    SetPixelV hDCMemory, 5, 4, clrShadow
    SetPixelV hDCMemory, 4, 5, clrShadow
    SetPixelV hDCMemory, 5, 5, clrShadow
    
    SetPixelV hDCMemory, 3, 3, clrHighLight
    SetPixelV hDCMemory, 4, 3, clrHighLight
    SetPixelV hDCMemory, 3, 4, clrHighLight
    SetPixelV hDCMemory, 4, 4, clrHighLight
    
    hBrush = CreatePatternBrush(hBmp)
    SelectObject hDCMemory, hOldBmp
    DeleteObject hBmp
    hBmp = CreateCompatibleBitmap(DC, DestWidth, DestHeight)
    hOldBmp = SelectObject(hDCMemory, hBmp)
    SetRect Rec, 0, 0, DestWidth, DestHeight
    FillRect hDCMemory, Rec, hBrush
    
    GdiTransparentBlt DestDC, DestX, DestY, DestWidth, DestHeight, hDCMemory, 0, 0, DestWidth, DestHeight, lOriginalColor

    DeleteObject hBrush
    SelectObject hDCMemory, hOldBmp
    DeleteObject hBmp
    DeleteDC DC
    DeleteDC hDCMemory    
End Sub

Private Sub Form_Paint()
    DrawGrip Me.hdc, 0, 50, Me.ScaleWidth / Screen.TwipsPerPixelX, 9
    DrawGrip Me.hdc, 100, 59, 16, Me.ScaleHeight / Screen.TwipsPerPixelY - 59
End Sub								
 Publicado por a las 23:57  Tagged with:
May 012009
 

Este proyecto es algo similar al Widget del Tiempo pero mucho más sencillo, lo que hace es poner un ícono con el estado del tiempo de la localidad seleccionada en la Barra de Tareas y al pasar el mouse sobre éste se despliega una ventana tipo ToolTip con una información más detallada, tal como se aprecia en la imágen.
En este proyecto utilicé una clase (ClsXML) para parsear un XML que descarga de accuweather.com con la información del clima, agradezco a xKiz por ayudarme con este paso, no utilicé la referencia de Microsoft ya que éste aumentaba mucho más el tamaño de la memoria en el ejecutable.
Para cambiar de localidad sólo basta con hacer doble click sobre el ícono y se abrirá una ventana con las opciones de búsqueda, si hacen click derecho se despliega un menú con otras opciones.

Clima en la Barra de Tareas

May 012009
 

En realidad este no es un módulo, sino un formulario, el cual utiliza las Apis de Google SpellCheck, cuenta con varios idiomas y su uso es muy sencillo, sólo basta con una línea de código, en este proyecto/código no utilicé ninguna api, sólo la creación de algunos objetos (estos objetos ya están por defecto en Windows, por lo tanto no hay dependencias), obviamente requerimos de conexión a internet para que funcione.
Básicamente lo que hace es crear un XML y dentro del contenido de éste, el texto a corregir, se lo envía a Google en una petición de tipo POST y éste nos devuelve otro XML con las posibles sugerencias, del resto se encarga este formulario que va listando las sugerencias, reemplazando u omitiendo.
También cuenta con la posibilidad de agregar palabras a un diccionario, este no es más que un archivo de texto plano en el que se irán almacenando todas las palabras que agreguemos.

Corrector Ortográfico Google

 Publicado por a las 23:14  Tagged with:
May 012009
 

Esta es una función para dibujar una selección al estilo Windows XP.

Draw Alpha Selection


Option Explicit
 
'=========Gdi32 Api========
Private Declare Function Rectangle Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GdiAlphaBlend Lib "gdi32.dll" (ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal BLENDFUNCT As Long) As Long
Private Declare Function CreatePen Lib "gdi32.dll" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
'=========user32 Api========
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
 
'=========Oleaut32 Api========
Private Declare Function OleTranslateColor Lib "oleaut32.dll" (ByVal lOleColor As Long, ByVal lHPalette As Long, ByVal lColorRef As Long) As Long
 
'=========Kernel32 Api========
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
 
Private Type UcsRgbQuad
    R                       As Byte
    G                       As Byte
    B                       As Byte
    a                       As Byte
End Type
 
Private Type BLENDFUNCTION
    BlendOp                 As Byte
    BlendFlags              As Byte
    SourceConstantAlpha     As Byte
    AlphaFormat             As Byte
End Type
 
Private Sub DrawAlphaSelection(hdc As Long, ByVal X As Long, ByVal y As Long, ByVal Width As Long, ByVal Height As Long, ByVal Color As OLE_COLOR)
 
    Dim BF                  As BLENDFUNCTION
    Dim hDCMemory           As Long
    Dim hBmp                As Long
    Dim hOldBmp             As Long
    Dim DC                  As Long
    Dim lColor              As Long
    Dim hPen                As Long
    Dim hBrush              As Long
    Dim lBF                 As Long
 
    BF.SourceConstantAlpha = 128
 
    DC = GetDC(0)
    hDCMemory = CreateCompatibleDC(0)
    hBmp = CreateCompatibleBitmap(DC, Width, Height)
    hOldBmp = SelectObject(hDCMemory, hBmp)
 
    hPen = CreatePen(0, 1, Color)
    hBrush = CreateSolidBrush(pvAlphaBlend(Color, vbWhite, 120))
    DeleteObject SelectObject(hDCMemory, hBrush)
    DeleteObject SelectObject(hDCMemory, hPen)
    Rectangle hDCMemory, 0, 0, Width, Height
 
    CopyMemory VarPtr(lBF), VarPtr(BF), 4
    GdiAlphaBlend hdc, X, y, Width, Height, hDCMemory, 0, 0, Width, Height, lBF
 
    SelectObject hDCMemory, hOldBmp
    DeleteObject hBmp
    ReleaseDC 0&, DC
    DeleteDC hDCMemory
    DeleteObject hPen
    DeleteObject hBrush
 
End Sub
 
Private Function pvAlphaBlend(ByVal clrFirst As Long, ByVal clrSecond As Long, ByVal lAlpha As Long) As Long
 
    Dim clrFore             As UcsRgbQuad
    Dim clrBack             As UcsRgbQuad
 
    OleTranslateColor clrFirst, 0, VarPtr(clrFore)
    OleTranslateColor clrSecond, 0, VarPtr(clrBack)
    With clrFore
        .R = (.R * lAlpha + clrBack.R * (255 - lAlpha)) / 255
        .G = (.G * lAlpha + clrBack.G * (255 - lAlpha)) / 255
        .B = (.B * lAlpha + clrBack.B * (255 - lAlpha)) / 255
    End With
    CopyMemory VarPtr(pvAlphaBlend), VarPtr(clrFore), 4
 
End Function
 
Private Sub Form_Paint()
    Cls
    DrawAlphaSelection Me.hdc, 10, 50, 100, 200, vbRed
    DrawAlphaSelection Me.hdc, 50, 30, 200, 100, vbBlue
    DrawAlphaSelection Me.hdc, 200, 80, 100, 100, vbGreen
    DrawAlphaSelection Me.hdc, 80, 200, 200, 30, vbYellow
    DrawAlphaSelection Me.hdc, 130, 70, 50, 200, vbMagenta
End Sub

 Publicado por a las 0:19  Tagged with:
Abr 252009
 

Este es un módulo .bas que autocompleta un TextBox, a medida que vamos escribiendo, con diez sugerencias posibles de estos cuatro buscadores: Google, Yahoo, Youtube y Wikipedia.
Las consultas las hace vía internet y son  muy rápidas ya que es un texto plano tal como pueden ver aquí buscando la palabra «casa» en Google.
Es importante que no confundan este ejemplo con el Api SHAutoComplete, ya que esta último completa con el historial de navegación, sólo encontré lo de autocompletar en estos cuatro buscadores mencionados, pero si alguien conoce algún otro sólo debe indicarle al módulo la Url.

Autocompletar Sugerencias

Abr 192009
 

Esta es una función que se encarga de dibujar un texto con un efecto espejado al estilo Windows Vista.

Texto Espejado

'-----------------------------'
'Autor: Leandro Ascierto
'Fecha: 27/11/2008
'Tercera Revision
'-----------------------------'

Option Explicit
Private Declare Function GetTextMetrics Lib "gdi32.dll" Alias "GetTextMetricsA" (ByVal hdc As Long, ByRef lpMetrics As TEXTMETRIC) As Long
Private Declare Function AlphaBlend Lib "msimg32.dll" (ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal hdc As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal lInt As Long, ByVal BLENDFUNCT As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function StretchBlt Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function DrawText Lib "user32.dll" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, ByRef lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare Function SetBkMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal nBkMode As Long) As Long
Private Declare Function GetBkMode Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetCurrentObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
Private Declare Function GetTextColor Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetBkColor Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function SetTextColor Lib "gdi32.dll" (ByVal hdc As Long, ByVal crColor As Long) As Long
Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Sub RtlMoveMemory Lib "kernel32.dll" (Destination As Any, Source As Any, ByVal Length As Long)

Private Type BLENDFUNCTION
    BlendOp As Byte
    BlendFlags As Byte
    SourceConstantAlpha As Byte
    AlphaFormat As Byte
End Type

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Type TEXTMETRIC
    tmHeight As Long
    tmAscent As Long
    tmDescent As Long
    tmInternalLeading As Long
    tmExternalLeading As Long
    tmAveCharWidth As Long
    tmMaxCharWidth As Long
    tmWeight As Long
    tmOverhang As Long
    tmDigitizedAspectX As Long
    tmDigitizedAspectY As Long
    tmFirstChar As Byte
    tmLastChar As Byte
    tmDefaultChar As Byte
    tmBreakChar As Byte
    tmItalic As Byte
    tmUnderlined As Byte
    tmStruckOut As Byte
    tmPitchAndFamily As Byte
    tmCharSet As Byte
End Type

Private Const DT_CALCRECT           As Long = &H400
Private Const DT_BOTTOM             As Long = &H8
Private Const DT_SINGLELINE         As Long = &H20
Private Const OBJ_FONT              As Long = 6
Private Const AC_SRC_OVER           As Long = &H0

Public Enum tShadowDirection
    sdCenter = 0
    sdLeft = 1
    sdRight = 2
    sdInside = 3
    sdOutside = 4
End Enum

Public Enum tPercent
    Percent100 = 0
    Percent75 = 1
    Percent50 = 2
    Percent25 = 3
End Enum

Public Function DrawTextReflecion(DestDC As Long, _
                        ByVal x As Long, _
                        ByVal y As Long, _
                        Text As String, _
                        Optional ByVal IgnoreTMDescent As Boolean, _
                        Optional ByVal WaveIntesity As Long, _
                        Optional ByVal ShadowDirection As tShadowDirection, _
                        Optional ByVal Color As OLE_COLOR = -1, _
                        Optional ByVal ShadowPecent As tPercent = Percent75, _
                        Optional ByVal BackLight As Boolean = True)

    Dim ShadowLeft As Long, ShadowRight As Long
    Dim Left As Long, Top As Long, Width As Long, Height As Long
    Dim DC As Long, MemDC As Long, hBmp As Long, OldhBmp As Long, OldhFont As Long
    Dim BF As BLENDFUNCTION, lBF As Long
    Dim TM As TEXTMETRIC
    Dim Rec As RECT
    Dim i As Integer

    Dim Percent As Single

    'Calculamos el tamaño del texto
    DrawText DestDC, Text, Len(Text), Rec, DT_CALCRECT

    Width = Rec.Right
    Height = Rec.Bottom

    'Creamos un Bitmap
    DC = GetDC(0)
    MemDC = CreateCompatibleDC(DC)
    hBmp = CreateCompatibleBitmap(DC, Width, Height)
    OldhBmp = SelectObject(MemDC, hBmp)
    ReleaseDC 0&, DC

    'Copiamos la fuente de destino
    OldhFont = SelectObject(MemDC, GetCurrentObject(DestDC, OBJ_FONT))

    'Copiamos el BackMode de destino
    SetBkMode MemDC, GetBkMode(DestDC)

    'Copiamos el color de texto de destino
    SetTextColor MemDC, IIf(Color <> -1, Color, GetTextColor(DestDC))

    'Tomamos una captura del destino
    StretchBlt MemDC, 0, 0, Width, Height, DestDC, x, y + Height * 2, Width, -Height, vbSrcCopy

    OffsetRect Rec, 0, 0
    'dibujamos el texto
    DrawText MemDC, Text, Len(Text), Rec, DT_BOTTOM Or DT_SINGLELINE

    'obtenemos informacion de la metrica de la fuente.
    GetTextMetrics MemDC, TM

    Select Case ShadowPecent
        Case 0: Percent = TM.tmAscent / 1
        Case 1: Percent = TM.tmAscent / 1.25
        Case 2: Percent = TM.tmAscent / 1.65
        Case 3: Percent = TM.tmAscent / 2
        Case Else: Percent = TM.tmAscent
    End Select

    'pintamos el hdc utilizando AlphaBlend para provocar el espejado.
    For i = TM.tmDescent To Percent
        With BF
            .BlendOp = AC_SRC_OVER
            .SourceConstantAlpha = Abs(200 - ((20 * i) / Percent) * 10)
        End With
        RtlMoveMemory lBF, BF, 4

        Select Case ShadowDirection
            Case 1
                ShadowLeft = -i + TM.tmDescent
            Case 2
                ShadowLeft = i - TM.tmDescent
            Case 3
                ShadowLeft = -i + TM.tmDescent
                ShadowRight = (i - TM.tmDescent) * 2
            Case 4
                ShadowLeft = i - TM.tmDescent
                ShadowRight = -(i - TM.tmDescent) * 2
        End Select

        Top = y + Height - 1
        Left = x - (Rnd(i) * WaveIntesity) + ShadowLeft
        AlphaBlend DestDC, Left, Top + IIf(BackLight, i, -i), Width + ShadowRight, 1, MemDC, 0, Height - i, Width, 1, lBF
    Next

    OffsetRect Rec, x, y + IIf(IgnoreTMDescent And BackLight, TM.tmDescent * 2, 0)

    'Bibujamos el texto original
    DrawText DestDC, Text, Len(Text), Rec, DT_BOTTOM Or DT_SINGLELINE

    'limpiamos la memoria
    SelectObject MemDC, OldhFont
    SelectObject MemDC, OldhBmp
    DeleteDC MemDC
    DeleteObject hBmp
End Function