Przegląd Dane wejściowe

Podsystem Windows Presentation Foundation (WPF) zapewnia zaawansowany interfejs API do uzyskiwania danych wejściowych z różnych urządzeń, w tym myszy, klawiatury, dotyku i rysika. W tym temacie opisano usługi udostępniane przez WPF i objaśniono architekturę systemów wejściowych.

Interfejs API danych wejściowych

Podstawowa ekspozycja interfejsu API danych wejściowych znajduje się w klasach podstawowych elementów: UIElement, , ContentElementFrameworkElementi FrameworkContentElement. Aby uzyskać więcej informacji na temat elementów podstawowych, zobacz Omówienie elementów podstawowych. Klasy te zapewniają funkcje zdarzeń wejściowych związanych z naciśnięciami klawiszy, przyciskami myszy, kółkiem myszy, ruchem myszy, zarządzaniem fokusem i przechwytywaniem myszy, aby wymienić kilka. Umieszczając wejściowy interfejs API w elementach podstawowych, a nie traktując wszystkich zdarzeń wejściowych jako usługi, architektura danych wejściowych umożliwia źródło zdarzeń wejściowych przez określony obiekt w interfejsie użytkownika oraz obsługę schematu routingu zdarzeń, w którym więcej niż jeden element ma możliwość obsługi zdarzenia wejściowego. Wiele zdarzeń wejściowych ma skojarzona para zdarzeń. Na przykład zdarzenie wyłączania klucza jest skojarzone z zdarzeniami KeyDown i .PreviewKeyDown Różnica w tych zdarzeniach polega na tym, jak są one kierowane do elementu docelowego. Podgląd zdarzeń tunelu w dół drzewa elementów z elementu głównego do elementu docelowego. Zdarzenia bubbling w górę z elementu docelowego do elementu głównego. Routing zdarzeń w WPF został omówiony bardziej szczegółowo w dalszej części tego przeglądu i w przeglądzie zdarzeń trasowanych.

Klasy klawiatury i myszy

Oprócz wejściowego interfejsu API w klasach Keyboard podstawowych elementów klasa i Mouse klasy zapewniają dodatkowy interfejs API do pracy z klawiaturą i wprowadzaniem myszy.

Przykłady wejściowego interfejsu API w Keyboard klasie to Modifiers właściwość, która zwraca ModifierKeys obecnie naciśnięcie, oraz IsKeyDown metodę, która określa, czy określony klawisz jest naciśnięty.

W poniższym przykładzie użyto GetKeyStates metody , aby określić, czy element Key znajduje się w stanie wyłączonym.

// Uses the Keyboard.GetKeyStates to determine if a key is down.
// A bitwise AND operation is used in the comparison.
// e is an instance of KeyEventArgs.
if ((Keyboard.GetKeyStates(Key.Return) & KeyStates.Down) > 0)
{
    btnNone.Background = Brushes.Red;
}
' Uses the Keyboard.GetKeyStates to determine if a key is down.
' A bitwise AND operation is used in the comparison. 
' e is an instance of KeyEventArgs.
If (Keyboard.GetKeyStates(Key.Return) And KeyStates.Down) > 0 Then
    btnNone.Background = Brushes.Red

Przykłady wejściowego interfejsu API w Mouse klasie to MiddleButton, który uzyskuje stan środkowego przycisku myszy, i DirectlyOver, który pobiera element wskaźnik myszy jest obecnie za przekroczeniem.

Poniższy przykład określa, czy LeftButton wskaźnik myszy znajduje się w Pressed stanie .

