VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "CMsgList"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'/***************************************************************
'*
'* Proyecto dx_lib32 2.2 -
'* Clase Lista de mensaje (MsgList)
'*
'* Requiere la dependendica a la libreria dx lib32 2.2.0
'*
'* Santiago de Chile Octubre 2008
'* Hechelion (Alberto Ortiz Barrera)
'*
'***************************************************************/

'/***************************************************************
'*
'* El color de fondo se asigna con la propiedad BackColor como un color RGB
'* o de forma individual con las propiedades BackRed, BackGreen y BackBlue
'* el alpfa se entrega como un porcentaje (0-100) con la propiedad opacidad
'* Por defecto se dibuja un cuadrado negro
'* Se a agregado una segunda opacidad (OpacidadSec) que se puede activar con
'* al tener el mouse encima o con al ganar foco
'*
'***************************************************************/

'/***************************************************************
'*
'* Prefijos:
'* p = privado
'* n = Nuevo
'* r = Referencia
'*
'* Sufijos
'* D = Dimención, utilizado para estructuras GFX_Rect
'*
'***************************************************************/

Option Explicit

Public Enum EnumTransparenciaCMsgList
    Msg_none = 0
    Msg_Only_Cursor = 1
    Msg_Only_Focus = 2
    Msg_Focus_OR_Cursor = 3
End Enum

'**********************************************************************
'variables privadas
'**********************************************************************
'Clases de la libreria dx_lib32.DLL
Dim p_gfx As dx_GFX_Class 'Referencia a la clase dx_GFX:
Dim p_Input As dx_Input_Class 'Referencia a la clase dx_Input.
Dim p_System As dx_System_Class 'Referencia a la clase dx_System

Dim Lista() As String 'Lista de cadenas de texto
Dim ListaDraw() As String 'Lista de la parte visible de las cadenas

Dim pOpacidad As Integer 'Opacidad
Dim pOpacidadSec As Integer 'Opacidad secundaria
Dim AlphaActual As Integer
Dim AlphaFinal As Integer

'Dim AltoTexto As Long 'alto en pixel asignados a una cadena
Dim pFont As Long 'referencia a la fuente a utilizar
Dim MaxLineas As Integer 'número total de lineas visibles dado el alto del marco
Dim Linea1 As Integer 'indice del array para la primera línea visible
Dim BordeSuperior As Long 'Margen superior entre texto y el borde del control
Dim BordeInferior As Long 'Margen inferior entre texto y el borde del control
Dim BordeDerecho As Long 'Margen inferior entre texto y el borde del control, el borde izquierdo es controlado por la variable Sangria
Dim AutoAjuste As Boolean

Dim DibujarAscensor As Boolean
Dim AscensorValor As Integer
Dim AscensorMax As Integer

Dim MarcoD As GFX_Rect 'Dimenciones del rectangulo que contiene el mensaje
Dim MarcoTextoD As GFX_Rect 'Dimenciones del rectangulo interno que contiene el texto
Dim AscensorD(2) As GFX_Rect 'Dimenciones de los rectangulos que dibujan el ascensor
Dim pfoco As Boolean
Dim pFocoPrevio As Boolean
Dim pCursorSobre As Boolean
Dim pCursorSobrePrevio As Boolean

Dim Left_Click_ant As Boolean

'Contenedores de las referencias de las imagenes utilizadas
Dim rEsquina1 As Long
Dim rBordeH As Long
Dim rBordeV As Long
Dim rFondo As Long

Dim HayEsquina1 As Boolean
Dim HayBordeH As Boolean
Dim HayBordeV As Boolean
Dim HayFondo As Boolean

Dim InfoEsquina1 As GFX_Info
Dim InfoBordeH As GFX_Info
Dim InfoBordeV As GFX_Info

'**********************************************************************
'Eventos
'**********************************************************************
Public Event Click()
Public Event SetFocus()
Public Event LostFocus()
Public Event SetCursor()
Public Event LostCursor()


'**********************************************************************
'Propiedades
'**********************************************************************
Public Visible As Boolean 'propiedad que determina si se debe o no dibujar el control
Public UseTransparency2 As EnumTransparenciaCMsgList

'Public BackRed As Integer 'Componente rojo del color de fondo
'Public BackGreen As Integer 'Componente verde del color de fondo
'Public BackBlue As Integer 'Componente azul del color de fondo
Public Zbuffer As Long
Public BorderColor As Long
Public BackColor As Long

Public FontColor As Long
Public Sangria As Long 'margen izquierdo entre texto y borde del control

