Integración de Windows Forms 2.0 en WPF

Esto a más de uno le puede parecer curioso a más de uno. ¿Para qué vamos a usar Windows Forms dentro de WPF si ya tenemos WPF? Eso, yo creo, que lo pensamos todos cuando empezamos con WPF, pero a medida que nos metemos en un proyecto nos damos cuenta que necesitamos más de que creemos Windows Forms, y para ser concretos las librerías de GDI+ (System.Drawing).


En mi caso tenía que integrar la captura de una WebCam en una ventana de WPF y grabarlo en el disco. En este artículo solo me centraré en lo primero, el tema de la grabación no es necesario para este ejemplo.


Para ello usé las librerías que se encuentran en este artículo de CodeProject.


Antes de empezar con el tema de integración voy a comentar una cosa. Para poder mostrar un control en Windows Forms éste se debe heredar de la clase Control (Sytem.Windows.Forms.Control, de la librería System.Windows.Forms.dll) mientras que para poder mostrar un elemento en WPF (declarándolo en XAML) éste se debe de heredar de la clase UIElement (System.Windows.UIElement, de la librería WindowsBase.dll). Y esa es la razón por la que no podemos añadir controles de Windows Forms en WPF y no podemos añadir controles de WPF en Windows Forms.


Pero todo tiene una solución, y esa se llama WindowsFormsIntegration.dll, que nos permite tanto la integración de controles de Windows Forms en WPF como la de elementos de WPF en Windows Forms.


Ya sé que esto es un poco lioso. Pero ahora vamos a ver un ejemplo. En este post solo trataremos de la integración de Windows Forms en WPF. Esto es lo que pretendemos obtener:









Para poder hacer ese ejemplo, debemos crear un proyecto tipo Windows Application (WPF), en mi caso C#. Y a él añadir las tres referencias que necesitamos:


·         System.Windows.Forms


·         DirectX.Capture


·         WindowsIntegration


La última referencia es la importante en este caso, ya que debemos usar el objeto WindowsFormsHost.


El XAML de nuestro ejemplo es:


<Window


      xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation


      xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml


      x:Class=WebCamCapture.Window1


      x:Name=Window


      Title=Window1


      Width=350


      Height=400


      Loaded=WindowLoaded>


 


      <Grid x:Name=LayoutRoot>


    <WindowsFormsHost x:Name=wfh


                               Height=300


                               Width=300  


                               Margin=8,50,0,55


                               HorizontalAlignment=Left />  


           


            <ComboBox x:Name=VideoList


                          SelectionChanged=VideoSelected


                          HorizontalAlignment=Left


                          Margin=64,12,0,0


                          Width=232


                          IsSynchronizedWithCurrentItem=True


                          Height=24


                          VerticalAlignment=Top />


    <Label Content=Video


               HorizontalAlignment=Left


               Margin=8,10.04,0,0


               Width=52 


               VerticalAlignment=Top />


  </Grid>


</Window>


Y el C#:


DirectX.Capture.Capture capt = null;


DirectX.Capture.Filters filters = new DirectX.Capture.Filters();


 


DirectX.Capture.Filter _video = null;


 


private void WindowLoaded(object sender, RoutedEventArgs e)


{


    VideoList.Items.Clear();


    ListBoxItem m = new ListBoxItem();


    m.Content = “(None)”;


    VideoList.Items.Add(m);


    foreach (DirectX.Capture.Filter var in filters.VideoInputDevices)


    {


        ListBoxItem lbi = new ListBoxItem();


        lbi.Content = var.Name;


        VideoList.Items.Add(lbi);


    }


    VideoList.SelectedIndex = 0;


    }


 


private void VideoSelected(object sender, SelectionChangedEventArgs e)


{


    string codec = (string)(VideoList.SelectedValue as ListBoxItem).Content;


    if (codec != “(None)”)


    {


        foreach (DirectX.Capture.Filter var in filters.VideoInputDevices)


        {


            if (var.Name == codec)


            {


                _video = var;


                break;


            }


        }


        Start();


    }


}


private void Start()


{


    if (capt == null)


    {


        capt = new DirectX.Capture.Capture(_video, null);


        //Usamos la propiedad Child del WindowsFormsHost


        //para poner controles de Windows Forms


        wfh.Child = new System.Windows.Forms.Panel();


        capt.PreviewWindow = wfh.Child;


    }


    else


    {


        System.Windows.Forms.Control oldPreview = capt.PreviewWindow;


 


        capt.PreviewWindow = null;


 


        capt = new DirectX.Capture.Capture(_video, null);


 


        capt.PreviewWindow = oldPreview;


        wfh.Child = capt.PreviewWindow;


    }


}


Como podeis ver usando la propiedad Child del WindowsFormsHost podemos incluir controles de Windows.Forms [:)].

3 thoughts on “Integración de Windows Forms 2.0 en WPF

  1. Buenos dias, soy nuevo en esto del WPF y estoy intentando capturar imagenes de una WebCam, y queria saber si me podrías ayudar.

    he estado intentando aplicar lo que explicas, pero al probar tu código (me creo un proyecto con Blend y copio tu código) al ejecutarlo me dá un error de aplicación y no se lanza.
    Con el VS2005 me dice lo siguiente:

    Cannot create instance of ‘Window1’ defined in assembly ‘WebCamCapture, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’. Exception has been thrown by the target of an invocation. Error in markup file ‘Window1.xaml’ Line 2 Position 2.

    Esa posición se corresponde a la siguiente linea:

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

    y no entiendo porqué me da este error.

    Como ya he dicho antes, soy nuevo en esto del WPF.

    Un Saludo y Muchas Gracias

  2. Hola de nuevo,
    ya no me da problemas. No se porque pasaba. Puede ser porque no me reconociera la WebCam.

    Excelente artículo, esto de integrar controles de Windows Form es muy bueno.

    Muchas Gracias y un Saludo.

  3. Hola de nuevo,
    he conseguido capturar video en “avi” y guardarlo en el disco duro.
    Pero no soy capaz de capturar una foto en “.jpg”.
    Lo que quiero es capturar una foto por la webCam y guardarla al disco duro.
    Si me pudieses ayudar te lo agradecería.

    Un Saludo y muchas Gracias…

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *