Programación General > Visual Basic para principiantes

 Skin Que Muestre El Control Image Vb 6.0

<< < (2/2)

Nebire:
No estoy muy seguro de a qué llamas 'graficar una línea'.... pero por suponer...

Hay otra cosa que debes saber, si te fijas el control image no tiene borde, entonces cuando metemos el control image en un control picturebox justo del mismo tamaño, en efecto puede verse que se tapan algunos pixeles por cada lado, esto es debido a que por defecto el picturebox si tiene borde.

Este marco puede quitarse si se desea estableciendo la propiedad borderstyle: picturebox1.borderstyle=0 ...esto quita el marco y en consecuencia deja ver esa línea de píxeles inferior superior y laterales que tapaba, que son 4 píxeles por cada lado lo que ocupa el 'marco'.

...pero si con graficar quieres decir que antes pintabas una línea en la parte superior del control image (lo que debía hacerse en realidad sobre su contenedor que era el formulario, ahora la situación no ha cambiado, ahora puedes dibujar esa línea sobre el control picturebox directamente. Al respecto hay que saber alguna cosa: Los controles se organizan por capas, que son niveles de profundidad, básicamente se consideran 3 capas (y cada capa puede tener tantos niveles como controles se ponga) . La métodos gráficos están en la capa media, por ejemplo si hacemos un Picture1.Line (0, 0)-(Picture1.Width, Picture1.Height), vbBlue  nos traza una línea azul en diagonal (si no llega de esquina a esquina es porque scalemode no está establecida a vbpixels, los métodos gráficos sólo trabajan con píxeles ellos no entienden los 'twips') si previamente hemos colocado por ejemplo un textbox dentro del picture que cruce la diagonal imaginaria, veríamos que se 'corta' donde se cruza con el textbox. Esto es porque el textbox tiene un nivel de profundidad inferior a los métodos gráficos. es decir está en primer plano. En cambio el control image está en la capa más baja, eso significa que la línea que hicimos atraviesa por encima de esa imagen.

Los controles comunes (aquellos que tienen una propiedad HDC o Handle) son de primer plano, los del fondo son los que no tienen esta propiedad, por ejemplo el control image, el control shape el control line o el control label. y los de la capa media son los métodos gráficos, esto es cuando manipulas píxeles directamente por ejemplo.

--- Código: Text --- print (&#34;Hola&#34;)  print (&#34;Hola 2&#34;);  print (&#34;Hola 3&#34;) ,  form1.line (0,0)-(20,40), vbred  ' coloca un button y mete este codígo dentro de su 'click'Private Sub Command1_Click()    Const colorMax = (2 ^ 24) - 1    Dim colo As Long        Me.Cls            For v = 500 To 2000 Step 20    For k = 1 To 10000 'HScrRayo.Value        colo = colorMax - ((((v * k) Mod colorMax) + k) Mod colorMax)        Form1.PSet (100 + ((v Mod k) * 30), 100 + ((k Mod 30) * (v Mod k))), colo ' vbRed    Next    DoEvents  Next   End Sub ' tambi´´en puedes probar con 'circle'.  
Entonces cuando quieres hacer algo encima de un control debes conocer previamente a qué capa pertenece....

No hay que confundir los métodos gráficos con los controles gráficos, el control line produce un resultado muy parecido al método line, pero el control line es un auténtico control, no se 'borra' al colocar algo encima aunque si se puede tapar, sin embargo existe en memoria, un método gráfico es situar píxeles y olvidarse de ellos, no se hace un 'memorizado' sobre ellos salvo que se establezca la propiedad autoredraw a true del contendor donde están... si se hace eso,  por ejemplo entonces  los controles gráficos se sobreponen sobre los métodos gráficos. es decir se redibujan los controles después del fondo.

Aparte puedes usar el control line y el más polifacético y práctico control shape....
Pero vamos por lo que entiendo que dices tu 'linea' ha sido tapada por el marco del picturebox que son 4 píxeles de perímetro sobre el control... y en cualquier caso cuando antes hacía form1.line ... para colocar una línea sobre el control  image ahora debes hacer picturebox1.line... pero en cualquier caso sigue siendo contendor.line siendo contendor el contendor donde está el objeto. Si en el control picturebox quieres colocar una línea encima del image necesariamente será en el píxel -1, los pixeles de coordenadas negativas no se ven, eso significa que si tu línea tiene pongamos 8 píxeles de grueso, deberás poner tu control image así: image1.top=8, y así desde el píxel 0 hasta el 7 puedes usarlo para poner esa línea. Naturalmente esos pixeles que has despalazado la imagen hacia abajo, debes tenerlas en cuenta para las modificaciones del picturebox (se supone que el picturebox lo ajusta al tamaño de la imagen).

ukyuky:
Muchas Gracias por toda tu ayuda..
Te molesto en una cosa más..
Tengo que dibujar un circulo dentro de un picturebox. Lo hago con el comando picture1.circle(x,y),radio.
Despues tengo que borrar el circulo que realice y hacer otro en otro punto del picturebox.
Mi pregunta..
¿Como hago para borrar el circulo que hice?
¿Como hago para que el circulo este relleno?(Probe con picture1.fillcolor= vbblue . No me lo rellena)

Nebire:
Los métodos gráficos se borran con 'cls' así: picturebox1.cls , pero ojo se borra todo lo que tengas en el picturebox. Para borrar de modo selectivo, por ejemplo un cudrado creado antes, habría que repintar otro encima en el mismo sitio  es decir usando la misma sentencia empleada, pero con algunas características que paso a señalarte...

De entrada vamos a trabajar con un cuadrado relleno, así de paso ves que una línea también se puede convertir en un cuadrado y depaso ves como se rellena que es otra cosa que preguntas.

--- Código: Text --- ' estructura de tipo punto, par de coordenadaspublic type Point     x as single     y as singleend type ' dibujamos un cuadrado dados dos pares de coordenadasPublic sub DibujarCuadrado(origen as point, final as point)      Form1.Line (origen.x, origen.y)-(final.x, final.y), vbRed, BFend sub  
Bien el código anterior podría ser llamado por ejemplo con la siguiente orden...

--- Código: Text ---     ' según tu pantalla modifica estos valores    dim a as point :   a.x=3000 : a.y=6000    dim b as point :   b.x=6000 : b.y=3000    call Dibujarcuadrado(a,b)  Ahora examinamos el código y comentamos....
En dibujarCuadrado, vemos que empleamos el método line, sin embargo al ejecutarlo se genera un cudrado, porqué.... porque se ha añadido el parámetro 'B'  al final de la línea, ese parámetro le indica que con las coordenadas dibuje un cuadrado, si no estuviera b, dibujaría una línea en 'diagonal' (en diagonal si los pares de x o de y no fueran del mismo valor) desde el punto de la coordenada origen al punto de la coordenada destino. Fíjate que en realidad podemos señalar como origen cualquiera de las 4 esquinas y como final la opuesta, en este caso origen es la esquina izquierda baja, para probarlo comenta la línea de código form1.line justo después de 'vbred' y ejecútalo, ahora ves que la misma rutina puede servirte para dibujar cuadrados y líneas con colo modificarla un poco añadiendo un parámetro que indique eso mismo, lo vamos a hacer, porque el código fuente hace eso mismo así se entenderá mejor como actúa.


--- Código: Text --- ' dibujamos un cuadrado dados dos pares de coordenadasPublic sub DibujarCuadrado(origen as point, final as point, optional cuadro as boolean=false)      if cuadro=true then            Form1.Line (origen.x, origen.y)-(final.x, final.y), vbRed, BF      else           Form1.Line (origen.x, origen.y)-(final.x, final.y), vbRed      end ifend sub ' para llamarlo ahora para dibujar la línea... tomando los valores anteriores      call Dibujarcuadrado(a,b) ó también      call Dibujarcuadrado(a,b, false)' para dibujar el cuadrado... se entiende que estas líneas van dentro del código de alguna rutina, por ejemplo de un botón.      call Dibujarcuadrado(a,b,true)  Seguimos... el cuadro podrá haberse rellenado o no. Bien tanto el relleno como el grosor de línea como el estilo de relleno como el color de relleno, se controlan a través del contenedor...

El contenedor además de usar el método gráfico contiene los 'fenes' de 'dispersión' de sus métodos gráficos... veamos cómo; ve a las propiedades del  picturebox donde dibujas cambia el valor de la propiedad drawwidth, por ejemplo a 5 así podrás apreciarlo bien, desde código también podrás cambiarlo por ejemplo: picture1.drawWidth=5 si ahora ejecutas verás que lo que cambia es el grosor de línea de borde del cuadrado o del círculo, es importante saber que cuando el grosor de línea es diferente de 1 algunas de las características que comentaremos a continuación se deshabilitan.

De igual modo modo usar 'fillColor' para elegir el color con que se rellena nuestro cuadro, pero ojo esto depende de otros factores, es decir queda alterado por otras propiedades.... por ejemplo 'FillStyle' . FillStyle por defecto es 'transparent' que es la razñon por la cual nuestro cuadro o círculo no se haya rellenado, si lo cambiamos a 'solid' ya se rellena 'de lo que sea, pero se rellena', pruébalo.

Bien si has probado a cambiar el color en fillcolor verás que 'no obedece', ello es porque nosotros hemos fijado VbRed que es una constante de color para definir el color rojo, cambia si quieres el VBREd del line por 'form1.FillColor', fillcolor es el color por defecto para los métodos gráficos cuando no se especifica color y el color no es obligatorio, si es obligatorio pero se ignora, entonces color es 0, es decir negro.

Más cosas... como borrar de modo selectivo... ya dijimos que si usas cls, se borran todos los métodos gráficos (en realidad redibuja todo el contenedor de nuevo, los píxeles que no constan memorizados por tanto se pierden que es lo que sucede con los métodos gráficos (salvo que tengamos autoredraw a true, que guarda copia del 'fondo' ), bien para borrar de modo selectivo hay que usar algún  método que consista en dejar algo como anteriormente estaba, te explicaré 3 métodos el primero es universal vale para todas las situaciones, es lo que hace el sistema pero nosotros a 'pequeña escala'

método 1: si vamos a cubrir una zona, antes de cubrirla hacemos copia de la sección a ocupar luego la cubrimos como queramos, cuando queramos restaurarla pegamos la copia que hicimos. Esto plantea 1 problema que pasa si hacemos sucesivos cambios en la misma zona... cada vez hacemos una copia de un trozo, eso significa que vamos guardando mucha información... este método si te fijas es lo que se hace para las opciones 'deshacer' de los programas gráficos, para nosotros puede ser un problema si no deseamos tener un control tan férreo , pués nos obligaría a tener un 'historial de copias' en una matriz, dicha matriz de imágenes la tendríamos que usar como cola tipo último en entrar primero en salir, para garantizar que se usa correctamente, sin embargo podríamos hacer trampa en esa cola y poder decidir que podemos usar directamente la del fondo eliminando eso sí el resto, es decir de un plumazo podríamos volver al primer cambio. Tu decides si implementas esto o no, seguramente como principiante no te atrevas, pero toma nota para el futuro. sin embargo si podrás tomar aunque sólo sea la 1ª vez no generar una amtriz, sino solo una.

método 2: El segundo método es más cómodo, se lo dejamos al sistema, pero no tendremos un control tan potente de decisión deberemos adaptarnos y conocer bien como funciona si no nos dará bastante trabajo, pero en principio es muy sencillo de usar. Establece la propiedad picture1.DrawMode=7 (Xor pen), por defecto es 13, CopyPen que es más o menos lo que se ve es lo que hay . Una operación Xor tiene una particularidad muy interesante al ejecutarlo hace algo al ejecutarlo nuevamente sobre el mismo valor anterior con el resultado anterior devuelve el estado anterior, con un ejemplo en palabras (no es exacto, vale, lo que pretendo es que lo entiendas sin perder tiempo en buscar una 'traducción exacta). imagina que tenemos 2 palabras: 'Barranco' y 'Ardgchfkl' , supongamos que al hacer un xor entre ambas palabras nos da este resultado: 'mgjrdisu' bien pués si ahora hacemos un xor entre este resultado y cualquiera de los 2 anteriores obtenemos justamente el otro que no hemos usado, es decir si hacemos xor con:
'mgjrdisu'  xor 'Barranco' = 'Ardgchfkl'  y si hacemos:
'mgjrdisu'  xor 'Ardgchfkl'  = 'Barranco'

Es decir después de un par de xor obtenemos nuevamente una copia exacta del original (ya te he dicho que el ejemplo es sólo para entender el concepto), pués eso es lo que haremos con nuestro DrawMode.. ahora ejecuta de nuevo dibujar el cuadro con fillStyle=0 (sólido), fillcolor y drawwidth como quieras, pero con DrawMode=7, cada 2 ejecuciones verás que se restaura, por tanto podrás mover tu círculo después de restaurado, por tanto es un 'cls' selectivo.

Esta técnica del xor se usa para casi todo, para los 'backBuffer' y en vídeo, donde sólo se redibujan los píxeles que cambian respecto de la imagen anterior, con lo que se redibuja una imagen más rápidamente. Este método conjunto con el anterior produce los mismos resulados que el anterior sólo pero ahorrando memoria empleada a base de un cálculo más complejo, en ocasiones es inevitable que algún píxel 'se pierda' lo cual habrás visto muchas veces en los programas en que algo gráfico cambia y parece que no se restablece... Para evitar estas situaciones el S.O. intenta que no se tenga acceso directo a los controladores de vídeo, y cuando esto deba suceder el S.O. entrega el 'poder' diciendo, eah, la pantalla es toda tuya, haz lo que necesitas... y así se entra en el modo 'pantalla completa' salvaguardando el resto de gráficos aparte, eso evita que éste corrompa a áquel si compartieran buffers en memoria.

método 3: Como todo esto no deja de tener cierta complejidad, es más cómodo usar un control que permite todo esto , un cuadro y un círculo a través de una propiedad, el control shape, el control shape es un control ligero como son los métodos gráficos, pero además posee toda esta funcionalidad de la que hemos estado hablando de forma independiente respecto del contenedor, es decir si antes decíamos picture1.drawWidth=5 porque queríamos que el grosor de un círculo fuera mayor veremos que también las nuevas líneas toman ese ancho, controlarlo implica establecer contínuamente de nuevo el valor, pués todas las acciones comparten el mismo valor, es lógico pues son propiedades y acciones del picturebox, sin embargo quita flexibilidad o mejor dicho añade complicación en un momento dado pudiéramos habernos perdido al no haber guardado el estado de algo en una variable específica. El control shape nos salva de esta complejidad pero con cierto límite... sin embargo todas estas propiedades que hemos descrito se usan por igual con el control shape, podría decirse que el control shape es un 'extracto' de los métodos gráficos, como ya te he explicado someramente sus propiedades solo me falta indicarte que definir un cuadro o un círculo se establece a través de su propiedad shape asi: shape1.shape=2 (óvalado). y finalmente ver que como todos los controles tiene medidas esto es top, left, width y height que son el par de coordenadas que usábamos para dibujar un picture1.line por ejemplo. Un control shape puede actuar como un control line si su porpiedad width  ó heigth (una sola a la vez tiene valor unitario), si nembargo para eso es mejor el conttrol line, el control line si se maneja con pares de coordenadas ya que 'carece' de alto y ancho, así se emplea x1,x2,y1,y2. Se entiende que traducir width y height a una coordenada final no tiene misterios, por eso lo he tratado tal como si fuera en si mismo una coordenada.... una licencia inocente...

Un punto importante cuando usar shape (ó line) y cuando usar métodos gráficos: aunque el control shape (y line) es mucho más cómodo de manejar que y controlar que los métodos gráficos tiene sus límites, por ejemplo si se ha de dibujar 400 cuadrados sin duda no interesa crear 400 controles shape. Imagina la siguiente situación:

coloca un timer en el formulario llámale TimCudros, establece interval a 200 y enabled a true, añade un botón  llamado 'Command1' pega el siguiente código en la ventana de código y ejecútalo....

--- Código: Text ---  Private Sub Command1_Click()    TimCuadros.Enabled = Not TimCuadros.EnabledEnd Sub Private Sub TimCuadros_Timer()    Dim coor(0 To 3) As Single ' esto es x1,x2,y1,y2 en ese orden    Dim veces As Integer, colorRnd As Long    Dim limite As Single   ' límite de ancho o de alto    Dim drawmodo As Byte   ' para cambiar el drawmode del contenedor        ' el número 50 limita el máximo    veces = Int(((50 - 0 + 1) - (1)) * Rnd) ' este si debe estar fuera, signa el bucle        ' estas 2 líneas si se meten dentro del bucle se cambia con cada cuadro dibujado    drawmodo = Int(((15 - 1 + 1) - (1 + 1)) * Rnd + 1)    Me.DrawMode = drawmodo    For v = 1 To veces        For k = 0 To 3   ' tomamos coordenadas aleatroiamente            If k Mod 2 = 0 Then                limite = Me.Width  ' es decir x1 y x2            Else                limite = Me.Height  ' es decir y1 e y2            End If            coor(k) = Int(((limite - 0 + 1) - (1)) * Rnd)        Next        colorRnd = Int((((2 ^ 24 - 1) - 0 + 1) - (1)) * Rnd)                   Form1.Line (coor(0), coor(1))-(coor(2), coor(3)), colorRnd, BF    NextEnd Sub  
Como puedes ver so ejecutaste el código, para cosas donde existe un número incierto de objetos o que es excesivamente grande es mala idea tener controles shape o line o circle, desde luego podríamos meterlos en una matriz para maenjarlo conjuntamente en vez de uno a uno por su nombre, pero que hacemos con ellos si de repente ya no los necesitamos...los podemos eliminar, pero si más tarde los volvemos a necesitar habráque volverlos crear.

Entonces de modo general si un gráfico no tiene un fin muy determinado y es finito en el tiempo es mejor usar métodos graficos, si por ejemplo creamos un contro, activex que tiene una forma rara y queremos darle un sombreado perimetral es mejor usar el método line para dibujarlo que el control line, las líneas no son persistentes, entonces todo lo que tendríamos que hacer es colocar el redibujado en el rutina 'paint' del control activex, cada vez que se redibuje se crearán las líneas, y se redibuja cada vez que se coloca en primer plano o se expone parte de él aemás de cuando lo llamamos explícitamente con control.refresh o desde el código interno al mçétodo 'paint'.

Para terminar... se puede crear una estructura que refleje el comportamiento similar al shape pero usado desde los contendores, esto es ya sabemos que propiedades utiliza el contendor para los métodos gráficos, a saber:

--- Código: Text --- public type MiShape     ' Nombre as string  ' se podría usar para identificarlo por nombre en vez de por índice     DrawMode as DrawModeConstants  ' se pueden usar en la forma vbXorPen...     DrawStyle as DrawStyleConstants     DrawWidth as byte     FillColor as long     FillStyle as FillStyleConstants     X1 as single     X2 as single     Y1 as single     Y2 as single     Operacion as boolean  ' true=dibujar, false=borrar     HdcContenedor as long  '(el HDC del contendor) para saber a quien pertence.end typedim Shapes() as MiShapedim tmp as Mishape   ' para cambios temporales  
Bien con esta estructura y parte de los métodos que ya describimos más arriba podríamos usarlo desde los contendores, para manejar cada línea cicculo ocuadro que manejemos, por ejemplo si queremos dibujar un círculo rellenamos los valores en un índice de la estructura, y llamamos a la rutnina dibujarCirculo (que sería similar a la que pusimos más arriba DibujarCuadro) pero con 1 parámetros más, el índice del control, entonces tendríamos otra rutina que sería dibujarlo en otro lado, esta rutina recibiría el parámetro 'x' que identifica el índice y las nuevas coordenadas y lo que haríamos dentro de esa rutina sería borrar shapes(x) de su ubicación actual  cambiar valores de posición según parámetros entrados y llamar a la rutina de dibujado....

Como ahora nuestro gráficos tiene valores asignados y por tanto hay 'memoria' de ellos podremos ahorrarnos el autoredraw, del contenedor y lo que haríamos sería colocar dentro del evento Paint del formulario un bucle que llamara a redibujar todos los 'objetos' que hay dentro de neustr matriz Shapes()

--- Código: Text --- Private Sub Form_Paint()    Me.Line (3000, 6000)-(6000, 3000), Form2.FillColor, BF ' ejemplo a falta de otra cosa...   for k=0 to ubound(Shapes)       call Dibujar_MiGrafico(k)    ' esta funcion sería para redibujar cuanlquier gráfico en la matriz con sus valores actuales, por tanto le bastaría con usar un identificador, en este caso el índice...   nextEnd Sub  

Claro que todo esto último se haría mejor como una clase para controlar todos sus métodos y no confundirse y mezclarse con el código del formulario, o mejor aún en un control activex, con lo cual ya tendríamos una emulación del control shape pero con la particularidad de que podríamos condicionarlo a nuestras necesidades, por ejemplo para crear polígonos dado el nº de lados.

nota final: los métodos gráficos sólo se rellenan si están cerradas, si por ejemplo usas un arco no se cierra, a no ser que lo 'tapes' con una línea... line se rellena con el parámetro BF, la B indica que es un cuadro no una línea y la F que se rellena...

Navegación

[0] Índice de Mensajes

[*] Página Anterior

Ir a la versión completa