Public ForceTransparency2 As Boolean 'Orden para forzar a segunda transparencia sin importar la condición

Public Property Let Top_Margin(nMargenSuperior As Long)
BordeSuperior = nMargenSuperior
Redimencionar
End Property
Public Property Get Top_Margin() As Long
Top_Margin = BordeSuperior
End Property
Public Property Let Low_Margin(nMargenInferior As Long)
BordeInferior = nMargenInferior
Redimencionar
End Property
Public Property Get Low_Margin() As Long
Low_Margin = BordeInferior
End Property
Public Property Let Left_Margin(nSangria As Long)
Sangria = nSangria
Redimencionar
End Property
Public Property Get Left_Margin() As Long
Left_Margin = Sangria
End Property

Public Property Let Right_Margin(nMargin As Long)
BordeDerecho = nMargin
End Property

Public Property Get Right_Margin() As Long
Right_Margin = BordeDerecho
End Property


Public Property Let AutoFitText(nAutoAjuste As Boolean)
AutoAjuste = nAutoAjuste
Comprobar_Ancho
End Property
Public Property Get AutoFitText() As Boolean
AutoFitText = AutoAjuste
End Property

'Obtener porcentaje de Opacidad
Public Property Let Transparency(nOpacidad As Integer)
pOpacidad = (Saturar(100 - nOpacidad, 0, 100) * 255 / 100)
End Property
Public Property Get Transparency() As Integer
Transparency = 100 - pOpacidad * 100 / 255
End Property

'Obtener porcentaje de Opacidad Secundaria
Public Property Let Transparency2(nOpacidad As Integer)
pOpacidadSec = (Saturar(100 - nOpacidad, 0, 100) * 255 / 100)
End Property
Public Property Get Transparency2() As Integer
Transparency2 = 100 - pOpacidadSec * 100 / 255
End Property

Public Property Let Focus(nfoco As Boolean)
pfoco = nfoco
End Property

Public Property Get Focus() As Boolean
Focus = pfoco
End Property


'Propiedad Font
Public Property Let Font(nFont As Long)
pFont = nFont 'obtener la referencia a la fuente cargada en memoria
'Calcular área visible a partir de la nueva fuente
'AltoTexto
Comprobar_Alto
Comprobar_Ancho
End Property
Public Property Get Font() As Long
Font = pFont
End Property

'PROPIEDADES POSCISIÓN
'Alto
Public Property Let Height(nHeight As Long)
MarcoD.Height = nHeight
Redimencionar
End Property
Public Property Get Height() As Long
Height = MarcoD.Height
End Property
'Ancho
Public Property Let Width(nWidth As Long)
MarcoD.Width = nWidth
Redimencionar
End Property
Public Property Get Width() As Long
Width = MarcoD.Width
End Property
'Posión X LEFT
Public Property Let Left(nLeft As Long)
MarcoD.X = nLeft
Redimencionar
End Property
Public Property Get Left() As Long
Left = MarcoD.X
End Property
'Posición Y TOP
Public Property Let Top(nTop As Long)
MarcoD.Y = nTop
Redimencionar
End Property
Public Property Get Top() As Long
Top = MarcoD.Y
End Property

'Propiedades de gráficos
'Gráfico 1 para la esquina
Public Property Let Map_Corner(nEsquina1 As Long)
rEsquina1 = nEsquina1
HayEsquina1 = True
Call p_gfx.MAP_GetInfo(rEsquina1, InfoEsquina1)
End Property
Public Property Get Map_Corner() As Long
Map_Corner = rEsquina1
End Property

'Gráfico borde
Public Property Let Map_BorderH(nBorde As Long)
rBordeH = nBorde
HayBordeH = True
Call p_gfx.MAP_GetInfo(rBordeH, InfoBordeH)
End Property
Public Property Get Map_BorderH() As Long
Map_BorderH = rBordeH
End Property

'Gráfico borde
Public Property Let Map_BorderV(nBorde As Long)
rBordeV = nBorde
HayBordeV = True
Call p_gfx.MAP_GetInfo(rBordeV, InfoBordeV)
End Property
Public Property Get Map_BorderV() As Long
Map_BorderV = rBordeV
End Property

'Gráfico fondo
Public Property Let Map_Picture(nPicture As Long)
rFondo = nPicture
HayFondo = True
End Property
Public Property Get Map_Picture() As Long
Map_Picture = rFondo
End Property

'Forzar foco
Public Property Let Foco1(nfoco As Boolean)
pfoco = nfoco
End Property

Public Property Get Foco() As Boolean
Focus = pfoco
End Property

