Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Windows Presentation Foundation (WPF) biedt een uitgebreide omgeving voor het maken van toepassingen. Als u echter een aanzienlijke investering in Win32-code hebt, is het mogelijk effectiever om ten minste een deel van die code in uw WPF-toepassing opnieuw te gebruiken in plaats van deze volledig te herschrijven. WPF biedt een eenvoudig mechanisme voor het hosten van een Win32-venster, op een WPF-pagina.
In dit onderwerp wordt u begeleid bij het gebruik van de toepassing Hosting a Win32 ListBox Control in WPF Sample, die als host fungeert voor een Win32-keuzelijst. Deze algemene procedure kan worden uitgebreid tot het hosten van elk Win32-venster.
Behoeften
In dit onderwerp wordt ervan uitgegaan dat u bekend bent met zowel WPF- als Windows API-programmering. Zie Aan de slag voor een eenvoudige inleiding tot WPF-programmering. Zie een van de vele boeken over het onderwerp, met name Programmeren van Windows door Charles Petzold voor een inleiding tot het programmeren van Windows-API's.
Omdat het voorbeeld dat bij dit onderwerp hoort, wordt geïmplementeerd in C#, wordt gebruikgemaakt van Platform Invocation Services (PInvoke) voor toegang tot de Windows-API. Enige bekendheid met PInvoke is nuttig, maar niet essentieel.
Opmerking
Dit onderwerp bevat een aantal codevoorbeelden uit het bijbehorende voorbeeld. Voor leesbaarheid bevat het echter niet de volledige voorbeeldcode. U kunt volledige code verkrijgen of weergeven via Het hosten van een Win32 ListBox-besturingselement in WPF-voorbeeld.
De basisprocedure
In deze sectie vindt u een overzicht van de basisprocedure voor het hosten van een Win32-venster op een WPF-pagina. De resterende secties doorlopen de details van elke stap.
De basishostingprocedure is:
Implementeer een WPF-pagina om het venster te hosten. Een techniek is het maken van een Border element om een sectie van de pagina voor het gehoste venster te reserveren.
Implementeer een klasse om het besturingselement te hosten dat erft van HwndHost.
In die klasse overschrijft u het HwndHost klasselid BuildWindowCore.
Maak het gehoste venster als een onderliggend element van het venster dat de WPF-pagina bevat. Hoewel conventionele WPF-programmering er niet expliciet gebruik van hoeft te maken, is de hostingpagina een venster met een ingang (HWND). U ontvangt de pagina HWND via de
hwndParentparameter van de BuildWindowCore methode. Het gehoste venster moet worden gemaakt als een onderliggend element van deze HWND.Zodra u het hostvenster hebt gemaakt, retourneert u de HWND van het gehoste venster. Als u een of meer Win32-besturingselementen wilt hosten, maakt u doorgaans een hostvenster als kindvenster van de HWND en maakt u de besturingselementen kinderen van dat hostvenster. Het verpakken van de besturingselementen in een hostvenster biedt een eenvoudige manier voor uw WPF-pagina om meldingen te ontvangen van de besturingselementen, die betrekking hebben op bepaalde Win32-problemen met meldingen over de HWND-grens.
Geselecteerde berichten verwerken die naar het hostvenster worden verzonden, zoals meldingen van kindbesturingselementen. Er zijn twee manieren om dit te doen.
Als u liever berichten in uw hostingklasse verwerkt, overschrijft u de WndProc methode van de HwndHost klasse.
Wilt u liever dat WPF de berichten afhandelt, behandel dan de HwndHost klasse gebeurtenis MessageHook in uw code-behind. Deze gebeurtenis vindt plaats voor elk bericht dat wordt ontvangen door het gehoste venster. Als u deze optie kiest, moet u nog steeds overschrijven WndProc, maar u hebt slechts een minimale implementatie nodig.
Overschrijf de DestroyWindowCore en WndProc methoden van HwndHost. U moet deze methoden overschrijven om aan het HwndHost contract te voldoen, maar u hoeft mogelijk slechts een minimale implementatie te bieden.
Maak in uw code-behind-bestand een exemplaar van de klasse die het besturingselement host en maak het een kind van het Border-element dat bedoeld is om het venster te hosten.
Communiceer met het gehoste venster door Microsoft Windows-berichten te verzenden en berichten van de kindvensters te verwerken, zoals meldingen die door besturingselementen worden verzonden.
De pagina-indeling implementeren
De indeling voor de WPF-pagina die als host fungeert voor het besturingselement Keuzelijst bestaat uit twee regio's. Aan de linkerkant van de pagina worden verschillende WPF-besturingselementen gehost die een gebruikersinterface (UI) bieden waarmee u het Win32-besturingselement kunt bewerken. De rechterbovenhoek van de pagina heeft een vierkant gebied voor het gehoste ListBox-besturingselement (Keuzelijst).
De code voor het implementeren van deze indeling is vrij eenvoudig. Het hoofdelement is een DockPanel element met twee onderliggende elementen. De eerste is een Border-element dat als host fungeert voor het keuzelijst-besturingselement. Het neemt een 200x200 vierkant in de rechterbovenhoek van de pagina. De tweede is een StackPanel element dat een set WPF-besturingselementen bevat waarmee informatie wordt weergegeven en waarmee u het besturingselement ListBox kunt bewerken door weergegeven interoperation-eigenschappen in te stellen. Zie voor elk van de elementen die onderliggende elementen van de StackPanelelementen zijn, het referentiemateriaal voor de verschillende elementen die worden gebruikt voor meer informatie over wat deze elementen zijn of wat ze doen, deze worden vermeld in de onderstaande voorbeeldcode, maar worden hier niet uitgelegd (het basisinteroperabiliteitsmodel vereist geen van deze elementen, ze worden verstrekt om enige interactiviteit toe te voegen aan het voorbeeld).
<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>
Een klasse implementeren voor het hosten van het Microsoft Win32-besturingselement
De kern van dit voorbeeld is de klasse die daadwerkelijk als host fungeert voor het besturingselement, ControlHost.cs. Het neemt over van HwndHost. De constructor heeft twee parameters, hoogte en breedte, die overeenkomen met de hoogte en breedte van het Border element dat als host fungeert voor het besturingselement Keuzelijst. Deze waarden worden later gebruikt om ervoor te zorgen dat de grootte van het besturingselement overeenkomt met het Border element.
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
Er is ook een set constanten. Deze constanten zijn grotendeels afkomstig van Winuser.h en bieden u de mogelijkheid om conventionele namen te gebruiken bij het aanroepen van Win32-functies.
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 overschrijven om het Microsoft Win32-venster te maken
U overschrijft deze methode om het Win32-venster te maken dat wordt gehost door de pagina en maakt de verbinding tussen het venster en de pagina. Omdat dit voorbeeld een ListBox controle-element host, worden er twee vensters aangemaakt. Het eerste is het venster dat daadwerkelijk wordt gehost door de WPF-pagina. Het besturingselement Keuzelijst wordt gemaakt als een onderliggend element van dat venster.
De reden voor deze aanpak is het vereenvoudigen van het proces van het ontvangen van meldingen van het besturingselement. Met de HwndHost klasse kunt u berichten verwerken die naar het venster worden verzonden dat wordt gehost. Als u een Win32-besturingselement rechtstreeks host, ontvangt u de berichten die naar de interne berichtenlus van het besturingselement worden verzonden. U kunt het besturingselement weergeven en berichten verzenden, maar u ontvangt niet de meldingen die het besturingselement naar het bovenliggende venster verzendt. Dit betekent onder andere dat u geen manier hebt om te detecteren wanneer de gebruiker met het besturingselement communiceert. Maak in plaats daarvan een hostvenster en maak het besturingselement een kind van dat venster. Hiermee kunt u de berichten voor het hostvenster verwerken, inclusief de meldingen die door het besturingselement worden verzonden. Omdat het hostvenster weinig meer is dan een eenvoudige wrapper voor het besturingselement, wordt het pakket aangeduid als een ListBox-besturingselement.
Het Hostvenster en Keuzelijst-besturingselement maken
U kunt PInvoke gebruiken om een hostvenster voor het besturingselement te maken door een vensterklasse te maken en te registreren, enzovoort. Een veel eenvoudigere benadering is echter het maken van een venster met de vooraf gedefinieerde 'statische' vensterklasse. Dit biedt u de vensterprocedure die u nodig hebt om meldingen van het besturingselement te ontvangen en vereist minimale codering.
De HWND van het besturingselement wordt weergegeven via een alleen-lezen eigenschap, zodat de hostpagina deze kan gebruiken om berichten naar het besturingselement te verzenden.
public IntPtr hwndListBox
{
get { return hwndControl; }
}
Public ReadOnly Property hwndListBox() As IntPtr
Get
Return hwndControl
End Get
End Property
Het lijstvakbesturingselement wordt gemaakt als een onderdeel van het hostvenster. De hoogte en breedte van beide vensters worden ingesteld op de waarden die worden doorgegeven aan de constructor, hierboven besproken. Dit zorgt ervoor dat de grootte van het hostvenster en het bedieningselement identiek zijn aan het gereserveerde gebied op de pagina. Nadat de vensters zijn gemaakt, retourneert het voorbeeld een HandleRef object dat de HWND van het hostvenster bevat.
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 en WndProc implementeren
Bovendien BuildWindowCore moet u ook de WndProc en DestroyWindowCore methoden van de HwndHost overschrijven. In dit voorbeeld worden de berichten voor het besturingselement verwerkt door de MessageHook handler, dus de implementatie van WndProc en DestroyWindowCore is minimaal. Stel in het geval van WndProc, handled in op false om aan te geven dat het bericht niet is verwerkt en retourneer 0. Voor DestroyWindowCore gewoon het venster vernietigen.
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
De controle integreren op de pagina
Als u het besturingselement op de pagina wilt hosten, maakt u eerst een nieuw exemplaar van de ControlHost klasse. Geef de hoogte en breedte van het randelement met het besturingselement (ControlHostElement) door aan de ControlHost constructor. Dit zorgt ervoor dat de keuzelijst op de juiste manier wordt aangepast. Vervolgens host u het besturingselement op de pagina door het ControlHost object toe te wijzen aan de Child eigenschap van de host Border.
In het voorbeeld wordt een handler gekoppeld aan de MessageHook gebeurtenis van de ControlHost om berichten van het besturingselement te ontvangen. Deze gebeurtenis wordt gegenereerd voor elk bericht dat naar het gehoste venster wordt verzonden. In dit geval zijn dit de berichten die worden verzonden naar het venster waarin het werkelijke besturingselement Keuzelijst wordt verpakt, inclusief meldingen van het besturingselement. In het voorbeeld wordt SendMessage aanroepen om informatie van het besturingselement te verkrijgen en de inhoud ervan te wijzigen. De details van hoe de pagina communiceert met het besturingselement, worden in de volgende sectie besproken.
Opmerking
U ziet dat er twee PInvoke-declaraties zijn voor SendMessage. Dit is nodig omdat de wParam parameter wordt gebruikt om een tekenreeks door te geven en de andere gebruikt deze om een geheel getal door te geven. U hebt een afzonderlijke verklaring nodig voor elke handtekening om ervoor te zorgen dat de gegevens correct worden verwerkt.
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
Implementatie van communicatie tussen het besturingselement en de pagina
U manipuleert het besturingselement door Windows-berichten te verzenden. Het element laat u weten wanneer de gebruiker ermee interageert door meldingen naar het hostvenster te verzenden. Het hosten van een Win32 ListBox-besturingselement in WPF-voorbeeld bevat een gebruikersinterface die verschillende voorbeelden biedt van hoe dit werkt:
Voeg een item toe aan de lijst.
Het geselecteerde item uit de lijst verwijderen
De tekst van het geselecteerde item weergeven.
Het aantal items in de lijst weergeven.
De gebruiker kan ook een item in de keuzelijst selecteren door erop te klikken, net zoals voor een conventionele Win32-toepassing. De weergegeven gegevens worden telkens bijgewerkt wanneer de gebruiker de status van de keuzelijst wijzigt door een item te selecteren, toe te voegen of toe te voegen.
Als u items wilt toevoegen, verzendt u de keuzelijst een LB_ADDSTRING bericht. Als u items wilt verwijderen, verzendt u deze LB_GETCURSEL om de index van de huidige selectie op te halen en vervolgens LB_DELETESTRING het item te verwijderen. Het voorbeeld verzendt LB_GETCOUNTook en gebruikt de geretourneerde waarde om de weergave bij te werken waarin het aantal items wordt weergegeven. Beide gebruiksexemplaren SendMessage zijn een van de PInvoke-declaraties die in de vorige sectie zijn besproken.
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
Wanneer de gebruiker een item selecteert of de selectie wijzigt, ontvangt het besturingselement een melding over het hostvenster door het berichtWM_COMMAND te verzenden, waardoor de MessageHook gebeurtenis voor de pagina wordt gegenereerd. De handler ontvangt dezelfde informatie als de hoofdvensterprocedure van het hostvenster. Het geeft ook een verwijzing door naar een Booleaanse waarde, handled. U stelt deze in handled om true aan te geven dat u het bericht hebt verwerkt en dat er geen verdere verwerking nodig is.
WM_COMMAND wordt om verschillende redenen verzonden, dus u moet de meldings-id onderzoeken om te bepalen of het een gebeurtenis is die u wilt verwerken. De id staat in het hoge woord van de wParam parameter. In het voorbeeld worden bitsgewijze operators gebruikt om de id te extraheren. Als de gebruiker de selectie heeft gemaakt of gewijzigd, is LBN_SELCHANGEde id.
Wanneer LBN_SELCHANGE wordt ontvangen, haalt het voorbeeld de index van het geselecteerde item op door een bericht naar de bedieningselementen te sturenLB_GETCURSEL. Als u de tekst wilt ophalen, maakt u eerst een StringBuilder. Vervolgens stuurt u de controle een LB_GETTEXT bericht. Geef het lege StringBuilder object door als de wParam parameter. Wanneer SendMessage terugkeert, bevat StringBuilder de tekst van het geselecteerde item. Dit gebruik van SendMessage vereist opnieuw een PInvoke-verklaring.
Stel ten slotte handled in op true om aan te geven dat het bericht is behandeld.
Zie ook
.NET Desktop feedback