• Domingo 22 de Diciembre de 2024, 19:25

Autor Tema:  Re: Problemas Al Dibujar En Un Control  (Leído 1667 veces)

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Problemas Al Dibujar En Un Control
« en: Domingo 9 de Abril de 2006, 14:21 »
0
Hola a todos

Estoy haciendo una aplicacion en la que quiero dibujar sobre un control Panel, el problema que tengo es que al minimizar o poner la ventana en segundo plano se me borran los graficos del panel. He estado mirando por internet y creo que hay que mandarle que dibuje de nuevo lo que habia con el metodo invalidate() pero no me funciona.Aca esta el codigo:

Código: Text
  1.  
  2.  
  3. // Aca dibujo un punto en el panel al clickear con el raton
  4.  
  5.         private void panelMontaje_MouseDown(object sender, MouseEventArgs e)
  6.         {
  7.             if (procRobot == true)
  8.             {
  9.                 Graphics gra = panelMontaje.CreateGraphics();
  10.                 robot.ptoBaseX = e.X;
  11.                 robot.ptoBaseY = e.Y;
  12.                 gra.DrawEllipse(boliRobot, e.X, e.Y, 2, 2);  
  13.             }
  14.         }
  15.  
  16. // Esto es lo que probe para forzar el redraw del panel cuando se recive un evento
  17. // de redibujar el form
  18.  
  19.         private void Form1_Paint(object sender, PaintEventArgs e)
  20.         {
  21.             panelMontaje.Invalidate();      
  22.         }
  23.  
  24.  
  25.  


Si alguien conoce la solucion le estaria agradecido

salu2

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Problemas Al Dibujar En Un Control
« Respuesta #1 en: Domingo 9 de Abril de 2006, 16:19 »
0
hola,
bien prueba con esto, o sea adaptalo:

Código: Text
  1.     public FrmCubo()
  2.     {
  3.       InitializeComponent();
  4.       this.SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint,true);
  5.     }
  6.  

Código: Text
  1. protected override void  OnPaint(PaintEventArgs e)
  2.     {
  3.             if (procRobot == true)
  4.            {
  5.                Graphics gra = panelMontaje.CreateGraphics();
  6.                robot.ptoBaseX = e.X;
  7.                robot.ptoBaseY = e.Y;
  8.                gra.DrawEllipse(boliRobot, e.X, e.Y, 2, 2);  
  9.            }
  10.                  }
  11.  

un tip es que trates  de no crear el dispoditivo grafico cada vez que se instancia el metodo, lo mejor es que lo crees como variable global. Bueno como no tengo donde probarlo, solo te puedo decir que trates de centrar tu atencion en

Código: Text
  1. this.SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint,true);
  2.  

ya que alli es donde esta el meollo del asunto.
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Problemas Al Dibujar En Un Control
« Respuesta #2 en: Domingo 9 de Abril de 2006, 23:41 »
0
Sólo agregar un detalle:

El objeto Graphics encapsula funcionalidades del HDC de la api de windows. Es decir determina donde se dibujará, maneja los objetos para dibujar, las funciones para dibujar, etc. Pero lo que no tiene es una MEMORIA PROPIA para dibujar. Necesitas un objeto bitmap para tener un pedazo de memoria reservado donde dibujar y que nadie más le meta mano.

Cuando dibujas directamente en un control de windows lo que haces es trabajar directamente en memoria de video (lo que es lento por cuestiones de transferencias de memoria RAM-Video) y la desventaja principal es que todo el mundo le mete mano, asi que si mueves tu ventana o mueves otra encima de la parte donde dibujaste pues simplemente se borra.

Asi que la solucion es dibujar primero en un bitmap y luego en el evento OnPaint pasar directamente el bitmap a memoria de video (es decir dibujar el bitmap usango el objeto graphics de tu control de windows para que lo dibuje en el control).

De esta forma cada vez que sea necesario redibujar la imagen se generará el evento onPaint y como el dibujo ya esta guardado en el bitmap lo que harás es mostrarlo nuevamente en pantalla, sin tener que renderizar nuevamente todo, es decir se reducira a un paso rápido de memoria RAM a memoria de video.

P.D.
Esto de pasar de memoria RAM a video se hace con la funcion bitblt del GDI de windows, pero por alguna razón no la pude hacer funcionar y no tuve otro remedio que usar una funcion de .NET para dibujar el bitmap. Esto ultimo no es recomendable por que esas funciones son mucho menos eficientes debido a que están pensadas para efectos más completos como alpha blending, escalamiento, etc. Asi que si pueden hacer funcionar este codigo avisen. ;) :

La idea es esta:

Usar la funcion del GDI BitBlt:

