Tutorial: Hosten von visuellen Objekten in einer Win32-AnwendungTutorial: Hosting Visual Objects in a Win32 Application

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) stellt eine umfangreiche Umgebung zum Erstellen von Anwendungen bereit.provides a rich environment for creating applications. Wenn Sie jedoch eine beträchtliche Investition in Win32Win32 den Code haben, kann es effektiver sein, der Anwendung Funktionalität hinzuzufügen WPFWPF , anstatt den Code neu zu schreiben.However, when you have a substantial investment in Win32Win32 code, it might be more effective to add WPFWPF functionality to your application rather than rewrite your code. Um Unterstützung für Win32Win32 - WPFWPF und-Grafik Subsysteme bereitzustellen, die WPFWPF gleichzeitig in einer Anwendung verwendet werden, Win32Win32 stellt einen Mechanismus zum Hosting von Objekten in einem-FensterTo provide support for Win32Win32 and WPFWPF graphics subsystems used concurrently in an application, WPFWPF provides a mechanism for hosting objects in a Win32Win32 window.

In diesem Tutorial wird beschrieben, wie Sie eine Beispielanwendung, ein Treffer Test mit Win32-Interoperation-Beispiel, erstellen Win32Win32 , das visuelle Objekte in einem Fenster hostet WPFWPF .This tutorial describes how to write a sample application, Hit Test with Win32 Interoperation Sample, that hosts WPFWPF visual objects in a Win32Win32 window.

AnforderungenRequirements

In diesem Lernprogramm wird vorausgesetzt, dass Sie mit den Grundlagen der WPFWPF-Programmierung und der Win32Win32-Programmierung vertraut sind.This tutorial assumes a basic familiarity with both WPFWPF and Win32Win32 programming. Eine grundlegende Einführung in WPFWPF die Programmierung finden Sie unter Exemplarische Vorgehensweise: Meine erste WPF-DesktopAnwendung.For a basic introduction to WPFWPF programming, see Walkthrough: My first WPF desktop application. Eine Einführung in die Win32Win32 Programmierung finden Sie in den zahlreichen Büchern zu diesem Thema, insbesondere in den Programmier Fenstern von Charles Petzold.For an introduction to Win32Win32 programming, see any of the numerous books on the subject, in particular Programming Windows by Charles Petzold.

Hinweis

Dieses Lernprogramm enthält eine Reihe von Codebeispielen aus dem genannten Beispiel.This tutorial includes a number of code examples from the associated sample. Aus Gründen der besseren Lesbarkeit wird jedoch nicht der gesamte Beispielcode aufgeführt.However, for readability, it does not include the complete sample code. Den gesamten Beispielcode finden Sie unter Beispiel für Treffer Tests mit Win32-Interoperation.For the complete sample code, see Hit Test with Win32 Interoperation Sample.

Erstellen des Host-Win32-FenstersCreating the Host Win32 Window

Der Schlüssel für das WPFWPF Hosting von Objekten Win32Win32 in einem- HwndSource Fenster ist die-Klasse.The key to hosting WPFWPF objects in a Win32Win32 window is the HwndSource class. Diese Klasse umschließt WPFWPF die-Objekte Win32Win32 in einem-Fenster, sodass Sie als unter Benutzeroberfläche (User Interface, UI)user interface (UI) geordnetes Fenster in Ihre eingebunden werden können.This class wraps the WPFWPF objects in a Win32Win32 window, allowing them to be incorporated into your Benutzeroberfläche (User Interface, UI)user interface (UI) as a child window.

Das folgende Beispiel zeigt den Code zum Erstellen des HwndSource -Objekts Win32Win32 als Containerfenster für die visuellen Objekte.The following example shows the code for creating the HwndSource object as the Win32Win32 container window for the visual objects. Verwenden Sie das HwndSourceParameters -Objekt, um den Fenster Stil, die Position Win32Win32 und andere Parameter für das Fenster festzulegen.To set the window style, position, and other parameters for the Win32Win32 window, use the HwndSourceParameters object.

// 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

Hinweis

Der Wert ExtendedWindowStyle der Eigenschaft kann nicht auf WS_EX_TRANSPARENT festgelegt werden.The value of the ExtendedWindowStyle property cannot be set to WS_EX_TRANSPARENT. Dies bedeutet, dass das Win32Win32 Host Fenster nicht transparent sein darf.This means that the host Win32Win32 window cannot be transparent. Aus diesem Grund wird die Hintergrundfarbe des Host Win32Win32 Fensters auf dieselbe Hintergrundfarbe wie das übergeordnete Fenster festgelegt.For this reason, the background color of the host Win32Win32 window is set to the same background color as its parent window.

