2011-03-04 12 views
19

¿Cómo puedo convertir un UserControl de WPF en un mapa de bits sin crear una ventana? Necesito renderizar un UserControl de WPF y subirlo a otro programa. Los mapas de bits se procesarán a través de un servicio de Windows, por lo que crear una ventana no es una opción (sé que hay formas de crear ventanas 'prácticamente', pero desafortunadamente todo lo que llama un comando para crear una ventana NO es una opción en mi caso). ¿Hay alguna manera de RENDER el UserControl sin vincularlo a una ventana?Cómo renderizar un UserControl de WPF en un mapa de bits sin crear una ventana

+0

Quizás podría proporcionar un poco más de información. Si el Control de usuario no se puede representar, ¿por qué existe? Es un elemento visual. –

+0

Tiene que representarse, pero no directamente en una pantalla (por lo que no puede haber ventana). Se está procesando en un cubo OpenGL. El renderizado de cubos funciona, pero actualmente tengo que crear una ventana separada para hacer el renderizado. Sería bueno si no necesitara una ventana separada para el renderizado de WPF. – IDWMaster

Respuesta

5

Terminó usando un HwndHost sin ventana real.

void cwind() 
    { 
     Application myapp = new Application(); 
     mrenderer = new WPFRenderer(); 
     mrenderer.Width = 256; 
     mrenderer.Height = 256; 

     HwndSourceParameters myparms = new HwndSourceParameters(); 
     HwndSource msrc = new HwndSource(myparms); 
     myparms.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter); 

     msrc.RootVisual = mrenderer; 
     myapp.Run(); 
    } 
    static IntPtr ApplicationMessageFilter(
IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     return IntPtr.Zero; 
    } 
+0

Tuve que modificar tu solución un poco para que funcione para mí, pero usar una envoltura Win32 para forzar a WPF a cargar en una ventana oculta es una gran idea. – floele

+0

@floele: tal vez para algunas soluciones, un contenedor 'Win32' es una gran idea. Pero en este caso, creo que @RQDQ tiene la solución adecuada. – IAbstract

+2

Por favor dígame ¿Qué es WPFRenderer? (dónde está el archivo de ensamblaje y el espacio de nombres) –

48

Ha intentado girar una instancia del control de usuario y hacer algo como esto:

UserControl control = new UserControl1(); 

control.Measure(new Size(300, 300)); 
control.Arrange(new Rect(new Size(300,300))); 

RenderTargetBitmap bmp = new RenderTargetBitmap(300, 300, 96, 96, PixelFormats.Pbgra32); 

bmp.Render(control); 

var encoder = new PngBitmapEncoder(); 

encoder.Frames.Add(BitmapFrame.Create(bmp)); 

using (Stream stm = File.Create(@"c:\test.png")) 
    encoder.Save(stm); 

Parece que hay que medir, Organizar. Esto funcionó para mí.

+1

Sí, excepto que solo funciona cuando está vinculado a una ventana. – IDWMaster

+3

Se agregaron Medida/Organizar llamadas. Esto funcionó para mí. – RQDQ

+1

Google búsqueda para exportar un control de usuario a un JPG me trajo aquí y esta respuesta fue perfecta. Muchas gracias. –

1

basado en la solución de IDWMaster lo hice un poco diferente con el System.Windows.Forms.UserControl. De lo contrario, los enlaces no estaban actualizados cuando se produjo la exportación al mapa de bits. Esto funciona para mí (this es el control de WPF a render):

System.Windows.Forms.UserControl controlContainer = new System.Windows.Forms.UserControl(); 
controlContainer.Width = width; 
controlContainer.Height = height; 
controlContainer.Load += delegate(object sender, EventArgs e) 
{ 
    this.Dispatcher.BeginInvoke((Action)delegate 
    { 
     using (FileStream fs = new FileStream(path, FileMode.Create)) 
     { 
      RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); 
      bmp.Render(this); 
      BitmapEncoder encoder = new PngBitmapEncoder(); 
      encoder.Frames.Add(BitmapFrame.Create(bmp)); 
      encoder.Save(fs); 
      controlContainer.Dispose(); 
     } 
    }, DispatcherPriority.Background); 
}; 

controlContainer.Controls.Add(new ElementHost() { Child = this, Dock = System.Windows.Forms.DockStyle.Fill }); 
IntPtr handle = controlContainer.Handle; 
3

Al parecer, si se llama a control.UpdateLayout() después de la medición y la organización, el control de usuario no tiene por qué estar en cualquier ventana.

Cuestiones relacionadas