2011-12-14 16 views
11

Deseo mostrar un control en algún mapa de bits fuera de la pantalla para tener acceso rápido a él.Invalidar en el propio mapa de bits

Desafortunadamente Control.DrawToBitmap parece dibujar todo el control al que se llama, incluidos todos sus controles secundarios. Internamente, emite un mensaje WM_PRINT con CC auto proporcionada a un mapa de bits. Este mapa de bits temporal se ajusta luego al mapa de bits proporcionado por el usuario. Inaceptable para mí, prefiero tener este mapa de bits actualizado según sea necesario para que mi rendimiento llegue cuando se necesita el mapa de bits se minimiza.

En el escenario ideal, me gustaría que el formulario se comportara como si estuviera visible en la pantalla (pero no puede ser). Eso significaría que si, por ejemplo, un control tiene su propiedad Text modificada, el formulario se invalidaría parcialmente. La captura de los mensajes/eventos relevantes me permitiría especificar mi propio DC para el formulario que se dibujará, o simplemente BitBlt los formularios DC a mi gusto.

Algunas direcciones que he mirado en:

  • El parámetro PaintEventArgs en OnPaint parece tener un miembro savedGraphicsState, tal vez se podría utilizar para averiguar lo que no requiere invalidar
  • Tener la forma visible pero fuera del área de la pantalla. Sin embargo, los controles no se pintan.
  • llamar manualmente RedrawWindow() en la ventana, la misma historia
+0

No estoy del todo claro sobre por qué 'DrawToBitmap' (el mensaje' WM_PRINT') es inaceptable para su uso. ¿Estás preocupado por * rendimiento *? Es muy poco probable que dibujar en un mapa de bits sea más lento que dibujar en la pantalla. –

+0

Necesito un mecanismo de almacenamiento en búfer. DrawToBitmap pinta todo el control desde cero, mientras que el sistema invalidante utilizado en las ventanas normales solo actualizaría las regiones que realmente cambiaron. –

+0

@Frank, ¿consideró usar Bitblt? http://www.codeproject.com/KB/GDI-plus/Bitblt_wrapper_class.aspx –

Respuesta

1

Creo que hay dos problemas:

  1. enterarse de la zona no válida del control (sin la ayuda de las ventanas)
  2. representación única la parte invalidada

Para el primer número, creo que es en gran parte por su cuenta. Debe hacer un seguimiento de los controles que cambian y tener la contabilidad que necesita actualizarse.

Para el segundo problema, puede intentar enviar el mensaje WM_PRINT usted mismo, y proporcionar un DC que se refiera solo a un pequeño mapa de bits. Las API de DC originales le permitieron compensar y recortar el área de dibujo válida de un HDC. Si tiene mucha suerte, Windows deducirá la región de renderizado del HDC, y si no lo hace, la mayoría de los comandos de renderización que quedan completamente fuera del mapa de bits deberían ser bastante baratos ya que no hay píxeles que deban cambiar.

Debería poder verificar esto imprimiendo en un mapa de bits 1x1 y probar si es más rápido, y/o verificar si la región del clip enviada en WM_PAINT se reduce al tamaño del mapa de bits.

0

creo que va a funcionar, si se clona el control, por lo que se obtiene un control que no se sienta en un formulario y que no tiene controles secundarios:

Control ctrl = ControlFactory.CloneCtrl(this.button3); 
Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height); 
ctrl.DrawToBitmap(bmp, new Rectangle(0, 0, ctrl.Width, ctrl.Height)); 
bmp.Save(@"C:\Users\Oli\Desktop\test.bmp"); 

yo usamos el escrito por lxwde encontrado en The Code Project.

El ControlFactory no es perfecto, pero es lo suficientemente simple y podría mejorarse fácilmente.

+0

Lo siento, no veo cómo esto es relevante. –

+0

Usted dice que desafortunadamente su solución atrae controles de niños. Mi solución no. Lo he intentado con un panel que contiene botones. Solo dibuja el panel en el mapa de bits pero sin los controles secundarios. También funciona cuando el control no está visible en la pantalla. –

+0

Realmente no entiendo lo que estás tratando de lograr. Usted dice: "Me gustaría que el formulario se comportara como si fuera visible en la pantalla (pero no puede ser)". ¿Por qué no puede ser visible en la pantalla? ¿Por qué quieres renderizar un formulario que no está visible en la pantalla? –

0

He hecho un proyecto de ejemplo para usted donde mostré algunos eventos onPaint. Si no puede verlo resuelto de esa manera, simplemente actualice el ejemplo.

¡Recuerdos! OnPaint example

Descargar aquí: http://www.goldengel.ch/temp/OnPaintExample.zip

Private Sub Button1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint 
    Dim bm As New Bitmap(Me.Button1.Width, Me.Button1.Height, PixelFormat.Format32bppRgb) 

    Button1.DrawToBitmap(bm, New Rectangle(0, 15, bm.Width -5, bm.Height+2)) 
    Using gr As Graphics = Graphics.FromImage(bm) 
     gr.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Lime, 0, 0) 
    End Using 
    Me.PictureBox1.BackgroundImageLayout = ImageLayout.Tile 
    Me.PictureBox1.BackgroundImage = bm 

End Sub 
    Public Class myTextBox 
     Inherits System.Windows.Forms.TextBox 


     Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) 
      MyBase.OnPaint(e) 
      e.Graphics.Clear(Color.Yellow) 
      e.Graphics.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Gray, 0, 0) 
     End Sub 

     Public Sub New() 
      SetStyle(ControlStyles.UserPaint, True) 
     End Sub 
    End Class 
Cuestiones relacionadas