Visual Basic Foro
Programación => Visual Basic 6 => Mensaje iniciado por: TOLO68 en Enero 05, 2017, 07:43:02 pm
-
Hola a todos, me llamo Tolo
y esta es mi primera pregunta en el foro
Estoy trabajando con graficos gdi+ en vb6 y ya he probado varias cosas pero no lo consigo.
en un picturebox cargo una imagen con:
GdipLoadImageFromFile StrPtr(App.Path & "\gauge_speedometer_chart_2.png"), img
GdipGetImageWidth img, w
GdipGetImageHeight img, h
luego la puedo rotar con:
GdipRotateWorldTransform g, Angle, MatrixOrderAppend
GdipTranslateWorldTransform g, X, Y, MatrixOrderAppend
pero la imagen es un archivo....
Mi pregunta es
se puede por ejemplo rotar una imagen de un picturebox que la he dibujado yo previamente con las funciones por ejemplo de:
GdipDrawLine
es decir en el picturebox dibujo una linea o elipse o lo que sea y despues rotar esta linea o todo lo que este dibujado en el picturebox, y si es posible, me gustaria rotar solo lo ke es la linea, o sea que el color de fondo del picturebox como si fuera transparente, porke esta linea seguramente la tengo que rotar en otro picturebox que tiene una imagen de fondo.
Gracias de antemano y espero que me puedan ayudar
ya que por google he visto que en esta web y en la de LaVolpe sabeis bastante sobre GDI+
-
Hola bienvenido al foro, para hacer lo que quieres el picture no serviria ya que no es transparente, para eso tenes que crear un lienzo transparente y dibujar sobre el y luego lo dibujas al picture con rotación, en este momento no recuerdo si se podía hacer directamente con alguna Api de GDI+ (casi seguro que si hay) pero bien, puedes utilizar el api CreateDIBSection() y en el cual puedes dibujar lineas y elipses
de todas formas te doy un consejo rotar una linea es mucho mas rapido que rortar una imagen por lo que no se hasta que punto te conviene hacer todo esto.
pero bueno quizas si en tu caso es necesario rotar como imagen, si conoces a LaVolpe el hizo una suite de clases si mal no recuerdo era algo de c32bppDIB.cls donde podes manipular bien lienzos, rotar imagen etc todo con GDI+
un link que te puede orientar https://autohotkey.com/board/topic/37927-help-with-gdi-clearing-image-after-updating/
cualquier duda preguntas, saludos.
-
¿ Y que es lo que quieres hacer ?, en este ejemplo basado de uno de codeproject, cada frame de la rotacion del pie se dibuja completo en un buffer y luego se copia en el usercontrol, lo que da la sensacion de que esta rotando, el control dibuja pie 2d y 3d
(https://s30.postimg.org/pb9m3jzzh/pie2d.png) (https://postimg.org/image/pb9m3jzzh/)
(https://s24.postimg.org/e4dol8jtt/pie3d.png) (https://postimg.org/image/e4dol8jtt/)
http://www.mediafire.com/file/dbjcqyma8in01e0/PieControl.rar (http://www.mediafire.com/file/dbjcqyma8in01e0/PieControl.rar)
Para trabajar gdiplus en vb6 utilizo una clase wrapper de psc, que te permite usar gdiplus casi con la misma sintaxis de .net
GpGDIPlus Wrapper v1.0---Using GDI+ From VB
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=45451&lngWId=1 (http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=45451&lngWId=1)
-
Hola de nuevo, os explico lo que quiero hacer, tenia de hace tiempo unos controles OCX desarrollados en VB que la web la visito casi todos los paises del mundo, y tuve un promedio de 1500 descargas por control. la mayoria de ellos eran para audio (knob, vumeter, switch, etc...)
Ahora los estoy mejorando con GDI+, mas que nada para lo de poder dibujar con antialias y algunas cosas mas, como la velocidad
He mirado el ejemplo este Virgil Tracy pero demasiado codigo, lo mismo que el control de LaVolpe que no se como se llama, que tambien tiene un monton de cosas que ni voy a usar, aunque bueno si que es, jejejejejejej
un ejemplo seria el vumeter analogico de estos de aguja
primero creo el fondo en un PictureBox_1
(https://s28.postimg.org/7s3to3s6x/Vumeter_Analogic.gif) (https://postimg.org/image/7s3to3s6x/)
seria el vumeter sin la aguja, por ejemplo un picturebox negro, con un Arc en GDI+
verde y rojo(eso ya se como hacerlo), ejejejej
Y aqui viene la pregunta
en el mismo usercontrol hay otro picturebox_2 con el color background blanco,donde dibujo una linea roja(por poner un ejemplo) con el metodo line.......
entonces tengo que pasar esta linea roja al otro picturebox_1 donde esta el fondo del vumeter, pero del picturebox_2 donde cojo la aguja, solo quiero esta linea sin el fondo, o sea que tendria que decirle, el color blanco quiero que sea transparente al copiarla en el picturebox_1 que contiene el fondo, para que al pasarla al solo se vea la linea, pero esta linea la quiero por ej mover o rotar una vez copiada, no se si me he explicado bien, esto lo he podido hacer teniendo la linea en un archivo gif o png, entonces cargo este archivo en el mismo picturebox que el fondo y, la puedo mover y rotar.
ojo.... cuando he creado el fondo hago picturebox.picture=picturebox.image, asi me conserva el fondo, y cuando hago el picturebox.cls al tener que mover la linea redibujandola el fondo no se borra, supongo que esto ya lo sabiais pero es para que entendais un poco mas lo que os digo, esto no creo que sea muy dificil, pero lo necesitare para bastantes controles.
porque otra manera que habia pensado es crear la linea en un picturebox, guardar esta imagen en un archivo con el color blanco como transparente, y luego cargarla en el PictureBox_1, pero no me agrada demasiado.
en resumen........
PictureBox_1 = Dibujo el Fondo
PictureBox_2 = Dibujo la Aguja(linea roja con fondo blanco)
Copio PictureBox_2 (sin el fondo blanco), al PictureBox_1. (Como si hiciera una mascara)
Mover o rotar el PictureBox_2 sobre el PictureBox_1
por cierto se pueden subir archivos zip en el foro????, porque si acaso subiria uno con el codigo fuente minimo si os fuera mejor para verlo
muchas gracias, seguire investigando, jejejejej.
ahhhhhhh, y feliz año nuevo!!!!!!!!
-
Bien, al parecer tú simplemente quieres rotar una línea y nada más...
Entonces simplemente haces uso de picture.line y todo lo que necesitas es rotar el punto de destino (si el de origen permanece en el radio, ese no hace falta rotarlo). Por tanto, es suficiente con cambiar el punto de destino conforme al ángulo que se requiera.
Eso sí, las líneas de VB, aparecen serradas, por lo que si quieres más calidad, debieras dibujarla en un backbuffer, y con GDI aplicarle un antialias (si conviene) y luego 'blit'arlo al destino... también con GDI.
Esto conlleva, que ya que vas a usar GDI (incluso GDI+) y un backbuffer, tengas una clase para permitir todo el trabajo y no solo la línea... es más trabajo preparatroio, pero la ventaja es que luego te valdrá para sucesivos proyectos.
Si la línea es de solo 1 ó 2 píxels de ancho, no se aprecia el aserramiento...
Código para rotar un punto:
Es importante notar el sentido de avance de los grados en sentido antihorario... y la corrección hecha para hacerlo al revés...
En un form, coloca lo siguientes objetos:
1 picturebox, 1 Scrollbar vertical u horizontal, 1 timer y un checkbox y disponlo tal como se aprecia en la imagen (más o menos)
(http://i65.tinypic.com/30ndhmw.png)
' nuestras variables
Dim Xo As Long ' x origen
Dim Yo As Long ' Y origen
Dim Xd As Long ' X destino
Dim Yd As Long ' Y destion
Dim Dxy As Long ' desplazamiento X e Y
' Las cordenadas destino del punto final de la línea corta del circulo pequeño
Dim dx As Long
Dim dy As Long
' Giro es el valor actual de partes del todal en que subdividamos el círculo:
' un valor entre 0 y MaxPartesPorGiro
Dim giro As Integer ' un valor entre 0 y 359, pero podría ser entre 0 y 100 o 0 y 150000... especifica las subdivisiones para completar una vuelta completa
Const MaxPartesPorGiro As Long = 360 ' este valor debe ser el límite del scroll...
Const naranja As Long = &H80FF& ' es el color para dibujar nuestra 'naranja'.
Const Pitag2 As Double = (2 * 3.14159265358979) ' la constante pitagórica *2 = 6'28 aprox.
' el chackbox activa y desactiva el timer, que es donde se eejcuta la rutina de calculo y dibujado
Private Sub Check1_Click()
If Check1.Value = 0 Then
Check1.Caption = "Rotar"
Else
Check1.Caption = "Parar"
End If
Timer1.Enabled = Not Timer1.Enabled
End Sub
' al crear el formulario establecemos los valores iniciales
Private Sub Form_Load()
Timer1.Enabled = False ' paramos el timer y le damos un valor rápido al intérvalo...
Timer1.Interval = 1
VScroll1.Max = (MaxPartesPorGiro - 1) ' limitamos nuestro scroll con la misma cantidad de pasos que queremos que dé para una vuelta completa de la 'naranaja'
VScroll1.LargeChange = 10
' dividimos el picturebox en 400 partes de ancho y alto, si el picturebox no es cuadrado del todo, los giros tendrán forma de elipse.... prueba a modificar el tamaño para verificarlo..
Picture1.Scale (-400, -400)-(400, 400)
With Picture1
.DrawWidth = 4 ' un grosor grande para que sea más perceptible a la vista
.BackColor = vbBlack
.AutoRedraw = True ' evitaremnos demasiados parpadeos... pero no todos.
End With
Xo = 80 ' nuestra naranja NO ESTÁ en el centro del mundo. por tanto nuestra rotación es alrededor del mundo, no sobre su propio eje. (con un punto tampoco lo notaríamos, si girara sobre su eje) --- he añadido también una línea y más cosas... para que lo estudies bien...
Yo = 80
Dxy = (80 / 2) ' la mitad del valor previo
dx = 30: dy = 30
Me.Show ' antes que nada lo dibujamos todo para que se vea donde está colocado inicialmente cada cosa...
Call Timer1_Timer
End Sub
' cuando no actúa el timer, podemos rotar manualmente, paso a paso la línea y la 'naranja'
Private Sub VScroll1_Change()
giro = VScroll1.Value
Call Timer1_Timer
End Sub
' por fin nuestra rutina de cálculo y dibujado
Private Sub Timer1_Timer()
Dim tmp As Long
Dim Radian As Double ' o single, para no despreciar decimales, aunque aquí nuestro 'mundo' (el picturebox) es entero
Picture1.Cls ' borramos el picturebox (a lo bruto, es un proyecto de ejemplo), sería más correcto borrar solo la línea y el punto que cambian, ...usando adecuadamente Drawmode con valor XOR, y redibujando en el mismo sitio, se consigue.
' Rotación en el centro del picture: Aquí se rota a lo largo de una línea recta imaginaria (el punto final de la línea)
' Estos objetos se dibujan en el centro del picture, nota, como aquí: Xo y Yo, desaparecen del cálculo de cordenadas del destino, se usan dX y dY y se preservan entre llamadas...
Radian = ((Pitag2 / 360) * giro) ' calculamos el ángulo (en radianes)
tmp = Cos(Radian) * dx + Sin(Radian) * dy ' calculamos la cordenada x de destino
Yd = Cos(Radian) * dy - Sin(Radian) * dx ' calculamos la cordenada y de destino
dx = tmp ' dx, no puede ser alterada pués debe usarse el valor de entrada tras serle asignado un nuevo valor.
' dibujamos un círculo, como referencia visual
Picture1.Circle (0, 0), 80, vbBlue
' dibujamos una línea desde el centro hacia una línea recta horizontal imaginaria...
Picture1.Line (0, 0)-(dx + 10, dy + 10), vbRed
' este punto en el centro del picture, cordenadas 0,0 encima de todo, para verlo claro.
Picture1.PSet (0, 0), vbGreen
' Rotación LOCAL respecto de una cordenada dada... (es decir no está en el centro del 'UNIVERSO')
' OJO: 'Xo' y 'Yo' se han fijado en 80... al inicio.
Radian = ((Pitag2 / 360) * (MaxPartesPorGiro - giro)) ' calculamos el ángulo (en radianes)
Xd = Cos(Radian) * Xo + Sin(Radian) * Yo ' calculamos la cordenada x de destino
Yd = Cos(Radian) * Yo - Sin(Radian) * Xo ' calculamos la cordenada y de destino
' OJO: tanto el círculo como la línea y el punto están desplazados, ya que VB, condiera los valores de dibujado en 0,0
' entonces para centrar nuestros 3 objetos consigo mismos, debemos dibujar todos desplazados 40puntos de escala
' (mirar unas líneas más arriba la nota sobre Xo y Yo)
' dibujamos un círculo, como referencia visual
Picture1.Circle (Dxy, Dxy), 140, vbBlue
' dibujamos una línea desde el centro hacia un punto en el círculo...
Picture1.Line (Dxy, Dxy)-(Xd + Dxy, Yd + Dxy), vbWhite
' dibujamos nuestra naranja, le hemos añadido a 'X' e 'Y' 40, porque es la mitad de 80 , la distancia a la que se encuentra del centro, para que sea una rotación concéntrica, sino sería describiría el círculo desplazado respecto delcentro del mundo... prueba quitando los valores...
Picture1.PSet (Xd + Dxy, Yd + Dxy), naranja
' aumentamos el giro para el próximo ciclo. Nota como truncamos el valor para que nunca exceda, y regrese al origen después del final...
giro = (giro + 1) Mod MaxPartesPorGiro ' 360 actualmente. ' Esto sirve solo cuando actúa el timer y realiza el giro de modo automático...
End Sub
Pulsa f5 y desliza el scroll con el ratón, o bien activa el checkbox... para que opere el timer automáticamente...
Nota que el parpadeo se ha reducido notablemente con la propiedad autoredraw a True, del picturebox, es causa de no usar un backbuffer, no existe una sincronización... y ciertamente usando VB6, requiere además una función antialias para suavizar las líneas... pero para lo que necesitas, te vale...
son apenas 7 líneas de código... el equivalente a tu código, sería la línea que va girando como el reloj, sobre el círculo...
Como puedes ver, ahora si dibujamos una línea, con origen en las cordenadas 0,0 y destino en el punto, hacemos lo que quieres, solo te falta delimitar el ángulo...
' Cordenadas de origen de la línea
Xo = 80
Yo = 80
Dxy = (80 / 2)
' Cálculo del punto final de la línea conforme al ángulo recibido.
Radian = ((Pitag2 / 360) * (MaxPartesPorGiro - giro)) ' calculamos el ángulo (en radianes)
Xd = Cos(Radian) * Xo + Sin(Radian) * Yo ' calculamos la cordenada x de destino
Yd = Cos(Radian) * Yo - Sin(Radian) * Xo ' calculamos la cordenada y de destino
Picture1.Line (Xo, Yo)-(Xo + Xd , Yo + Yd), vbWhite
Lo que te queda por tanto es acotar los límites del ángulo en que se mueve la aguja del búmetro, por tanto practica con el ejemplo del código limitando los valores min y max de VScroll...
-
Hola tal como te dice NEBIRE, no es necesario rotar una imagen se puede hacer tranquilamente dibujando la linea sobre el destino, como te dije anteriormente es muchisimo mas rapdio que rotar un gráfico (excepto que quieras que tu flecha sea una imagen)
ya que buscas el antialias, es conveniente GDI+ hasta para hacer el arco, te voy a pasar un ejemplo pero no me funciona bien la parte de la flecha porque no me llevo bien con las matemáticas (sin, cos) quizás NEBIRE o Virgil Tracy puedan ayudar mas en ese tema.
Option Explicit
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
Private Declare Function GdiplusStartup Lib "gdiplus" (ByRef token As Long, ByRef lpInput As GDIPlusStartupInput, Optional ByRef lpOutput As Any) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdipSetSmoothingMode Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mSmoothingMode As Long) As Long
Private Declare Function GdipDeleteBrush Lib "GdiPlus.dll" (ByVal mBrush As Long) As Long
Private Declare Function GdipFillEllipseI Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mBrush As Long, ByVal mX As Long, ByVal mY As Long, ByVal mWidth As Long, ByVal mHeight As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GdipCreatePath Lib "GdiPlus.dll" (ByVal mBrushMode As Long, ByRef mPath As Long) As Long
Private Declare Function GdipDeletePath Lib "GdiPlus.dll" (ByVal mPath As Long) As Long
Private Declare Function GdipCreateLineBrushFromRectI Lib "GdiPlus.dll" (ByRef mRect As RECTL, ByVal mColor1 As Long, ByVal mColor2 As Long, ByVal mMode As LinearGradientMode, ByVal mWrapMode As WrapMode, ByRef mLineGradient As Long) As Long
Private Declare Function GdipAddPathEllipseI Lib "GdiPlus.dll" (ByVal mPath As Long, ByVal mX As Long, ByVal mY As Long, ByVal mWidth As Long, ByVal mHeight As Long) As Long
Private Declare Function GdipSetPathGradientCenterColor Lib "GdiPlus.dll" (ByVal mBrush As Long, ByVal mColors As Long) As Long
Private Declare Function GdipSetPathGradientSurroundColorsWithCount Lib "GdiPlus.dll" (ByVal mBrush As Long, ByRef mColor As Long, ByRef mCount As Long) As Long
Private Declare Function GdipCreatePathGradientFromPath Lib "GdiPlus.dll" (ByVal mPath As Long, ByRef mPolyGradient As Long) As Long
Private Declare Function GdipSetLinePresetBlend Lib "GdiPlus.dll" (ByVal mBrush As Long, ByRef mBlend As Long, ByRef mPositions As Single, ByVal mCount As Long) As Long
Private Declare Function OleTranslateColor Lib "oleaut32.dll" (ByVal lOleColor As Long, ByVal lHPalette As Long, ByVal lColorRef As Long) As Long
Private Declare Function GdipAddPathArc Lib "GdiPlus.dll" (ByVal mPath As Long, ByVal mX As Single, ByVal mY As Single, ByVal mWidth As Single, ByVal mHeight As Single, ByVal mStartAngle As Single, ByVal mSweepAngle As Single) As Long
Private Declare Function GdipDrawPath Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mPen As Long, ByVal mPath As Long) As Long
Private Declare Function GdipClearPathMarkers Lib "GdiPlus.dll" (ByVal mPath As Long) As Long
Private Declare Function GdipAddPathLine Lib "GdiPlus.dll" (ByVal mPath As Long, ByVal mX1 As Single, ByVal mY1 As Single, ByVal mX2 As Single, ByVal mY2 As Single) As Long
Private Declare Function GdipCreatePen1 Lib "GdiPlus.dll" (ByVal mColor As Long, ByVal mWidth As Single, ByVal mUnit As Long, ByRef mPen As Long) As Long
Private Declare Function GdipDeletePen Lib "GdiPlus.dll" (ByVal mPen As Long) As Long
Private Declare Function GdipResetPath Lib "GdiPlus.dll" (ByVal mPath As Long) As Long
Private Declare Function GdipSetPenStartCap Lib "GdiPlus.dll" (ByVal mPen As Long, ByVal mStartCap As LineCap) As Long
Private Enum LineCap
LineCapFlat = &H0
LineCapSquare = &H1
LineCapRound = &H2
LineCapTriangle = &H3
LineCapNoAnchor = &H10
LineCapSquareAnchor = &H11
LineCapRoundAnchor = &H12
LineCapDiamondAnchor = &H13
LineCapArrowAnchor = &H14
LineCapCustom = &HFF
LineCapAnchorMask = &HF0
End Enum
Private Type RECTL
Left As Long
Top As Long
Width As Long
Height As Long
End Type
Private Enum LinearGradientMode
LinearGradientModeHorizontal = &H0
LinearGradientModeVertical = &H1
LinearGradientModeForwardDiagonal = &H2
LinearGradientModeBackwardDiagonal = &H3
End Enum
Private Enum WrapMode
WrapModeTile = &H0
WrapModeTileFlipX = &H1
WrapModeTileFlipy = &H2
WrapModeTileFlipXY = &H3
WrapModeClamp = &H4
End Enum
Private Type GDIPlusStartupInput
GdiPlusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Const UnitPixel = &H2
Const PI = 3.14159265359
Private Const SmoothingModeAntiAlias As Long = &H4
Private GdipToken As Long
Private Sub Form_Load()
Call InitGDI
Me.BackColor = vbBlack
Me.ScaleMode = vbPixels
Me.AutoRedraw = True
Call TEST
End Sub
Private Sub TEST()
Dim hGraphics As Long
Dim hBrush As Long
Dim mPath As Long
Dim mRect As RECTL
Dim col(2) As Long
Dim pos(2) As Single
Dim Angle As Single
Dim hPen As Long
Dim X As Single
Dim Y As Single
Dim Radius As Double
Dim AngleInRadians As Double
If GdipCreateFromHDC(hdc, hGraphics) = 0 Then
'aplica el modo antialias
Call GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias)
Call GdipCreatePath(&H0, mPath)
'Arco Verde
Angle = 90
GdipAddPathArc mPath, 50, 50, Me.ScaleWidth - 100, Me.ScaleHeight, -160, Angle + 1
GdipCreatePen1 ConvertColor(vbGreen, 100), 10, UnitPixel, hPen
GdipDrawPath hGraphics, hPen, mPath
GdipDeletePen hPen
GdipResetPath mPath
'Arco Rojo
Angle = 45
GdipAddPathArc mPath, 50, 50, Me.ScaleWidth - 100, Me.ScaleHeight, -160 + 90, Angle + 1
GdipCreatePen1 ConvertColor(vbRed, 100), 10, UnitPixel, hPen
GdipDrawPath hGraphics, hPen, mPath
GdipDeletePen hPen
GdipResetPath mPath
'Linea
'-----------------------------------Esto esta mal------------
Angle = -160 '+ 90
Radius = -(Me.ScaleWidth - 100) / 2
AngleInRadians = Angle * PI / 180
X = Radius * Cos(AngleInRadians)
Radius = -Me.ScaleHeight
Y = Radius * Sin(AngleInRadians)
'--------------------------------------------------------------
GdipAddPathLine mPath, X, Y, Me.ScaleWidth / 2, 200
GdipCreatePen1 ConvertColor(vbWhite, 100), 4, UnitPixel, hPen
GdipSetPenStartCap hPen, LineCapArrowAnchor
GdipDrawPath hGraphics, hPen, mPath
GdipDeletePen hPen
Call GdipDeletePath(mPath)
Call GdipDeleteGraphics(hGraphics)
End If
End Sub
Private Sub Form_Resize()
Cls
Call TEST
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call TerminateGDI
End Sub
' funcion para convertir un color long a un BGRA(Blue, Green, Red, Alpha)
Private Function ConvertColor(Color As Long, Opacity As Long) As Long
Dim BGRA(0 To 3) As Byte
BGRA(3) = CByte((Abs(Opacity) / 100) * 255)
BGRA(0) = ((Color \ &H10000) And &HFF)
BGRA(1) = ((Color \ &H100) And &HFF)
BGRA(2) = (Color And &HFF)
CopyMemory ConvertColor, BGRA(0), 4&
End Function
'Inicia GDI+
Private Sub InitGDI()
Dim GdipStartupInput As GDIPlusStartupInput
GdipStartupInput.GdiPlusVersion = 1&
Call GdiplusStartup(GdipToken, GdipStartupInput, ByVal 0)
End Sub
'Termina GDI+
Private Sub TerminateGDI()
Call GdiplusShutdown(GdipToken)
End Sub
hay muchas apis declaradas de mas, no las quite por si luego te sirven.
-
Leandro, una flechita es un triángulo, y un triángulo son tres puntos, luego basta con reposicionar localmente cada uno de los 3 puntos, conforme a su posición inicial y luego con un floodFill, pintar el interior... Más simple incluso, una vez rotado los puntos, usarlos para crear un polígono relleno, con GDI+...
Otra solución es dibujar un 'pie', esto es un cuadrante de un circulo, con la puta como vértice final de la flecha...
Tolo68, la flechita puedes verla como 3 líneas, cuyos vertices van de uno al otro, es decir
objeto.line (x,y)-(dx,dy), color
objeto.line - (dx1,dy1), color
objeto.line - (x,y), colorYa que sin usar el otro par de cordenadas (sena las de origen o las de destino), refiere a los valores CurrentX y CurrentY actuales, que son las cordenadas gráficas donde se ha pintado por última vez (con métodos gráficos, pset, circle, print... por tanto conociendo los valores de los puntos x,y ... dx,dy ... dx1, dy1 con esto, lo pintas con 3 líneas...
public type Point2D
X as long
Y as long
end type
' Rota un punto (Pt) los grados (G) reclamados en un plano 2D, y devuelve la posición del punto.
' G: grados de giro (ver notas debajo del código)
' Pt: El punto con sus cordenadas. OJO:
public function RotarPunto2D(byval G as single, byref Pt as Point2D) as Point2D
Const Pi2 as double= (2 * 3.14159265358979) `la costante es mejor definirla a nivel del módulo.
Dim Radian as double
Radian = Pi2 / (360 * G)
RotarPunto2D.X = Cos(Radian ) * Pt.X + Sin(Radian ) * Pt.Y
RotarPunto2D.Y = Cos(Radian ) * Pt.Y - Sin(Radian ) * Pt.X
end function
OJO: Si el ángulo recibido, es absoluto (0-359 grados) o relativos (incrementales al valor actual. Esto determina que valores deben pasarse como punto. Es preferible siempre que sea absoluto, por dos razones, 1º el valor del punto a pasar siempre será el mismo lo que simplifica el asunto y 2º evitamos que se pierda precisión, por culpa de los redondedos decimales, ya que se van incrementando errores...
Si el "Angulo es Absoluto", entonces las cordenadas son las iniciales siempre, esto es, el valor que tenían esos puntos cuando tenía un ángulo de 0º... por ejemplo: si se recibe un ángulo de 15º y antes estaba en un ángulo de 124º, ahora estará en 15º (valor absoluto)
Si el "Angulo es Relativo", entonces las cordenadas a enviar son las cordenadas actuales del punto, en este caso, el ángulo implica aumentar o disminuir el que tiene actualemnte, por ejemplo: si antes estaba a 124º y se recibe 15º, ahora tendrá 139º (valor incremental).
El giro debe ser considerado SIEMPRE respecto del centro del eje de cordenadas, es decir cordenadas 0,0. Como en VB las cordenadas 0,0 son la esquina superior izquierda de las ventanas, por tanto a la hora de dibujar, siempre hay que aplicar (sumar) el desplazamiento (Left y Top) del objeto a los valores obtenidos (del punto en cuestión). Si no quieres complicarte con esto último, lo mejos es escalar el contenedor con objeto.Scale(-x,-y)-(x,y) si los valores de x son mayores que los de Y, tienes una elipse, parecida al búmetro de tu imagen.
Dibujar un pie (cuadrante) con Circle, en VB
' Nota, las cordenadas negativas, es para dibujarla sobre el picture del código de arriba, donde el picture esta escalado a (-400,-400)-(400,400), si no es usa escala, hay que darle valores positivos, si no quedara fuera de la zona del picture...
Picture1.Circle (-300, -200), 180, , -0.00002, - pi/2 ' 1.57
-
Hola de nuevo, gracias por responder
creo que me enrolle demasiado la ultima vez, os pego el codigo de lo que estoy usando y al final os digo realmente lo que quiero.
Lo de rotar la linea con Sin y Cos, y otros ejemplos, todo eso ya lo habia hecho en el Vumeter Antiguo
Aqui va el codigo
////////////////////////////////////////////////////////////
Private Sub Form_Load()
"linea.gif" es la linea de la que os hablaba, que es un dibujo creado con paintshop o cualquier otro programa
Form1.Cls
InitGDIPlus
GdipCreateFromHDC Picture1.hDC, graphics
GdipSetSmoothingMode graphics, SmoothingModeAntiAlias
GdipLoadImageFromFile StrPtr("Linea.gif"), img
'----- aqui cargo linea.gif en img
GdipGetImageWidth img, w
GdipGetImageHeight img, h
Rotate HScroll1.Value, graphics, 142, 143
End Sub
------------------------------------------------------------
Private Sub HScroll1_Scroll()
Picture1.Cls
InitGDIPlus
GdipCreateFromHDC Picture1.hDC, graphics
GdipSetSmoothingMode graphics, SmoothingModeAntiAlias
GdipLoadImageFromFile StrPtr("Linea.gif"), img
'----- aqui cargo linea.gif en img
GdipGetImageWidth img, w
GdipGetImageHeight img, h
Rotate HScroll1.Value, graphics, 142, 142
End Sub
------------------------------------------------------------
Sub Rotate(Angle As Single, g As Long, x As Single, y As Integer)
GdipRotateWorldTransform g, Angle, MatrixOrderAppend
GdipTranslateWorldTransform g, x, y, MatrixOrderAppend
GdipDrawImageRect g, img, -w + HScroll2.Value, -h \ 2, w, h
End Sub
------------------------------------------------------------
Private Sub Form_Unload(Cancel As Integer)
TerminateGDIPlus
End Sub
------------------------------------------------------------
Private Sub InitGDIPlus()
Dim uInput As GdiplusStartupInput
uInput.GdiplusVersion = 1
If GdiplusStartup(token, uInput) <> Ok Then
MsgBox "GDI+ ?????????????", vbCritical, "InitError"
End
End If
End Sub
------------------------------------------------------------
Private Sub TerminateGDIPlus()
GdipDisposeImage img
GdipDeleteGraphics graphics
GdiplusShutdown token
End Sub
////////////////////////////////////////////////////////////
si probais este codigo y os da algun error no os preocupeis porque estoy en pruebas y le he hecho modificaciones
aqui viene la cuestion
si os fijais en la linea siguiente:
GdipLoadImageFromFile StrPtr("Linea.gif"), img
'----- aqui cargo linea.gif en img
Esta me carga la imagen desde un fichero.
y lo que yo quiero es que la imagen la coja desde otro picturebox que tengo puesto (por ejemplo "PictureBox2" donde yo le dibujo lo que quiero, lineas, circulos o flechas con metodos como picture2.pset(0,0)-(24,65),vbred o picture2.circle(.....)
o sea que quedaria algo asi, pero no se que llamada a gdiplus necesito
por ej
GdipLoadImageFromHdc StrPtr(PictureBox2.hdc), img
la llamada "GdipLoadImageFromHdc" me la he inventado, es para que veais mas o menos lo que quiero
como hacer un BitBlt desde picture2.hdc a picture1.hdc
entonces con esto rotaria lo que tengo dibujado en el PictureBox2 y no la linea.gif
imaginaros que tengo en un picturebox el chasis de un auto visto de lado, y en otro picturebox las ruedas, entonces copio las ruedas al picturebox del auto, y las ruedas las giro con rotate
Otra vez ya me enrolle sin querer jejejejejeje
espero haberme explicado bien
Si puedo os paso un link de un ejemplo parecido pero en GDI normal, no en GDI+
Gracias de antemano
Saludos a todos los del Foro
-
Hola a Todos, Leandro acabo de usar el ejemplo que me has puesto y lo voy a probar, pero te juro que solo abrirlo me mondaba de la risa, porque has hecho el vumeter que parecia un "clon" de la foto que habia enviado, jaajaja, menudo currazo te has pegado!!!!!!!
Gracias
-
Hola Tolo68, no se si ya lo resolviste pero bueno tuve un poco de tiempo y pude hacer lo de la flecha, ademas lo que te pase estaba utilizando Paths y no era necesario ya que se puede trabajar directamente sobre el gráfico.
aca te arme un ejemplo con la flecha funcionando, agrega un hscroll1 en el ejemplo se maneja por % de 1 a 100, después vos lo adaptas a tus necesidades. y lo pasas al usercontrol.
Option Explicit
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, ByRef graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
Private Declare Function GdiplusStartup Lib "gdiplus" (ByRef token As Long, ByRef lpInput As GDIPlusStartupInput, Optional ByRef lpOutput As Any) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdipSetSmoothingMode Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mSmoothingMode As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function OleTranslateColor Lib "oleaut32.dll" (ByVal lOleColor As Long, ByVal lHPalette As Long, ByVal lColorRef As Long) As Long
Private Declare Function GdipCreatePen1 Lib "GdiPlus.dll" (ByVal mColor As Long, ByVal mWidth As Single, ByVal mUnit As Long, ByRef mPen As Long) As Long
Private Declare Function GdipDeletePen Lib "GdiPlus.dll" (ByVal mPen As Long) As Long
Private Declare Function GdipSetPenStartCap Lib "GdiPlus.dll" (ByVal mPen As Long, ByVal mStartCap As Long) As Long
Private Declare Function GdipDrawArc Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mPen As Long, ByVal mX As Single, ByVal mY As Single, ByVal mWidth As Single, ByVal mHeight As Single, ByVal mStartAngle As Single, ByVal mSweepAngle As Single) As Long
Private Declare Function GdipDrawLine Lib "GdiPlus.dll" (ByVal mGraphics As Long, ByVal mPen As Long, ByVal mX1 As Single, ByVal mY1 As Single, ByVal mX2 As Single, ByVal mY2 As Single) As Long
Private Type GDIPlusStartupInput
GdiPlusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Private Const LineCapDiamondAnchor = &H13
Private Const UnitPixel = &H2
Private Const PI = 3.14159265359
Private Const SmoothingModeAntiAlias As Long = &H4
Private GdipToken As Long
Private Sub Form_Load()
Call InitGDI
Me.BackColor = vbBlack
Me.ScaleMode = vbPixels
Me.AutoRedraw = True
HScroll1.Max = 100
Me.Height = Me.Width / 2
Call TEST
End Sub
Private Sub TEST()
Dim hGraphics As Long
Dim Angle As Single
Dim hPen As Long
Dim X As Single
Dim Y As Single
Dim Radian As Single
Dim Percent As Integer
Dim Radio As Single
If GdipCreateFromHDC(hdc, hGraphics) = 0 Then
'aplica el modo antialias
Call GdipSetSmoothingMode(hGraphics, SmoothingModeAntiAlias)
'Arco Verde
Angle = 90 '+ 45
GdipCreatePen1 ConvertColor(vbGreen, 100), 10, UnitPixel, hPen
GdipDrawArc hGraphics, hPen, 50, 50, Me.ScaleWidth - 100, Me.ScaleWidth - 100, -160, Angle + 1
GdipDeletePen hPen
'Arco Rojo
Angle = 45
GdipCreatePen1 ConvertColor(vbRed, 100), 10, UnitPixel, hPen
GdipDrawArc hGraphics, hPen, 50, 50, Me.ScaleWidth - 100, Me.ScaleWidth - 100, -160 + 90, Angle + 1
GdipDeletePen hPen
'Linea
Percent = HScroll1.Value
Angle = 200 + (Percent * 136 / 100)
Radio = (Me.ScaleWidth - 100) / 2
Radian = ((PI * 2) / 360) * Angle
X = Cos(Radian) * Radio
Y = Sin(Radian) * Radio
GdipCreatePen1 ConvertColor(vbWhite, 100), 4, UnitPixel, hPen
GdipSetPenStartCap hPen, LineCapDiamondAnchor
GdipDrawLine hGraphics, hPen, Me.ScaleWidth / 2 + X, Me.ScaleWidth / 2 + Y, Me.ScaleWidth / 2, Me.ScaleWidth / 2
GdipDeletePen hPen
Call GdipDeleteGraphics(hGraphics)
End If
End Sub
Private Sub Form_Resize()
Cls
Call TEST
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call TerminateGDI
End Sub
' funcion para convertir un color long a un BGRA(Blue, Green, Red, Alpha)
Private Function ConvertColor(Color As Long, Opacity As Long) As Long
Dim BGRA(0 To 3) As Byte
BGRA(3) = CByte((Abs(Opacity) / 100) * 255)
BGRA(0) = ((Color \ &H10000) And &HFF)
BGRA(1) = ((Color \ &H100) And &HFF)
BGRA(2) = (Color And &HFF)
CopyMemory ConvertColor, BGRA(0), 4&
End Function
'Inicia GDI+
Private Sub InitGDI()
Dim GdipStartupInput As GDIPlusStartupInput
GdipStartupInput.GdiPlusVersion = 1&
Call GdiplusStartup(GdipToken, GdipStartupInput, ByVal 0)
End Sub
'Termina GDI+
Private Sub TerminateGDI()
Call GdiplusShutdown(GdipToken)
End Sub
Private Sub HScroll1_Change()
Cls
TEST
End Sub
Private Sub HScroll1_Scroll()
Cls
TEST
End Sub
un tips puede que utilizando GDI+ con usercontrols te de algunos problemas en el ide, pero eso tiene solución cualquier cosa pregunta. Saludos.
-
Yo también estuve anoche corrigiendo la línea sobre el código de Leandro y básicamente es poco diferente...
Solo reseñar que yo opté por no borrar con Cls, si no sobrescribir la línea con negro (el color del fondo) y añadí un reborde gris a todo el arco...
El cambio del código respecto de este último código que ha puesto Leandro:
- Comentar todos los Cls, excepto el del Form_resize
- Para rescribir la línea es necesario mantener las cordenadas previas X,Y del extremo de la aguja, luego es necesario sacar los Dim X as single y Dim Y as single, de la sub Test, al módulo...
- El siguiente código va justo antes de dibujar el arco verde:
' Borrar la anterior Aguja un poco más gruesa la aguja que borra
GdipCreatePen1 ConvertColor(vbBlack, 100), 6, UnitPixel, hPen
GdipSetPenStartCap hPen, LineCapDiamondAnchor
GdipDrawLine hGraphics, hPen, ((Me.ScaleWidth / 2) + X), ((Me.ScaleWidth / 2) + Y), (Me.ScaleWidth / 2), (Me.ScaleWidth / 2)
GdipDeletePen hPen
' Arco Gris
Angle = 137 ' Esto es: la suma de los siguientes + un margen por cada extremo
GdipCreatePen1 ConvertColor(&H808080, 100), 14, UnitPixel, hPen
GdipDrawArc hGraphics, hPen, 50, 50, Me.ScaleWidth - 100, Me.ScaleWidth - 100, -160 - 1, Angle + 1
GdipDeletePen hPen
Y Después de la línea:
Call GdipDeleteGraphics(hGraphics)
Requiere un:
Call GdipDeleteGraphics(hGraphics)
Me.Refresh ' de lo contrario no se redibuja...
El efecto de sobrescribir la aguja en la posición previa antes de cambiar a la nueva, tiene un efecto, brillante, debido al antialias cuando va dibuando el blanco sobre fondo negro, que a gran tamaño desmerece, pero a pequeño tamaño resulta más o menos agrabable... Para borrar bien del todo, basta definir un poco más gruesa la brocha (pen), que hace las veces de aguja, por eso se ha puesto a un ancho de 6, puede cambiarse a 4, para ver el efecto descrito...
-
Hola a todos, gracias Leandro y Nebire por haber dedicado vuestro valioso tiempo a ayudarme en estos 2 ultimos codigos, pero siento deciros que todo esto ya lo tenia hecho, jejejej, tanto lo de dibujar el arco rojo y negro(que alli si que era un bitmap), como la linea movil con el sin y cos, de hecho en el control antiguo ya usaba este sistema.
Si buscais en google "rotate plgblt vb6" hasta que veais una foto como esta, podeis descargar el codigo
(https://s30.postimg.org/tmuv8bh71/rotate.jpg) (https://postimg.org/image/tmuv8bh71/)
es de una pagina llamada VBForums.com
Y asi podreis ver lo que quiero, no pongo el link porque no se que pasa que desde casa no puedo entrar en VBForums, pero si en el resto de webs, cosas de la informatica.
os explico un poco antes lo que es
El fondo es un bitmap estatico, la rejilla la dibuja el propio VB, pero en el cuadro negro de arriba a la izquiera yo voy dibujando con el mouse todo ese garabato de lineas que hay, este no rota, pero el contenido de este lo copia al de la derecha con el fondo transparente(haciendo una mascara), y por ultimo copia el de la derecha abajo y alli lo va rotando con un timer que va poniendo los grados.
yo voy dibujando con el mouse en el picturebox negro, que aqui es donde dibujaria
la flecha circulo o mando giratorio tipo knob, a base de codigo(lo del mouse es porque el ejemplo es asi.
realmente quiero hacerlo asi, porque la aguja me la va a dibujar el mismo control, asi la dibuja con el color y forma que yo quiero con metodos line, circle etc, pero.... solo la creo al iniciar el control o redimensionarlo, en un picturebox_1 por ej, y una vez creada la copio del picturebox_1 al picturebox_2 y en el 2 es donde la roto, me explico.
asi podria crear agujas, knobs, o lo que sea
Que esto es lo que no tengo en los primeros codigos que puse, porque la aguja me la carga de un archivo del disco "C:\.....Archivo.gif" que es un dibujo asi
(https://s24.postimg.org/pgokw13cx/Aguja.gif) (https://postimg.org/image/pgokw13cx/)
en resumen, lo que no quiero es dibujar una linea y moverla con coordenadas,
si no crear esta linea en un picturebox, para luego copiarla y rotarla en otro
seria algo como crear un dibujo en una ventana de photoshop, y una vez creado copiarlo a otra ventana y rotarlo, o rotarlo en la primera y copiarlo a la otra ya rotado.
o sea lo que necesito saber es como copiar el contenido el picturebox_1 que he creado yo al picturebox_2, pero con GdiPlus, para que la rotacion tenga antialias.
Bueno ojala entendais mas o menos lo que quiero, aparte lo mejor de este foro es que esta en español, porque yo de ingles poco, jejejejeje
Muchas gracias
-
Ahora si te entendí... Cuando hablabas de GDI+ solo lo quieres usar para asegurarte cierta calidad.
Y si, PlgBlt, es la api ParalelogramoBlt, que puede rotar en 3D una imagen cargada. es la Api, que suele usarse cuando ves esos efectos de 'pasar página' en las imágenes...
Ya veré esta noche de montarte algo sencillo con transparencia (dibujando en el fondo de un picturebox, por ejemplo, aunque insisto que usando un backbuffer y usando GDI, tienes más calidad en el dibujo.
De entrada te comento, que pitando en VB, puedes pasarlo a picturedisp y luego usarlo con APIs, sin problema...
por ejemplo:
public function Dibujo as IpictureDisp
picture1.Line (0,0)-(4000,4000), vbblue,bf ' un rectángulo relleno
picture1.line (120,120)-(3880,3880),vbwhite, bf ' otro rectángulo relleno, dentro del anterior
picture1.line(1900,1900)-(2100,2100),vbred ' un rectangulo dentro del anterior.
Set Dibujo = picture1.Image ' image contiene el gráfico actual.
End sub
Y lo podrías llamar así:
picture1.move(6000) ' apartamos el picturebox, del área donde se pinta en el formulario... (o picture1.left = 6000)
form1.autoredraw=true ' que el form, tenga gráficos persistentes, para que se autoredibuje, cuando algo se coloque encima
Set Form1.picture = Dibujo
Esta noche te miro algo sencillo con transparencia en un contenedor que acepta métodos gráficos... Un usercontrol , es muy buena opción, porque tiene tanto la propiedad Maskpicture, como la propiedad Maskcolor...
-
Muchas gracias NEBIRE, me imagino que has mirado el ejemplo.
Eso es lo que tendria que haber hecho el primer dia de la pregunta, ejejejeje. Bueno voy a seguir con los otros controles que tengo para ver si los voy acabando.
Tengo que hacer los manuales, los PAD, etc... Uno de los mejores es el "Vumeter LED" que cuando lo redimensionas, el mismo se va autocreando, va añadiendo leds y pintandolos segun el color normal o peek, o el "Display HEX" o "Display Matrix", que lo hice con mascaras asi, puedo elegir entre los 16 millones de colores para los digitos y el fondo, con solo 1 bitmap de 2 colores.
Y tambien probare el codigo que me has enviado.
Saludos. :)
-
Hola Tolo68...
Se me ha hecho tarde llegar a casa (en España son ya las 00:40), pero el poquito tiempo que he podido dedicarle, ya está en marcha...
Solo le proveo de unas simples funciones de dibujo luego tu ya lo amplías bajo tus necesidades, incluso mejor si usas funciones GDI, con API... yo para algo rápido simplemente te proveo funciones de VB... pero una vez que veas como está hecho, te será muy fácil extenderlo...
Te montaré un proyecto cargado con dos instancias del control para mostrar su uso...
El código es extremadamente sencillo. De hecho, no llleva ni APIs, ni otro código que replicar las funciones que VB ya posee (eso sí, bajo una perspectiva más cómoda, ya que los métodos gráficos son heredados del viejo QuickBasic y VB, los mantuvo por compatibilidad y nunca los quitó, porque no los sustituyó por nada mejor...)
Bueno, se pueden añadir un par de propiedades para manejar el color deseado... ...podría ser útil y hasta necesario en alguna circunstancia...
-
Aquí subo un proyecto comprimido en rar...
Es un control de Usuario, con transparencia...
Puedes ir dibujando sobre el control de usuario o sobre la máscara (alojada en un picturebox). También puedes cargar una imagen que haga de máscara desde lña propiedad máscara...
Toquetea bastante la interfaz, para ver, ya que e lcomportamiento varía en función de que haya activado...
Por último he añadido, un modo de editor para dibujar con el ratón (o un lápiz óptico, si fuera el caso). Manteniendo el botón del ratón pulsado se entra en el modo de edición, para dibujar con él, al soltar, termina el trazo... Si dibujas con el ratón sobre el control de usuario, se va viendo mientras se pinta, si lo haces sobre la máscara, el dibujo aparece cuando sueltas el ratón...
Hay un método "GrEndPath", que a modo de las API, de windows, "EndRegion", te permite ir acumulando acción y cuando terminas, es cuando se vuelca la imagen al control (en este caso el MaskPicture).
Hay suficiente código, como para investigar en profundidad... Eso sí, sería preferible usar un DC en memoria, en vez de un picturebox, para dibujar la máscara (o sobre ella), con llamadas a la API, pero eso ya queda a tu consideración y esfuerzos...
También incluye el proyecto una imagen con una máscara, que puedes cargar. En ella el color de máscara es un rosa chicle, que rara vez suele formar parte de dibujos... obviamente si cambias el color de máscara, la imagen ya no servirá como máscara...
Las funciones gráficas empiezan todas con 'Gr...' para que aparezcan juntas en el Intellisense...
Modifica el código a tus necesidades...
(http://img.fenixzone.net/i/qg2ldvz.jpeg)
Enlace de descarga:
http://workupload.com/file/cv5YHQA
-
NEBIRE acabo de ver la respuesta con el enlace, aunque aun no he probado el codigo, muchas gracias de todas formas, y ya te digo como me ha ido :)
-
Ok... cualquier duda, pregunta...
-
Admirable dedicación NEBIRE si no equivoco hace rato que andas con vb? muy prolijo. felicitaciones.
-
NEBIRE vaya trabajazo has hechooo!!!!!, muchas gracias, la verdad es que te lo has currado, yo tambien ya hice algo asi para el control Knob, Veo que le has puesto bastantes propiedades y demas.
Pero una preguntita, jejejejej, donde esta lo de antialias ???, porque no veo por ningun lado lo de GDI+ para que haga el antialias. Si acaso a ver si te envio el codigo de lo que tengo hecho hasta ahora con el antialias, para que lo veas, lo del color rosa para la mascara tambien se puede hacer con el negro puro RGB(0,0,0), y si el dibujo tiene que tener un negro lo haces con el RGB(0,0,1) por ejemplo, que se ve negro, pero no es negro, y a partir de aqui todos los colores hacia adelante, asi lo tienes al principio de la gama de colores.
O tambien el blanco puro RGB(255,255,255), asi sabes que no tienes un color por enmedio de la gama, siempre esta en un extremo
Por cierto no se si te gusta tambien la electronica, pero si te gusta y necesitas ayuda yo tambien se Analogica y Digital :), a ver si pongo algun circuito por el foro en la seccion, he hecho varios circuitos, Amplificadores, Generadores de Señal, etc, incluso me hice un Router CNC, y el software para importar DXF y pasar las coordenadas a los motores paso a paso a traves del puerto LPT
Por cierto, para subir un zip me imagino que primero lo subo en el mismo sitio que tu y luego pongo el link aqui no???
-
Tolo68, no, ahí no hay ninguna función antialias... de otra si lo necesitas te hago un ejemplo sencillo...
Eso si, te lo haría operando sobre los bytes de la imagen directamente, sin llamar siquiera a funciones GDI... (excepto las necesarias para obtener acceso a la imagen y copymemory, por cuestiones de velocidad)...
Tampoco he incluído nada sobre giro... las funciones de worldTransform, son lo suficientemente sencillas de usar y rápidas...
Y no, no es necesario cambiar el color MaskColor... piensa que la máscara se divide en dos colores: maskcolor y el resto, el resto en la máscara se traduce como negro... Es decir una máscara se compone siempre de 2 colores, uno es negro, el otro es el color de máscara, típicamente es blanco....
Lo puso de ese rosa, porque con las mismas funciones dibujamos también en el Usercontrol (la máscara se dibuja sobre un control picturebox, contenido en el usercontrol), para que no te líes, elegí un color que díficilmente vayas a usar.... la propiedad ColorMascara, es para poder albergar más que nada, la posibilidad de tomar una imagen externa (de disco), y que ya tenga su propio color definido como máscara y por tanto poder cambiarlo... De hecho prueba a crear una imagen y decide un color como máscara, pinta en la imagen con ese color y guarda la imagen (procura que si se comprime, no sea modificado el color, ya que si no, el color de máscara se pierde, de ahí que siendo máscara sea mejor limitar la imagen a solo dos colores, el de máscara y el negro. Luego que hayas creado una imagen así, cárgala como Maskpicture (propiedad Mascara en el control)...
Bueno, yo estudié electrónica, pero no lo terminé. Me dí cuentas a tiempo que toda la elctrónica analógicva sería remplazada por la digitasl en los próximos años, y que sería "tiempo perdido", vamos que no iba a ser una profesión para toda la vida, que entraría en declive pocos años más tarde, como así ocurrió... También me apasiona la electrónica digital, pero más a nivel teórico que práctico.
Síii... sube zip, rar, taro cualquier comprimido a una página de descarga y cuelga el enlace... yo creo que todo el mundo, a estas alturas puede descomprimir en cualquier formato...
Leandro, síii... yo pasé desde QuickBasic allá de los 80s, 90s a VB... y aunque NET, me gusta, VB6, me apasiona más... no sé bien por qué, a pesar de algunas carencias graves...
-
bien, no estoy seguro si hay alguna api de GDI+ para hacerlo directamente, probablemente no, tampoco estoy seguro si modificando la paleta se pueda indicar el color transparente, asi que bien yo opte por el siguiente método crear una imagen desde el picture.image con GdipCreateBitmapFromHBITMAP luego obtener el array de bits de esa imagen GdipBitmapLockBits crear una nueva imagen vacia GdipCreateBitmapFromScan0 e ir pasando los bits de un array al otro, y si se encuentra con el color de mascara entonces a la segunda imagen marque 0 para su canal Alfa. con una imagen no muy grande el proceso es rápido pero si hablamos de gigantografías ya se va a poner lento.
http://workupload.com/file/qwXMshp
te aclaro por las, tu imagen (la del picture) no debe tener antialias, porque de lo contrario parte del color de mascara se va a ver, el antialias se lo aplicas al gráfico de destino, insisto hacer esto así es un tanto al cuete, primero se puede hacer lo mismo con GDI común (SetStretchBltMode), asi no creo que le saques mucho provecho al antialias.
yo creo que si queres trabajar con antialias desde el momento que dibujas la linea, tenes que hacerlo en un Dib32argb y no sobre un picture.
Saludos.
PD: si queres ganar velocidad anula esta linea:
GdipSetInterpolationMode hGraphics, InterpolationModeHighQualityBicubic
-
LeandrooooooA!!!!!!!
Eso es justo lo que necesitabaaaaa!!!!!
ademas has hecho lo del color que hace lo transparente (el color rosa), que cuando he abierto el proyecto y he visto el pedazo de cuadro rosa, los ojos me han hecho lo mismo que cuando "miras el sol, sin gafas de sol", jejejejeje.
y lo mejor de todo, es que con pocas lineas de codigo
la rotacion es algo lenta me imagino que es, porque en cada cambio de angulo llama todas las funciones, pero ya se como hacerla mas rapida.
Te paso el codigo que tenia yo que encontre por internet pero cargando un gif,
este rota bien rapido, aunque claro la imagen es mas pequeña
http://workupload.com/file/k7cyY4u
Ahora con tu codigo y el que tenia yo, ya se como hacerlo transparente desde el picturebox y rapido.
Ya sabia yo que esto no podian ser muchas lineas de codigo, solo era entre escoger el .Gif o la imagen que contiene el picturebox
lo de que la image del picture no tenia que tener antialias ya lo sabia tambien, por lo mismo que dices tu, porque se veria todo el borde.
Muchas gracias a TI, NEBIRE, y al foro en general
Por cierto de donde sois si es que puede saberse, yo de Mallorca.
-
hola yo soy de Argentina, aqui la mayoria somo de Americanos, creo que hay pocos españoles en el foro asi que bienvenido.
http://leandroascierto.com/foro/index.php?topic=1013.0
-
¿ Y que es lo que quieres hacer ?, en este ejemplo basado de uno de codeproject, cada frame de la rotacion del pie se dibuja completo en un buffer y luego se copia en el usercontrol, lo que da la sensacion de que esta rotando, el control dibuja pie 2d y 3d
(https://s30.postimg.org/pb9m3jzzh/pie2d.png) (https://postimg.org/image/pb9m3jzzh/)
(https://s24.postimg.org/e4dol8jtt/pie3d.png) (https://postimg.org/image/e4dol8jtt/)
http://www.mediafire.com/file/dbjcqyma8in01e0/PieControl.rar (http://www.mediafire.com/file/dbjcqyma8in01e0/PieControl.rar)
Para trabajar gdiplus en vb6 utilizo una clase wrapper de psc, que te permite usar gdiplus casi con la misma sintaxis de .net
GpGDIPlus Wrapper v1.0---Using GDI+ From VB
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=45451&lngWId=1 (http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=45451&lngWId=1)
the C++ code on CodePage has been updated. Refer to https://www.codeproject.com/Articles/35759/A-Simple-Pie-Chart-Control-Improved-D-Pie-Chart
-
Me gusta el código Leandro, aunque creo que a Tolo68, le bastaba el código anterior...
Después de todo, es que creo que no acaba de entender el concepto de Backbuffer. Así que se lo explico más claramente a ver si lo entiende:
Cuando necesitas dibujar y 'pegar' con transparencia, es lo mismo que dibujar un fondo (llamémosle el picture destino), e ir dibujando encima el resto de cosas y capas, en el orden adecuado (si unas cubren partes de otras), esto último equivale a 'pegar' otro picture con transparencia, pero la diferencia radical es la velocidad que implica, ya que no necesitas pegar todo un picture sobre el otro, si no pequeñas partes.. líneas por aquí y allá, arcos, flechas, númeritos, etc...
Para todo eso, VB6 basta por sí mismo, pero si necesitas algo de más calidad gráfica y también algo más de velocidad, efectivamente recurrir a GDI (o GDI+), es buena solución, pero no cambia el concepto, en nada, sólo cambia por decirlo así, la 'máquina de pintar'...
Entonces si yo fuera tú, me quedaba con el código del proyecto anterior que te puso Leandro... con las siguientes modificaciones:
A - En otro picturebox (mejor si creas un DC en memoria, ya que usas GDI, como ya he comentado otras veces) allí pegas el fondo siempre, dado que el fondo no va a variar, básicamente, puede permanecer en un Ipicturedisp (Picture) o en un hBitmap y la primera operación es pegar ese fondo en el DC en memoria (o picturebox oculto).
B - Cuando salta un evento resize en el usercontrol, CALCULAS y solo calculas, las posiciones de la aguja para los 90º... y los retienes en un array, esto es CordenadasDestino(0 to 89) as Point (el origen taambién se recalcula en es emomento, pero es 1solo punto.
C - Cuando necesitas redibujar la aguja a otra postura (cambió el valor que actúa sobre la aguja, el ángulo), y cuando hay un resize, y cuando se cambia algún aspecto (propiedad) modificable por el cliente, como el BackColor, o el 'ArcColor', etc... se invoca una rutina RedibujarTodo.
D1 - Si el control no tiene autoRedraw, activado, en el método Usercontrol_Paint invocas RedibujarTodo (ya que sin autoRedraw, cuando otro objeto 'pise' el usercontrol se borrará y será necesario redibujarlo.
D2 - Si el control tiene activado AutoRedraw, desde donde se precisa se invoca 'RedibujarTodo' y el método Usercontrol_Paint (el evento Paint del usercontrol), no se necesita.
E - El método, RedibujarTodo, lo que hace entonces es pegar el fondo en un DC del mismo tamaño que el usercontrol, luego pegas los textos de los números 0, 15, 30, 45, 60, 75, 90, 105, 120, 135 sobre el arco (encima de ellos) y quizás unas líneas o unos puntos en esos ángulos. Todo esto incluso podría ser el propio fondo ya predibujdo con un programa gráfico y precargado en un Ipcituredisp y finalmente pegas la aguja sin necesidad de recalcular cada vez su posición (ya se conocen sus puntos de destino, son los mismos precalculados, cuando se redimensiona el control... basta calcular los 136, más el de origen una sola vez, cuando se Redimensiona el usercontrol.
F - Finalmente el backbuffer se pega en el usercontrol de destino (painpicture, BitBlt...)
Esto es rápido, limpio, fácil de modificar y libre de parpadeos.
Y dado que el backbuffer siempre se dibuja fuera de la vista, no se pierde tiempo en actualizar la vista, y cuando se vuelca al usercontrol es una operación muy muy muy rápida, una sola operación gráfica de refresco del control, lo que agiliza mucho la visualización sin sobrecarga... ya que cada vez que pintas algo en un objeto que está visible (en primer plano), debe actualizarse el gráfico al completo, así sea solo un único pixel lo que cambie, por eso, pintar sobre la marcha muchos trazos gráficos, es una sobrecarga inútil, y lastrante... para cosas de poca monta, pruebas... está bien, para algo más 'profesional', no es lo adecuado.
De hecho, si alguna vez has cargado un listbox, con miles de entradas (intenta 100.000), verás que es lentísimo... porque a cada entrada, se actualiza el gráfico (se redibuja al completo el Listbox, lo cual se puede observar sobre las barras de scroll, donde el deslizador debe actualizarse para ajustarse al tamaño y altura en función del alto del listbox y el número de ítems que contiene). Pués bien, si antes de añadir las entradas, se hace un:
ListBox1.visible= false
Y luego se cargan las miles de entradas del listbox, y cuando se hayan cargado todas, de nuevo se hace visible el listbox, se observará que el tiempo de carga se ha reducido drásticamente por 10-100 veces... con los objetos gráficos, sucede lo mismo... para tener en refreshRate alto (como pareces indicar a Leandro, en su último código), es preciso dibujar todo en un backbuffer y volcar luego un único gráfico al lienzo destino.
Dibujar un objeto gráfico, en una zona con un fondo que luego hay que detectar para hacerlo transparente, es mal planteamiento (perfectamente aceptable, para pruebas y demostraciones, pero no para un código definitivo), ya que si se parte del fondo que originalmente habrá de ser, ya no se precisa hacer esa operación (que puede consumir su tiempo)... el color de máscara, es más bien, para cuando se cargan imágenes externas que obviamente no tienen de fondo lo que tu deseas (por ejemplo Sprites), es decir cuando la situación es compleja y tan cambiante que no hay un fondo fijo... y debe recrearse nuevamente cada vez con objetos complejos tal que redibujarlos o calcularlos cada vez, es lento y se opta por tener imágenes ya precalculadas, tal y como se hace en los videojuegos... en tu caso, como solo consta de dos arcos quizás unos textos con números y una aguja, no hay mucha diferencia entre tener ya un fondo gráfico elaborado y cargado en una imagen que trazarlo all actualizar la imagen, en cuanto a rendimiento (si te aclaro que es más rápido pegar una imagen ya que es solo transferencia de memoria, no hay cálculos de por medio)...
También si necesitas más velocidad, olvida operar con single y double, opera con integer o long, poco importa la precisión de un ángulo si por redondeo es un píxele más allá o más acá. Siempre y cuando no sean cálculos acumulativos...
Saludos...