elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Trabajando con las ramas de git (tercera parte)


  Mostrar Mensajes
Páginas: 1 ... 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 [289] 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 ... 436
2881  Programación / Programación Visual Basic / Re: No puedo utilizar Load Label en PictureBox en: 10 Julio 2018, 03:25 am
Saque un tiempo el fin de semana para hacer un sencillo ejemplo de prueba, pero me faltó tiempo para probarlo y subirlo...

Aunque se puede hablar largo y variado sobre la trnasparencia, vamos a ir al grano...
En los controles d eusuario de VB6, hay dos formas de dibujar:

A - La primera es usar el evento paint del propio usercontrol... cuando una parte dle control queda expuesta y luego liberada, salta un evento paint, que da la ocasión de redibujar el control. Así que en éste caso todo lo que se deba dibujar debe estar dentro de ese evento.
B - Un defecto del método propio, es que en generla se procede a dibujar por completo el control aunque solo hay sido expuesta una pequeña área. VB6, provee un método alternativo.
Cuando se pone la propiedad Autoredraw a TRUE, una vez pintado, VB6, hace una especie de 'capura' del gráfico, luego cuando se tapa y expone, VB6, solo pega parcialmente el área recién descubierta en vez de redibujar todo.
Naturalmente cuando haya que hacer cambios, hay que redibujar el control al completo por lo general...
Es importante saber que si se pone Autoredraw a TRUE, el evento paint, no salta, porque VB6 se encarga de repintar el área que lo precise, sin embargo o mejor dicho queda a cargo del programador actualizar convenientemente el gráfico cuando convenga...

Aclarado el tema, podemos crear una función llamada por ejemplo "Redibujar", si autoredraw está a false, saltará el evento paint, allí simplemente innnvocamos a esta función y listo. Y si Autoredraw está a TRUE, simplemente desde nuestro código debemos invocar dicha función cuando necesitemos actualizar el gráfico...

Vamos a  lo primero, algunas propiedades para controlar y que sirvan de ejemplo...

' OK: Devuelve o establece si el color del fondo del display es transparente y deja ver lo que hay bajo él.

Código
  1. ' En la sección de declaraciones:
  2. Private p_Transparente          As Boolean
  3. Private p_ColorTapiz              As Long
  4. Private p_ColorTinta              As Long
  5.  
  6.  
  7.  
  8. Public Property Get Transparente() As Boolean
  9.    Transparente = p_Transparente
  10. End Property
  11.    Public Property Let Transparente(ByVal X As Boolean)
  12.        If (X <> p_Transparente) Then
  13.            p_Transparente = X
  14.            Call Redibujar
  15.            PropertyChanged "Transparente"
  16.        End If
  17.    End Property
  18.  
  19. ' Devuelve o establece el color del fondo del control.
  20. '   Todo lo que se pinte de este color será transparente.
  21. ' No hay problema en delegar la propiedad en Usercontrol.Backcolor
  22. Public Property Get ColorTapiz() As OLE_COLOR
  23.    ColorTapiz = p_ColorTapiz
  24. End Property
  25.    Public Property Let ColorTapiz(ByVal X As OLE_COLOR)
  26.        If (X <> p_ColorTapiz) Then
  27.            p_ColorTapiz = X
  28.            Call Redibujar
  29.            PropertyChanged "ColorTapiz"
  30.        End If
  31.    End Property
  32.  
  33. ' Devuelve o establece el color de la tinta del control. Por defecto, lo que se dibue se hará con este color.
  34. '  puede delegarle la propiedad en Usercontrol.Forecolor sin problemas...
  35. Public Property Get ColorTinta() As OLE_COLOR
  36.    ColorTinta = p_ColorTinta
  37. End Property
  38.    Public Property Let ColorTinta(ByVal X As OLE_COLOR)
  39.        If (X <> p_ColorTinta) Then
  40.            p_ColorTinta = X             'UserControl.ForeColor = X
  41.            Call Redibujar
  42.            PropertyChanged "ColorTinta"
  43.        End If
  44.    End Property
  45.  

Añade tus funciones gráficas, en general pinta con el 'ColorTinta', digamos que es el color por defecto para pintar...
Es útil disponer también de una propiedad: "ColorPreset". que no es otra cosa que un array de colores...
Si son fijos los estableces en código, si son elegibles por el usuario, que el mismo los pueda remplazar, aunque siempre conviene que existan por defecto... en generla basta con 16 colores, digamos 15 para el array + el 'color Tinta' (el valor por defecto).
La ventaja de un color preset, es que si tiene spongamos 300 líneas que dibujar y 35 de ellas tienen un color morado y decides cambiarlo a amarillo, en vez de recordar que líneas son es preferible asignar un color preset a cada línea, luego cuando se queira cambiar el color, la propiedad detecta que ha cambiado y al dibujar lo hará con el nuevo color... sin tener que recorrer las 300 líneas para asignarle un nuevo color... así pasamos por ejemplo de la estructura:
Código
  1. public type DatosLinea
  2.    X1 as integer
  3.    Y1 as integer
  4.    X2 as integer
  5.    Y2 as integer
  6.    Color as long
  7. end type
  8.  
Es preferible usar una estructura ligeramente diferente...
Código
  1. public type DatosLinea
  2.    X1 as integer
  3.    Y1 as integer
  4.    X2 as integer
  5.    Y2 as integer
  6.    IndexColor as Integer
  7. end type
  8.  

IndexColor apunta a un índice en el array de ColorPreset, así cambiar el color a 52 líneas no exige más que cambiar el color al índice concreto, y no a todas las 52 lineas recorriendo las 300... Una vez hecho el cambio, al dibujar sería algo como:
Código
  1.    For k = 0 to p_NumLineas
  2.        with ColLineas(k)  ' una colección o array de 'DatosLinea'
  3.            UserControl.Line (.x1, .y1)-(.x2, .y2), p_ColorPreset(.IndexColor), BF
  4.        end with
  5.    Next
  6.  

La propiedad ColorPreset, requiere dos parámetros, el índice y el color que se asigna a dicho índice:
Código
  1. ' en las declaraciones:
  2. private p_ColorPreset(-1 to 15)    as long  ' el valor del índice -1, refleja el ColorTinta
  3.  
  4. public property get ColorPreset(byval Indice as byte) as OLE_Color
  5.    ColorPreset = p_ColorPreset(indice)
  6. end property
  7.    ' Como indice está declarado como byte, el índice -1 no puede ser alterado externamente
  8.    Public property let ColorPreset(byval Indice as byte, byval X as OLE_Color)
  9.        if (indice > 15) then err.raise 381  ' indice de array fuera de rango.
  10.        If (p_ColorPreset(Indice) <> X) then
  11.            p_ColorPreset(Indice) = X
  12.            Call Redibujar
  13.            PropertyChanged "ColorPreset"
  14.        end if
  15.    end property
  16.  