Hinzufügen von visuellen Objekten zum Host-Win32-FensterAdding Visual Objects to the Host Win32 Window

Nachdem Sie ein Host Win32Win32 Containerfenster für die visuellen Objekte erstellt haben, können Sie visuelle Objekte hinzufügen.Once you have created a host Win32Win32 container window for the visual objects, you can add visual objects to it. Sie müssen sicherstellen, dass alle Transformationen der visuellen Objekte (z. b. Animationen) nicht über die Grenzen des umgebenden Rechtecks des Host Win32Win32 Fensters hinausgehen.You will want to ensure that any transformations of the visual objects, such as animations, do not extend beyond the bounds of the host Win32Win32 window's bounding rectangle.

Das folgende Beispiel zeigt den Code zum Erstellen des HwndSource -Objekts und zum Hinzufügen von visuellen Objekten.The following example shows the code for creating the HwndSource object and adding visual objects to it.

Hinweis

Die RootVisual -Eigenschaft HwndSource des-Objekts wird auf das erste visuelle Objekt festgelegt, das Win32Win32 dem Host Fenster hinzugefügt wird.The RootVisual property of the HwndSource object is set to the first visual object added to the host Win32Win32 window. Das visuelle Stammobjekt definiert den obersten Knoten der Struktur des visuellen Objekts.The root visual object defines the top-most node of the visual object tree. Alle nachfolgenden visuellen Objekte, die dem Win32Win32 Host Fenster hinzugefügt werden, werden als untergeordnete Objekte hinzugefügt.Any subsequent visual objects added to the host Win32Win32 window are added as child objects.

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

Implementieren des Win32-NachrichtenfiltersImplementing the Win32 Message Filter

Das Host Win32Win32 Fenster für die visuellen Objekte erfordert eine Fenster Meldungs Filter Prozedur, um Meldungen zu verarbeiten, die aus der Anwendungs Warteschlange an das Fenster gesendet werden.The host Win32Win32 window for the visual objects requires a window message filter procedure to handle messages that are sent to the window from the application queue. Die Fenster Prozedur empfängt Nachrichten vom Win32Win32 System.The window procedure receives messages from the Win32Win32 system. Dabei kann es sich um Eingabe- oder Fensterverwaltungsmeldungen handeln.These may be input messages or window-management messages. Sie können wahlweise eine Meldung in der Fensterprozedur verarbeiten oder die Meldung zwecks Standardverarbeitung an das System übergeben.You can optionally handle a message in your window procedure or pass the message to the system for default processing.

Das HwndSource Objekt, das Sie als übergeordnetes Element für die visuellen Objekte definiert haben, muss auf die von Ihnen bereitgestellte Fenster Nachrichtenfilter-Prozedur verweisen.The HwndSource object that you defined as the parent for the visual objects must reference the window message filter procedure you provide. Wenn Sie das HwndSource Objekt erstellen, legen Sie HwndSourceHook die-Eigenschaft so fest, dass Sie auf die Fenster Prozedur verweist.When you create the HwndSource object, set the HwndSourceHook property to reference the window procedure.

parameters.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);
parameters.HwndSourceHook = New HwndSourceHook(AddressOf ApplicationMessageFilter)

Das folgende Beispiel zeigt den Code für die Verarbeitung der Meldungen der linken und rechten Maustaste.The following example shows the code for handling the left and right mouse button up messages. Der Koordinaten Wert der Maus Treffer Position ist im Wert des lParam -Parameters enthalten.The coordinate value of the mouse hit position is contained in the value of the lParam parameter.

// 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

Verarbeiten der Win32-MeldungenProcessing the Win32 Messages

Der Code im folgenden Beispiel zeigt, wie ein Treffer Test für die Hierarchie von visuellen Objekten durchgeführt wird, die Win32Win32 im Host Fenster enthalten sind.The code in the following example shows how a hit test is performed against the hierarchy of visual objects contained in the host Win32Win32 window. Sie können ermitteln, ob sich ein Punkt innerhalb der Geometrie eines visuellen Objekts befindet, indem Sie HitTest die-Methode verwenden, um das visuelle Stamm Objekt und den Koordinaten Wert anzugeben, für den der Treffer Test durch gefunden werden soll.You can identify whether a point is within the geometry of a visual object, by using the HitTest method to specify the root visual object and the coordinate value to hit test against. In diesem Fall ist das visuelle Stamm Objekt der Wert der RootVisual -Eigenschaft HwndSource des-Objekts.In this case, the root visual object is the value of the RootVisual property of the HwndSource object.

// 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

Weitere Informationen zu Treffer Tests für visuelle Objekte finden Sie unter Treffer Tests in der visuellen Ebene.For more information on hit testing against visual objects, see Hit Testing in the Visual Layer.

Siehe auchSee also