if (Mouse.LeftButton == MouseButtonState.Pressed)
{
    UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
    UpdateSampleResults("Left Button Pressed")
End If

Klasy Mouse i Keyboard zostały szczegółowo omówione w tym omówieniu.

Wprowadzanie rysików

WPF ma zintegrowaną obsługę programu Stylus. Jest Stylus to dane wejściowe pióra, które są popularne przez komputer Typu Tablet. Aplikacje WPF mogą traktować rysik jako mysz przy użyciu interfejsu API myszy, ale WPF uwidacznia również abstrakcję urządzenia rysika, który używa modelu podobnego do klawiatury i myszy. Wszystkie interfejsy API związane z rysikami zawierają słowo "Stylus".

Ponieważ rysik może działać jako mysz, aplikacje, które obsługują tylko wprowadzanie myszy, nadal mogą uzyskać pewien poziom obsługi rysika automatycznie. Gdy rysik jest używany w taki sposób, aplikacja ma możliwość obsługi odpowiedniego zdarzenia rysika, a następnie obsługuje odpowiednie zdarzenie myszy. Ponadto usługi wyższego poziomu, takie jak dane wejściowe pisma oddyskowego, są również dostępne za pośrednictwem abstrakcji urządzenia stylus. Aby uzyskać więcej informacji na temat pisma oddyskowego jako danych wejściowych, zobacz Wprowadzenie do pisma odk.

Routing zdarzeń

Element FrameworkElement może zawierać inne elementy jako elementy podrzędne w kon tryb namiotu l, tworząc drzewo elementów. W WPF element nadrzędny może uczestniczyć w danych wejściowych skierowanych do jego elementów podrzędnych lub innych elementów potomnych przez przekazanie zdarzeń. Jest to szczególnie przydatne w przypadku tworzenia kontrolek z mniejszych kontrolek, procesu znanego jako "kompozycja sterowania" lub "komponowanie". Aby uzyskać więcej informacji na temat drzew elementów i sposobu, w jaki drzewa elementów odnoszą się do tras zdarzeń, zobacz Drzewa w WPF.

Routing zdarzeń to proces przekazywania zdarzeń do wielu elementów, dzięki czemu określony obiekt lub element wzdłuż trasy może wybrać opcję zaoferowania znaczącej odpowiedzi (poprzez obsługę) zdarzenia, które mogło zostać pozyskane przez inny element. Zdarzenia trasowane używają jednego z trzech mechanizmów routingu: bezpośredniego, bubbling i tunelowania. W routingu bezpośrednim element źródłowy jest jedynym elementem powiadamianym, a zdarzenie nie jest kierowane do żadnych innych elementów. Jednak zdarzenie kierowane bezpośrednio nadal oferuje pewne dodatkowe możliwości, które są obecne tylko dla zdarzeń kierowanych, w przeciwieństwie do standardowych zdarzeń CLR. Bubbling działa w drzewie elementów, najpierw powiadamiając element, który wygenerował zdarzenie, a następnie element nadrzędny itd. Tunelowanie rozpoczyna się od katalogu głównego drzewa elementów i działa w dół, kończąc na oryginalnym elemenie źródłowym. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Routed Events Overview (Przegląd zdarzeń trasowanych).

Zdarzenia wejściowe WPF zazwyczaj występują w parach składających się z zdarzenia tunelowania i zdarzenia bubbling. Zdarzenia tunelowania różnią się od zdarzeń bubbling z prefiksem "Wersja zapoznawcza". Na przykład PreviewMouseMove jest to wersja tunelowania zdarzenia przenoszenia myszy i MouseMove jest wersję bubbling tego zdarzenia. To parowanie zdarzeń jest konwencją zaimplementowaną na poziomie elementu i nie jest nieodłączną możliwością systemu zdarzeń WPF. Aby uzyskać szczegółowe informacje, zobacz sekcję Zdarzenia wejściowe WPF w temacie Przegląd zdarzeń trasowanych.

Obsługa zdarzeń wejściowych

Aby odbierać dane wejściowe dla elementu, program obsługi zdarzeń musi być skojarzony z tym konkretnym zdarzeniem. W języku XAML jest to proste: odwołujesz się do nazwy zdarzenia jako atrybutu elementu, który będzie nasłuchiwać tego zdarzenia. Następnie należy ustawić wartość atrybutu na nazwę zdefiniowanej procedury obsługi zdarzeń na podstawie delegata. Procedura obsługi zdarzeń musi być napisana w kodzie, takim jak C#, i może być zawarta w pliku za pomocą kodu.

Zdarzenia klawiatury występują, gdy system operacyjny zgłasza akcje klawiszy, które występują, gdy fokus klawiatury dotyczy elementu. Zdarzenia myszy i rysika są podzielone na dwie kategorie: zdarzenia, które zgłaszają zmiany położenia wskaźnika względem elementu, oraz zdarzenia, które zgłaszają zmiany stanu przycisków urządzenia.

Przykład zdarzenia wprowadzania klawiatury

Poniższy przykład nasłuchuje naciśnięcia klawisza strzałki w lewo. Zostanie StackPanel utworzony element z elementem Button. Procedura obsługi zdarzeń do nasłuchiwania naciśnięcia klawisza strzałki po lewej Button stronie jest dołączona do wystąpienia.

Pierwsza sekcja przykładu tworzy StackPanel element i Button i dołącza procedurę obsługi zdarzeń dla elementu KeyDown.

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
// Create the UI elements.
StackPanel keyboardStackPanel = new StackPanel();
Button keyboardButton1 = new Button();

// Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue;
keyboardButton1.Content = "Button 1";

// Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1);

// Attach event handler.
keyboardButton1.KeyDown += new KeyEventHandler(OnButtonKeyDown);
' Create the UI elements.
Dim keyboardStackPanel As New StackPanel()
Dim keyboardButton1 As New Button()

' Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue
keyboardButton1.Content = "Button 1"

' Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1)

' Attach event handler.
AddHandler keyboardButton1.KeyDown, AddressOf OnButtonKeyDown

Druga sekcja jest napisana w kodzie i definiuje procedurę obsługi zdarzeń. Po naciśnięciu klawisza strzałki w lewo i naciśnięciu fokusu Button klawiatury program obsługi zostanie uruchomiony, a Background kolor Button elementu zostanie zmieniony. Jeśli klawisz jest naciśnięty, ale nie jest to klawisz strzałki w lewo, Background kolor Button elementu zostanie zmieniony z powrotem na jego kolor początkowy.

private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    Button source = e.Source as Button;
    if (source != null)
    {
        if (e.Key == Key.Left)
        {
            source.Background = Brushes.LemonChiffon;
        }
        else
        {
            source.Background = Brushes.AliceBlue;
        }
    }
}
Private Sub OnButtonKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    Dim source As Button = TryCast(e.Source, Button)
    If source IsNot Nothing Then
        If e.Key = Key.Left Then
            source.Background = Brushes.LemonChiffon
        Else
            source.Background = Brushes.AliceBlue
        End If
    End If
