Учебник. Размещение визуальных объектов в приложении Win32
Windows Presentation Foundation (WPF) предоставляет среду с широкими возможностями для создания приложений. Тем не менее, если имеются существенные преимущества в Win32 код, он может быть более эффективно добавить WPF функциональные возможности приложения, а не переписывать код. Чтобы обеспечить поддержку Win32 и WPF графических подсистем, одновременно используемых в приложении, WPF предоставляет механизм для размещения объектов в Win32 окна.
Этом руководстве описывается создание примера приложения, проверка нажатия с помощью примера взаимодействия Win32, в котором узлы WPF визуальные объекты в Win32 окна.
Требования
В этом учебнике предполагается, что вы знакомы с основами программирования в WPF и Win32. Основные сведения о WPF программирования, см. в разделе Пошаговое руководство: Создание первого классического приложения WPF. Общие сведения о Win32 программирования, см. в разделе любой из многочисленных книг по этой теме, в частности программирования Windows Чарльза Петцольда.
Note
Этот учебник включает ряд примеров кода из связанного образца приложения. Однако для удобства чтения он не содержит полный пример кода. Полный образец кода, см. в разделе проверка нажатия с помощью примера взаимодействия Win32.
Создание окна размещения Win32
Ключом к размещению WPF объекты в Win32 окно HwndSource класса. Этот класс заключает WPF объекты в Win32 окна, позволяя им должна быть включена в ваш UI как дочернего окна.
В примере показан код для создания HwndSource объекта в виде Win32 окна контейнера для визуальных объектов. Чтобы задать стиль окна, положение и другие параметры для Win32 окно, используйте 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;
}
Note
Значение ExtendedWindowStyle свойство нельзя установить значение WS_EX_TRANSPARENT. Это означает, что узел Win32 окно не может быть прозрачным. По этой причине цвет фона узла Win32 окно присваивается один и тот же цвет фона родительского окна.
Добавление визуальных объектов в окно размещения Win32
После создания узла Win32 окна контейнера для визуальных объектов, к нему можно добавить визуальные объекты. Необходимо убедиться, что любые преобразования визуальных объектов, такие как анимация, не выходят за пределы узла Win32 ограничивающего прямоугольника окна.
В примере показан код для создания HwndSource объекта и добавления в него визуальных объектов.
Note
RootVisual Свойство HwndSource присваивается первый визуальный объект, добавленный к узлу Win32 окна. Корневой визуальный объект определяет верхний узел дерева визуальных объектов. Все последующие визуальные объекты, добавленные в главное Win32 окна добавляются как дочерние объекты.
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(ApplicationMessageFilter);
В следующем примере показан код для обработки сообщений при отпускании левой и правой кнопок мыши. Значение координаты мыши была нажата содержится в значении параметра 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;
}
Обработка сообщений Win32
Код в следующем примере показано, как выполняется нажатия иерархии визуальных объектов, содержащихся в окне размещения Win32 окна. Можно определить, находится ли точка в пределах визуального объекта, с помощью HitTest метод, чтобы задать корневой визуальный объект и значение координаты для проверки нажатия. В этом случае корневой визуальный объект является значение RootVisual свойство 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();
}
}
Дополнительные сведения о проверке нажатия для визуальных объектов, см. в разделе проверка нажатия на визуальном уровне.