'**********************************************************************
'Procedimientos Privados
'**********************************************************************
Private Sub Class_Initialize()

pOpacidad = 128
pOpacidadSec = 255
Sangria = 10
BordeSuperior = 10
BordeInferior = 10
BordeDerecho = 40
AlphaActual = pOpacidad
FontColor = &HFFFFFF
Visible = True
AutoAjuste = True

ReDim Lista(0)
ReDim ListaDraw(0)
Limpiar_Lista
End Sub

Private Sub Limpiar_Lista()
Dim i As Integer
For i = 0 To UBound(Lista)
    Lista(i) = ""
    ListaDraw(i) = ""
Next
End Sub

Private Function Saturar(ByVal Valor As Integer, ByVal Min As Integer, ByVal Max As Integer) As Integer
Saturar = Valor
If Valor < Min Then Saturar = Min
If Valor > Max Then Saturar = Max
End Function

Private Sub Alto_Texto()
'AltoTexto = p_gfx.FONT_SystemGetTextHeight(pFont, "Tgj" & vbCrLf & "Hola") + 2
End Sub

Private Sub Redimencionar()
Dim nHeight As Long
Dim nWidth As Long

MarcoTextoD.X = MarcoD.X + Sangria
MarcoTextoD.Y = MarcoD.Y + BordeSuperior

'comprobar si existe cambio en la altura del marco para minimizar el número de llamados a calculos de texto visible
nHeight = MarcoD.Height - BordeSuperior - BordeInferior
If nHeight <> MarcoTextoD.Height And nHeight > 10 Then
    MarcoTextoD.Height = nHeight
    Comprobar_Alto
End If

'comprobar si existe cambio en el ancho del marco para minimizar el número de llamados a calculos de texto visible
nWidth = MarcoD.Width - Sangria - BordeDerecho 'Se reservan 40 pixel al lado derecho para dibujar el ascensor
If nWidth <> MarcoTextoD.Width And nWidth > 10 Then
    MarcoTextoD.Width = nWidth
    Comprobar_Ancho
End If

'Dimensionar ascensor
AscensorD(0).X = MarcoD.X + MarcoD.Width - 35
AscensorD(0).Y = MarcoTextoD.Y
AscensorD(0).Width = 20
AscensorD(0).Height = 30
AscensorD(1).X = AscensorD(0).X
AscensorD(1).Y = MarcoTextoD.Y + AscensorD(0).Height
AscensorD(1).Width = 20
AscensorD(1).Height = MarcoTextoD.Height - 60
AscensorD(2).X = AscensorD(0).X
AscensorD(2).Y = AscensorD(1).Y + AscensorD(1).Height
AscensorD(2).Width = 20
AscensorD(2).Height = 30


End Sub

Private Sub Comprobar_Alto() 'Comprueba la cantidad de líneas que se pueden visualizar
Dim i As Integer
Dim Cadena As String
Dim gato As Integer

i = 0
Cadena = "Tgj"
Do While MarcoTextoD.Height > p_gfx.FONT_SystemGetTextHeight(pFont, Cadena) + 2
    Cadena = Cadena & vbCrLf & "Tgj"
    i = i + 1
Loop
MaxLineas = i
End Sub

Private Sub Comprobar_Ancho() 'Reviza toda la lista ListaDraw a partir del ancho actual
Dim i, e As Integer
Dim Cadena As String

For i = 0 To UBound(Lista)
    Cadena = Lista(i)
    Do While p_gfx.FONT_SystemGetTextWidth(pFont, Cadena) >= MarcoTextoD.Width
        Cadena = Mid(Cadena, 1, Len(Cadena) - 1)
    Loop
    ListaDraw(i) = Cadena
Next
End Sub

'**********************************************************************
'Procedimientos Publicos
'**********************************************************************
Public Sub Iniciar(Tgfx As dx_GFX_Class, Tinput As dx_Input_Class, TSystem As dx_System_Class, TFont As Long, Optional Theigth As Long, Optional TWidth As Long, Optional TTop As Long, Optional TLeft As Long)
'asignar clases externas
Set p_gfx = Tgfx
Set p_Input = Tinput
Set p_System = TSystem
pFont = TFont
'asignar valores
If Theigth > 0 Then Height = Theigth
If TWidth > 0 Then Width = TWidth
Top = TTop
Left = TLeft
End Sub

Public Sub Draw()
Dim i As Integer
Dim Posy As Long
Dim PartX As Long
Dim PartY As Long
Dim Cadena As String
Dim LineasDraw As Integer
Dim TempColor As Long