End Sub

Przykład zdarzenia wprowadzania myszy

W poniższym przykładzie kolor elementu Button jest zmieniany po Background wprowadzeniu Buttonwskaźnika myszy. Kolor Background jest przywracany, gdy mysz opuszcza Buttonelement .

Pierwsza sekcja przykładu tworzy kontrolkę StackPanelButton i dołącza programy obsługi zdarzeń dla zdarzeń MouseEnter i MouseLeave do elementu Button.

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button
          
  </Button>
</StackPanel>
// Create the UI elements.
StackPanel mouseMoveStackPanel = new StackPanel();
Button mouseMoveButton = new Button();

// Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue;
mouseMoveButton.Content = "Button";

// Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton);

// Attach event handler.
mouseMoveButton.MouseEnter += new MouseEventHandler(OnMouseExampleMouseEnter);
mouseMoveButton.MouseLeave += new MouseEventHandler(OnMosueExampleMouseLeave);
' Create the UI elements.
Dim mouseMoveStackPanel As New StackPanel()
Dim mouseMoveButton As New Button()

' Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue
mouseMoveButton.Content = "Button"

' Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton)

' Attach event handler.
AddHandler mouseMoveButton.MouseEnter, AddressOf OnMouseExampleMouseEnter
AddHandler mouseMoveButton.MouseLeave, AddressOf OnMosueExampleMouseLeave

Druga sekcja przykładu jest napisana w kodzie i definiuje procedury obsługi zdarzeń. Gdy mysz wprowadzi Buttonznak , Background kolor elementu Button zostanie zmieniony na SlateGray. Gdy mysz opuszcza Buttonelement , Background kolor Button elementu zostanie zmieniony z powrotem na AliceBlue.

private void OnMouseExampleMouseEnter(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.SlateGray;
    }
}
Private Sub OnMouseExampleMouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.SlateGray
    End If
End Sub
private void OnMosueExampleMouseLeave(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.AliceBlue;
    }
}
Private Sub OnMosueExampleMouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.AliceBlue
    End If
End Sub

Wprowadzanie tekstu

Zdarzenie TextInput umożliwia nasłuchiwanie wprowadzania tekstu w sposób niezależny od urządzenia. Klawiatura jest podstawowym sposobem wprowadzania tekstu, ale mowy, pisma ręcznego i innych urządzeń wejściowych może również generować dane wejściowe tekstu.

W przypadku danych wejściowych za pomocą klawiatury WPF najpierw wysyła odpowiednie KeyDown/KeyUp zdarzenia. Jeśli te zdarzenia nie są obsługiwane, a klucz jest tekstowy (zamiast klucza sterującego, takiego jak strzałki kierunkowe lub klucze funkcji), TextInput zdarzenie jest zgłaszane. Nie zawsze istnieje proste mapowanie jeden do jednego między zdarzeniami KeyDown/KeyUp i TextInput , ponieważ wiele naciśnięć klawiszy może wygenerować pojedynczy znak wprowadzania tekstu i pojedyncze naciśnięcia klawiszy może generować ciągi wieloznakowe. Dotyczy to szczególnie języków, takich jak chiński, japoński i koreański, które używają edytorów metod wejściowych (IME) do generowania tysięcy możliwych znaków w odpowiednich alfabetach.

Gdy WPF wysyła KeyUp/KeyDown zdarzenie, jest ustawiana na Key.System wartość , Key jeśli naciśnięcie klawiszy może stać się częścią TextInput zdarzenia (jeśli na przykład alt+S jest naciśnięty). Dzięki temu kod w procedurze obsługi zdarzeń KeyDown umożliwia sprawdzenie Key.System i, w przypadku znalezienia, pozostawienie przetwarzania dla procedury obsługi zdarzenia, które następnie zostało zgłoszone TextInput . W takich przypadkach różne właściwości argumentu TextCompositionEventArgs mogą służyć do określania oryginalnych naciśnięć klawiszy. Podobnie, jeśli IME jest aktywny, Key ma wartość Key.ImeProcessedi ImeProcessedKey daje oryginalne naciśnięcie klawiszy lub naciśnięcia klawiszy.

W poniższym przykładzie zdefiniowano procedurę obsługi dla Click zdarzenia i procedurę obsługi dla KeyDown zdarzenia.

Pierwszy segment kodu lub znaczników tworzy interfejs użytkownika.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
// Create the UI elements.
StackPanel textInputStackPanel = new StackPanel();
Button textInputeButton = new Button();
TextBox textInputTextBox = new TextBox();
textInputeButton.Content = "Open";

// Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton);
textInputStackPanel.Children.Add(textInputTextBox);

