Share via


Tutorial: Hospedar objetos visuales en una aplicación Win32

Actualización: noviembre 2007

Windows Presentation Foundation (WPF) proporciona un entorno enriquecido para crear aplicaciones. Sin embargo, cuando ya se tiene una inversión sustancial en código de Win32, puede ser más eficaz agregar la funcionalidad de WPF a la aplicación en lugar de volver a escribir el código. Para proporcionar la compatibilidad con los subsistemas de gráficos de Win32 y WPF que se utilizan de manera simultánea en una aplicación, WPF proporciona un mecanismo para hospedar objetos en una ventana de Win32.

En este tutorial se describe cómo escribir una aplicación de ejemplo, Ejemplo Hit Test with Win32 Interoperation, que hospeda objetos visuales de WPF en una ventana de Win32.

Este tema contiene las secciones siguientes.

  • Requisitos   
  • Crear la ventana host de Win32
  • Agregar objetos visuales a la ventana host de Win32
  • Implementar el filtro de mensajes de Win32
  • Procesar mensajes de Win32
  • Temas relacionados

Requisitos   

En este tutorial se da por hecho que está familiarizado con la programación básica en WPF y Win32. Para obtener una introducción básica a la programación en WPF, vea Información general sobre Windows Presentation Foundation. Para obtener una introducción a la programación en Win32, vea cualquiera de los numerosos libros sobre el tema, en particular Programming Windows escrito por Charles Petzold.

Nota

En este tutorial se incluyen varios ejemplos de código del ejemplo asociado. Sin embargo, para facilitar la legibilidad, no se incluye el código de ejemplo completo. Para obtener el ejemplo de código completo, vea Ejemplo Hit Test with Win32 Interoperation.

Crear la ventana host de Win32

La clave para hospedar objetos de WPF en una ventana de Win32 es la clase HwndSource. Esta clase ajusta los objetos de WPF en una ventana de Win32, con lo que permite incorporarlos a la interfaz de usuario (UI) como una ventana secundaria.

En el ejemplo siguiente se muestra el código utilizado para crear el objeto HwndSource como la ventana contenedora de Win32 para los objetos visuales. Para establecer el estilo, la posición y otros parámetros de la ventana de Win32 ventana, utilice el objeto HwndSourceParameters.

// Constant values from the "winuser.h" header file.
internal const int WS_CHILD = 0x40000000,
                   WS_VISIBLE = 0x10000000;

internal static void CreateHostHwnd(IntPtr parentHwnd)
{
    // Set up the parameters for the host hwnd.
    HwndSourceParameters parameters = new HwndSourceParameters("Visual Hit Test", _width, _height);
    parameters.WindowStyle = WS_VISIBLE | WS_CHILD;
    parameters.SetPosition(0, 24);
    parameters.ParentWindow = parentHwnd;
    parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);

    // Create the host hwnd for the visuals.
    myHwndSource = new HwndSource(parameters);

    // Set the hwnd background color to the form's background color.
    myHwndSource.CompositionTarget.BackgroundColor = System.Windows.Media.Brushes.OldLace.Color;
}

Nota

El valor de la propiedad ExtendedWindowStyle no se puede establecer en WS_EX_TRANSPARENT. Esto significa que la ventana host de Win32 no puede ser transparente. Por esta razón, el color de fondo de la ventana host de Win32 está establecido en el mismo color de fondo que su ventana primaria.

Agregar objetos visuales a la ventana host de Win32

Una vez creada la ventana host de Win32 contenedora para los objetos visuales, puede agregarle los objetos visuales. Es conveniente asegurarse de que ninguna transformación de los objetos visuales, como las animaciones, se extienda más allá de los límites del rectángulo delimitador de la ventana host de Win32.

En el ejemplo siguiente se muestra el código utilizado para crear el objeto HwndSource y agregarle objetos visuales.

Nota

La propiedad RootVisual del objeto HwndSource se establece en el primer objeto visual agregado a la ventana host de Win32. El objeto visual raíz define el nodo de nivel superior del árbol de objetos visuales. Todos los objetos visuales subsiguientes se agregan a la ventana host de Win32 como objetos secundarios.

public static void CreateShape(IntPtr parentHwnd)
{
    // Create an instance of the shape.
    MyShape myShape = new MyShape();

    // Determine whether the host container window has been created.
    if (myHwndSource == null)
    {
        // Create the host container window for the visual objects.
        CreateHostHwnd(parentHwnd);

        // Associate the shape with the host container window.
        myHwndSource.RootVisual = myShape;
    }
    else
    {
        // Assign the shape as a child of the root visual.
        ((ContainerVisual)myHwndSource.RootVisual).Children.Add(myShape);
    }
}

Implementar el filtro de mensajes de Win32

La ventana host de Win32 para los objetos visuales requiere un procedimiento de filtro de mensaje de ventana que administre los mensajes que se envían a la ventana desde la cola de la aplicación. El procedimiento de ventana recibe los mensajes del sistema de Win32. Éstos pueden ser mensajes de entrada o de administración de ventanas. Si lo desea, puede administrar un mensaje en el procedimiento de ventana o pasárselo al sistema para que se efectúe el procesamiento predeterminado.

El objeto HwndSource que definió como elemento primario para los objetos visuales debe hacer referencia al procedimiento de filtro de mensajes de ventana que proporcione. Al crear el objeto HwndSource, establezca la HwndSourceHook de tal forma que haga referencia al procedimiento de ventana.

parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);

En el ejemplo siguiente se muestra el código para administrar los mensajes que se emiten al soltar el botón primario y secundario del mouse. El valor del parámetro lParam contiene el valor de las coordenadas de la posición donde se hace clic con el mouse.

// Constant values from the "winuser.h" header file.
internal const int WM_LBUTTONUP = 0x0202,
                   WM_RBUTTONUP = 0x0205;

internal static IntPtr ApplicationMessageFilter(
    IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // Handle messages passed to the visual.
    switch (message)
    {
        // Handle the left and right mouse button up messages.
        case WM_LBUTTONUP:
        case WM_RBUTTONUP:
            System.Windows.Point pt = new System.Windows.Point();
            pt.X = (uint)lParam & (uint)0x0000ffff;  // LOWORD = x
            pt.Y = (uint)lParam >> 16;               // HIWORD = y
            MyShape.OnHitTest(pt, message);
            break;
    }

    return IntPtr.Zero;
}

Procesar mensajes de Win32

En el código del ejemplo siguiente se muestra cómo se efectúa una prueba de posicionamiento con respecto a la jerarquía de objetos visuales contenida en la ventana host de Win32. Puede identificar si un punto está dentro de la geometría de un objeto visual utilizando el método HitTest para especificar el objeto visual raíz y el valor de las coordenadas con las que se comparará la prueba de posicionamiento. En este caso, el objeto visual raíz es el valor de la propiedad RootVisual del objeto HwndSource.

// Constant values from the "winuser.h" header file.
public const int WM_LBUTTONUP = 0x0202,
                 WM_RBUTTONUP = 0x0205;

// Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
public static void OnHitTest(System.Windows.Point pt, int msg)
{
    // Clear the contents of the list used for hit test results.
    hitResultsList.Clear();

    // Determine whether to change the color of the circle or to delete the shape.
    if (msg == WM_LBUTTONUP)
    {
        MyWindow.changeColor = true;
    }
    if (msg == WM_RBUTTONUP)
    {
        MyWindow.changeColor = false;
    }

    // Set up a callback to receive the hit test results enumeration.
    VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual,
                             null,
                             new HitTestResultCallback(CircleHitTestResult),
                             new PointHitTestParameters(pt));

    // Perform actions on the hit test results list.
    if (hitResultsList.Count > 0)
    {
        ProcessHitTestResultsList();
    }
}

Para obtener más información sobre las pruebas de posicionamiento con respecto a objetos visuales, vea Realizar pruebas de posicionamiento en la capa visual.

Vea también

Tareas

Ejemplo Hit Test with Win32 Interoperation

Conceptos

Realizar pruebas de posicionamiento en la capa visual

Referencia

HwndSource