Esto sin embargo es mejorable en dos aspectos.
Lo primero es que al poner dos parámetros en una propiedad, ya no puede aparecer en la "ventana de propiedades" durante el diseño y por tanto durante diseño, la aplicación cliente, no podrá poner reasignar colores salvoque se añada una página d epropiedades, que es complicarlo solo para esto.
Hay una técnica muy sencilla, que admeás puede también aplicarse a otros objetos que posena índice  y varia spropiedades... y consiste en desdoblar la propiedad en dos...
por un lado el índice y por otro el color, como se muestra a continuación:
Código
  1. ' en las declaraciones:
  2.    private p_IndexPreset     as byte
  3.    private p_ColorPreset(-1 to 15)    as long  ' el valor del índice -1, refleja el ColorTinta  
  4.  
  5. ' Esta propiedad refleja en diseño el índice al que se aplica el colorPreset...
  6. public property get IndexPreset() as byte
  7.    IndexPreset = p_IndexPreset
  8. end property
  9.    ' Como indice está declarado como byte, el índice -1 no puede ser alterado externamente
  10.    Public property let IndexPreset(byval X as byte)
  11.        if (x > 15) then err.raise 381  ' indice de array fuera de rango.
  12.        If (p_IndexPreset <> X) then
  13.            p_IndexPreset(Indice) = X
  14.            ' no necesita guardarse esta propiedad, puede ser 0 cada vez... que se carguen las propiedades.
  15.        end if
  16.    end property
  17.  
  18. public property get ColorPreset() as OLE_Color
  19.    ColorPreset = p_ColorPreset(p_IndexPreset)
  20. end property
  21.    ' Como indice está declarado como byte, el índice -1 no puede ser alterado externamente
  22.    Public property let ColorPreset(byval X as OLE_Color)
  23.        If (p_ColorPreset(p_IndexPreset) <> X) then
  24.            p_ColorPreset(p_IndexPreset) = X
  25.            Call Redibujar
  26.            PropertyChanged "ColorPreset"
  27.        end if
  28.    end property
  29.  
Ahora ya aparece esa propiedad en la 'ventana de propiedades', para cambiar un color del array, basta cambiar el array y luego asignar un color...

Antes decía que tenía dos carencias, una ya ha quedado subsanada, la otra es que anque tenemos 16 colores, no necesariamente deben estar todos en uso, sin embargo al cambiar un color del preset, forzamos un redibujado... algo caro si resulta que nada está dibujado con ese color.
Algo más optimo es mantener un array paralelo que lleve la cuenta de 'objetos' que usan cada color...
Cuando se añade un nuevo 'objeto gráfico', se añade 1 a la cuenta, si se elimina (o se cambia de índice asignado de color), se resta 1 para ese índice (y se suma uno al otro si cambió de índice).
Entonces ahora la última propiedad puede mejorarse así:
Código
  1. private p_CuentaObjColor(0 to 15)         as integer
  2.  
  3. public property get ColorPreset() as OLE_Color
  4.    ColorPreset = p_ColorPreset(p_IndexPreset)
  5. end property
  6.    ' Como indice está declarado como byte, el índice -1 no puede ser alterado externamente
  7.    Public property let ColorPreset(byval X as OLE_Color)
  8.        If (p_ColorPreset(p_IndexPreset) <> X) then
  9.            p_ColorPreset(p_IndexPreset) = X
  10.            if (p_CuentaObjColor(p_indexPreset)>0) then
  11.                Call Redibujar
  12.            end if
  13.            PropertyChanged "ColorPreset"
  14.        end if
  15.    end property
  16.  
Ahora es más eficiente, al coste de mantener convenientemente actualizado el array con la cuenta de objetos que mantienen tal o cual color...
Claramente si el número de líneas a dibujar son pocas, redibujarlo todo cada vez, no sea pesado y a cambio uno se olvida de la complejidad añadida por la eficiencia, en cambio sin son algunas miles d elínea sa dibujar... redibujarlas todas cuando ningún objeto utiliza dicho color, no es ideal... En fin uno debe decidir que conviene mas dado el caso de que vaya a usarse muchas o pocos objetos gráficos...

Todo lo previo es para optimizar operaciones, ahora veremos unamanera de reutilizar el mismo control para 3 tareas diferentes...
- Polilínea: Son varios puntos conectados entre sí, formando un único objeto gráfico, más o menos complejo...
Se dibuja una línea de un punto a otro, si uno no está activo se pasa al siguiente (es decir el que noes
´te activo se ignora).
- Múltiples líneas inconexas entre sí. Es decir cada línea tiene dos puntos que definen su inicio y su fin.
Cad alínea comienza en un índice par como X1,Y1 y termina en el siguiente punto delarray (punto impar), como X2, Y2.
- Poligonos: Cada polígono se compone de varios vértices. realmente también puede considerarse múltples polilíneas, ya que ser polígono, exige que la última línea del polígono se conecte a la primera.
Un poligono dibuja de un punto a otro, hasta encontrar uno no activo, momento en que se considera que acaba e polígono (o polilínea en múltiples polilineas).
Todo ello soportado con una misma y única colección o array (luego un par de párrafos al respecto).

Aquí, código para dar salida a todas esas ideas...
Código
  1. ' en las declaraciones:
  2. Public Type PuntoPolilinea
  3.    X       As Single
  4.    Y       As Single
  5.    Activo  As Byte         ' Valor 255 = activo, se dibuja, otro valor no se dibuja
  6.    ' (interesa un byte mejor que Boolean, porque incluso puede usarse como cuenta y al alcanzar el valor 255 será 'dibujable', en cualquier caso, un boolean en vb6 ocupa 2 bytes).
  7. End Type
  8.  
  9. ' Comportamiento del control a la hora de dibujar.
  10. Public Enum ModosDeDibujado
  11.    DIBUJA_INCONEXA = 0        ' De un punto par al siguiente impar, del impar salta (sin dibujar) al siguiente par.
  12.    DIBUJA_POLILINEA = 1       ' Se comporta como una línea continua de un punto (activo) a otro.
  13.    DIBUJA_POLIGONOS = 2       ' Se comporta como si fueran polígonos, cada polígono termina cuando un punto está desactivado.
  14. End Enum
  15.  
  16. Private p_Polilinea         As ModosDeDibujado  ' Se comporta de diferentes maneras...
  17.  
  18. Private p_ptActual          As Integer              ' para señalar valores dado su índice.
  19. ' Permite dibujar desde un punto a otro específico...
  20. Private p_ptInicio          As Integer             ' Punto desde el que se empieza a dibujar.
  21. Private p_ptFinal           As Integer             ' Punto donde se termina de dibujar (si circular hasta el sigiente).
  22. Private p_ptEvento          As Integer          ' dispara un evento al dibujar dicho punto, para tener ocasión de asignar color, ancho paqra la siguiente línea (o para el resto), incluso para poder cambiar el índice de otro punto para evento...
  23.  
  24. ' en las propiedades:
  25.  
  26. ' Devuelve o establece un valor que determina si los puntos se comportan como una polílínea, como líneas inconexas o como polígonos (o múltiples polilíneas). Actuando como líneas inconexas cada línea queda definidar por un punto par y el siguiente.
  27. ' OJO: Dado que como múltiples líneas, cada línea(inconexa) requiere dos puntos, queda definida por un punto par y el siguiente impar,
  28. '  luego definir como punto inicial (para empezar a dibujar) uno impar, haría una conexión errónea (conectando el punto final de una línea con el punto inicial de otra), para todas ellas.
  29. Public Property Get ModoDibujo() As ModosDeDibujado
  30.    ModoDibujo = p_Polilinea
  31. End Property
  32.    ' La idea es que el control se utilice para una sola cosa durante su tiempo de ejecución.
  33.    Public Property Let ModoDibujo(ByVal X As ModosDeDibujado)
  34.        If (X <> p_Polilinea) Then
  35.            If (p_Polilinea = DIBUJA_POLIGONOS) Then
  36.                p_Polilinea = X
  37.                Call AjustarArray
  38.  
  39.                If (X = DIBUJA_INCONEXA) Then
  40.                    ' Garantiza la integridad de dibujar líneas como se definieron.
  41.                    If (p_ptInicio And 1) Then          ' si es impar, se resta uno,
  42.                        p_ptInicio = (p_ptInicio - 1)   ' para apuntar al punto inicial de la línea.
  43.                    End If
  44.                End If
  45.  
  46.                If (p_Autodibujar = True) Then
  47.                    Call Redibujar
  48.                End If
  49.            Else
  50.                p_Polilinea = DIBUJA_POLIGONOS
  51.                ' no se debe redibujar, sin cargar primero los puntos.
  52.            End If
  53.            PropertyChanged "ModoDibujo"
  54.        End If
  55.    End Property
  56.  

Los campos para otras propiedades:
- p_ptActual: Sirve para usar la misma técnica anterior y poder asignar línea durante diseño, sobre la ventana d epropiedades... va bien cuando son pocas, si son muchas es preferible usar un fichero externo y proveer una función de carga d elos datos...

- p_ptInicio, p_ptFinal... aunque se comentan brevemente en su declaración, sirven para dibujar en un bucle... por defecto una vale 0 y la otra el último punto del array/colección, pero en la práctica, puede ser usado como separador de objetos, por ejemplo podrías tener olilíneas entre el indice 0 y el 60, línea ssueltas entre el índice 61 y 130 y poligonos (de pocos lados cada uno) entre el punto índice 131 y el 540, y otro objeto más complejo entre el índice 541 y el 650 (por ejemplo)... así si precisas redibujar solo las líneas, estbalece inicio y fin a los valores 61 y 130 respectivamente y luego con polilinea = DIBUJA_INCONEXA, si está establecda una propiedad AutoRedibujar , ya haría el redibujado, y si no puede crearse una función publica que admita dichos parámetros...

Ahora la función de dibujado que aplica las diferentes formas de dibujado:
Código
  1. ' redibuja toda la figura desde el punto inicial hasta el final (perop uede hacerse pública y admitir los parámetros antedichos más arriba, para ser invocada también desde fuera...
  2. Private Sub DibujarMiContenido()
  3.    Dim k As Integer, j As Integer, i As Integer, n As Integer
  4.    Dim X1 As Single, X2 As Single, Y1 As Single, Y2 As Single
  5.    Dim kol As Long, Ancho As Byte
  6.    Dim pts() As PuntoPolilinea
  7.  
  8.    If (p_NumPuntos > 1) Then
  9.        ' para permitir (durante evento de punto), dibujar con coloy ancho distintos sin alterar el valor 'general'.
  10.        kol = p_ColorTinta ' UserControl.ForeColor
  11.        Ancho = UserControl.DrawWidth
  12.  
  13.        If (p_ptInicio < p_ptFinal) Then
  14.            i = p_ptInicio: j = p_ptFinal: n = 1
  15.        Else
  16.            j = p_ptInicio: i = p_ptFinal: n = -1
  17.        End If
  18.  
  19.        ' 2 arrays, uno mantiene los puntos originales para no perse rprecisión por escalados contínuos, el otro
  20.        '    mantiene los valores escalados...
  21.        If (p_AutoEscalado = True) Then
  22.            pts = s_Escala
  23.        Else
  24.            pts = p_Puntos
  25.        End If
  26.  
  27.        If (p_Polilinea = DIBUJA_POLILINEA) Then
  28.            ' Dibuja como una polílinea. Líneas conexas entre puntos activos...
  29.            ' Donde cada línea queda definida entre un par de puntos activos.
  30.            '  Los puntos pueden estar activos individualmente.
  31.            If (p_NumPtActivos = 0) Then Exit Sub
  32.  
  33.            With pts(p_ptInicio)
  34.                X1 = .X: Y1 = .Y
  35.            End With
  36.  
  37.            For k = i + n To j Step n
  38.                With pts(k)
  39.                    If (.Activo = 255) Then
  40.                        X2 = .X: Y2 = .Y
  41.                        If (k = p_ptEvento) Then
  42.                            ' El cliente tiene con éste evento oportunidad de dibujar algo en ese momento, cambiar valor de puntos
  43.                            '   cambiar color para dibujar, el ancho, e incluso definir otro momento de evento como éste para hacer más cambios.
  44.                            RaiseEvent DibujandoPuntoSel(p_ptEvento, kol, Ancho)
  45.                        End If
  46.                        UserControl.Line (X1, Y1)-(X2, Y2), kol
  47.                        X1 = X2: Y1 = Y2
  48.                    End If
  49.                End With
  50.            Next
  51.  
  52.            If (p_Circular = True) Then
  53.                With pts(i)
  54.                    X2 = .X: Y2 = .Y
  55.                    UserControl.Line (X1, Y1)-(X2, Y2), kol
  56.                End With
  57.            End If
  58.  
  59.        ElseIf (p_Polilinea = DIBUJA_INCONEXA) Then
  60.            ' Dibuja como múltiples líneas inconexas entre sí...
  61.            ' Donde cada línea queda definida por un par de puntos par-impar.
  62.            '  La línea está 'activa' si el primero lo está (obviando el estado del 2º).
  63.            If (i And 1) Then i = (i - 1)
  64.            For k = i To j Step (n * 2)
  65.                With pts(k)
  66.                    If (.Activo = 255) Then
  67.                        X1 = .X: Y1 = .Y
  68.                        ' Como múltiples líneas se ignora el estado activo del segundo punto.
  69.                        With pts(k + n)
  70.                            X2 = .X: Y2 = .Y
  71.                        End With
  72.  
  73.                        ' Igualmente: éste punto debiera ser par, o modificarse como  está comentado
  74.                        If (k = p_ptEvento) Then   ' or ((k+n) = p_ptEvento) then
  75.                            ' El cliente tiene con éste evento oportunidad de dibujar algo en ese momento, cambiar valor de puntos
  76.                            '   cambiar color para dibujar, el ancho, e incluso definir otro momento de evento como éste para hacer más cambios.
  77.                            RaiseEvent DibujandoPuntoSel(p_ptEvento, kol, Ancho)
  78.                        End If
  79.  
  80.                        UserControl.Line (X1, Y1)-(X2, Y2), kol
  81.                    End If
  82.                End With
  83.            Next
  84.        Else ' poligonos...
  85.            ' polígonos solo se dibuja en orden hacia arriba...
  86.            Do While (i < j)
  87.                With pts(i)
  88.                    X1 = .X: Y1 = .Y
  89.                End With
  90.  
  91.                ' un polígono acaba cuando encuentra un punto 'no activo'
  92.                Do While pts(i).Activo = True
  93.                    i = (i + 1)
  94.                    With pts(i)
  95.                        X2 = .X: Y2 = .Y
  96.                        ' Igualmente: éste punto debiera ser par, o modificarse como  está comentado
  97.                        If (i = p_ptEvento) Then   ' or ((k+n) = p_ptEvento) then
  98.                            ' El cliente tiene con éste evento oportunidad de dibujar algo en ese momento, cambiar valor de puntos
  99.                            '   cambiar color para dibujar, el ancho, e incluso definir otro momento de evento como éste para hacer más cambios.
  100.                            RaiseEvent DibujandoPuntoSel(p_ptEvento, kol, Ancho)
  101.                        End If
  102.  
  103.                        UserControl.Line (X1, Y1)-(X2, Y2), kol
  104.                    End With
  105.                    X1 = X2: Y1 = Y2
  106.                Loop
  107.                i = (i + 1)
  108.            Loop
  109.        End If
  110.  
  111.        ' restaura el ancho de dibujado...
  112.        UserControl.DrawWidth = Ancho
  113.    End If
  114. End Sub
  115.  

El campo "p_ptEvento" da pie a otra propiedad... por eejmplo dado un indice que se debe dibujar con un color o ancho distintos, alllegar aél se lanza el evento, y se responde cambiando el color y/o el ancho de dibujado de la línea y/o también el próximo punto donde parar...

en este ejemplo de función no he hecho uso del array ColorPreset, ya puse un ejemplo muy simple más arriba de como usarlo, aquí se ha puesto para el caso, p_ColorTinta, ya que la estructura definida algo más arriba, no aloja un color, si no otro campo interesante "Activo", para señalar qué hacer o para que sirve o como funcionar con dicho punto de formas diversas...