// Attach event handlers.
textInputStackPanel.KeyDown += new KeyEventHandler(OnTextInputKeyDown);
textInputeButton.Click += new RoutedEventHandler(OnTextInputButtonClick);
' Create the UI elements.
Dim textInputStackPanel As New StackPanel()
Dim textInputeButton As New Button()
Dim textInputTextBox As New TextBox()
textInputeButton.Content = "Open"

' Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton)
textInputStackPanel.Children.Add(textInputTextBox)

' Attach event handlers.
AddHandler textInputStackPanel.KeyDown, AddressOf OnTextInputKeyDown
AddHandler textInputeButton.Click, AddressOf OnTextInputButtonClick

Drugi segment kodu zawiera programy obsługi zdarzeń.

private void OnTextInputKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.O && Keyboard.Modifiers == ModifierKeys.Control)
    {
        handle();
        e.Handled = true;
    }
}

private void OnTextInputButtonClick(object sender, RoutedEventArgs e)
{
    handle();
    e.Handled = true;
}

public void handle()
{
    MessageBox.Show("Pretend this opens a file");
}
Private Sub OnTextInputKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.Key = Key.O AndAlso Keyboard.Modifiers = ModifierKeys.Control Then
        handle()
        e.Handled = True
    End If
End Sub

Private Sub OnTextInputButtonClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
    handle()
    e.Handled = True
End Sub

Public Sub handle()
    MessageBox.Show("Pretend this opens a file")
End Sub

Ponieważ zdarzenia wejściowe bąbelki trasy zdarzeń, odbiera dane wejściowe niezależnie od tego, StackPanel który element ma fokus klawiatury. Kontrolka TextBox jest najpierw powiadamiana, a OnTextInputKeyDown procedura obsługi jest wywoływana tylko wtedy, gdy TextBox nie obsłuży danych wejściowych. Jeśli zdarzenie PreviewKeyDown jest używane zamiast KeyDown zdarzenia, program obsługi jest wywoływany OnTextInputKeyDown jako pierwszy.

W tym przykładzie logika obsługi jest zapisywana dwa razy — raz dla ctrl+O i ponownie dla zdarzenia kliknięcia przycisku. Można to uprościć za pomocą poleceń zamiast bezpośrednio obsługiwać zdarzenia wejściowe. Polecenia zostały omówione w tym omówieniu i w temacie Commanding Overview (Omówienie poleceń).

Dotyk i manipulowanie

Nowy sprzęt i interfejs API w systemie operacyjnym Windows 7 zapewniają aplikacjom możliwość odbierania danych wejściowych z wielu dotknięciów jednocześnie. WPF umożliwia aplikacjom wykrywanie i reagowanie na dotyk w sposób podobny do reagowania na inne dane wejściowe, takie jak mysz lub klawiatura, przez wywoływanie zdarzeń w przypadku wystąpienia dotyku.

WPF uwidacznia dwa typy zdarzeń w przypadku wystąpienia dotyku: zdarzenia dotykowe i zdarzenia manipulowania. Zdarzenia dotykowe zapewniają nieprzetworzone dane dotyczące każdego palca na ekranie dotykowym i jego ruchu. Zdarzenia manipulowania interpretują dane wejściowe jako określone akcje. Oba typy zdarzeń zostały omówione w tej sekcji.

Wymagania wstępne

Potrzebne są następujące składniki, aby utworzyć aplikację, która reaguje na dotyk.

  • Visual Studio 2010.

  • Windows 7.

  • Urządzenie, takie jak ekran dotykowy, który obsługuje funkcję Windows Touch.

Terminologia

Podczas omawiania dotyku są używane następujące terminy.

  • Touch to typ danych wejściowych użytkownika rozpoznawanych przez system Windows 7. Zazwyczaj dotyk jest inicjowany przez umieszczenie palców na ekranie dotykowym. Należy pamiętać, że urządzenia takie jak touchpad, który jest typowy na komputerach przenośnych, nie obsługują dotyku, jeśli urządzenie tylko konwertuje położenie i ruch palca jako wejście myszy.

  • Multitouch to dotyk, który występuje z więcej niż jednego punktu jednocześnie. Systemy Windows 7 i WPF obsługują funkcję multitouch. Za każdym razem, gdy dotyk jest omówiony w dokumentacji platformy WPF, koncepcje mają zastosowanie do wielodotyku.

  • Manipulacja występuje, gdy dotyk jest interpretowany jako akcja fizyczna stosowana do obiektu. W WPF zdarzenia manipulowania interpretują dane wejściowe jako translacja, rozszerzanie lub manipulowanie rotacją.

  • Element touch device reprezentuje urządzenie, które generuje dane wejściowe dotyku, takie jak pojedynczy palec na ekranie dotykowym.

Kontrolki reagujące na dotyk

Poniższe kontrolki można przewijać, przeciągając palcem przez kontrolkę, jeśli zawiera zawartość przewiniętą z widoku.

Definiuje ScrollViewer dołączoną ScrollViewer.PanningMode właściwość, która umożliwia określenie, czy przesuwanie dotykowe jest włączone w poziomie, w pionie, zarówno, jak i nie. Właściwość ScrollViewer.PanningDeceleration określa, jak szybko przewijanie spowalnia, gdy użytkownik podnosi palec z ekranu dotykowego. Dołączona ScrollViewer.PanningRatio właściwość określa stosunek przesunięcia przewijania do przesunięcia manipulowania translacji.

Zdarzenia dotykowe

Klasy bazowe , UIElement, UIElement3Di ContentElementdefiniują zdarzenia, które można subskrybować, aby aplikacja odpowiadała na dotyk. Zdarzenia dotykowe są przydatne, gdy aplikacja interpretuje dotyk jako coś innego niż manipulowanie obiektem. Na przykład aplikacja, która umożliwia użytkownikowi rysowanie za pomocą co najmniej jednego palca, będzie subskrybować zdarzenia dotykowe.

Wszystkie trzy klasy definiują następujące zdarzenia, które zachowują się podobnie, niezależnie od klasy definiującej.

Podobnie jak zdarzenia klawiatury i myszy, zdarzenia dotykowe są kierowane zdarzenia. Zdarzenia, które zaczynają się od Preview , to zdarzenia tunelowania i zdarzenia, które zaczynają się Touch od, to zdarzenia bubbling. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Routed Events Overview (Przegląd zdarzeń trasowanych). Po obsłużeniu tych zdarzeń można uzyskać pozycję danych wejściowych względem dowolnego elementu, wywołując metodę GetTouchPoint or GetIntermediateTouchPoints .

Aby zrozumieć interakcję między zdarzeniami dotykowymi, rozważ scenariusz, w którym użytkownik umieszcza jeden palec na elemecie, przenosi palcem w element, a następnie podnosi palec z elementu. Na poniższej ilustracji przedstawiono wykonywanie zdarzeń bubbling (zdarzenia tunelowania są pomijane dla uproszczenia).

The sequence of touch events. Zdarzenia dotykowe

Poniższa lista zawiera opis sekwencji zdarzeń na poprzedniej ilustracji.

  1. Zdarzenie TouchEnter występuje jeden raz, gdy użytkownik umieści palec na elemecie.

  2. Zdarzenie TouchDown występuje jeden raz.

  3. Zdarzenie TouchMove występuje wiele razy, gdy użytkownik przesuwa palec w elemecie .

  4. Zdarzenie TouchUp występuje jeden raz, gdy użytkownik podnosi palec z elementu.

  5. Zdarzenie TouchLeave występuje jeden raz.

Gdy używane są więcej niż dwa palce, zdarzenia występują dla każdego palca.

Zdarzenia manipulowania

W przypadkach, gdy aplikacja umożliwia użytkownikowi manipulowanie obiektem, UIElement klasa definiuje zdarzenia manipulowania. W przeciwieństwie do zdarzeń dotykowych, które po prostu zgłaszają położenie dotyku, zdarzenia manipulacji raportują sposób interpretowania danych wejściowych. Istnieją trzy typy manipulacji, tłumaczenia, rozszerzania i rotacji. Na poniższej liście opisano sposób wywoływania trzech typów manipulacji.

  • Umieść palec na obiekcie i przesuń palcem przez ekran dotykowy, aby wywołać manipulację tłumaczenia. Zwykle powoduje to przeniesienie obiektu.

  • Umieść dwa palce na obiekcie i przesuń palce bliżej lub dalej od siebie, aby wywołać manipulację ekspansji. Zwykle zmienia to rozmiar obiektu.

  • Umieść dwa palce na obiekcie i obróć palce wokół siebie, aby wywołać manipulację rotacją. Zwykle obraca to obiekt.

Jednocześnie może wystąpić więcej niż jeden typ manipulacji.

Gdy obiekty reagują na manipulacje, może pojawić się, że obiekt ma inercję. Może to sprawić, że obiekty symulują świat fizyczny. Na przykład, gdy wypchniesz książkę do stołu, jeśli wypchniesz wystarczająco mocno, książka będzie nadal przenosić się po jej wydaniu. WPF umożliwia symulowanie tego zachowania przez podniesienie zdarzeń manipulacji po tym, jak palce użytkownika zwalniają obiekt.

Aby uzyskać informacje o sposobie tworzenia aplikacji, która umożliwia użytkownikowi przenoszenie, zmienianie rozmiaru i obracanie obiektu, zobacz Przewodnik: tworzenie pierwszej aplikacji dotykowej.

Element UIElement definiuje następujące zdarzenia manipulowania.

Domyślnie element UIElement nie odbiera tych zdarzeń manipulowania. Aby odbierać zdarzenia manipulacji w obiekcie UIElement, ustaw UIElement.IsManipulationEnabled wartość true.

Ścieżka wykonywania zdarzeń manipulowania

Rozważmy scenariusz, w którym użytkownik "zgłasza" obiekt. Użytkownik umieszcza palec na obiekcie, porusza palcem przez ekran dotykowy na krótką odległość, a następnie podnosi palec, gdy porusza się. Wynikiem tego jest to, że obiekt zostanie przeniesiony pod palec użytkownika i będzie nadal poruszać się po tym, jak użytkownik podnosi palec.

Na poniższej ilustracji przedstawiono ścieżkę wykonywania zdarzeń manipulowania i ważne informacje o każdym zdarzeniu.

The sequence of manipulation events. Zdarzenia manipulowania

Poniższa lista zawiera opis sekwencji zdarzeń na poprzedniej ilustracji.

  1. Zdarzenie ManipulationStarting występuje, gdy użytkownik umieszcza palec na obiekcie. Między innymi to zdarzenie umożliwia ustawienie ManipulationContainer właściwości. W kolejnych zdarzeniach pozycja manipulacji będzie względna względem elementu ManipulationContainer. W przypadku zdarzeń innych niż ManipulationStartingta właściwość jest tylko do odczytu, więc ManipulationStarting zdarzenie jest jedynym czasem, w którym można ustawić tę właściwość.

  2. Zdarzenie ManipulationStarted odbywa się dalej. To zdarzenie zgłasza źródło manipulacji.

  3. Zdarzenie ManipulationDelta występuje wielokrotnie, gdy palce użytkownika poruszają się na ekranie dotykowym. Właściwość DeltaManipulationManipulationDeltaEventArgs klasy zgłasza, czy manipulacja jest interpretowana jako ruch, rozszerzanie lub tłumaczenie. W tym miejscu wykonujesz większość pracy podczas manipulowania obiektem.

  4. Zdarzenie ManipulationInertiaStarting występuje, gdy palce użytkownika tracą kontakt z obiektem. To zdarzenie umożliwia określenie opóźnienia manipulacji podczas inercji. Jest to tak, aby obiekt mógł emulować różne przestrzenie fizyczne lub atrybuty, jeśli wybierzesz. Załóżmy na przykład, że aplikacja ma dwa obiekty reprezentujące elementy w świecie fizycznym, a jeden jest cięższy niż drugi. Można sprawić, że cięższy obiekt zwolnić szybciej niż lżejszy obiekt.

  5. Zdarzenie ManipulationDelta występuje wiele razy w miarę inercji. Należy pamiętać, że to zdarzenie występuje, gdy palce użytkownika poruszają się po ekranie dotykowym i gdy WPF symuluje inercję. Innymi słowy, ManipulationDelta występuje przed i po ManipulationInertiaStarting zdarzeniu. Właściwość ManipulationDeltaEventArgs.IsInertial zgłasza, ManipulationDelta czy zdarzenie występuje podczas inercji, aby można było sprawdzić tę właściwość i wykonać różne akcje, w zależności od jego wartości.

  6. Zdarzenie ManipulationCompleted występuje po zakończeniu manipulacji i inercji. Oznacza to, ManipulationCompleted że po wystąpieniu ManipulationDelta wszystkich zdarzeń zdarzenie ma na celu sygnalizowanie ukończenia manipulacji.

Element UIElement definiuje ManipulationBoundaryFeedback również zdarzenie. To zdarzenie występuje, gdy ReportBoundaryFeedback metoda jest wywoływana ManipulationDelta w zdarzeniu. Zdarzenie ManipulationBoundaryFeedback umożliwia aplikacjom lub składnikom przekazywanie opinii wizualnych, gdy obiekt osiąga granicę. Na przykład Window klasa obsługuje ManipulationBoundaryFeedback zdarzenie, aby spowodować nieznaczne przesunięcie okna po napotkaniu krawędzi.

Manipulowanie można anulować, wywołując metodę Cancel na argumentach zdarzeń w dowolnym zdarzeniu manipulowania, z wyjątkiem ManipulationBoundaryFeedback zdarzenia. Wywołanie Cancelmetody powoduje, że zdarzenia manipulowania nie są już wywoływane, a zdarzenia myszy występują w przypadku dotyku. W poniższej tabeli opisano relację między czasem anulowania manipulacji a zdarzeniami myszy, które występują.

Zdarzenie, które anuluj jest wywoływane w Zdarzenia myszy występujące dla danych wejściowych, które już wystąpiły
ManipulationStarting i ManipulationStarted Zdarzenia myszy w dół.
ManipulationDelta Zdarzenia przenoszenia myszy w dół i myszy.
ManipulationInertiaStarting i ManipulationCompleted Myszy w dół, ruch myszą i zdarzenia myszy w górę.

Należy pamiętać, że jeśli wywołasz Cancel metodę , gdy manipulacja jest niewładna, metoda zwraca false wartość , a dane wejściowe nie zgłaszają zdarzeń myszy.

Relacja między zdarzeniami dotyku i manipulowania

Zawsze UIElement może odbierać zdarzenia dotykowe. Gdy właściwość jest ustawiona IsManipulationEnabled na truewartość , UIElement element może odbierać zdarzenia dotyku i manipulowania. TouchDown Jeśli zdarzenie nie jest obsługiwane (czyli Handled właściwość to false), logika manipulowania przechwytuje dotyk do elementu i generuje zdarzenia manipulacji. Jeśli właściwość jest ustawiona Handled na true wartość w TouchDown zdarzeniu, logika manipulowania nie generuje zdarzeń manipulowania. Na poniższej ilustracji przedstawiono relację między zdarzeniami dotykowymi i zdarzeniami manipulowania.

