Поделиться через


Руководство по размещению визуальных объектов в приложении Win32

Клиент Windows Presentation Foundation (WPF) предоставляет среду с широкими возможностями для создания приложений. Однако, если имеются существенные преимущества в коде Win32, возможно, более эффективным будет добавление функциональности WPF в приложение вместо переписывания вашего кода. Для обеспечения поддержки графических подсистем Win32 и WPF, одновременно используемых в приложении, WPF предоставляет механизм для размещения объектов в окне Win32.

В этом руководстве описан процесс написания приложения Пример проверки нажатий, включающий взаимодействие с Win32, в котором визуальные объекты WPF размещены в окне Win32.

В этом разделе содержатся следующие подразделы.

  • Требования
  • Создание главного окна Win32
  • Добавление визуального объекта в главное окно Win32
  • Реализация фильтра сообщений Win32
  • Обработка сообщений Win32
  • Связанные разделы

Требования

Это руководство предполагает начальное знакомство с программированием WPF и Win32. Введение в программирование WPF см. в разделе Пошаговое руководство. Начало работы с WPF. Введение в программирование Win32 содержится в любой из многочисленных книг на данную тему, в частности, Programming Windows Charles Petzold.

ПримечаниеПримечание

Это руководство включает ряд примеров кода из сопровождающего его образца.Тем не менее, для удобства чтения, он не включает в себя полный код примера.Полный код примера см. в разделе Пример проверки нажатий, включающий взаимодействие с Win32.

Создание главного окна Win32

Ключом для размещению объектов WPF в окне Win32 является класс HwndSource. Этот класс переносит объекты WPF в окне Win32, позволяя им присоединиться к вашему user interface (UI) в качестве дочернего окна.

В следующем примере показан код для создания объекта HwndSource в качестве контейнера окна Win32 для визуальных объектов. Для задания стиля окна, положения и других параметров окна Win32 используйте объект HwndSourceParameters.

' 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
// 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;
}
ПримечаниеПримечание

Значению свойства ExtendedWindowStyle не может быть равно WS_EX_TRANSPARENT.Это означает, что главное окно Win32 не может быть прозрачным.По этой причине цвету фона главного окна Win32 задается тот же цвет фона, что и у родительского окна.

Добавление визуального объекта в главное окно Win32

После создания главного окна контейнера Win32 для визуальных объектов на него можно добавить визуальные объекты. Необходимо убедиться, что любые преобразования визуальных объектов, такие как анимация, не выходят за пределы ограничивающего прямоугольника главного окна Win32.

В следующем примере показан код для создания объекта HwndSource и добавления визуальных объектов к нему.

ПримечаниеПримечание

Свойство RootVisual объекта HwndSource установлено в значение первого визуального объекта, добавленного в главное окно Win32.Корневой визуальный объект определяет самый верхний узел дерева визуальных объектов.Все последующие визуальные объекты, добавленные в главное окно Win32, добавляются как дочерние объекты.

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
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);
    }
}

Реализация фильтра сообщений Win32

Для главного окна Win32 визуальных объектов требуется процедура фильтрации сообщений окна для обработки сообщений, отправляемых из очереди приложения окну. Процедура окна получает сообщения из системы Win32. Это могут быть входные сообщения или сообщения от управления окнами. Можно дополнительно обработать сообщение в процедуре окна или передать сообщение системе для обработки по умолчанию.

На объект HwndSource, который определен вами как родительский для визуальных объектов, должна ссылаться предоставленная вами процедура фильтрации сообщении. При создании объекта HwndSource, установите свойству HwndSourceHook значение ссылки на процедуру окна.

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

В следующем примере показан код для обработки сообщений при нажатии левой и правой кнопок мыши. Значение координаты положения мыши содержатся в значении параметра lParam.

' 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
// 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;
}

Обработка сообщений Win32

В коде следующего примера показано, как выполняется проверка посещение по иерархии визуальных объектов, содержащихся в главном окне Win32. Можно определить, расположена ли точка внутри визуального объекта, с помощью метода HitTest, указав корневой визуальный объект и значение координаты, которую следует проверить. В этом случае корневой визуальный объект является значением свойства RootVisual объекта HwndSource.

        ' 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
// 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();
    }
}

Дополнительные сведения о тестировании на посещение визуальных объектов содержатся в разделе Проверка попадания на визуальном уровне.

См. также

Ссылки

HwndSource

Основные понятия

Проверка попадания на визуальном уровне

Другие ресурсы

Hit Test with Win32 Interoperation Sample