Y como ya me he extendido más d elo que pretendía, finalmente podrmeos dibujar con transparencia...
Respeta lo que en esta función aparece y lo que modifiques que sea en una función aparte o bien enciam o debajo de la función usada para todo el dibujado...
Código
  1. ' Con AutoRedraw=True, nunca se invoca este método,
  2. '  se puede solucionar así...
  3. ' Private Sub UserControl_Paint()
  4. '     call Redibujar
  5. ' end sub
  6.  
  7. ' siempre conviene tener una funcion externa que redibuje todo...
  8. public sub Refresh
  9.    call Redibujar  
  10. end sub
  11.  
  12. '  pero si se pone a False, no requiere invocarse otro método.
  13. Private Sub Redibujar()
  14.    With UserControl
  15.        .BackStyle = 1
  16.        .DrawMode = vbCopyPen
  17.        .FillStyle = vbFSTransparent
  18.  
  19.        ' Color del fondo...
  20.        '.Cls ' aplicando el color al usercontrol.backcolor, pero como no delegamos en usercontrol.backcolor...
  21.        ' pintmaos el fondo 'a mano'.
  22.        UserControl.Line (0, 0)-(.Width, .Height), p_ColorTapiz, BF  ' "B"oxed y "F"illed
  23.  
  24.        'Call DibujarFondo ' dibujamos si hay alguna imagen de fondo con algo transparente o no, quizás una cuadrícula
  25.        Call DibujarMiContenido ' dibujamos el valor
  26.        Call DibujarRelieve ' dibujamos el borde. Si el borde va ser sencillo, mejor delegar en el usercontrol.BorderStyle, pero si redondeamos esquinas, o se da un margen mayor, etc... viene bien dibujarlo después del resto.
  27.  
  28.        If (p_Transparente = True) Then
  29.            .MaskColor = p_ColorTapiz
  30.            .BackStyle = 0
  31.            Set .MaskPicture = .Image
  32.        End If
  33.  
  34.        If (p_Activo = False) Then ' usercontrol.Enabled
  35.            Call DibujarEstadoDisabled
  36.        End If
  37.    End With
  38.    'RaiseEvent Pintado
  39. End Sub
  40.  

pongo alguna imagen... y como ya se me hace tarde para más, mañana (o pasado, si no tengo tiempo mañana) comprimo el proyecto de ejemplo y lo subo a alguna página de descarga... comentaré alguna cosa más antes...




2882  Programación / Programación General / Re: Duda sobre expresiones condicionales. en: 9 Julio 2018, 02:26 am
Dije que no sé si mi lenguaje admite paréntesis en las condiciones, ejemplo "V1<V2 or (V1==V2 and V2==V3)" ni cómo las toma, lo cual evidentemente es algo que yo debo averiguar, no pedí ayuda con eso.
 Action Script de Macromedia Flash 5. Es prácticamente el único que uso y mi favorito.
Tienes solo 2 problemas (aunque gordos).
- En primer lugar tienes dificultad para entender... lo que se te dice. Pasas de largo por las soluciones, como esperando una receta mágica (que no existe).
- En segundo lugar 'tu lenguaje' al margen de calificarlo, ni siquiera lo conoces a fondo aún 'siendo tu favorito' como dices.

