Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Odbieranie, przetwarzanie i zarządzanie danymi wejściowymi z urządzeń wskazujących (takich jak dotyk, mysz, pióro/rysik i touchpad) w aplikacjach systemu Windows.
Ważne
Tworzenie interakcji niestandardowych tylko wtedy, gdy istnieje jasne, dobrze zdefiniowane wymaganie i interakcje obsługiwane przez kontrolki platformy nie obsługują twojego scenariusza.
Jeśli dostosujesz środowiska interakcji w aplikacji systemu Windows, użytkownicy oczekują, że będą one spójne, intuicyjne i wykrywalne. Z tych powodów zalecamy modelowanie niestandardowych interakcji na tych obsługiwanych przez kontrolki platformy. Kontrolki platformy zapewniają pełne doświadczenie interakcji użytkownika z aplikacją systemu Windows, w tym standardowe interakcje, animowane efekty fizyczne, informacje zwrotne wizualne i ułatwienia dostępu.
Ważne interfejsy API
Pointers
Większość środowisk interakcji zwykle obejmuje użytkownika identyfikującego obiekt, z którym chce korzystać, wskazując go za pośrednictwem urządzeń wejściowych, takich jak dotyk, mysz, pióro/rysik i touchpad. Ponieważ nieprzetworzone dane urządzenia interfejsu człowieka (HID) udostępniane przez te urządzenia wejściowe zawierają wiele typowych właściwości, dane są promowane i konsolidowane w ujednoliconym stosie wejściowym i udostępniane jako dane wskaźnika niezależnego od urządzeń. Aplikacje systemu Windows mogą następnie korzystać z tych danych bez obaw o używane urządzenie wejściowe.
Uwaga / Notatka
Informacje specyficzne dla urządzenia są również promowane z nieprzetworzonych danych HID, jeśli aplikacja tego wymaga.
Każdy punkt wejściowy (lub kontakt) w stosie wejściowym jest reprezentowany przez obiekt wskaźnika uwidoczniony za pośrednictwem parametru PointerRoutedEventArgs w różnych programach obsługi zdarzeń wskaźnika. W przypadku wprowadzania przy użyciu wielu piór lub wielodotykowego, każdy kontakt jest traktowany jako unikalny wskaźnik wejściowy.
Zdarzenia wskaźnika
Zdarzenia wskaźnika uwidaczniają podstawowe informacje, takie jak typ urządzenia wejściowego i stan wykrywania (w zakresie lub kontakcie), oraz rozszerzone informacje, takie jak lokalizacja, ciśnienie i geometria kontaktu. Określone właściwości urządzenia, takie jak to, który przycisk myszy jest używany przez użytkownika lub czy końcówka gumki pióra jest używana, są również dostępne. Jeśli aplikacja musi rozróżniać urządzenia wejściowe i ich możliwości, zobacz Identyfikowanie urządzeń wejściowych.
Aplikacje systemu Windows mogą nasłuchiwać następujących zdarzeń wskaźnika:
Uwaga / Notatka
Ogranicz dane wejściowe wskaźnika do określonego elementu interfejsu użytkownika, wywołując metodę CapturePointer na tym elemencie w obrębie obsługi zdarzenia wskaźnika. Gdy wskaźnik jest przechwytywany przez element, tylko ten obiekt odbiera zdarzenia wejściowe wskaźnika, nawet gdy wskaźnik porusza się poza obszarem ograniczenia obiektu. IsInContact (naciśnięcie przycisku myszy, dotyk lub kontakt rysika) musi mieć wartość 'true', aby CapturePointer zakończył się pomyślnie.
| Event | Description |
|---|---|
Występuje, gdy wskaźnik (pointer) jest anulowany przez platformę. Może się to zdarzyć w następujących okolicznościach:
|
|
Występuje, gdy inny element interfejsu użytkownika przechwytuje wskaźnik, gdy wskaźnik zostanie zwolniony lub gdy inny wskaźnik zostanie przechwycony programowo.
Uwaga Nie ma odpowiedniego zdarzenia przechwytywania wskaźnika.
|
|
Występuje, gdy wskaźnik przechodzi do obszaru ograniczenia elementu. Może się to zdarzyć w nieco inny sposób dla dotyku, touchpada, myszy i rysika.
|
|
Występuje, gdy wskaźnik opuszcza obszar graniczny elementu. Może się to zdarzyć w nieco inny sposób na dotyk, touchpad, mysz i wprowadzanie pióra.
|
|
Występuje, gdy wskaźnik zmienia położenie, stan przycisku, ciśnienie, pochylenie lub geometrię styku (na przykład szerokość i wysokość) w granicach elementu. Może się to zdarzyć w nieco inny sposób przy użyciu wprowadzania dotykowego, touchpada, myszy i pióra.
|
|
Występuje, gdy wskaźnik wskazuje akcję naciśnięcia (taką jak dotknięcie, naciśnięcie przycisku myszy, dotknięcie piórem lub naciśnięcie przycisku touchpada) w obszarze graniczącym z elementem. CapturePointer musi być wywołany przez obsługującego dla tego zdarzenia. |
|
Występuje, gdy wskaźnik wskazuje akcję zwolnienia (na przykład puszczenie dotyku, puszczenie przycisku myszy, podniesienie pióra lub puszczenie przycisku touchpada) w obszarze ograniczającym elementu lub, jeśli wskaźnik jest przechwytywany, poza obszarem ograniczającym. |
|
Występuje, gdy koło myszy jest obracane. Dane wejściowe myszy są skojarzone z pojedynczym wskaźnikiem przypisanym podczas pierwszego wykrycia danych wejściowych myszy. Kliknięcie przycisku myszy (lewego, rolki lub prawego) powoduje ustanowienie drugorzędnego skojarzenia między wskaźnikiem a tym przyciskiem poprzez zdarzenie WskaźnikPrzesunięty. |
Przykład zdarzenia wskaźnika
Poniżej przedstawiono kilka fragmentów kodu z podstawowej aplikacji do śledzenia wskaźników, która pokazuje, jak nasłuchiwać zdarzeń dla wielu wskaźników i obsługiwać je oraz pobierać różne właściwości skojarzonych wskaźników.
Pobierz ten przykład z przykładu danych wejściowych wskaźnika (podstawowy)
Tworzenie interfejsu użytkownika
W tym przykładzie używamy prostokąta (Target) jako obiektu zużywającego dane wejściowe wskaźnika. Kolor miejsca docelowego zmienia się po zmianie stanu wskaźnika.
Szczegóły każdego wskaźnika są wyświetlane w ruchomym polu tekstowym TextBlock, które podąża za wskaźnikiem podczas jego przesuwania. Zdarzenia wskaźników są zgłaszane w elemencie RichTextBlock po prawej stronie prostokąta.
Jest to rozszerzalny język znaczników aplikacji (XAML) interfejsu użytkownika w tym przykładzie.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="320" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Canvas Name="Container"
Grid.Column="0"
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="245,0"
Height="320" Width="640">
<Rectangle Name="Target"
Fill="#FF0000"
Stroke="Black"
StrokeThickness="0"
Height="320" Width="640" />
</Canvas>
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="3">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Name="buttonClear"
Grid.Row="0"
Content="Clear"
Foreground="White"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
</Button>
<ScrollViewer Name="eventLogScrollViewer" Grid.Row="1"
VerticalScrollMode="Auto"
Background="Black">
<RichTextBlock Name="eventLog"
TextWrapping="Wrap"
Foreground="#FFFFFF"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Grid.ColumnSpan="2">
</RichTextBlock>
</ScrollViewer>
</Grid>
</Grid>
Nasłuchiwanie zdarzeń wskaźnika
W większości przypadków zalecamy uzyskanie informacji o wskaźniku za pośrednictwem elementu PointerRoutedEventArgs programu obsługi zdarzeń.
Jeśli argument zdarzenia nie udostępnia wymaganych szczegółów wskaźnika, możesz uzyskać dostęp do rozszerzonych informacji PointerPoint udostępnionych za pośrednictwem metod GetCurrentPoint i GetIntermediatePoints w PointerRoutedEventArgs.
Poniższy kod konfiguruje obiekt słownika globalnego do śledzenia każdego aktywnego wskaźnika i identyfikuje różne odbiorniki zdarzeń wskaźnika dla obiektu docelowego.
// Dictionary to maintain information about each active pointer.
// An entry is added during PointerPressed/PointerEntered events and removed
// during PointerReleased/PointerCaptureLost/PointerCanceled/PointerExited events.
Dictionary<uint, Windows.UI.Xaml.Input.Pointer> pointers;
public MainPage()
{
this.InitializeComponent();
// Initialize the dictionary.
pointers = new Dictionary<uint, Windows.UI.Xaml.Input.Pointer>();
// Declare the pointer event handlers.
Target.PointerPressed +=
new PointerEventHandler(Target_PointerPressed);
Target.PointerEntered +=
new PointerEventHandler(Target_PointerEntered);
Target.PointerReleased +=
new PointerEventHandler(Target_PointerReleased);
Target.PointerExited +=
new PointerEventHandler(Target_PointerExited);
Target.PointerCanceled +=
new PointerEventHandler(Target_PointerCanceled);
Target.PointerCaptureLost +=
new PointerEventHandler(Target_PointerCaptureLost);
Target.PointerMoved +=
new PointerEventHandler(Target_PointerMoved);
Target.PointerWheelChanged +=
new PointerEventHandler(Target_PointerWheelChanged);
buttonClear.Click +=
new RoutedEventHandler(ButtonClear_Click);
}
Obsługa zdarzeń wskaźnika
Następnie użyjemy opinii interfejsu użytkownika, aby zademonstrować podstawowe procedury obsługi zdarzeń wskaźnika.
Ta procedura obsługi zarządza zdarzeniem PointerPressed . Dodajemy zdarzenie do dziennika zdarzeń, dodajemy wskaźnik do aktywnego słownika wskaźnika i wyświetlamy szczegóły wskaźnika.
Uwaga / Notatka
Zdarzenia PointerPressed i PointerReleased nie zawsze występują w parach. Aplikacja powinna nasłuchiwać i obsługiwać dowolne zdarzenie, które może zakończyć wciśnięcie wskaźnika (czyli PointerExited, PointerCanceled i PointerCaptureLost).
/// <summary>
/// The pointer pressed event handler.
/// PointerPressed and PointerReleased don't always occur in pairs.
/// Your app should listen for and handle any event that can conclude
/// a pointer down (PointerExited, PointerCanceled, PointerCaptureLost).
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
void Target_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Down: " + ptrPt.PointerId);
// Lock the pointer to the target.
Target.CapturePointer(e.Pointer);
// Update event log.
UpdateEventLog("Pointer captured: " + ptrPt.PointerId);
// Check if pointer exists in dictionary (ie, enter occurred prior to press).
if (!pointers.ContainsKey(ptrPt.PointerId))
{
// Add contact to dictionary.
pointers[ptrPt.PointerId] = e.Pointer;
}
// Change background color of target when pointer contact detected.
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Green);
// Display pointer details.
CreateInfoPop(ptrPt);
}
- Ten program obsługuje zdarzenie PointerEntered. Dodajemy zdarzenie do dziennika zdarzeń, dodajemy wskaźnik do kolekcji wskaźników i wyświetlamy szczegóły wskaźnika.
/// <summary>
/// The pointer entered event handler.
/// We do not capture the pointer on this event.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerEntered(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Entered: " + ptrPt.PointerId);
// Check if pointer already exists (if enter occurred prior to down).
if (!pointers.ContainsKey(ptrPt.PointerId))
{
// Add contact to dictionary.
pointers[ptrPt.PointerId] = e.Pointer;
}
if (pointers.Count == 0)
{
// Change background color of target when pointer contact detected.
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
}
// Display pointer details.
CreateInfoPop(ptrPt);
}
Ten obsługiwacz obsługuje zdarzenie PointerMoved. Dodajemy zdarzenie do dziennika zdarzeń i aktualizujemy szczegóły wskaźnika.
Ważne
Dane wejściowe myszy są skojarzone z pojedynczym wskaźnikiem przypisanym podczas pierwszego wykrycia danych wejściowych myszy. Kliknięcie przycisku myszy (lewy, środkowy lub prawy) powoduje utworzenie pomocniczego skojarzenia między wskaźnikiem a tym przyciskiem za pośrednictwem zdarzenia PointerPressed. Zdarzenie PointerReleased jest uruchamiane tylko wtedy, gdy ten sam przycisk myszy zostanie zwolniony (żaden inny przycisk nie może być skojarzony ze wskaźnikiem do momentu ukończenia tego zdarzenia). Ze względu na to wyłączne skojarzenie inne kliknięcia przycisku myszy są kierowane przez zdarzenie PointerMoved .
/// <summary>
/// The pointer moved event handler.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Multiple, simultaneous mouse button inputs are processed here.
// Mouse input is associated with a single pointer assigned when
// mouse input is first detected.
// Clicking additional mouse buttons (left, wheel, or right) during
// the interaction creates secondary associations between those buttons
// and the pointer through the pointer pressed event.
// The pointer released event is fired only when the last mouse button
// associated with the interaction (not necessarily the initial button)
// is released.
// Because of this exclusive association, other mouse button clicks are
// routed through the pointer move event.
if (ptrPt.PointerDevice.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
if (ptrPt.Properties.IsLeftButtonPressed)
{
UpdateEventLog("Left button: " + ptrPt.PointerId);
}
if (ptrPt.Properties.IsMiddleButtonPressed)
{
UpdateEventLog("Wheel button: " + ptrPt.PointerId);
}
if (ptrPt.Properties.IsRightButtonPressed)
{
UpdateEventLog("Right button: " + ptrPt.PointerId);
}
}
// Display pointer details.
UpdateInfoPop(ptrPt);
}
- Ta obsługiwacz zarządza zdarzeniem PointerWheelChanged. Dodajemy zdarzenie do dziennika zdarzeń, dodajemy wskaźnik do tablicy wskaźników (w razie potrzeby) i wyświetlamy szczegóły wskaźnika.
/// <summary>
/// The pointer wheel event handler.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Mouse wheel: " + ptrPt.PointerId);
// Check if pointer already exists (for example, enter occurred prior to wheel).
if (!pointers.ContainsKey(ptrPt.PointerId))
{
// Add contact to dictionary.
pointers[ptrPt.PointerId] = e.Pointer;
}
// Display pointer details.
CreateInfoPop(ptrPt);
}
- Ta procedura obsługi zarządza zdarzeniem PointerReleased , w którym następuje zakończenie kontaktu z cyfryzatorem. Dodajemy zdarzenie do dziennika zdarzeń, usuwamy wskaźnik z kolekcji wskaźników i aktualizujemy szczegóły wskaźnika.
/// <summary>
/// The pointer released event handler.
/// PointerPressed and PointerReleased don't always occur in pairs.
/// Your app should listen for and handle any event that can conclude
/// a pointer down (PointerExited, PointerCanceled, PointerCaptureLost).
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
void Target_PointerReleased(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Up: " + ptrPt.PointerId);
// If event source is mouse or touchpad and the pointer is still
// over the target, retain pointer and pointer details.
// Return without removing pointer from pointers dictionary.
// For this example, we assume a maximum of one mouse pointer.
if (ptrPt.PointerDevice.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse)
{
// Update target UI.
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
DestroyInfoPop(ptrPt);
// Remove contact from dictionary.
if (pointers.ContainsKey(ptrPt.PointerId))
{
pointers[ptrPt.PointerId] = null;
pointers.Remove(ptrPt.PointerId);
}
// Release the pointer from the target.
Target.ReleasePointerCapture(e.Pointer);
// Update event log.
UpdateEventLog("Pointer released: " + ptrPt.PointerId);
}
else
{
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
}
}
- Ta procedura obsługi zarządza zdarzeniem PointerExited (gdy kontakt z cyfryzatorem jest utrzymywany). Dodajemy zdarzenie do dziennika zdarzeń, usuwamy wskaźnik z tablicy wskaźników i aktualizujemy szczegóły wskaźnika.
/// <summary>
/// The pointer exited event handler.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerExited(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Pointer exited: " + ptrPt.PointerId);
// Remove contact from dictionary.
if (pointers.ContainsKey(ptrPt.PointerId))
{
pointers[ptrPt.PointerId] = null;
pointers.Remove(ptrPt.PointerId);
}
if (pointers.Count == 0)
{
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Red);
}
// Update the UI and pointer details.
DestroyInfoPop(ptrPt);
}
- Ta procedura obsługi zarządza zdarzeniem pointerCanceled . Dodajemy zdarzenie do dziennika zdarzeń, usuwamy wskaźnik z tablicy wskaźników i aktualizujemy szczegóły wskaźnika.
/// <summary>
/// The pointer canceled event handler.
/// Fires for various reasons, including:
/// - Touch contact canceled by pen coming into range of the surface.
/// - The device doesn't report an active contact for more than 100ms.
/// - The desktop is locked or the user logged off.
/// - The number of simultaneous contacts exceeded the number supported by the device.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Pointer canceled: " + ptrPt.PointerId);
// Remove contact from dictionary.
if (pointers.ContainsKey(ptrPt.PointerId))
{
pointers[ptrPt.PointerId] = null;
pointers.Remove(ptrPt.PointerId);
}
if (pointers.Count == 0)
{
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
}
DestroyInfoPop(ptrPt);
}
Ta procedura obsługi zdarzeń zarządza zdarzeniem PointerCaptureLost. Dodajemy zdarzenie do dziennika zdarzeń, usuwamy wskaźnik z tablicy wskaźników i aktualizujemy szczegóły wskaźnika.
Uwaga / Notatka
UtrataPrzechwyceniaWskaźnika może wystąpić zamiast ZwolnieniaWskaźnika. Przechwytywanie wskaźnika można utracić z różnych powodów, takich jak interakcja użytkownika, programowe przechwytywanie innego wskaźnika, wywoływanie funkcji PointerReleased.
/// <summary>
/// The pointer capture lost event handler.
/// Fires for various reasons, including:
/// - User interactions
/// - Programmatic capture of another pointer
/// - Captured pointer was deliberately released
// PointerCaptureLost can fire instead of PointerReleased.
/// </summary>
/// <param name="sender">Source of the pointer event.</param>
/// <param name="e">Event args for the pointer routed event.</param>
private void Target_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
// Prevent most handlers along the event route from handling the same event again.
e.Handled = true;
PointerPoint ptrPt = e.GetCurrentPoint(Target);
// Update event log.
UpdateEventLog("Pointer capture lost: " + ptrPt.PointerId);
if (pointers.Count == 0)
{
Target.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
}
// Remove contact from dictionary.
if (pointers.ContainsKey(ptrPt.PointerId))
{
pointers[ptrPt.PointerId] = null;
pointers.Remove(ptrPt.PointerId);
}
DestroyInfoPop(ptrPt);
}
Pobierz właściwości wskaźnika
Jak wspomniano wcześniej, należy uzyskać rozszerzone informacje o wskaźniku z obiektu Windows.UI.Input.PointerPoint uzyskanego za pomocą metod GetCurrentPoint i GetIntermediatePoints klasy PointerRoutedEventArgs. Poniższe fragmenty kodu pokazują, jak to zrobić.
- Najpierw utworzymy nowy element TextBlock dla każdego wskaźnika.
/// <summary>
/// Create the pointer info popup.
/// </summary>
/// <param name="ptrPt">Reference to the input pointer.</param>
void CreateInfoPop(PointerPoint ptrPt)
{
TextBlock pointerDetails = new TextBlock();
pointerDetails.Name = ptrPt.PointerId.ToString();
pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
pointerDetails.Text = QueryPointer(ptrPt);
TranslateTransform x = new TranslateTransform();
x.X = ptrPt.Position.X + 20;
x.Y = ptrPt.Position.Y + 20;
pointerDetails.RenderTransform = x;
Container.Children.Add(pointerDetails);
}
- Następnie udostępniamy sposób aktualizowania informacji wskaźnika w istniejącym elemecie TextBlock skojarzonym z tym wskaźnikiem.
/// <summary>
/// Update the pointer info popup.
/// </summary>
/// <param name="ptrPt">Reference to the input pointer.</param>
void UpdateInfoPop(PointerPoint ptrPt)
{
foreach (var pointerDetails in Container.Children)
{
if (pointerDetails.GetType().ToString() == "Windows.UI.Xaml.Controls.TextBlock")
{
TextBlock textBlock = (TextBlock)pointerDetails;
if (textBlock.Name == ptrPt.PointerId.ToString())
{
// To get pointer location details, we need extended pointer info.
// We get the pointer info through the getCurrentPoint method
// of the event argument.
TranslateTransform x = new TranslateTransform();
x.X = ptrPt.Position.X + 20;
x.Y = ptrPt.Position.Y + 20;
pointerDetails.RenderTransform = x;
textBlock.Text = QueryPointer(ptrPt);
}
}
}
}
- Na koniec odpytujemy różne właściwości wskaźnika.
/// <summary>
/// Get pointer details.
/// </summary>
/// <param name="ptrPt">Reference to the input pointer.</param>
/// <returns>A string composed of pointer details.</returns>
String QueryPointer(PointerPoint ptrPt)
{
String details = "";
switch (ptrPt.PointerDevice.PointerDeviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
details += "\nPointer type: mouse";
break;
case Windows.Devices.Input.PointerDeviceType.Pen:
details += "\nPointer type: pen";
if (ptrPt.IsInContact)
{
details += "\nPressure: " + ptrPt.Properties.Pressure;
details += "\nrotation: " + ptrPt.Properties.Orientation;
details += "\nTilt X: " + ptrPt.Properties.XTilt;
details += "\nTilt Y: " + ptrPt.Properties.YTilt;
details += "\nBarrel button pressed: " + ptrPt.Properties.IsBarrelButtonPressed;
}
break;
case Windows.Devices.Input.PointerDeviceType.Touch:
details += "\nPointer type: touch";
details += "\nrotation: " + ptrPt.Properties.Orientation;
details += "\nTilt X: " + ptrPt.Properties.XTilt;
details += "\nTilt Y: " + ptrPt.Properties.YTilt;
break;
default:
details += "\nPointer type: n/a";
break;
}
GeneralTransform gt = Target.TransformToVisual(this);
Point screenPoint;
screenPoint = gt.TransformPoint(new Point(ptrPt.Position.X, ptrPt.Position.Y));
details += "\nPointer Id: " + ptrPt.PointerId.ToString() +
"\nPointer location (target): " + Math.Round(ptrPt.Position.X) + ", " + Math.Round(ptrPt.Position.Y) +
"\nPointer location (container): " + Math.Round(screenPoint.X) + ", " + Math.Round(screenPoint.Y);
return details;
}
Wskaźnik podstawowy
Niektóre urządzenia wejściowe, takie jak cyfrowy panel dotykowy lub touchpad, obsługują więcej niż typowy pojedynczy wskaźnik myszy lub pióra (w większości przypadków Surface Hub obsługuje dwa wejścia pióra).
Użyj właściwości IsPrimary tylko do odczytu klasy PointerPointerProperties , aby zidentyfikować i odróżnić pojedynczy wskaźnik podstawowy (podstawowy wskaźnik jest zawsze pierwszym wskaźnikiem wykrytym podczas sekwencji danych wejściowych).
Identyfikując podstawowy wskaźnik, można go użyć do emulowania danych wejściowych myszy lub pióra, dostosowywania interakcji lub udostępniania innych określonych funkcji lub interfejsu użytkownika.
Uwaga / Notatka
Jeśli podstawowy wskaźnik jest zwalniany, anulowany lub utracony podczas sekwencji danych wejściowych, podstawowy wskaźnik wejściowy nie zostanie utworzony, dopóki nie zostanie zainicjowana nowa sekwencja wejściowa (sekwencja wejściowa kończy się po zwolnieniu, anulowaniu lub utracie wszystkich wskaźników).
Przykład animacji wskaźnika podstawowego
Te fragmenty kodu pokazują, jak można zapewnić specjalną informację zwrotną wizualną, aby ułatwić użytkownikowi rozróżnienie między wejściami wskaźnika w aplikacji.
Ta konkretna aplikacja używa zarówno koloru, jak i animacji, aby wyróżnić wskaźnik podstawowy.
Pobierz ten przykład z przykładu danych wejściowych wskaźnika (UserControl z animacją)
Opinie wizualne
Definiujemy element UserControl oparty na obiekcie wielokropka XAML, który wyróżnia miejsce, w którym każdy wskaźnik znajduje się na kanwie i używa scenorysu do animowania wielokropka odpowiadającego wskaźnikowi podstawowemu.
Oto kod XAML:
<UserControl
x:Class="UWP_Pointers.PointerEllipse"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWP_Pointers"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="100"
d:DesignWidth="100">
<UserControl.Resources>
<Style x:Key="EllipseStyle" TargetType="Ellipse">
<Setter Property="Transitions">
<Setter.Value>
<TransitionCollection>
<ContentThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
<Storyboard x:Name="myStoryboard">
<!-- Animates the value of a Double property between
two target values using linear interpolation over the
specified Duration. -->
<DoubleAnimation
Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)"
Duration="0:0:1"
AutoReverse="True"
RepeatBehavior="Forever" From="1.0" To="1.4">
</DoubleAnimation>
<!-- Animates the value of a Double property between
two target values using linear interpolation over the
specified Duration. -->
<DoubleAnimation
Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleX)"
Duration="0:0:1"
AutoReverse="True"
RepeatBehavior="Forever" From="1.0" To="1.4">
</DoubleAnimation>
<!-- Animates the value of a Color property between
two target values using linear interpolation over the
specified Duration. -->
<ColorAnimation
Storyboard.TargetName="ellipse"
EnableDependentAnimation="True"
Storyboard.TargetProperty="(Fill).(SolidColorBrush.Color)"
From="White" To="Red" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="CompositionContainer">
<Ellipse Name="ellipse"
StrokeThickness="2"
Width="{x:Bind Diameter}"
Height="{x:Bind Diameter}"
Style="{StaticResource EllipseStyle}" />
</Grid>
</UserControl>
Oto kod:
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
// The User Control item template is documented at
// https://go.microsoft.com/fwlink/?LinkId=234236
namespace UWP_Pointers
{
/// <summary>
/// Pointer feedback object.
/// </summary>
public sealed partial class PointerEllipse : UserControl
{
// Reference to the application canvas.
Canvas canvas;
/// <summary>
/// Ellipse UI for pointer feedback.
/// </summary>
/// <param name="c">The drawing canvas.</param>
public PointerEllipse(Canvas c)
{
this.InitializeComponent();
canvas = c;
}
/// <summary>
/// Gets or sets the pointer Id to associate with the PointerEllipse object.
/// </summary>
public uint PointerId
{
get { return (uint)GetValue(PointerIdProperty); }
set { SetValue(PointerIdProperty, value); }
}
// Using a DependencyProperty as the backing store for PointerId.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty PointerIdProperty =
DependencyProperty.Register("PointerId", typeof(uint),
typeof(PointerEllipse), new PropertyMetadata(null));
/// <summary>
/// Gets or sets whether the associated pointer is Primary.
/// </summary>
public bool PrimaryPointer
{
get { return (bool)GetValue(PrimaryPointerProperty); }
set
{
SetValue(PrimaryPointerProperty, value);
}
}
// Using a DependencyProperty as the backing store for PrimaryPointer.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty PrimaryPointerProperty =
DependencyProperty.Register("PrimaryPointer", typeof(bool),
typeof(PointerEllipse), new PropertyMetadata(false));
/// <summary>
/// Gets or sets the ellipse style based on whether the pointer is Primary.
/// </summary>
public bool PrimaryEllipse
{
get { return (bool)GetValue(PrimaryEllipseProperty); }
set
{
SetValue(PrimaryEllipseProperty, value);
if (value)
{
SolidColorBrush fillBrush =
(SolidColorBrush)Application.Current.Resources["PrimaryFillBrush"];
SolidColorBrush strokeBrush =
(SolidColorBrush)Application.Current.Resources["PrimaryStrokeBrush"];
ellipse.Fill = fillBrush;
ellipse.Stroke = strokeBrush;
ellipse.RenderTransform = new CompositeTransform();
ellipse.RenderTransformOrigin = new Point(.5, .5);
myStoryboard.Begin();
}
else
{
SolidColorBrush fillBrush =
(SolidColorBrush)Application.Current.Resources["SecondaryFillBrush"];
SolidColorBrush strokeBrush =
(SolidColorBrush)Application.Current.Resources["SecondaryStrokeBrush"];
ellipse.Fill = fillBrush;
ellipse.Stroke = strokeBrush;
}
}
}
// Using a DependencyProperty as the backing store for PrimaryEllipse.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty PrimaryEllipseProperty =
DependencyProperty.Register("PrimaryEllipse",
typeof(bool), typeof(PointerEllipse), new PropertyMetadata(false));
/// <summary>
/// Gets or sets the diameter of the PointerEllipse object.
/// </summary>
public int Diameter
{
get { return (int)GetValue(DiameterProperty); }
set { SetValue(DiameterProperty, value); }
}
// Using a DependencyProperty as the backing store for Diameter. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DiameterProperty =
DependencyProperty.Register("Diameter", typeof(int),
typeof(PointerEllipse), new PropertyMetadata(120));
}
}
Tworzenie interfejsu użytkownika
Interfejs użytkownika w tym przykładzie jest ograniczony do wejściowej kanwy , w której śledzimy wszystkie wskaźniki i renderujemy wskaźniki wskaźnika i animację wskaźnika podstawowego (jeśli dotyczy) wraz z paskiem nagłówka zawierającym licznik wskaźnika i identyfikatorem wskaźnika podstawowego.
Oto plik MainPage.xaml:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="HeaderPanel"
Orientation="Horizontal"
Grid.Row="0">
<StackPanel.Transitions>
<TransitionCollection>
<AddDeleteThemeTransition/>
</TransitionCollection>
</StackPanel.Transitions>
<TextBlock x:Name="Header"
Text="Basic pointer tracking sample - IsPrimary"
Style="{ThemeResource HeaderTextBlockStyle}"
Margin="10,0,0,0" />
<TextBlock x:Name="PointerCounterLabel"
VerticalAlignment="Center"
Style="{ThemeResource BodyTextBlockStyle}"
Text="Number of pointers: "
Margin="50,0,0,0"/>
<TextBlock x:Name="PointerCounter"
VerticalAlignment="Center"
Style="{ThemeResource BodyTextBlockStyle}"
Text="0"
Margin="10,0,0,0"/>
<TextBlock x:Name="PointerPrimaryLabel"
VerticalAlignment="Center"
Style="{ThemeResource BodyTextBlockStyle}"
Text="Primary: "
Margin="50,0,0,0"/>
<TextBlock x:Name="PointerPrimary"
VerticalAlignment="Center"
Style="{ThemeResource BodyTextBlockStyle}"
Text="n/a"
Margin="10,0,0,0"/>
</StackPanel>
<Grid Grid.Row="1">
<!--The canvas where we render the pointer UI.-->
<Canvas x:Name="pointerCanvas"/>
</Grid>
</Grid>
Obsługa zdarzeń wskaźnika
Na koniec definiujemy nasze podstawowe obsługiwacze zdarzeń wskaźnika w pliku MainPage.xaml.cs jako kod zaplecza. Nie odtwórzmy tutaj kodu, ponieważ podstawy zostały omówione w poprzednim przykładzie, ale możesz pobrać przykład roboczy z przykładu wejściowego wskaźnika (UserControl z animacją).
Powiązane artykuły
Przykłady tematów
- Przykład danych wejściowych wskaźnika (podstawowy)
- Przykład danych wejściowych wskaźnika (UserControl z animacją)
Inne przykłady
- Podstawowy przykład danych wejściowych
- Przykład danych wejściowych o małym opóźnieniu
- Przykład trybu interakcji użytkownika
- Przykładowe wizualizacje stanu fokusu
Próbki archiwalne
- Dane wejściowe: przykładowe zdarzenia wejściowe użytkownika XAML
- Dane wejściowe: przykład możliwości urządzenia
- Dane wejściowe: próbka manipulacji i gestów
- Dane wejściowe: przykład testu trafień dotykowych
- Przykład XAML na przewijanie, przesuwanie i powiększanie
- Dane wejściowe: uproszczona próbka tuszu
Windows developer