Autor Tema: Copiar y Rotar Graficos con GDI+ en VB6  (Leído 8577 veces)

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

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #15 en: Enero 11, 2017, 05:26:34 pm »
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...



Enlace de descarga:
http://workupload.com/file/cv5YHQA

« última modificación: Enero 11, 2017, 05:29:05 pm por NEBIRE »

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #16 en: Enero 11, 2017, 06:00:36 pm »
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 :)

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #17 en: Enero 11, 2017, 06:08:03 pm »
Ok... cualquier duda, pregunta...

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #18 en: Enero 11, 2017, 06:22:44 pm »
Admirable dedicación NEBIRE si no equivoco hace rato que andas con vb? muy prolijo. felicitaciones.

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #19 en: Enero 11, 2017, 06:38:42 pm »
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???

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #20 en: Enero 11, 2017, 07:35:57 pm »
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...


LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #21 en: Enero 12, 2017, 08:41:18 am »
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
« última modificación: Enero 12, 2017, 08:49:07 am por LeandroA »

TOLO68

  • Kilobyte
  • **
  • Mensajes: 60
  • Reputación: +2/-0
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #22 en: Enero 12, 2017, 02:00:36 pm »
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.

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #23 en: Enero 13, 2017, 03:33:04 pm »
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

Jen

  • Kilobyte
  • **
  • Mensajes: 54
  • Reputación: +2/-0
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #24 en: Enero 14, 2017, 12:44:41 am »
¿ 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






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
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

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 57
  • Reputación: +7/-1
    • Ver Perfil
Re:Copiar y Rotar Graficos con GDI+ en VB6
« Respuesta #25 en: Enero 15, 2017, 06:37:14 am »
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...
« última modificación: Enero 15, 2017, 07:05:21 am por NEBIRE »