Código: Text
  1.  
  2.   public static class GDI
  3.   {
  4.     [System.Runtime.InteropServices.DllImport("gdi32.dll")]
  5.     internal static extern int BitBlt (
  6.       IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
  7.       IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
  8.   }
  9.  
  10.  

Estas son las constantes para el parametro dwRop (Raster Operation) Notaran que estan definidas para otro lenguaje pero seguro entienden cual es el valor hexadecimal correspondiente.

Código: Text
  1.  
  2.  SRCCOPY = &HCC0020          ' Copies the source rectangle directly to the destination rectangle.
  3.   SRCPAINT = &HEE0086         ' Combines the colors of the source and destination rectangles by using the Boolean OR operator.
  4.   SRCAND = &H8800C6           ' Combines the colors of the source and destination rectangles by using the Boolean AND operator.
  5.   SRCINVERT = &H660046        ' Combines the colors of the source and destination rectangles by using the Boolean XOR operator.
  6.   SRCERASE = &H440328         ' Combines the inverted colors of the destination rectangle with the colors of the source rectangle by using the Boolean AND operator.
  7.   NOTSRCCOPY = &H330008       ' Copies the inverted source rectangle to the destination.
  8.   NOTSRCERASE = &H1100A6      ' Combines the colors of the source and destination rectangles by using the Boolean OR operator and then inverts the resultant color.
  9.   MERGECOPY = &HC000CA        ' Merges the colors of the source rectangle with the brush currently selected in hdcDest, by using the Boolean AND operator.
  10.   MERGEPAINT = &HBB0226       ' Merges the colors of the inverted source rectangle with the colors of the destination rectangle by using the Boolean OR operator.
  11.   PATCOPY = &HF00021          ' Copies the brush currently selected in hdcDest, into the destination bitmap.
  12.   PATPAINT = &HFB0A09         ' Combines the colors of the brush currently selected in hdcDest, with the colors of the inverted source rectangle by using the Boolean OR operator. The result of this operation is combined with the colors of the destination rectangle by using the Boolean OR operator.
  13.   PATINVERT = &H5A0049        ' Combines the colors of the brush currently selected in hdcDest, with the colors of the destination rectangle by using the Boolean XOR operator.
  14.   DSTINVERT = &H550009        ' Inverts the destination rectangle.
  15.   BLACKNESS = &H42            ' Fills the destination rectangle using the color associated with index 0 in the physical palette. (This color is black for the default physical palette.)
  16.   WHITENESS = &HFF0062        ' Fills the destination rectangle using the color associated with index 1 in the physical palette. (This color is white for the default physical palette.)
  17.   NOMIRRORBITMAP = &H80000000 ' Windows 98, Windows 2000: Prevents the bitmap from being mirrored.
  18.   CAPTUREBLT = &H40000000     ' Windows 98, Windows 2000: Includes any windows that are layered on top of your window in the resulting image. By default, the image only contains your window.
  19.  
  20.  

Luego obtener los handles de los objetos que encapsulan el GDI y llamar a la funcion anterior:


Código: Text
  1.  
  2.       IntPtr HdcDst = e.Graphics.GetHdc();
  3.       if (HdcDst != null)
  4.       {
  5.         IntPtr HdcSrc = RenderSurfaceCanvas.GetHdc();
  6.         if (HdcSrc != null)
  7.         {
  8.           //GDI.BitBlt(HdcDst, e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width, e.ClipRectangle.Height, HdcSrc, 0, 0, 0xCC0020);
  9.           GDI.BitBlt(HdcDst, 0, 0, 50, 50, HdcSrc, 0, 0, 0x00CC0020);
  10.           //GDI.BitBlt(HdcDst, 10, 10, 260, 60, HdcSrc, 30, 100, 0xFF0062);
  11.           RenderSurfaceCanvas.ReleaseHdc(HdcSrc);
  12.         }
  13.         e.Graphics.ReleaseHdc(HdcDst);
  14.       }
  15.  
  16.  

Pero no funciona :(, por alguna razón no copia los bytes del origen, incluso funcionan las operaciones para limpiar los bytes destino colocandolos en blanco o negro, pero lo otro no. :(

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Problemas Al Dibujar En Un Control
« Respuesta #3 en: Lunes 10 de Abril de 2006, 16:58 »
0
Citar
El objeto Graphics encapsula funcionalidades del HDC de la api de windows. Es decir determina donde se dibujará, maneja los objetos para dibujar, las funciones para dibujar, etc. Pero lo que no tiene es una MEMORIA PROPIA para dibujar. Necesitas un objeto bitmap para tener un pedazo de memoria reservado donde dibujar y que nadie más le meta mano.

Ya me parecia raro que se borrara lo echo anteriormente al volver a usar la variable Graphics.Gracias por la explicacion Amilius. Usare un bitmap como dices a ver que tal .......

Citar
this.SetStyle(ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint,true);

JuanK ,no logre averiguar de que modo usar esta sentencia.Es para aplicarle al control en cuestion?? Y con ella se me vuelve a dibujar lo que habia??? Gracias ¡¡

JuanK

  • Miembro de ORO
  • ******
  • Mensajes: 5393
  • Nacionalidad: co
    • Ver Perfil
    • http://juank.io
Re: Problemas Al Dibujar En Un Control
« Respuesta #4 en: Lunes 10 de Abril de 2006, 17:04 »
0
Código: Text
  1. JuanK ,no logre averiguar de que modo usar esta sentencia.Es para aplicarle al control en cuestion?? Y con ella se me vuelve a dibujar lo que habia??? Gracias ¡¡
  2.  

Si, se le aplica al conteneor actual
lo he heco con formularios cuan do uso direct 3D y direct Draw, y en efecto vuelve a dibujar todo.
[size=109]Juan Carlos Ruiz Pacheco
[/size]
Microsoft Technical Evangelist
@JuanKRuiz
http://juank.io