Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Windows Presentation Foundation (WPF) предоставляет многофункциональную среду для создания приложений. Однако при наличии существенных инвестиций в код Win32 может быть более эффективным повторное использование по крайней мере некоторой части этого кода в приложении WPF, а не переписывание его полностью. WPF предоставляет простой механизм размещения окна Win32 на странице WPF.
В этом разделе вас познакомят с приложением Hosting a Win32 ListBox Control в примере WPF, которое размещает элемент управления списка Win32. Эта общая процедура может быть расширена для размещения любого окна Win32.
Требования
В этом разделе предполагается базовое знакомство с программированием WPF и Windows API. Чтобы получить базовое введение в программирование WPF, см. Приступая к работе. Общие сведения о программировании API Windows см. в любой из многочисленных книг по теме, в частности программирование Windows Чарльзом Петзольдом.
Так как пример, сопровождающий этот раздел, реализуется в C#, он использует службы вызова платформы (PInvoke) для доступа к API Windows. Некоторые знания с PInvoke полезны, но не являются важными.
Замечание
В этом разделе содержится ряд примеров кода из связанного примера. Однако для удобства чтения он не включает полный пример кода. Вы можете получить или просмотреть полный код из примера размещения элемента управления Win32 ListBox в WPF.
Базовая процедура
В этом разделе описана базовая процедура размещения окна Win32 на странице WPF. Остальные разделы содержат подробности каждого шага.
Базовая процедура размещения:
Реализуйте страницу WPF для размещения окна. Одним из методов является создание Border элемента для резервирования места на странице для размещённого окна.
Реализуйте класс для размещения элемента управления, наследуемого от HwndHost.
В этом классе переопределите HwndHost член BuildWindowCore класса.
Создайте размещенное окно в качестве дочернего окна, содержащего страницу WPF. Хотя в обычном программировании WPF нет необходимости явно использовать его, хостинговая страница представляет собой окно с дескриптором (HWND). HWND страницы вы получаете через параметр
hwndParentметода BuildWindowCore. Размещенное окно должно быть создано как дочерний элемент этого HWND.После того, как вы создадите окно хоста, верните дескриптор (HWND) размещенного окна. Если вы хотите разместить один или несколько элементов управления Win32, обычно создается окно-контейнер в качестве дочернего элемента HWND и элементы управления делаются дочерними элементами этого окна-контейнера. Обёртывание элементов управления в окне хоста предоставляет простой способ для вашей страницы WPF получать уведомления от элементов управления, что решает некоторые конкретные проблемы Win32 с уведомлениями через границу HWND.
Обработайте выбранные сообщения, отправленные в окно хоста, такие как уведомления от дочерних элементов управления. Это можно сделать двумя способами.
Если вы предпочитаете обрабатывать сообщения в классе размещения, переопределите WndProc метод HwndHost класса.
Если вы предпочитаете обрабатывать сообщения WPF, обработайте HwndHost событие класса MessageHook в коде программной части. Это событие происходит для каждого сообщения, полученного размещенным окном. Если вы выбрали этот параметр, вам всё равно придется переопределить WndProc, но потребуется только минимальная реализация.
Переопределите методы DestroyWindowCore и WndProc класса HwndHost. Для выполнения договора HwndHost необходимо переопределить эти методы, но вам, возможно, потребуется предоставить лишь минимальную реализацию.
В файле связанного кода создайте экземпляр класса размещающего элемента управления и сделайте его дочерним элементом Border, предназначенным для размещения окна.
Обмен данными с размещенным окном путем отправки сообщений Microsoft Windows и обработки сообщений из дочерних окон, таких как уведомления, отправленные элементами управления.
Реализация макета страницы
Макет страницы WPF, на котором размещен элемент управления ListBox, состоит из двух регионов. В левой части страницы размещается несколько элементов управления WPF, которые предоставляют пользовательский интерфейс, который позволяет управлять элементом управления Win32. Верхний правый угол страницы имеет квадратную область для размещенного элемента управления ListBox.
Код для реализации этого макета довольно прост. Корневой DockPanel элемент — это элемент с двумя дочерними элементами. Первым является элемент, на котором размещается Border элемент управления ListBox. Он занимает площадь 200x200 в правом верхнем углу страницы. Второй — это StackPanel элемент, содержащий набор элементов управления WPF, которые отображают сведения и позволяют управлять элементом управления ListBox, задав доступные свойства взаимодействия. Для каждого из элементов, которые являются дочерними StackPanelэлементами, см. справочный материал для различных элементов, используемых для подробных сведений о том, что эти элементы являются или что они делают, они перечислены в приведенном ниже примере кода, но не будут описаны здесь (базовая модель взаимодействия не требует каких-либо из них, они предоставляются для добавления некоторой интерактивности в пример).
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WPF_Hosting_Win32_Control.HostWindow"
Name="mainWindow"
Loaded="On_UIReady">
<DockPanel Background="LightGreen">
<Border Name="ControlHostElement"
Width="200"
Height="200"
HorizontalAlignment="Right"
VerticalAlignment="Top"
BorderBrush="LightGray"
BorderThickness="3"
DockPanel.Dock="Right"/>
<StackPanel>
<Label HorizontalAlignment="Center"
Margin="0,10,0,0"
FontSize="14"
FontWeight="Bold">Control the Control</Label>
<TextBlock Margin="10,10,10,10" >Selected Text: <TextBlock Name="selectedText"/></TextBlock>
<TextBlock Margin="10,10,10,10" >Number of Items: <TextBlock Name="numItems"/></TextBlock>
<Line X1="0" X2="200"
Stroke="LightYellow"
StrokeThickness="2"
HorizontalAlignment="Center"
Margin="0,20,0,0"/>
<Label HorizontalAlignment="Center"
Margin="10,10,10,10">Append an Item to the List</Label>
<StackPanel Orientation="Horizontal">
<Label HorizontalAlignment="Left"
Margin="10,10,10,10">Item Text</Label>
<TextBox HorizontalAlignment="Left"
Name="txtAppend"
Width="200"
Margin="10,10,10,10"></TextBox>
</StackPanel>
<Button HorizontalAlignment="Left"
Click="AppendText"
Width="75"
Margin="10,10,10,10">Append</Button>
<Line X1="0" X2="200"
Stroke="LightYellow"
StrokeThickness="2"
HorizontalAlignment="Center"
Margin="0,20,0,0"/>
<Label HorizontalAlignment="Center"
Margin="10,10,10,10">Delete the Selected Item</Label>
<Button Click="DeleteText"
Width="125"
Margin="10,10,10,10"
HorizontalAlignment="Left">Delete</Button>
</StackPanel>
</DockPanel>
</Window>
Реализация класса для размещения контрола Microsoft Win32
Основной частью этого примера является класс, на котором фактически размещается элемент управления, ControlHost.cs. Он наследует от HwndHost. Конструктор принимает два параметра, высоту и ширину, соответствующую высоте и ширине Border элемента, на котором размещен элемент управления ListBox. Эти значения используются позже, чтобы убедиться, что размер элемента управления соответствует элементу Border .
public class ControlHost : HwndHost
{
IntPtr hwndControl;
IntPtr hwndHost;
int hostHeight, hostWidth;
public ControlHost(double height, double width)
{
hostHeight = (int)height;
hostWidth = (int)width;
}
Public Class ControlHost
Inherits HwndHost
Private hwndControl As IntPtr
Private hwndHost As IntPtr
Private hostHeight, hostWidth As Integer
Public Sub New(ByVal height As Double, ByVal width As Double)
hostHeight = CInt(height)
hostWidth = CInt(width)
End Sub
Существует также набор констант. Эти константы в значительной степени взяты из Winuser.h и позволяют использовать обычные имена при вызове функций Win32.
internal const int
WS_CHILD = 0x40000000,
WS_VISIBLE = 0x10000000,
LBS_NOTIFY = 0x00000001,
HOST_ID = 0x00000002,
LISTBOX_ID = 0x00000001,
WS_VSCROLL = 0x00200000,
WS_BORDER = 0x00800000;
Friend Const WS_CHILD As Integer = &H40000000, WS_VISIBLE As Integer = &H10000000, LBS_NOTIFY As Integer = &H00000001, HOST_ID As Integer = &H00000002, LISTBOX_ID As Integer = &H00000001, WS_VSCROLL As Integer = &H00200000, WS_BORDER As Integer = &H00800000
Переопределите BuildWindowCore, чтобы создать окно Microsoft Win32
Вы переопределите этот метод, чтобы создать окно Win32, которое будет размещаться на странице, и сделать подключение между окном и страницей. Так как этот пример включает размещение элемента управления ListBox, создаются два окна. Первым является окно, которое фактически размещается на странице WPF. Элемент управления ListBox создается в качестве дочернего элемента этого окна.
Причиной этого подхода является упрощение процесса получения уведомлений от элемента управления. Класс HwndHost позволяет обрабатывать сообщения, отправленные в окно, которое он размещает. Если вы размещаете элемент управления Win32 напрямую, вы получите сообщения, отправленные во внутренний цикл сообщений элемента управления. Элемент управления можно отобразить и отправить сообщения, но вы не получаете уведомления, которые элемент управления отправляет в родительское окно. Это означает, что, помимо прочего, вы не можете обнаружить, когда пользователь взаимодействует с элементом управления. Вместо этого создайте главное окно и сделайте элемент управления дочерним элементом этого окна. Это позволяет обрабатывать сообщения для окна узла, включая уведомления, отправленные в него элементом управления. Для удобства, так как окно узла не более простой оболочки для элемента управления, пакет будет называться элементом управления ListBox.
Создание основного окна и элемента управления ListBox
С помощью PInvoke можно создать главное окно для элемента управления, создав и зарегистрировав класс окна и т. д. Однако гораздо проще создать окно с предопределенным "статическим" классом окна. Это предоставляет вам процедуру обработки оконных сообщений, которая необходима для получения уведомлений от управляющего элемента и требует минимального объема кода.
HWND элемента управления предоставляется через свойство только для чтения, таким образом, что на хост-странице можно использовать его для отправки сообщений в элемент управления.
public IntPtr hwndListBox
{
get { return hwndControl; }
}
Public ReadOnly Property hwndListBox() As IntPtr
Get
Return hwndControl
End Get
End Property
Элемент управления ListBox создается в качестве дочернего элемента главного окна. Высота и ширина обоих окон задаются значениями, передаваемыми конструктору, описанным выше. Это гарантирует, что размер хост-окна и управляющего элемента идентичен зарезервированной области на странице. После создания окон пример возвращает объект HandleRef, содержащий HWND окна хоста.
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
hwndControl = IntPtr.Zero;
hwndHost = IntPtr.Zero;
hwndHost = CreateWindowEx(0, "static", "",
WS_CHILD | WS_VISIBLE,
0, 0,
hostWidth, hostHeight,
hwndParent.Handle,
(IntPtr)HOST_ID,
IntPtr.Zero,
0);
hwndControl = CreateWindowEx(0, "listbox", "",
WS_CHILD | WS_VISIBLE | LBS_NOTIFY
| WS_VSCROLL | WS_BORDER,
0, 0,
hostWidth, hostHeight,
hwndHost,
(IntPtr) LISTBOX_ID,
IntPtr.Zero,
0);
return new HandleRef(this, hwndHost);
}
Protected Overrides Function BuildWindowCore(ByVal hwndParent As HandleRef) As HandleRef
hwndControl = IntPtr.Zero
hwndHost = IntPtr.Zero
hwndHost = CreateWindowEx(0, "static", "", WS_CHILD Or WS_VISIBLE, 0, 0, hostWidth, hostHeight, hwndParent.Handle, New IntPtr(HOST_ID), IntPtr.Zero, 0)
hwndControl = CreateWindowEx(0, "listbox", "", WS_CHILD Or WS_VISIBLE Or LBS_NOTIFY Or WS_VSCROLL Or WS_BORDER, 0, 0, hostWidth, hostHeight, hwndHost, New IntPtr(LISTBOX_ID), IntPtr.Zero, 0)
Return New HandleRef(Me, hwndHost)
End Function
//PInvoke declarations
[DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateWindowEx(int dwExStyle,
string lpszClassName,
string lpszWindowName,
int style,
int x, int y,
int width, int height,
IntPtr hwndParent,
IntPtr hMenu,
IntPtr hInst,
[MarshalAs(UnmanagedType.AsAny)] object pvParam);
'PInvoke declarations
<DllImport("user32.dll", EntryPoint := "CreateWindowEx", CharSet := CharSet.Unicode)>
Friend Shared Function CreateWindowEx(ByVal dwExStyle As Integer, ByVal lpszClassName As String, ByVal lpszWindowName As String, ByVal style As Integer, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal hwndParent As IntPtr, ByVal hMenu As IntPtr, ByVal hInst As IntPtr, <MarshalAs(UnmanagedType.AsAny)> ByVal pvParam As Object) As IntPtr
End Function
Реализация DestroyWindow и WndProc
Кроме BuildWindowCore, необходимо также переопределить методы WndProc и DestroyWindowCore в HwndHost. В этом примере сообщения для элемента управления обрабатываются обработчиком MessageHook , поэтому реализация WndProc и DestroyWindowCore является минимальной. В случае WndProc установите handled в false, чтобы указать, что сообщение не обработано, и верните 0. Для DestroyWindowCore этого просто закройте окно.
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
handled = false;
return IntPtr.Zero;
}
protected override void DestroyWindowCore(HandleRef hwnd)
{
DestroyWindow(hwnd.Handle);
}
Protected Overrides Function WndProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
handled = False
Return IntPtr.Zero
End Function
Protected Overrides Sub DestroyWindowCore(ByVal hwnd As HandleRef)
DestroyWindow(hwnd.Handle)
End Sub
[DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
internal static extern bool DestroyWindow(IntPtr hwnd);
<DllImport("user32.dll", EntryPoint := "DestroyWindow", CharSet := CharSet.Unicode)>
Friend Shared Function DestroyWindow(ByVal hwnd As IntPtr) As Boolean
End Function
Размещение элемента управления на странице
Чтобы разместить элемент управления на странице, сначала создайте новый экземпляр ControlHost класса. Передайте высоту и ширину элемента границы, содержащего элемент управления (ControlHostElement) конструктору ControlHost . Это гарантирует правильность размера ListBox. Затем вы размещаете элемент управления на странице, назначив ControlHost объект Child свойству узла Border.
Пример присоединяет обработчик к MessageHook событию ControlHost, чтобы принимать сообщения из элемента управления. Это событие вызывается для каждого сообщения, отправленного в размещенное окно. В этом случае это сообщения, отправляемые в окно, включающее фактический элемент управления ListBox, включая уведомления из элемента управления. Пример вызывает SendMessage для получения информации из элемента управления и изменения его содержимого. Сведения о том, как страница взаимодействует с элементом управления, рассматриваются в следующем разделе.
Замечание
Обратите внимание, что для функции SendMessage есть два объявления PInvoke. Это необходимо, так как один использует wParam параметр для передачи строки, а другой использует его для передачи целого числа. Для каждой подписи требуется отдельное объявление, чтобы гарантировать правильную обработку данных.
public partial class HostWindow : Window
{
int selectedItem;
IntPtr hwndListBox;
ControlHost listControl;
Application app;
Window myWindow;
int itemCount;
private void On_UIReady(object sender, EventArgs e)
{
app = System.Windows.Application.Current;
myWindow = app.MainWindow;
myWindow.SizeToContent = SizeToContent.WidthAndHeight;
listControl = new ControlHost(ControlHostElement.ActualHeight, ControlHostElement.ActualWidth);
ControlHostElement.Child = listControl;
listControl.MessageHook += new HwndSourceHook(ControlMsgFilter);
hwndListBox = listControl.hwndListBox;
for (int i = 0; i < 15; i++) //populate listbox
{
string itemText = "Item" + i.ToString();
SendMessage(hwndListBox, LB_ADDSTRING, IntPtr.Zero, itemText);
}
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
numItems.Text = "" + itemCount.ToString();
}
Partial Public Class HostWindow
Inherits Window
Private selectedItem As Integer
Private hwndListBox As IntPtr
Private listControl As ControlHost
Private app As Application
Private myWindow As Window
Private itemCount As Integer
Private Sub On_UIReady(ByVal sender As Object, ByVal e As EventArgs)
app = System.Windows.Application.Current
myWindow = app.MainWindow
myWindow.SizeToContent = SizeToContent.WidthAndHeight
listControl = New ControlHost(ControlHostElement.ActualHeight, ControlHostElement.ActualWidth)
ControlHostElement.Child = listControl
AddHandler listControl.MessageHook, AddressOf ControlMsgFilter
hwndListBox = listControl.hwndListBox
For i As Integer = 0 To 14 'populate listbox
Dim itemText As String = "Item" & i.ToString()
SendMessage(hwndListBox, LB_ADDSTRING, IntPtr.Zero, itemText)
Next i
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero)
numItems.Text = "" & itemCount.ToString()
End Sub
private IntPtr ControlMsgFilter(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
int textLength;
handled = false;
if (msg == WM_COMMAND)
{
switch ((uint)wParam.ToInt32() >> 16 & 0xFFFF) //extract the HIWORD
{
case LBN_SELCHANGE : //Get the item text and display it
selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero);
textLength = SendMessage(listControl.hwndListBox, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero);
StringBuilder itemText = new StringBuilder();
SendMessage(hwndListBox, LB_GETTEXT, selectedItem, itemText);
selectedText.Text = itemText.ToString();
handled = true;
break;
}
}
return IntPtr.Zero;
}
internal const int
LBN_SELCHANGE = 0x00000001,
WM_COMMAND = 0x00000111,
LB_GETCURSEL = 0x00000188,
LB_GETTEXTLEN = 0x0000018A,
LB_ADDSTRING = 0x00000180,
LB_GETTEXT = 0x00000189,
LB_DELETESTRING = 0x00000182,
LB_GETCOUNT = 0x0000018B;
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
internal static extern int SendMessage(IntPtr hwnd,
int msg,
IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
internal static extern int SendMessage(IntPtr hwnd,
int msg,
int wParam,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
internal static extern IntPtr SendMessage(IntPtr hwnd,
int msg,
IntPtr wParam,
String lParam);
Private Function ControlMsgFilter(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
Dim textLength As Integer
handled = False
If msg = WM_COMMAND Then
Select Case CUInt(wParam.ToInt32()) >> 16 And &HFFFF 'extract the HIWORD
Case LBN_SELCHANGE 'Get the item text and display it
selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero)
textLength = SendMessage(listControl.hwndListBox, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero)
Dim itemText As New StringBuilder()
SendMessage(hwndListBox, LB_GETTEXT, selectedItem, itemText)
selectedText.Text = itemText.ToString()
handled = True
End Select
End If
Return IntPtr.Zero
End Function
Friend Const LBN_SELCHANGE As Integer = &H1, WM_COMMAND As Integer = &H111, LB_GETCURSEL As Integer = &H188, LB_GETTEXTLEN As Integer = &H18A, LB_ADDSTRING As Integer = &H180, LB_GETTEXT As Integer = &H189, LB_DELETESTRING As Integer = &H182, LB_GETCOUNT As Integer = &H18B
<DllImport("user32.dll", EntryPoint:="SendMessage", CharSet:=CharSet.Unicode)>
Friend Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
<DllImport("user32.dll", EntryPoint:="SendMessage", CharSet:=CharSet.Unicode)>
Friend Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As StringBuilder) As Integer
End Function
<DllImport("user32.dll", EntryPoint:="SendMessage", CharSet:=CharSet.Unicode)>
Friend Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
End Function
Реализация взаимодействия между элементом управления и страницей
Вы управляете элементом управления, отправляя им сообщения Windows. Элемент управления уведомляет вас, когда пользователь взаимодействует с ним, отправляя уведомления в окно хоста. Пример размещения элемента управления Win32 ListBox в WPF включает пользовательский интерфейс, который показывает несколько примеров его работы.
Добавьте элемент в список.
Удаление выбранного элемента из списка
Отображение текста выбранного элемента.
Отображение количества элементов в списке.
Пользователь также может выбрать элемент в списке, щелкнув его так же, как и для обычного приложения Win32. Отображаемые данные обновляются каждый раз, когда пользователь изменяет состояние поля списка путем выбора, добавления или добавления элемента.
Чтобы добавить элементы, отправьте сообщение в поле LB_ADDSTRING списка. Чтобы удалить элементы, отправьте LB_GETCURSEL , чтобы получить индекс текущего выбора, а затем LB_DELETESTRING удалить элемент. Пример также отправляет LB_GETCOUNTи использует возвращаемое значение для обновления отображения, отображающего количество элементов. Оба этих экземпляра SendMessage используют одно из объявлений PInvoke, обсуждавшихся в предыдущем разделе.
private void AppendText(object sender, EventArgs args)
{
if (!string.IsNullOrEmpty(txtAppend.Text))
{
SendMessage(hwndListBox, LB_ADDSTRING, IntPtr.Zero, txtAppend.Text);
}
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
numItems.Text = "" + itemCount.ToString();
}
private void DeleteText(object sender, EventArgs args)
{
selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero);
if (selectedItem != -1) //check for selected item
{
SendMessage(hwndListBox, LB_DELETESTRING, (IntPtr)selectedItem, IntPtr.Zero);
}
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
numItems.Text = "" + itemCount.ToString();
}
Private Sub AppendText(ByVal sender As Object, ByVal args As EventArgs)
If txtAppend.Text <> String.Empty Then
SendMessage(hwndListBox, LB_ADDSTRING, IntPtr.Zero, txtAppend.Text)
End If
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero)
numItems.Text = "" & itemCount.ToString()
End Sub
Private Sub DeleteText(ByVal sender As Object, ByVal args As EventArgs)
selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero)
If selectedItem <> -1 Then 'check for selected item
SendMessage(hwndListBox, LB_DELETESTRING, New IntPtr(selectedItem), IntPtr.Zero)
End If
itemCount = SendMessage(hwndListBox, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero)
numItems.Text = "" & itemCount.ToString()
End Sub
Когда пользователь выбирает элемент или изменяет свой выбор, элемент управления уведомляет окно узла, отправив ему WM_COMMAND сообщение, которое вызывает MessageHook событие для страницы. Обработчик получает те же сведения, что и процедура главного окна хост-окна. Он также передает ссылку на логическое значение handled. Установите handled на true, чтобы указать, что вы обработали сообщение и дополнительная обработка не требуется.
WM_COMMAND отправляется по различным причинам, поэтому необходимо проверить идентификатор уведомления, чтобы определить, является ли это событием, которое требуется обрабатывать. Идентификатор содержится в высоком слове wParam параметра. В примере используются битовые операторы для извлечения идентификатора. Если пользователь сделал или изменил свой выбор, идентификатор будет LBN_SELCHANGE.
Когда LBN_SELCHANGE получено, выборка получает индекс выбранного элемента, отправляя элементу управления сообщение LB_GETCURSEL. Чтобы получить текст, сначала создайте StringBuilder. Затем вы отправляете элемент управления LB_GETTEXT сообщение. Передайте пустой StringBuilder объект в качестве wParam параметра. Когда SendMessage возвращается, StringBuilder будет содержать текст выбранного элемента. Это использование SendMessage требует еще одного объявления PInvoke.
Наконец, задайте значение handled на true, чтобы указать, что сообщение было обработано.
См. также
.NET Desktop feedback