Visual Basic Foro
Programación => Visual Basic 6 => Mensaje iniciado por: emaaldaz 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".
(https://i.ibb.co/FqzvVZG/Screenshot-2.png)
(https://i.ibb.co/rvb8Y6F/Video-1614595595-online-video-cutter-com.gif)
-
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.
-
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
pic.Cls
b-Graficamos la grilla (hacemos líneas verticales y horizontales. La cantidad varia por la escala y tamaño de la pantalla.)
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.
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?
-
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
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
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
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.
-
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?
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"
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.
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
(https://i.ibb.co/N26pvnD/0-metodo-nativo.gif)
Método gdi con GdiCreatePath y GdipAddPathLine.
(https://i.ibb.co/8jhzQpj/2-gdi-path.gif)
Método gdi con gdiCreatePen1 y GdipDrawLine
(https://i.ibb.co/6YZdkYX/1-gdi-line.gif)
Estos errores (En el caso de no poder hacer "capas") se solucionarían si pudiera dibujar la grilla mucho mas rápido.
-
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.
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:
(https://i.ibb.co/F4Vm75M/uc-Image-test-autoredraw-true.gif)