Cualquier lenguaje por miserable que sea, admitirá paréntesis para resolver la precedencia de operadores (debe importarte nada que un operador sea 'or', 'and' ó '+', '/', o cualquier otro... un operador es un operador sea del tipo que sea y a tí debe bastarte con saber que como tal cualquier operador tiene un valor de precedencia (prioridad en ser resuelto cuando no tiene paréntesis que lo delimite).

Esto quiere decir que siempre que tu pongas una expresión ordenada por precedencia, tampoco necesitarás usar paréntesis... pero esa forma la podrás usar en determinadas ocasiones, en otras ocasiones resultará forzado, poco natural y por tanto difícil de leer  y/o erscribir... aparte dle tiempo perdido en ello (solo por evitar colocar unos paréntesis).

Pero no entiendo a que viene tanto problema con los paréntesis... úsalos cuando y donde correspondan y listo. Y a tu pregunta sobre si existe alguna forma de evitarlos, ya te he aclarado que sí... que un lenguaje no admita directamente la notación polaca no es problema, precisamente para eso como programador uno programa el algoritmo que precise al problema que surja.

La mayoría de lenguajes carecen de interpretación para dicha notación, pero el compilador de todos y cada uno de ellos, acaba teniendo una implementación del algortimo para convertir la expresiones que el programador escribe en el lenguaje, para pasarlo a notación polaca...

lo que quisiera saber cómo arreglar, en lo posible sin usar paréntesis.
Ya te he contestado...
O reordenas las expresiones para que de izquierda a derecha, estén ordenados los operadores por precedencia, o recurres a la notaciópn polaca.

Ante mi pregunta
"¿Cualquier relación puede expresarse sin necesidad de paréntesis, y se interpretaría bien?" no veo un problema.
Es que insisito... para qué necesitas NO PONER paréntesis, cuando poniéndolos solo de un vistazo queda perfectamente claro y ordenado, sin importar lo compleja que sea una expresión????.

Es que tu te empeñas en no usar paréntesis por simple cabezonería... es como pretender prescindir de barcos o aviones y querer cruzar el océano a nado, y tu preguntas si puedes cruzarlo sin morir en el intento... maneras hay, pero ya son ganas de morir en el intento. Cuando en barco o avión el trayecto es seguro y rápido.

El problema son las expresiones que parecen requerirlo (a algún paréntesis) ¿realmente lo requieren o hay otra forma de decirlas que no use paréntesis?
Sí... ya te he explicado, reordena la expresión, para que los operadores de mayor precedencia queden a la izquierda... y el de menor precedencia a la derecha (siguiendo el orden estricto... pero esto resulta complejo incluso con expresiones no muy complejas, ya que si una operación tiene por ejemplo suma y resta y en otra parte aparece multiplicación, pero esta debe aplicarse después de haber hecho las previas, no podrá ponerse a la izquierda... en la misma línea, es decir tendrás que resolverlo en varias líneas... y así resulta tortuoso, pero poder s epuede, complicándolo innecesariamente... cruza el oceáno a nado, si te place.


Hombre, yo estoy hablando de los operadores AND y OR.
Tú me vienes con +, *, -.
En el mundo d ela programación, los operadores que  tiene un lenguaje son los que son, sin importar los que a ti te vengan bien o uses... En la especificación de cad alenguaje hay un apartado que expecifica el orden en que se evalúan los operadores (todos los que dispone el lenguaje, no solo los que a Pepito ó a Juanito le  vienen bien).

En tus descripciones de los operadores te has hecho un lío, pero la idea la entendí gracias a los ejemplos.
Vaya hombre... me he hecho un lío... buen chiste.... a estas horas, un poco de humor no viene mal.

EDIT2: El "xor" y cosas así más complejas que and y or creo que no las necesito, pero supongo que acortan ciertas expresiones, veremos...
XOR no es más complejo que OR ni AND, sino a su mismo nivel...

Tabla de verdad de XOR
----------------------------
0 xor 0 = 0
0 xor 1 = 1
1 xor 0 = 1
1 xor 1 = 0

En resumen es TRUE si solo una de ellas es TRUE. Si se aplica a más de 2 operandos es TRUE, si el número de evaluaciones TRUE es impar, FALSE si son pares...

1 xor 1 xor 1 xor 1 = 0   (4 unos, son pares luego = FALSE)
1 xor 1 xor 1 xor 0 = 1   ( 3 unos, son impares luego es = TRUE)

XOR te puede ahorrar muchas comparaciones...  


(la notación polaca) Probablemente sea la respuesta que necesitaba. Lo que no entiendo bien es cómo se interpretaría cada uno, pero sería cuestión de investigar y de práctica.
Investiga, pero yo te aconsejaría mejor que desistas de no querer usar paréntesis... A no ser que vivas en Marte, y las teclas de paréntesis se hayan fastidiado y no tengas posibilidades de arreglarlo...

Sí, la verdad que sí. Pero si son como las expresiones matemáticas entonces no. ¿Cómo interpretarías esto, si fueses de izquierda a derecha?
A y B y C o D o E y F o G
La precedencia de operadores lógicos: primero AND, luego OR y finalmente XOR... en tu ejemplo sería lo mismo que si AND lo cambiar por '-'  y 'or' por '+', ya qe mantienen entre si la misma recedencia...
La expresión que pides quedaría así:
A B y C y D o E o F y G o
Los operadores aritméticos tienen precedencia sobre los lógicos.
La precedencia en los operadores de comparación, es esta:  =, <, <=, >, >=


Ni siquiera sé de lo que me estás hablando. Para mí pila es un "aparato" que se guarda en otros para darle energía, o una montaña con cierto orden.
Ni te preocupes en aclarármelo, sólo te comento.
Ya... me hago cargo... por eso decía que si tienes problemas para enteder expresiones sencillas, o para entender la simpleza y elegancia de los paréntesis, no vale la pena decir nada más... La testarudez, no tiene cura. ...pero bueno, si aprendes algo, pués vale.


Buscando por la red, algún pdf sobre ActionScript, aparece claramente...

Citar
() parentheses operator
(expression1 [, expression2])
( expression1, expression2 )
function ( parameter1,..., parameterN )

Performs a grouping operation on one or more parameters, performs sequential evaluation of expressions, or surrounds one or more parameters and passes them as parameters to a function outside the parentheses.

Usage 1: Controls the order in which the operators execute in the expression. Parentheses override the normal precedence order and cause the expressions within the parentheses to be evaluated first. When parentheses are nested, the contents of the innermost parentheses are evaluated before the contents of the outer ones.

Usage 2: Evaluates a series of expressions, separated by commas, in sequence, and returns the result of the final expression.

Usage 3: Surrounds one or more parameters and passes them as parameters to the function outside the parentheses.
Availability: ActionScript 1.0; Flash Player 4

Operands
expression1 : Object - Numbers, strings, variables, or text.
expression2 : Object - Numbers, strings, variables, or text.
function : Function - The function to be performed on the contents of the parentheses.
parameter1...parameterN : Object - A series of parameters to execute before the results are passed as parameters to the function outside the parentheses.

Example
Usage 1: The following statements show the use of parentheses to control the order in which expressions are executed (the value of each expression appears in the Output panel):
trace((2 + 3)*(4 + 5)); // Output: 45
trace((2 + 3) * (4 + 5)); // Output: 45
trace(2 + (3 * (4 + 5))); // // writes 29
trace(2 + (3 * (4 + 5))); // Output: 29
trace(2+(3*4)+5); // writes 19
trace(2 + (3 * 4) + 5); // Output: 19

Usage 2: The following example evaluates the function foo(), and then the function bar(), and returns the result of the expression a + b:
var a:Number = 1;
var b:Number = 2;
function foo() { a += b; }
function bar() { b *= 10; }
trace((foo(), bar(), a + b)); // outputs 23

Usage 3: The following example shows the use of parentheses with functions:
var today:Date = new Date();
trace(today.getFullYear()); // traces current year
function traceParameter(param):Void { trace(param); }
traceParameter(2 * 2); //traces 4
2883  Foros Generales / Noticias / Re: WhatsApp lanza un concurso: 50.000 dólares para combatir las ‘fake news’ en: 8 Julio 2018, 14:43 pm
Citar
y de paso de gratis, porque no creo que que el grupo de ingenieros que trabajar para mark zuckerberg cobren 50 mil dolares al año.

mark si quieres atraer gente talentosa que resuelva tus problemas, no ofrezcas bonos irrisorios, ofrece porcentajes y acciones de la compañía, para que veas que te lo resuelven en semanas!!!
Eso mismo iba a decir... pero claro, s ehan curado en salud...

Citar
es un llamamiento a académicos y aficionados, para que presenten un proyecto de investigación
Es decir ellos quieren tu idea, y ya ellos luego la patentan y la explotan...

Otra cosa que no soporto, es la nomenclatura 'millonaria' inglesa, mal traducida...
con nada menos que 1,5 billones de cuentas de usuarios
En el mundo somo alrededor de 10mil millones, así que no se de donde salen esos 1'5 Billones...

2884  Programación / Programación General / Re: aprender a programar en: 8 Julio 2018, 12:42 pm
Scratch, es y seguirá siendo un ¿lenguaje? de juguete... Es válido para quien no sabe nada, y pretende a futuro seguir sin saber nada.

Parte de la filosofía (tan de moda hoy día), de la creciente pereza y vaguedad en el esfuerzo. La vida es intuitiva, pero todo artefacto artificial, ha requerido y requerirá siempre un aprendizaje, al margen de la destreza natural que cada cual posea en dicho campo... Un lenguaje pretendidamente 100% intuititivo, no puede ser si no totalmente insuficiente, porque la vida guste o no tiene complejidades e incluso hay cosas extremedamente simples, pero que el acceso a ellas exige complejidad. Solo cuando el conocimiento está por encima, lo complejo se vuelve simple, pero la experiencia y la intuición, por sí solas no valen... el conocimiento adquirido por el parendizaje es necesario si se quiere acelerar dicho proceso.

Cuando alguien quiere aprender a programar en seriro, es mejor que lo haga así, para toda la vida y entonces cuanto antes se meta a fondo con algún lenguaje 'completo', mejor que mejor...

No hay nada peor que dedicar 4-5 años de tu vida a aprender algo que al final no servirá para nada profesional, y delo que nunca podrás sacar nada en claro a excepción de 'imágenes mentales obtusas'. Más matemáticas, y menos chorradas de click en 500 sitios... programar empieza por saber que quieres hacer y ordenar las cosas para saber cómo hacerlo. Pero para esto segundo, es preciso saber con qué herramientas cuentas y para esto lo mejor es no perder el tiempo y aprenderlo cuanto antes (aunque no sea a fondo, hasta que uno no lo precise, después de todo es inabarcable por nadie)...
2885  Programación / Programación General / Re: ¿que programa me recomiendan usar para este proyecto? en: 8 Julio 2018, 02:19 am
Una vez me dijeron ... VisualBasic, pero que también sería demasiada complicación para un programa tan simple como el que quiero hacer.
¿?¿?¿¿?¿?¿
El que te dijo eso, probablemente no sepa distinguir su mano izquierda del pie derecho.

Si has manejado Excel, Visual Basic, te irá perfecto...
2886  Foros Generales / Foro Libre / Re: (+1 Oculto (s)) - El “por qué” del misterio, y explicación psicológica en: 6 Julio 2018, 22:50 pm
Pués no sé qué resulta más intrigante, si los ocultos, o los visitantes...  :laugh: :laugh: :laugh:

...pareciera que vienen de Orión (o más lejos aún, de "Raticulín"),  :laugh: :laugh: :laugh: :laugh: :laugh:



2887  Foros Generales / Foro Libre / Re: Trump, a su gabinete: "¿No podemos simplemente invadir Venezuela? en: 6 Julio 2018, 21:48 pm
Citar
por otro lado no solo se droga XD el va a nueva york a invadir la casa blanca

mmm... pudiera ser que utilice la palabra 'invadir' como sinónimo de 'cagar en'.... ???

...con la falta de papel higiénico en Venezuela, "la Casa Blanca" debe sonar como a un lugar repleto de rollos de papel higiénico por todas partes, a cada paso un rollo colgando de la pared, descendiendo por el suelo hasta mitad del pasillo... vamos, un paraíso orgíastico, para un cagón.
2888  Programación / Programación C/C++ / Re: Ordenar alfabéticamente una varios string sin hacer un vector o un matriz en: 6 Julio 2018, 21:29 pm
Creas una función que admita como parámetros 2 cadenas, las compara y si B es menor que A, las intercambia.

Código:
string A = Luis 
string B = Andrés
string C = Pedro

invocar Ordenar3Cadenas(A, B, C)
imprimir A
imprimir B
imprimir C

Y aquí las dos funciones...
Código:
// Como son 3 cadenas, la función será invocada 3 veces
Funcion Ordenar3Cadenas(string ref A, string ref B, string ref C)
    Compara(A, B)
    Compara(A, C) // A la salida de aquí, ya se tiene la menor de las 3 en A
    Compara(B, C) // A la salida de aquí, ya están ordenadas las otras dos.
fin funcion

funcion Compara(string ref A, string ref B)
    string tmp

    Si (B < A)
        tmp = A
        A = B
        B = tmp
    fin si
fin funcion

...y listo... prueba con diferentes cadenas y siempre al final imprime el resultado.
2889  Programación / Programación Visual Basic / Re: No puedo utilizar Load Label en PictureBox en: 6 Julio 2018, 19:33 pm
... Como se hace un control de usuario transparente, que sería el que tendría el Picture que tengo donde se dibuja todo, y entonces sería reemplazar en todo el código en nombre del Picture. ...
No es difícil, son solo un cúmulo de condiciones concretas que como mínimo hay que mantener inalterables o bien, los cambios que se hagan deben ser consecuentes...

Mañana que tengo un poco más de tiempo libre, te hago uno con la funcionalidad mínima y adecuada al caso, del que partir...
2890  Programación / Programación Visual Basic / Re: No puedo utilizar Load Label en PictureBox en: 5 Julio 2018, 10:39 am
Al final se me hizo muy tarde...

He visto el vídeo, y aunque sirve para hacerse una ídea d elo que estás haciendo, no aporta detalles sobre el problema. Quiero decir que no recala en ningún momento en el error que reportas.

Te decía que cuando debes utilizar gráficos a mansalva, los gráficos conviene que sean 'dibujados', es decir métodos y no 'controles'. Los controles ocupan espacio de memoria, pero más alla de eso, el uso indiscriminado puede hacerlo lento y caer en el error que te sugrge. estoy convencido que has alcanzado el límite máximo de controles que s epermite para un formulario (ahora mismo no recuerdo cual es, ya que es algo que uno nunca considera que se va a dar y lo acaba olvidando (el valor exacto)).

Para usar métodos gráficos, lo más adecuado es recurrir a las API gráficas que proveen GDI32 o al menos simplemente GDI, indistintamente de que uno se provea sus propios métodos cuando se quiera hacer algo específico que no esté prtevisto, o que no satisfaga por algna razón.
El inconveniente de usar las API, es que evidentemente se necesita aprender a conocerlo y eso lleva su tiempo. Especialmente si uno nunca se ha acercado a usar APIs, puede sonarle a chino, la forma de funcionar y no entender ciertos detalles por que se alejan (de alguna manera), de la forma relativamente sencilla (y a veces tortuosa) en que funcionan las cosas en VB6.

Otro forma, es que sin salirse de vb6, cree uno mismo determinada funcionalidad, por ejemplo crear un control de usuario transparente, que provea no solo funcionalidad gráfica, sino también alguna colección, para almacenar métodos gráficos, entonces de ese modo, un solo control, podría tener por ejemplo 200 métodos gráficos, usando un único control de usuario... y por ejemplo, el control podría contener dibujado toda esa escalera sobre sí, podrías tener luego otro control (otra instancia del mismo control), para la leyenda, o bien otros métodos gráficos en el mismo control...

Asumo que básicamente operas en un entorno 2D... aunque se puede hacer también un entorno 3D, e incluso ir más alla, con raytracing y tal... se sale de la envergadura de ayuda para unos foros, aunque siempre se puede dar orientación si la precisas...

...si el fin de semana saco un poquito de tiempo libre, veo de hacer un control así, bueno me conozco, y al final sé que aunque tenga tiempo libre surgirá algo, así que aprovecho ahora y en un momento te doy alguna orientación que puede servirte de guía...

La colección podría almacenar una estructura (o clase) con los siguientes tipos (así a bote pronto):
Código
  1. Private ColGrPaths            As New Collection
  2. private p_NumGrPaths       As long
  3.  
  4. ' El texto o una polilínea requerirá otro desarrollo, porque el uno exige un string, y el otro múltiples puntos...
  5. Public Type DatosGraficos
  6.    Orden       As Byte     ' punto, línea, rectángulo, círculo, arco, polígono, elipse...
  7.    SubOrden    As Byte     ' si línea, si círculo ó elipse, si arco...
  8.    Activo      As Byte     ' Se dibuja si tiene valor 255, si no se omite (cuando se pide dibujar todo).
  9.    X           As Long     ' cordenadas
  10.    Y           As Long     '   "
  11.    Ancho       As Long     ' medidas (radio en caso de círculo polígono, etc...)
  12.    Alto        As Long     '   "     (aristas en caso de polígono, etc...)
  13.    Color       As Long     ' Color con que se dibuja. Un flag determina si se usa el color por defecto, del control o se delega en el que aquí se designe.
  14.    Grosor      As Byte     ' Grueso de línea "        "      "
  15.    FlagABC     As Byte     ' Modificador de acciones
  16.    Flags       As Long     ' por ejemplo rellenar interior (casos de círculo, elipse, polígono, etc)
  17.    FlagXYZ     As Long     ' modificadores de posicionado, desplazamiento y escala...
  18. End Type
  19.  
  20. ' Dibuja toda la colección almacenada de métodos gráficos... (solo los que estén activos).
  21. Public Sub PathDibujarTodo(Optional ByVal Actualizar As Boolean = True)
  22.    Call PathsDibujar(0, ColGrPaths.Count - 1, Actualizar)
  23. End Sub
  24.  
  25. ' Dibuja de un plumazo todas las órdenes gráficas reclamadas y (si se reclama) acto seguido actualiza la imagen. Si cantidad es un valor negativo, dibuja en orden inverso. Si Cantidad excede el límite se ignora.
  26. Public Sub PathsDibujar(ByVal Desde As Long, ByVal Cantidad As Long, Optional ByVal Actualizar As Boolean = True)
  27.    Dim k As Long, Final As Long
  28.  
  29.    If (EnRango(Desde) = True) Then ' se exige que desde sea un valor 'dentro' de la colección.
  30.        If Cantidad = 0 Then Exit Sub ' nada que dibujar... caso típico que el valor sea el resultado de una expresión.
  31.  
  32.        Final = (Desde + Cantidad)
  33.        If (Cantidad > 0) Then
  34.            If (Final >= ColGrPaths.Count) Then Final = ColGrPaths.Count - 1
  35.  
  36.            For k = Desde To Final
  37.                If (ColGrPaths(k).Activo And c_Activo) Then
  38.                    Dibujar (ColGrPaths(k))
  39.                End If
  40.            Next
  41.        Else
  42.            Final = -Final
  43.  
  44.            For k = Final To Desde Step -1
  45.                If (ColGrPaths(k).Activo And c_Activo) Then
  46.                    Dibujar (ColGrPaths(k))
  47.                End If
  48.            Next
  49.        End If
  50.  
  51.        If (Actualizar = True) Then
  52.            Call GrEndPath ' actualiza la imagen
  53.        End If
  54.    End If
  55. End Sub
  56.  
  57. '...
  58.  
  59.  
  60.  

Dibujar sería una función que simplemente recibe el objeto y mediante un 'select case' invoca a la función específica que se encarga de dibujar la orden específica...

Nota como esta función también es pública, para permitir dibujar una orden que no conste en la colección, peor que a cierto momento pueda interesar.
Lógicamente también podrán invocarse externamente los métodos gráficos, sin necesidad de que existan como un 'objeto'...
Código
  1. Public Sub DibujarOrden(ByRef dg As DatosGraficos)
  2.    With dg
  3.        Select Case .Orden
  4.            Case ORDEN_GRAFICA_LINEA   ' 0 más arriba las que sean más frecuentes de ser dibujadas
  5.                Call Me.GrLinea(.X, .Y, .X + .Ancho, .Y + .Alto, .Color, .Grosor)
  6.            Case ORDEN_GRAFICA_RECTANGULO
  7.            Case ORDEN_GRAFICA_CIRCULO
  8.            Case ORDEN_GRAFICA_POLIGONO
  9.            ' ...
  10.            Case Else             ' orden desconocida...
  11.        End Select
  12.    End With
  13. End Sub
  14.  

Y algunas funciones... en este ejemplo, varias funciones que definen un objeto sin ambigüedad, finalmente invocan al mismo (privado)...
Código
  1. Public Sub GrLinea(Optional ByVal X1 As Variant, Optional ByVal Y1 As Variant, Optional ByVal X2 As Variant, Optional ByVal Y2 As Variant, Optional ByVal Color As Variant, Optional ByVal Ancho As Byte = 1, Optional ByVal AbsolutoOrigen As Boolean = True, Optional ByVal AbsolutoDestino As Boolean = True)
  2.    Call LinRectCaja(X1, Y1, X2, Y2, Color, Ancho, AbsolutoOrigen, AbsolutoDestino)
  3. End Sub
  4.  
  5. Public Sub GrRectangulo(Optional ByVal X1 As Variant, Optional ByVal Y1 As Variant, Optional ByVal X2 As Variant, Optional ByVal Y2 As Variant, Optional ByVal Color As Variant, Optional ByVal Ancho As Byte = 1, Optional ModoFusion As DrawModeConstants = vbCopyPen, Optional ByVal AbsolutoOrigen As Boolean = True, Optional ByVal AbsolutoDestino As Boolean = True)
  6.    Call LinRectCaja(X1, Y1, X2, Y2, Color, Ancho, AbsolutoOrigen, AbsolutoDestino, ModoFusion, True)
  7. End Sub
  8.  
  9. Public Sub GrCaja(Optional ByVal X1 As Variant, Optional ByVal Y1 As Variant, Optional ByVal X2 As Variant, Optional ByVal Y2 As Variant, Optional ByVal Color As Variant, Optional ModoFusion As DrawModeConstants = vbCopyPen, Optional ByVal AbsolutoOrigen As Boolean = True, Optional ByVal AbsolutoDestino As Boolean = True)
  10.    Call LinRectCaja(X1, Y1, X2, Y2, Color, , AbsolutoOrigen, AbsolutoDestino, ModoFusion, True, True)
  11. End Sub
  12.  
  13. ' Resume las 3 funciones previas en una sola.
  14. Private Sub LinRectCaja(Optional ByVal X1 As Variant, Optional ByVal Y1 As Variant, Optional ByVal X2 As Variant, Optional ByVal Y2 As Variant, Optional ByVal Color As Variant, Optional ByVal Ancho As Byte = 1, Optional ByVal AbsolutoOrigen As Boolean = True, Optional ByVal AbsolutoDestino As Boolean = True, Optional ModoFusion As DrawModeConstants = vbCopyPen, Optional ByVal Box As Boolean = False, Optional ByVal Relleno As Boolean = False)
  15.    Dim AnchoPrevio             As Integer
  16.    Dim ModoFusionPrevio        As DrawModeConstants
  17.  
  18.    With PicMask  ' es un objeto oculto, puede ser incluso un picturebox...(no visible)
  19.        AnchoPrevio = .DrawWidth: .DrawWidth = Ancho
  20.        ModoFusionPrevio = .DrawMode: .DrawMode = ModoFusion
  21.  
  22.        ' si se omiten ambos (x1 y x2), se trazará una línea de currentX a 0
  23.        If (IsMissing(X1) = True) Then
  24.            X1 = .CurrentX
  25.        ElseIf (IsMissing(X2) = True) Then
  26.            X2 = .CurrentX
  27.        End If
  28.  
  29.        ' si se omiten ambos (y1 e y2), se trazará una línea de currentY a 0
  30.        If (IsMissing(Y1) = True) Then
  31.            Y1 = .CurrentY
  32.        ElseIf (IsMissing(Y2) = True) Then
  33.            Y2 = .CurrentY
  34.        End If
  35.  
  36.        '
  37.        If (Relleno = True) Then ' exige Boxed también
  38.            If (IsMissing(Color) = True) Then Color = .FillColor
  39.            If (AbsolutoOrigen = True) Then
  40.                If (AbsolutoDestino = True) Then
  41.                    PicMask.Line (X1, Y1)-(X2, Y2), Color, BF
  42.                Else
  43.                    PicMask.Line (X1, Y1)-Step(X2, Y2), Color, BF
  44.                End If
  45.            Else
  46.                If (AbsolutoDestino = True) Then
  47.                    PicMask.Line Step(X1, Y1)-(X2, Y2), Color, BF
  48.                Else
  49.                    PicMask.Line Step(X1, Y1)-Step(X2, Y2), Color, BF
  50.                End If
  51.            End If
  52.        ElseIf (Box = True) Then
  53.            If (IsMissing(Color) = True) Then Color = .ForeColor
  54.            If (AbsolutoOrigen = True) Then
  55.                If (AbsolutoDestino = True) Then
  56.                    PicMask.Line (X1, Y1)-(X2, Y2), Color, B
  57.                Else
  58.                    PicMask.Line (X1, Y1)-Step(X2, Y2), Color, B
  59.                End If
  60.            Else
  61.                If (AbsolutoDestino = True) Then
  62.                    PicMask.Line Step(X1, Y1)-(X2, Y2), Color, B
  63.                Else
  64.                    PicMask.Line Step(X1, Y1)-Step(X2, Y2), Color, B
  65.                End If
  66.            End If
  67.        Else
  68.            If (IsMissing(Color) = True) Then Color = .ForeColor
  69.            If (AbsolutoOrigen = True) Then
  70.                If (AbsolutoDestino = True) Then
  71.                    PicMask.Line (X1, Y1)-(X2, Y2), Color
  72.                Else
  73.                    PicMask.Line (X1, Y1)-Step(X2, Y2), Color
  74.                End If
  75.            Else
  76.                If (AbsolutoDestino = True) Then
  77.                    PicMask.Line Step(X1, Y1)-(X2, Y2), Color
  78.                Else
  79.                    PicMask.Line Step(X1, Y1)-Step(X2, Y2), Color
  80.                End If
  81.            End If
  82.        End If
  83.  
  84.        .DrawWidth = AnchoPrevio
  85.        .DrawMode = ModoFusionPrevio
  86.    End With
  87. End Sub
  88.  

También puede suceder

CurrentX y CurrentY se guardan como propiedades que no aparecen en el visor de propiedades (deben retirarse, para estar disponibles solo en tiempo de ejecución), es adecuado, para trazar por ejemplo polilíneas... Una polilínea, sería simplemente una colección de puntos, + 1 orden gráfica que defina el primer punto, el color, ancho, etc...
Esto te permite obtener donde terminó de dibujar un objeto para (por ejemplo) seguir dibujando en un punto específico, algo que
Código
  1. ' Devuelve o establece las coordenadas verticales para el siguiente método Print o Draw.
  2. Public Property Get CurrentY() As Single
  3.    CurrentY = UserControl.CurrentY
  4. End Property
  5.    Public Property Let CurrentY(ByVal Y As Single)
  6.        UserControl.CurrentY = Y
  7.    End Property
  8.  
  9. ' Devuelve o establece las coordenadas horizontales para el siguiente método Print o Draw.
  10. Public Property Get CurrentX() As Single
  11.    CurrentX = UserControl.CurrentX
  12. End Property
  13.    Public Property Let CurrentX(ByVal X As Single)
  14.        UserControl.CurrentX = X
  15.    End Property
  16.  

Como hablamos de una colección lógicamente hacen falta dos cosas para ello, además operaciones en la colección: añadir, eliminar, vaciar...
Aquí un ejemplo para añadir:
Código
  1. ' Añade los datos de una orden gráfica en la posición indicada y devuelve el valor de dicha posición. Si el índice está fuera de rango, lo añade al final.
  2. ' OJO: No verifica si la orden existe o no, al dibujar, si no existe, o un parámetro no es válido, se ignora... y continúa con el siguiente.
  3. '   Puede ser mejor desde aquí señalar que es erróneo... o devolver false, y el index devolverlo por referencia.
  4. ' DibujarAhora: fuerza a dibujar ahora mismo la orden gráfica, aunque en general es mejor almacenarlas y luego dibujarlas.
  5. Public Function PathsAñadirIndex(ByRef Graf As DatosGraficos, Optional ByVal Index As Long = -1, Optional ByVal DibujarAhora As Boolean = False) As Long
  6.    If ((Index < 0) Or (Index > ColGrPaths.Count)) Then
  7.        Index = (ColGrPaths.Count + 1) ' en ambos casos se añade al final
  8.    End If
  9.  
  10.    Call ColGrPaths.Add(Graf, , Index)
  11.  
  12.    If (DibujarAhora = True) Then
  13.        Call Me.DibujarOrden(Graf)
  14.        RaiseEvent Actualizado
  15.    End If
  16.  
  17.    PathsAñadirIndex = Index
  18. End Function
  19.  
  20.  

También es adecuado contar con otras operaciones menos frecuentes, pero igualmente útiles...
Aquí remplazar (una existente por otra que se entrega), y una que intercambia el orden de dos (el orden almacenado supone el orden en que se dibujan).
Código
  1. ' Remplaza un ítem gráfico (orden), que consta en la colección por otra orden procedente del exterior. Devuelve True, si el íitem existe.
  2. Public Function PathsRemplazar(ByVal Index As Long, ByRef Graf As DatosGraficos) As Boolean
  3.    If (EnRango(Index) = True) Then
  4.        Call ColGrPaths.Add(Graf, , Index)
  5.        Call ColGrPaths.Remove(Index + 1)
  6.        PathsRemplazar = True
  7.    End If
  8. End Function
  9.  
  10. ' Intercambia dos ítems (órdenes gráficas), de posición entre sí. Devuelve True, si ambos ítems existen.
  11. Public Function PathsIntercambiar(ByVal Index As Long, ByVal PorIndex As Long) As Boolean
  12.    Dim g As DatosGraficos
  13.  
  14.    If (EnRango(Index) = True) Then
  15.        If (EnRango(PorIndex) = True) Then
  16.            With ColGrPaths
  17.                g = .Item(Index)
  18.                .Item(Index) = .Item(PorIndex)
  19.                .Item(PorIndex) = g
  20.            End With
  21.            PathsIntercambiar = True
  22.        End If
  23.    End If
  24. End Function
  25.  

También puede suceder que uno no quiera dibujar en orden todo, sino solo ciertas órdenes... puede construirse funciones que recorriendo la colección solo dibuje determinadas funciones, si es complicado y exige ciertos condicioonantes muy variables, se puede reclamar una enumeración de la colección y entonces en la entrega evaluar si debe o no dibujarse:
Código
  1. ' Enumera los ítems de la colección (por evento) desde el índice indicado hasta el final, en la dirección señalada. Es posible cancelar cuando se desee. Cuando llega al último ítem, lo indica expresamente.
  2. Public Function PathsEnumerar(ByVal DesdeIndex As Long, Optional ByVal HaciaAtras As Boolean = False) As Boolean
  3.    Dim k As Long, Cancelar As Boolean, Final As Long
  4.    Dim dir As Long
  5.    Dim g As DatosGraficos
  6.  
  7.    If (EnRango(DesdeIndex) = True) Then
  8.        ' Con solo esto, podemos recorrer la colección enambas direcciones, el bucle apenas sufre cambios.
  9.        If (HaciaAtras = False) Then    ' desde index hasta el final.
  10.            Final = (ColGrPaths.Count - 1): dir = 1
  11.        Else                            ' desde index hasta el 1º
  12.            Final = 2: dir = -1
  13.        End If
  14.  
  15.        ' si el index es el final, no entra en el bucle
  16.        Do While (DesdeIndex <> Final)
  17.            g = ColGrPaths.Item(DesdeIndex)
  18.            RaiseEvent Listado(DesdeIndex, g, Cancelar, False)
  19.            If (Cancelar = True) Then Exit Do
  20.            DesdeIndex = (DesdeIndex + dir)
  21.        Loop
  22.        ' aunque se salga del Do...Loop, sabemos si se canceló porque el índice no llegó a sumar hasta el final.
  23.        '   luego lo enviamos ahora, y ahora da igual que cancele, ya no hay más...
  24.        If (DesdeIndex = Final) Then
  25.            g = ColGrPaths.Item(Final)
  26.            RaiseEvent Listado(Final, g, False, True) ' indicamos que es el final...
  27.        End If
  28.  
  29.        PathsEnumerar = True ' también podría devolver el nº de ítems enviados.
  30.    End If
  31. End Function
  32.  

Se ha mostrado algún evento... el control puede proveer algunos eventos, como cuando termina de redibujartodo, por si se precisa hacer algo desde fuera, como activar algún botón, etc...
Código
  1. ' Ocurre cada vez que se actualiza la Imagen.
  2. Public Event Redibujado()
  3. ' Ocurre cada vez que se actualiza la imagen, cuando se reclama dibujar una sola orden gráfica.
  4. Public Event Actualizado()
  5. ' Ocurre cuando se reclama una peración de Listar Paths (órdenes gráficas), adecuado cuando se deban modificar, algunos ítems.
  6. Public Event Listado(ByVal Indice As Long, ByRef Grafico As DatosGraficos, ByRef Cancelar As Boolean, ByVal Final As Boolean)
  7.  


Con el valor activo, puedes desactivar que un método gráfico no se dibuje la próxima vez, etc...
Como ves, un control así permite almacenar muchos métodos gráficos contiene todos los datos precisos para dibujar, pero no alcanza ni sobrepasa límites impuestos, además permite aislar adecuadamente unos gráficos de otros, por ejemplo un único control podría contener todos los métodos gráficos para dibujar la escalera... añadiendo además por ejemplo una función GrEscala(byval Escala as single), podría tomar toda la colección de métoso y rescalar su 'ancho y alto' o sólo a aqellos métodos que sean de cierto tipo... igualmente moverlos todos de sitio sería desplazar el control, pero mover a determinados objetos de sitio, podría hacer otra función que recorra la colección para añadir restar a las cordenadas un valor específico...

...y fíjate que sin embargo todo ese código, está en VB6 "puro", sin APIs, recurriendo a las APIs, sería más potente... (gráficamente VB6 es bastante pobre, no es esforzaron demasiado durante el diseño de VB, de dotarle de buneas funcionalidades) pero asumo que no dominas el mundo de las API.
Páginas: 1 ... 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 [289] 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 ... 436
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines