Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Windows Presentation Foundation (WPF) proporciona un entorno enriquecido para crear aplicaciones. Sin embargo, cuando tiene una inversión sustancial en el código Win32, puede ser más eficaz agregar funcionalidad de WPF a la aplicación en lugar de volver a escribir el código. Para proporcionar compatibilidad con subsistemas de gráficos Win32 y WPF usados simultáneamente en una aplicación, WPF proporciona un mecanismo para hospedar objetos en una ventana win32.
En este tutorial se describe cómo escribir una aplicación de ejemplo, Prueba de posicionamiento con ejemplo de interoperación win32, que hospeda objetos visuales de WPF en una ventana de Win32.
Requisitos
En este tutorial se presupone una familiaridad básica con la programación de WPF y Win32. Para obtener una introducción básica a la programación de WPF, vea Tutorial: Mi primera aplicación de escritorio wpF. Para obtener una introducción a la programación Win32, consulta cualquiera de los numerosos libros sobre el tema, en particular Programación windows de Charles Petzold.
Nota:
En este tutorial se incluyen varios ejemplos de código del ejemplo asociado. Sin embargo, para mejorar la legibilidad, no incluye el código de ejemplo completo. Para obtener el código de ejemplo completo, consulta Prueba de impacto con ejemplo de interoperación Win32.
Creación de la ventana Win32 del host
La clave para hospedar objetos WPF en una ventana win32 es la HwndSource clase . Esta clase encapsula los objetos WPF en una ventana win32, lo que les permite incorporarlos en la interfaz de usuario (UI) como una ventana secundaria.
En el ejemplo siguiente se muestra el código para crear el HwndSource objeto como la ventana de contenedor win32 para los objetos visuales. Para establecer el estilo, la posición y otros parámetros de la ventana win32, use el HwndSourceParameters objeto .
// 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;
}
' Constant values from the "winuser.h" header file.
Friend Const WS_CHILD As Integer = &H40000000, WS_VISIBLE As Integer = &H10000000
Friend Shared Sub CreateHostHwnd(ByVal parentHwnd As IntPtr)
' Set up the parameters for the host hwnd.
Dim parameters As New HwndSourceParameters("Visual Hit Test", _width, _height)
parameters.WindowStyle = WS_VISIBLE Or WS_CHILD
parameters.SetPosition(0, 24)
parameters.ParentWindow = parentHwnd
parameters.HwndSourceHook = New HwndSourceHook(AddressOf 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
End Sub
Nota:
El valor de la ExtendedWindowStyle propiedad no se puede establecer en WS_EX_TRANSPARENT. Esto significa que la ventana win32 del host no puede ser transparente. Por este motivo, el color de fondo de la ventana win32 del host se establece en el mismo color de fondo que su ventana primaria.
Agregar objetos visuales a la ventana Win32 del host
Una vez que haya creado una ventana de contenedor win32 host para los objetos visuales, puede agregar objetos visuales a él. Querrá asegurarse de que las transformaciones de los objetos visuales, como las animaciones, no se extiendan más allá de los límites del rectángulo delimitador de la ventana Win32 del host.
En el ejemplo siguiente se muestra el código para crear el HwndSource objeto y agregarle objetos visuales.
Nota:
La RootVisual propiedad del HwndSource objeto se establece en el primer objeto visual agregado a la ventana host Win32. El objeto visual raíz define el nodo superior del árbol de objetos visuales. Los objetos visuales posteriores agregados a la ventana win32 host se agregan 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);
}
}
Public Shared Sub CreateShape(ByVal parentHwnd As IntPtr)
' Create an instance of the shape.
Dim myShape As New MyShape()
' Determine whether the host container window has been created.
If myHwndSource Is Nothing Then
' 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.
CType(myHwndSource.RootVisual, ContainerVisual).Children.Add(myShape)
End If
End Sub
Implementación del filtro de mensajes Win32
La ventana win32 del host para los objetos visuales requiere un procedimiento de filtro de mensajes de ventana para controlar los mensajes que se envían a la ventana desde la cola de la aplicación. El procedimiento de ventana recibe mensajes del sistema Win32. Pueden ser mensajes de entrada o mensajes de administración de ventanas. Opcionalmente, puede controlar un mensaje en el procedimiento de ventana o pasar el mensaje al sistema para su procesamiento predeterminado.
El HwndSource objeto 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 HwndSource objeto, establezca la HwndSourceHook propiedad para que haga referencia al procedimiento de ventana.
parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
parameters.HwndSourceHook = New HwndSourceHook(AddressOf ApplicationMessageFilter)
En el ejemplo siguiente se muestra el código para manejar los mensajes de liberación de los botones izquierdo y derecho del ratón. El valor de la coordenada de la posición del ratón se encuentra en el parámetro lParam
.
// 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;
}
' Constant values from the "winuser.h" header file.
Friend Const WM_LBUTTONUP As Integer = &H202, WM_RBUTTONUP As Integer = &H205
Friend Shared Function ApplicationMessageFilter(ByVal hwnd As IntPtr, ByVal message As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
' Handle messages passed to the visual.
Select Case message
' Handle the left and right mouse button up messages.
Case WM_LBUTTONUP, WM_RBUTTONUP
Dim pt As New System.Windows.Point()
pt.X = CUInt(lParam) And CUInt(&HFFFF) ' LOWORD = x
pt.Y = CUInt(lParam) >> 16 ' HIWORD = y
MyShape.OnHitTest(pt, message)
End Select
Return IntPtr.Zero
End Function
Procesamiento de los mensajes Win32
El código del ejemplo siguiente muestra cómo se realiza una prueba de impacto en la jerarquía de objetos visuales contenidos en la ventana Win32 del host. 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 coordenada con el que se va a realizar la prueba de impacto. En este caso, el objeto visual raíz es el valor de la RootVisual propiedad del HwndSource objeto .
// 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();
}
}
' Constant values from the "winuser.h" header file.
Public Const WM_LBUTTONUP As Integer = &H0202, WM_RBUTTONUP As Integer = &H0205
' Respond to WM_LBUTTONUP or WM_RBUTTONUP messages by determining which visual object was clicked.
Public Shared Sub OnHitTest(ByVal pt As System.Windows.Point, ByVal msg As Integer)
' 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 Then
MyWindow.changeColor = True
End If
If msg = WM_RBUTTONUP Then
MyWindow.changeColor = False
End If
' Set up a callback to receive the hit test results enumeration.
VisualTreeHelper.HitTest(MyWindow.myHwndSource.RootVisual, Nothing, New HitTestResultCallback(AddressOf CircleHitTestResult), New PointHitTestParameters(pt))
' Perform actions on the hit test results list.
If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub
Para obtener más información sobre la prueba de impactos en objetos visuales, vea Prueba de impactos en la capa visual.
Consulte también
.NET Desktop feedback