Relationship between touch and manipulation events Zdarzenia dotyku i manipulowania

Na poniższej liście opisano relację między zdarzeniami dotyku i manipulacji pokazanymi na poprzedniej ilustracji.

Ukierunkowanie

Istnieją dwa główne pojęcia, które odnoszą się do koncentracji uwagi w WPF: fokus klawiatury i fokus logiczny.

Fokus klawiatury

Fokus klawiatury odnosi się do elementu odbierającego dane wejściowe klawiatury. Na całym pulpicie może znajdować się tylko jeden element, który ma fokus klawiatury. W WPF element, który ma fokus klawiatury, będzie miał IsKeyboardFocused ustawioną wartość true. Metoda FocusedElement statyczna Keyboard zwraca element, który obecnie ma fokus klawiatury.

Fokus klawiatury można uzyskać za pomocą klawisza tabulacji do elementu lub przez kliknięcie myszy na niektórych elementach, takich jak TextBox. Fokus klawiatury można również uzyskać programowo przy użyciu Focus metody w Keyboard klasie . Focus próbuje nadać określonemu elementowi fokus klawiatury. Element zwracany przez Focus jest elementem, który obecnie ma fokus klawiatury.

Aby element mógł uzyskać fokus klawiatury, Focusable właściwość i IsVisible właściwości muszą być ustawione na true. Niektóre klasy, takie jak Panel, mają Focusable domyślnie ustawioną false wartość , dlatego może być konieczne ustawienie tej właściwości na true wartość , jeśli chcesz, aby ten element mógł uzyskać fokus.

W poniższym przykładzie użyto Focus metody ustawiania fokusu klawiatury na obiekcie Button. Zalecane miejsce ustawiania początkowego fokusu w aplikacji znajduje się w procedurze obsługi zdarzeń Loaded .

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton)
End Sub

Aby uzyskać więcej informacji na temat koncentracji uwagi na klawiaturze, zobacz Omówienie fokusu.

Fokus logiczny

Fokus logiczny odnosi się do FocusManager.FocusedElement zakresu fokusu w zakresie koncentracji uwagi. W aplikacji może istnieć wiele elementów, które mają fokus logiczny, ale może istnieć tylko jeden element, który ma fokus logiczny w określonym zakresie koncentracji uwagi.

Zakres fokusu to element kontenera, który śledzi FocusedElement zakres w jego zakresie. Gdy fokus pozostawia zakres fokusu, element fokusu na klawiaturze utraci fokus, ale zachowa fokus logiczny. Gdy fokus powróci do zakresu koncentracji uwagi, element fokusu uzyska fokus klawiatury. Dzięki temu można zmienić fokus klawiatury między wieloma zakresami fokusu, ale zapewnia, że element fokusu w zakresie fokusu pozostaje elementem fokusu po powrocie fokusu.

Element można przekształcić w zakres fokusu w języku XAML (Extensible Application Markup Language), ustawiając dołączoną FocusManager właściwość na true, lub w kodzie, ustawiając dołączoną właściwość IsFocusScope przy użyciu SetIsFocusScope metody .

W poniższym przykładzie element znajduje StackPanel się w zakresie koncentracji uwagi, ustawiając dołączoną IsFocusScope właściwość.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

Klasy w WPF, które są zakresami fokusu domyślnie to Window, Menu, ToolBari ContextMenu.

Element, który ma fokus klawiatury, będzie również miał logiczny fokus dla zakresu fokusu, do którego należy; dlatego ustawienie fokusu Focus na elemecie z metodą w Keyboard klasie lub klasach elementów podstawowych podejmie próbę nadania fokusowi klawiatury elementu i fokusowi logicznemu.

Aby określić element fokusu w zakresie koncentracji uwagi, użyj polecenia GetFocusedElement. Aby zmienić element fokusu dla zakresu fokusu, użyj polecenia SetFocusedElement.

Aby uzyskać więcej informacji na temat fokusu logicznego, zobacz Omówienie fokusu.

Położenie myszy

Interfejs API danych wejściowych WPF zawiera przydatne informacje dotyczące przestrzeni współrzędnych. Na przykład współrzędna to współrzędna (0,0) w lewym górnym rogu, ale lewy górny element w drzewie? Element, który jest obiektem docelowym danych wejściowych? Do elementu, do którego dołączono procedurę obsługi zdarzeń? Czy coś innego? Aby uniknąć nieporozumień, interfejs API danych wejściowych WPF wymaga określenia ramki odwołania podczas pracy ze współrzędnymi uzyskanymi za pośrednictwem myszy. Metoda GetPosition zwraca współrzędną wskaźnika myszy względem określonego elementu.

Przechwytywanie myszy

