Autor Tema: Gdip en capas?  (Leído 1379 veces)

0 Usuarios y 1 Visitante están viendo este tema.

emaaldaz

  • Bit
  • Mensajes: 4
  • Reputación: +0/-0
    • Ver Perfil
Gdip en capas?
« en: Marzo 01, 2021, 10:53:38 am »
Muy buenas a todos, mi nombre es Emanuel. Soy nuevo en el foro.

Estoy trabajando hace poco tiempo en un proyecto que utiliza la librería gdip.
Al final del mensaje voy adjuntar algunas imágenes con la descripción que realizare a continuación.

Me encuentro graficando dentro de un PictureBox una grilla y varias figuras geométricas.
Estas figuras pueden ser arrastradas mediante el calculo de posición x-y con los eventos del mouse.

Hasta aquí todo bien. El problema está en que esta recargando todo el tiempo la imagen y es lo que quiero lograr, pero solo la figura seleccionada.
Es posible graficar en capas? Es decir, dejar la grilla de fondo fija y solo mover un rectangulo?

Si o si necesito que se vea el movimiento del mismo en todo momento, no me sirve tener que dejar de dibujar para luego volver a hacerlo cuando finalice este tipo de "Drag and Drop".




LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +150/-8
    • Ver Perfil
Re:Gdip en capas?
« Respuesta #1 en: Marzo 01, 2021, 04:02:34 pm »
Hola bienvenido al foro, no se que código empleas y como lo estas haciendo pero bien, si vos queres que la grilla quede fija primero dibujas la grilla y luego haces que esa imagen quede como picture del picture, osea ya queda como un fondo para que vos te olvides de dibujarlo, luego cada ves que dibujas la ventanita haces primero picture1.cls y luego pintas la ventana en tu posX, PosY.

de todas formas esto que te sugiero y pintar todo por cada movimiento es casi lo mismo porque el picture hace los mismo internamente, o también podría recomendarte que uses algunos controles como los que hay en el blog (UcImage o LabelPlus) pero no es necesario prescindir de ellos, yo creo que tienes que repintar todo por cada movimiento que hagas, si quieres publica tu código y vemos si se puede optimizar.

Saludos.

emaaldaz

  • Bit
  • Mensajes: 4
  • Reputación: +0/-0
    • Ver Perfil
Re:Gdip en capas?
« Respuesta #2 en: Marzo 01, 2021, 04:56:10 pm »
Gracias por tu respuesta  :) , justo estaba por emplear el ejemplo del ucImage para probar exactamente lo que describías en tu mensaje.

Te explico brevemente lo que hago en este momento. ;D

Trabajo con un PictureBox dentro de un Form.
Tenemos un objeto (ventana) que se grafica por partes (c/u de esos rectángulos tienen una posX-posY y una medida que se obtiene desde una base de datos).

Llamamos al método principal y pasamos como parámetros el PictureBox y el Objeto ventana.

a-Limpiamos el picturebox
Código: [Seleccionar]
pic.Cls

b-Graficamos la grilla (hacemos líneas verticales y horizontales. La cantidad varia por la escala y tamaño de la pantalla.)
Código: [Seleccionar]
Public Function GDI_graficaLinea(ByVal hdc As Long, ByVal X1 As Long, ByVal y1 As Long, ByVal X2 As Long, _
                ByVal y2 As Long, ByVal FirstColor As Long, ByVal SecondColor As Long, ByVal BorderColor As Long, EstiloDeLinea As Long) As Boolean
 
    Dim hGraphics As Long
    Dim hPen As Long, hBrush As Long
    Dim mPath As Long
    Dim mRect As RECTL
    Dim lAttributes As Long
     
    On Error GoTo VerError
   
    InitGDI
   
    If GdipCreateFromHDC(hdc, hGraphics) = 0 Then
        Call GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias)
        'Crea una Path - devuelve el mPath
        If GdipCreatePath(&H0, mPath) = 0 Then
            GdipAddPathLine mPath, X1, y1, X2, y2
            'Define los valores de las variables de la estructura mRect
            With mRect
                .Left = X: .Top = Y: .Width = 100: .Height = 100
            End With
           
            'Determina propiedades de las lineas del Path
            Call GdipCreateLineBrushFromRectI(mRect, ConvertColor(FirstColor, 10), ConvertColor(SecondColor, 30), 3, 3, hBrush)
            'Crea el Pen - trae el hpen
            Call GdipCreatePen1(ConvertColor(BorderColor, 100), 1, &H2, hPen)
           
            If EstiloDeLinea = 0 Then
           
            ElseIf EstiloDeLinea = 1 Then
                Call GdipSetPenDashStyle(hPen, 1)
            End If
           
            'Determina el color de relleno del Path
            GdipFillPath hGraphics, hBrush, mPath
            GdipDrawPath hGraphics, hPen, mPath
           
            'Elimina los h... utilizados
            Call GdipDeleteBrush(hBrush)
            Call GdipDeletePath(mPath)
            Call GdipDeletePen(hPen)
        End If
       
        Call GdipDeleteGraphics(hGraphics)
       
    End If
   
    TerminateGDI

End Function

c-Graficamos cada parte del objeto.

Código: [Seleccionar]
Public Function GDI_graficarectangulo(ByVal hdc As Long, X, Y, Ancho, Alto As Long, orientacion As String, _
                                        FirstColor As Long, SecondColor As Long) As Boolean

    Dim hGraphics As Long
    Dim hPen As Long, hBrush As Long, hBrush2 As Long
    Dim mPath As Long
    Dim mRect As RECTL
    Dim mRect2 As RECTL
    Dim lAttributes As Long
    Dim col(2) As Long
    Dim pos(2) As Single
   
    Dim BorderColor As Long
   
    On Error GoTo VerError
   
   
    BorderColor = &H999999

    InitGDI
   
    'crea un grafico a partir de un hdc
    If GdipCreateFromHDC(hdc, hGraphics) = 0 Then
        'Aplica el modo antialias
        Call GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias)
       
        'Crea una Path - devuelve el mPath
        If GdipCreatePath(&H0, mPath) = 0 Then
           
            GdipAddPathLine mPath, X, Y, X + Ancho, Y
            GdipAddPathLine mPath, X + Ancho, Y, X + Ancho, Y + Alto
            GdipAddPathLine mPath, X + Ancho, Y + Alto, X, Y + Alto
            GdipAddPathLine mPath, X, Y + Alto, X, Y
           
            'Define los valores de las variables de la estructura mRect
            With mRect
                .Left = X: .Top = Y: .Width = 100: .Height = 100
            End With
           
            'Determina propiedades de las lineas del Path
            Call GdipCreateLineBrushFromRectI(mRect, ConvertColor(FirstColor, 100), ConvertColor(FirstColor, 100), LinearGradientModeHorizontal, 0, hBrush)

           
                       
            'Crea el Pen - trae el hpen
            Call GdipCreatePen1(ConvertColor(vbBlack, 100), 1, &H2, hPen)
            Call GdipCreatePen2(hPen, 1, &H2, hBrush)
           
           
            GdipFillPath hGraphics, hBrush, mPath
            GdipDrawPath hGraphics, hPen, mPath
           
            'Elimina los h... utilizados
            Call GdipDeleteBrush(hBrush)
            Call GdipDeletePath(mPath)
            Call GdipDeletePen(hPen)

        End If
        Call GdipDeleteGraphics(hGraphics)
    End If
   
    TerminateGDI
End Function


Esto se repite cada que yo arrastre el mouse dentro de la ventana.
Entonces dibuja muchísimas veces todo y pierdo esa calidad.


Poder graficar como en capas, sin usar otros controles, no es posible verdad?


LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +150/-8
    • Ver Perfil
Re:Gdip en capas?
« Respuesta #3 en: Marzo 01, 2021, 05:43:44 pm »
Bien no se si se podría hacer mas optimo, quizas si se quiere guardar en memoria el Brush  de la cuadricula, pero no creo que sea visual mente notable, si es eso solo, tendría que ser rápido.
una cosa por lo que vi en el Gif que pusiste eso parpadea asi? o es por lo que captura la imagen?, me imagino que estas trabajando con picture1.autoredraw = true para no tener parpadeo?.