If Visible Then
    'dibujar fondo del control
    If HayFondo Then
        TempColor = p_gfx.ARGB_Set(AlphaActual, 255, 255, 255)
        Call p_gfx.DRAW_MapEx(rFondo, MarcoD.X, MarcoD.Y, Zbuffer, MarcoD.Width, MarcoD.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
    Else
        TempColor = p_gfx.ARGB_Set(AlphaActual, (BackColor And &HFF0000) / 65536, (BackColor And &HFF00&) / 256, (BackColor And &HFF))
        Call p_gfx.DRAW_Box(MarcoD.X, MarcoD.Y, MarcoD.Width + MarcoD.X, MarcoD.Height + MarcoD.Y, Zbuffer, TempColor, True, TempColor)
    End If
    
    
    'Dibujar esquinas, si corresponde
    TempColor = p_gfx.ARGB_Set(AlphaActual, 255, 255, 255)
    If HayEsquina1 Then
        Call p_gfx.DRAW_MapEx(rEsquina1, MarcoD.X, MarcoD.Y, Zbuffer, InfoEsquina1.Image_Width, InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
        Call p_gfx.DRAW_MapEx(rEsquina1, MarcoD.X + MarcoD.Width - InfoEsquina1.Image_Width, MarcoD.Y, Zbuffer, InfoEsquina1.Image_Width, InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_Vertical, Filter_None, False)
        Call p_gfx.DRAW_MapEx(rEsquina1, MarcoD.X, MarcoD.Y + MarcoD.Height - InfoEsquina1.Height, Zbuffer, InfoEsquina1.Image_Width, InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_Horizontal, Filter_None, False)
        Call p_gfx.DRAW_MapEx(rEsquina1, MarcoD.X + MarcoD.Width - InfoEsquina1.Image_Width, MarcoD.Y + MarcoD.Height - InfoEsquina1.Height, Zbuffer, InfoEsquina1.Image_Width, InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_Both, Filter_None, False)
    End If
    
            'Dibujar bordes si corresponde
    If HayBordeH Then
        Call p_gfx.DRAW_MapEx(rBordeH, MarcoD.X + InfoEsquina1.Width, MarcoD.Y, Zbuffer, MarcoD.Width - 2 * InfoEsquina1.Width, InfoBordeH.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
        Call p_gfx.DRAW_MapEx(rBordeH, MarcoD.X + InfoEsquina1.Width, MarcoD.Y + MarcoD.Height - InfoBordeH.Height, Zbuffer, MarcoD.Width - 2 * InfoEsquina1.Width, InfoBordeH.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
    End If
    
    If HayBordeV Then
        Call p_gfx.DRAW_MapEx(rBordeV, MarcoD.X, MarcoD.Y + InfoEsquina1.Height, Zbuffer, InfoBordeV.Width, MarcoD.Height - 2 * InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
        Call p_gfx.DRAW_MapEx(rBordeV, MarcoD.X + MarcoD.Width - InfoBordeV.Width, MarcoD.Y + InfoEsquina1.Height, Zbuffer, InfoBordeV.Width, MarcoD.Height - 2 * InfoEsquina1.Height, 0, Blendop_Color, TempColor, Mirror_None, Filter_None, False)
    End If

    
    'Dibujar texto
    LineasDraw = UBound(ListaDraw)
    If LineasDraw > MaxLineas Then LineasDraw = MaxLineas
    For i = 1 To LineasDraw
        Cadena = Cadena & ListaDraw(i + AscensorValor) & vbCrLf
    Next
    TempColor = p_gfx.ARGB_Set(AlphaActual, (FontColor And &HFF0000) / 65536, (FontColor And &HFF00&) / 256, (FontColor And &HFF))
    Call p_gfx.DRAW_Text(pFont, Cadena, MarcoTextoD.X, MarcoTextoD.Y, Zbuffer, TempColor, Align_Left)

    
    'dibujar ascensor si corresponde
    If DibujarAscensor Then
    TempColor = p_gfx.ARGB_Set(AlphaActual, (BorderColor And &HFF0000) / 65536, (BorderColor And &HFF00&) / 256, (BorderColor And &HFF))
    For i = 0 To 2
        Call p_gfx.DRAW_Box(AscensorD(i).X, AscensorD(i).Y, AscensorD(i).X + AscensorD(i).Width, AscensorD(i).Y + AscensorD(i).Height, Zbuffer, TempColor, False) 'dibujar borde
    Next
    Dim Posiy As Long
    Dim AltoY As Long
    Posiy = ((AscensorD(1).Height / (AscensorMax + 1)) * AscensorValor) + AscensorD(1).Y
    AltoY = (AscensorD(1).Height / (AscensorMax + 1))
    Call p_gfx.DRAW_Box(AscensorD(1).X + 2, Posiy, AscensorD(1).X + AscensorD(1).Width - 2, Posiy + AltoY, Zbuffer, TempColor, True, TempColor) 'dibujar valor
    End If
End If
End Sub

Public Sub AddItem(ByVal Linea As String)
Dim i, e, o As Integer
Dim Cadenas() As String

Cadenas = Split(Linea, vbCrLf) 'detectar y agregar multiples linea en un sólo llamado
For e = 0 To UBound(Cadenas)
    'Agregar nueva linea a la lista
    ReDim Preserve Lista(UBound(Lista) + 1)
    ReDim Preserve ListaDraw(UBound(ListaDraw) + 1)
    
    i = UBound(Lista)
    Lista(i) = Cadenas(e) 'asignar string a buffer interno
    
    'comprobar tamaño del string dibujado contra los margenes del control y almacenar el buffer para dibujo de fuente
    Do While p_gfx.FONT_SystemGetTextWidth(pFont, Cadenas(e)) >= MarcoTextoD.Width
        Cadenas(e) = Mid(Cadenas(e), 1, Len(Cadenas(e)) - 1)
    Loop
    ListaDraw(i) = Cadenas(e)
    
    If i > MaxLineas Then
        DibujarAscensor = True
        AscensorMax = i - MaxLineas
    End If
Next
End Sub

Public Sub Clear()

ReDim Lista(0)
ReDim ListaDraw(0)
DibujarAscensor = False

End Sub

Public Sub Input_()
Dim Left_click As Boolean

'si el ratón esta sobre el marco
If p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, MarcoD) Then

    'corregir opacidad actual si el cursor pasa encima del marco
    If UseTransparency2 = Msg_Only_Cursor Or UseTransparency2 = Msg_Focus_OR_Cursor Then AlphaActual = pOpacidadSec
    
    'Detectar foco
    If p_Input.Mouse.Left_Button Then
        pfoco = True
    End If
    
    If pfoco And (UseTransparency2 = Msg_Focus_OR_Cursor Or UseTransparency2 = Msg_Only_Focus) Then AlphaActual = pOpacidadSec
    
    'Detectar ascensor
    If DibujarAscensor Then
        If Left_Click_ant = False And p_Input.Mouse.Left_Button Then 'detectar mouse_press
            If p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, AscensorD(0)) Then AscensorValor = Saturar(AscensorValor - 1, 0, AscensorMax) 'si se preciona subir
            If p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, AscensorD(2)) Then AscensorValor = Saturar(AscensorValor + 1, 0, AscensorMax) 'si se preciona bajar
        End If
        If p_Input.Mouse.Left_Button And p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, AscensorD(1)) Then 'si se preciona el cuerpo del ascensor
            AscensorValor = ((p_Input.Mouse.Y - AscensorD(1).Y) / (AscensorD(1).Height / AscensorMax))
        End If
            'Llamar a función externa de click sólo si preciona sobre el área de texto
        If p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, MarcoTextoD) And p_Input.Mouse.Left_Button And Left_Click_ant = False Then
            RaiseEvent Click
        End If
    Else
        If p_System.MATH_PointInRect(p_Input.Mouse.X, p_Input.Mouse.Y, MarcoD) And p_Input.Mouse.Left_Button And Left_Click_ant = False Then
            RaiseEvent Click
        End If
    
    End If
    
    pCursorSobre = True
Else
    If (Not (UseTransparency2 = Msg_Focus_OR_Cursor Or UseTransparency2 = Msg_Only_Focus)) Or pfoco = False Then AlphaActual = pOpacidad
    'Detectar foco
    If (p_Input.Mouse.Left_Button Or p_Input.Mouse.Right_Button) And Left_Click_ant = False Then pfoco = False
    pCursorSobre = False
End If

'pasar último valor de left click del mouse
Left_Click_ant = p_Input.Mouse.Left_Button


'Detectar foco y cursor sobre el control
If pFocoPrevio = False And pfoco = True Then RaiseEvent SetFocus
If pFocoPrevio = True And pfoco = False Then RaiseEvent LostFocus
If pCursorSobrePrevio = False And pCursorSobre = True Then RaiseEvent SetCursor
If pCursorSobrePrevio = True And pCursorSobre = False Then RaiseEvent LostCursor

pFocoPrevio = pfoco
pCursorSobrePrevio = pCursorSobre
End Sub