Urządzenia myszy posiadają w szczególności modalną cechę znaną jako przechwytywanie myszy. Przechwytywanie myszy służy do utrzymania przejściowego stanu wejściowego podczas uruchamiania operacji przeciągania i upuszczania, dzięki czemu inne operacje obejmujące nominalne położenie wskaźnika myszy niekoniecznie występują. Podczas przeciągania użytkownik nie może kliknąć bez przerywania przeciągania i upuszczania, co sprawia, że większość wskazówek myszy jest nieodpowiednia, podczas gdy przechwytywanie myszy jest trzymane przez źródło przeciągania. System wejściowy uwidacznia interfejsy API, które mogą określać stan przechwytywania myszy, a także interfejsy API, które mogą wymusić przechwytywanie myszy do określonego elementu lub wyczyść stan przechwytywania myszy. Aby uzyskać więcej informacji na temat operacji przeciągania i upuszczania, zobacz Przeciąganie i upuszczanie — omówienie.

Polecenia

Polecenia umożliwiają obsługę danych wejściowych na bardziej semantycznym poziomie niż dane wejściowe urządzenia. Polecenia to proste dyrektywy, takie jak Cut, Copy, Pastelub Open. Polecenia są przydatne do scentralizowanego logiki poleceń. Do tego samego polecenia można uzyskać dostęp z Menuelementu w obiekcie w ToolBarobiekcie lub za pomocą skrótu klawiaturowego. Polecenia zapewniają również mechanizm wyłączania kontrolek, gdy polecenie stanie się niedostępne.

RoutedCommandto implementacja WPF .ICommand RoutedCommand Po wykonaniu elementu zdarzenie PreviewExecuted i Executed jest wywoływane w obiekcie docelowym polecenia, które tuneluje i bąbelek przez drzewo elementów, podobnie jak inne dane wejściowe. Jeśli element docelowy polecenia nie jest ustawiony, element z fokusem klawiatury będzie obiektem docelowym polecenia. Logika wykonująca polecenie jest dołączana do elementu CommandBinding. Gdy zdarzenie osiągnie CommandBinding wartość Executed dla tego konkretnego polecenia, ExecutedRoutedEventHandler wywołana jest wartość on .CommandBinding Ta procedura obsługi wykonuje akcję polecenia .

Aby uzyskać więcej informacji na temat poleceń, zobacz Commanding Overview (Omówienie poleceń).

WPF udostępnia bibliotekę typowych poleceń, które składają się z ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommandsi EditingCommands, lub można zdefiniować własne.

W poniższym przykładzie pokazano, jak skonfigurować MenuItem element tak, aby po kliknięciu wywołał Paste polecenie na obiekcie , przy założeniu TextBoxTextBox, że fokus klawiatury.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

Aby uzyskać więcej informacji na temat poleceń w WPF, zobacz Commanding Overview (Omówienie poleceń).

System wejściowy i elementy podstawowe

Zdarzenia wejściowe, takie jak dołączone zdarzenia zdefiniowane przez klasy , Keyboardi Stylus są wywoływane przez Mousesystem wejściowy i wstrzykiwane do określonej pozycji w modelu obiektów na podstawie trafienia testowania drzewa wizualnego w czasie wykonywania.

Każdy z zdarzeń, które Mouse, Keyboardi Stylus definiuje jako dołączone zdarzenie, jest również ponownie uwidaczniony przez klasy UIElement elementów podstawowych i ContentElement jako nowe zdarzenie kierowane. Zdarzenia kierowane przez element podstawowy są generowane przez klasy obsługujące oryginalne dołączone zdarzenie i ponownie używając danych zdarzenia.

Gdy zdarzenie wejściowe zostanie skojarzone z konkretnym elementem źródłowym za pośrednictwem implementacji zdarzeń wejściowych elementu podstawowego, może być kierowane przez pozostałą część trasy zdarzeń opartej na kombinacji obiektów drzewa logicznego i wizualnego i obsługiwanego przez kod aplikacji. Ogólnie rzecz biorąc, bardziej wygodne jest obsługę tych zdarzeń wejściowych związanych z urządzeniem przy użyciu zdarzeń trasowanych w systemach UIElement i ContentElement, ponieważ można użyć bardziej intuicyjnej składni obsługi zdarzeń zarówno w języku XAML, jak i w kodzie. Możesz zamiast tego obsłużyć dołączone zdarzenie, które zainicjowało proces, ale napotkasz kilka problemów: dołączone zdarzenie może być oznaczone przez obsługę klasy elementów podstawowych i należy użyć metod dostępu, a nie prawdziwej składni zdarzeń, aby dołączyć programy obsługi dołączonych zdarzeń.

Co dalej?

Masz teraz kilka technik do obsługi danych wejściowych w WPF. Należy również lepiej zrozumieć różne typy zdarzeń wejściowych i mechanizmów zdarzeń kierowanych używanych przez WPF.

Dostępne są dodatkowe zasoby, które bardziej szczegółowo wyjaśniają elementy struktury WPF i routing zdarzeń. Zobacz następujące omówienie, aby uzyskać więcej informacji, Omówienie poleceń, Przegląd fokusu, Przegląd elementów podstawowych, Drzewa w WPF i Przegląd zdarzeń trasowanych.

Zobacz też