cuando te referis a capas lo que supongo es que podes hacer esto
Código: [Seleccionar]
        GdipCreateBitmapFromScan0 Width, Height, 0&, PixelFormat32bppPARGB, ByVal 0&, hImage1
        GdipGetImageGraphicsContext hImage1, hGraphics
        GdipSetSmoothingMode hGraphics, SmoothingModeAntiAlias



eso crea algo asi como un lienzo ahí pintas lo que tu quieres sobre su hGraphics, eso lo mantienes en memoria y  luego pintas sobre el picture con  GdipDrawImageRectRectI

Código: [Seleccionar]
para limpiar la capa utilizas 
Private Declare Function GdipGraphicsClear Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mColor As Long) As long
luego cuando quieres eliminar todo
Código: [Seleccionar]
        GdipDeleteGraphics hGraphics
        GdipDisposeImage hImage1


pero aclaro no se si es mas rapido, al menos para el fondo, ahora si tuvieras muchas ventnaitas.png y las pintas todas en una capa quizás eso seria mas rápido que pintarlas de a una.

emaaldaz

  • Bit
  • Mensajes: 4
  • Reputación: +0/-0
    • Ver Perfil
Re:Gdip en capas?
« Respuesta #4 en: Marzo 03, 2021, 08:50:57 am »
Buenas, después de intentar y hacer unos pequeños test vuelvo a la carga con otras dudas.

Como podría guardar en memoria el brush de la cuadricula?

Citar
Bien no se si se podría hacer mas optimo, quizás si se quiere guardar en memoria el Brush  de la cuadricula, pero no creo que sea visual mente notable, si es eso solo, tendría que ser rápido.

Si, eso parpadea asi porque se esta moviendo la ventana. Y por cada arrastre con el mouse se redibuja todo.
Ejemplo:
a-Se dibuja la grilla (Líneas horizontales y luego verticales una por una)
b-Se dibuja cada parte de la ventana
c-arrastro la ventana con el mouse
Y se vuelven a repetir los pasos por cada que entra al evento del mouse.

Es lo que quiero lograr, mover la ventana pero sin tener que redibujar la grilla. El autoredraw = true no me permite ver ese movimiento en "tiempo real"

Citar
Una cosa por lo que vi en el Gif que pusiste eso parpadea así? o es por lo que captura la imagen?, me imagino que estas trabajando con picture1.autoredraw = true para no tener parpadeo?.


En realidad cuando digo capas, me refiero a la posibilidad de que la grilla quede fija y solo mover la ventana como en una capa superior. Pero no lo veo posible en gdip.

Citar
cuando te referís a capas lo que supongo es que podes hacer esto


Adjunto algunos "test" en la grilla:

Método nativo Picturebox.Line



Método gdi con GdiCreatePath y GdipAddPathLine.



Método gdi con gdiCreatePen1 y GdipDrawLine




Estos errores (En el caso de no poder hacer "capas") se solucionarían si pudiera dibujar la grilla mucho mas rápido.

emaaldaz

  • Bit
  • Mensajes: 4
  • Reputación: +0/-0
    • Ver Perfil
Re:Gdip en capas?
« Respuesta #5 en: Marzo 03, 2021, 10:19:26 am »
Esta respuesta corresponde a la primer sugerencia sobre usar un control, en este caso ucImage; Al mismo le cargo una imagen de la ventana y programo el arrastre.

Dibujo la grilla de fondo, asigno autoredraw = true y muevo el control ucImage.

Lo que sucede es que se me borra el fondo (grilla) cuando arrastro el control por todo el formulario.

Citar
de todas formas esto que te sugiero y pintar todo por cada movimiento es casi lo mismo porque el picture hace los mismo internamente, o también podría recomendarte que uses algunos controles como los que hay en el blog (UcImage o LabelPlus) pero no es necesario prescindir de ellos, yo creo que tienes que repintar todo por cada movimiento que hagas, si quieres publica tu código y vemos si se puede optimizar.



Adjunto ejemplo gif: