Przegląd Dane wejściowe

Windows Presentation Foundation (WPF)Podsystem udostępnia zaawansowany interfejs API umożliwiający uzyskiwanie danych z różnych urządzeń, w tym myszy, klawiatury, dotyku i pióra. W tym temacie opisano usługi zapewniane przez program WPF i wyjaśniono architekturę systemów wejściowych.

Wejściowy interfejs API

Naświetlanie podstawowego interfejsu API wejścia znajduje się w klasach elementu podstawowego: UIElement , ContentElement , FrameworkElement , i FrameworkContentElement . Aby uzyskać więcej informacji na temat elementów podstawowych, zobacz Omówienie elementów podstawowych. Klasy te zapewniają funkcjonalność dla zdarzeń wejściowych związanych z naciśnięciami klawiszy, przyciskami myszy, kółkiem myszy, przenoszeniem myszy, zarządzaniem fokusem i przechwytywaniem myszy, co pozwala na kilka nazw. Umieszczając wejściowy interfejs API na elementach podstawowych, zamiast traktować wszystkie zdarzenia wejściowe jako usługę, architektura wejścia umożliwia źródło zdarzeń wejściowych przez określony obiekt w interfejsie użytkownika, a także obsługę schematu routingu zdarzeń, w przypadku których więcej niż jeden element ma szansę obsługi zdarzenia wejściowego. Wiele zdarzeń wejściowych ma parę zdarzeń skojarzonych z nimi. Na przykład zdarzenie usługi Key jest skojarzone ze KeyDown PreviewKeyDown zdarzeniami i. Różnica w tych zdarzeniach jest w sposób, w jaki są kierowane do elementu docelowego. Wyświetl podgląd zdarzeń w dół drzewo elementów od elementu głównego do elementu docelowego. Propagacja zdarzeń z elementu docelowego do elementu głównego. Routing zdarzeń w programie WPF został szczegółowo omówiony w dalszej części tego omówienia oraz w omówieniu zdarzeń kierowanych.

Klasy klawiatury i myszy

Oprócz wejściowego interfejsu API w klasach elementu podstawowego Keyboard Klasa i Mouse klasy zapewniają dodatkowy interfejs API do pracy z klawiaturą i myszą.

Przykładami wejściowego interfejsu API w Keyboard klasie są Modifiers właściwości, które zwraca ModifierKeys aktualnie naciśnięte i IsKeyDown metodę, która określa, czy zostanie naciśnięty określony klucz.

W poniższym przykładzie zastosowano GetKeyStates metodę, aby określić, Key czy jest w stanie down.

// 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ładami wejściowego interfejsu API w Mouse klasie są MiddleButton , które uzyskują stan środkowego przycisku myszy, i DirectlyOver , który pobiera element wskaźnik myszy jest przełączany.

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

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

MouseKlasy i Keyboard zostały omówione bardziej szczegółowo w tym omówieniu.

Wprowadzanie piórem

WPF ma zintegrowaną obsługę Stylus . StylusJest to wejście piórem popularne przez komputer typu Tablet. WPF aplikacje mogą traktować pióro jako mysz przy użyciu interfejsu API myszy, ale WPF również uwidaczniają abstrakcję urządzenia pióra, która używa modelu podobnego do klawiatury i myszy. Wszystkie interfejsy API związane z piórem zawierają słowo "Pisak".

Ponieważ pióro może działać jako mysz, aplikacje obsługujące tylko wprowadzanie za pomocą myszy mogą w dalszym ciągu uzyskać obsługę pióra. Gdy pióro jest używane w taki sposób, aplikacja uzyskuje możliwość obsługi odpowiedniego zdarzenia pióra, a następnie obsługuje odpowiednie zdarzenie myszy. Ponadto usługi wyższego poziomu, takie jak dane wejściowe pisma odręcznego, są również dostępne za pomocą abstrakcji urządzenia pióra. Aby uzyskać więcej informacji na temat pisma odręcznego, zobacz wprowadzenie with Ink.

Routing zdarzeń

Element FrameworkElement może zawierać inne elementy jako elementy podrzędne w modelu zawartości, tworząc drzewo elementów. W programie WPF element nadrzędny może uczestniczyć w danych wejściowych skierowanych do jego elementów podrzędnych lub innych elementów podrzędnych przez przekazanie zdarzeń. Jest to szczególnie przydatne w przypadku kompilowania kontrolek z mniejszych kontrolek, procesów znanych jako "skład kontrolny" lub "złożenie". 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 na trasie może zaoferować znaczną odpowiedź (za pomocą obsługi) do zdarzenia, które mogło zostać spowodowane przez inny element. Zdarzenia kierowane korzystają z jednego z trzech mechanizmów routingu: bezpośrednie, propagacja i tunelowanie. W przypadku routingu bezpośredniego element źródłowy jest jedynym powiadamianym elementem, a zdarzenie nie jest kierowane do żadnych innych elementów. Jednak bezpośrednie kierowanie Zdarzenia nadal oferuje pewne dodatkowe możliwości, które są dostępne tylko dla zdarzeń kierowanych, zamiast standardowych zdarzeń CLR. Propagacja działa w drzewie elementów przez pierwsze powiadomienie elementu, który podaje zdarzenie, następnie element nadrzędny i tak dalej. Tunelowanie rozpoczyna się w katalogu głównym drzewa elementów i działa, kończąc na oryginalnym elemencie source. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Omówienie zdarzeń kierowanych.

WPF zdarzenia wejściowe zwykle są parami, które składają się z zdarzenia tunelowania i zdarzenia propagacji. Zdarzenia tunelowania różnią się od propagacji zdarzeń z prefiksem "wersja zapoznawcza". Na przykład PreviewMouseMove to wersja tunelowania zdarzenia przenoszenia myszy i MouseMove jest to wersja propagacji tego zdarzenia. To parowanie zdarzeń jest konwencją, która jest implementowana na poziomie elementu i nie jest zainstalowaną możliwością WPF systemu zdarzeń. Aby uzyskać szczegółowe informacje, zobacz sekcję zdarzenia wejściowe WPF w temacie zdarzenia kierowane — Omówienie.

Obsługa zdarzeń wejściowych

Aby można było odbierać dane wejściowe dla elementu, program obsługi zdarzeń musi być skojarzony z tym konkretnym zdarzeniem. W XAML takim przypadku jest to proste: odwołanie się do nazwy zdarzenia jako atrybutu elementu, który będzie nasłuchiwać tego zdarzenia. Następnie należy ustawić wartość atrybutu na nazwę zdefiniowanego programu obsługi zdarzeń na podstawie delegata. Program obsługi zdarzeń musi być zapisany w kodzie, takim jak C#, i może zostać uwzględniony w pliku związanym z kodem.

Zdarzenia klawiatury pojawiają się, gdy system operacyjny zgłasza kluczowe akcje, które występują, gdy fokus klawiatury znajduje się na elemencie. Zdarzenia myszy i pióra dzielą się na dwie kategorie: zdarzenia, które raportują zmiany w pozycji wskaźnika względem elementu, i zdarzenia, które raportują zmiany w stanie przycisków urządzeń.

Przykład zdarzenia wejściowego klawiatury

Poniższy przykład nasłuchuje naciśnięcie klawisza Strzałka w lewo. StackPanelTworzony jest element Button . Procedura obsługi zdarzeń do nasłuchiwania dla klawisza Strzałka w lewo jest dołączona do Button wystąpienia.

Pierwsza sekcja przykładu tworzy StackPanel i Button dołącza program obsługi zdarzeń dla 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 zapisywana w kodzie i definiuje procedurę obsługi zdarzeń. Po naciśnięciu klawisza Strzałka w lewo Button , gdy ma fokus klawiatury, program obsługi jest uruchamiany i Background kolor elementu Button jest zmieniany. Jeśli klawisz jest wciśnięty, ale nie jest klawiszem Strzałka w lewo, Background kolor obiektu Button jest zmieniany na 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 wejściowego myszy

W poniższym przykładzie Background kolor obiektu Button jest zmieniany, gdy wskaźnik myszy zostanie wprowadzony Button . BackgroundKolor zostanie przywrócony, gdy mysz opuści Button .

Pierwsza sekcja przykładu tworzy StackPanel i Button formant i dołącza obsługę zdarzeń dla MouseEnter MouseLeave zdarzeń i do 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 zapisywana w kodzie i definiuje procedury obsługi zdarzeń. Gdy wskaźnik myszy zostanie przesunięty Button , Background kolor obiektu Button jest zmieniany na SlateGray . Gdy wskaźnik myszy opuszcza Button , kolor obiektu Background Button 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

To TextInput zdarzenie umożliwia nasłuchiwanie danych tekstowych w sposób niezależny od urządzenia. Klawiatura jest podstawowym środkiem wprowadzania tekstu, ale mowy, pismem ręcznym i innymi urządzeniami wejściowymi może również generować dane wejściowe tekstu.

W przypadku wprowadzania z klawiatury program WPF najpierw wysyła odpowiednie KeyDown / KeyUp zdarzenia. Jeśli te zdarzenia nie są obsługiwane, a klucz to tekst (a nie klawisz kontrolny, taki jak strzałki kierunkowe lub klawisze funkcyjne), TextInput zostanie zgłoszone zdarzenie. Nie zawsze jest proste mapowanie jeden do jednego między KeyDown / KeyUp i TextInput zdarzeniami, ponieważ wielokrotne naciśnięcie klawiszy może generować pojedynczy znak wprowadzania tekstu, a pojedynczy naciśnięcie klawisza może generować ciągi znaków wielobajtowych. Jest to szczególnie prawdziwe w przypadku języków takich jak chiński, japoński i koreański, które używają edytorów Input Method Editors (IME) do generowania tysięcy możliwych znaków w odpowiadających im alfabetach.

Gdy WPF wysyła KeyUp / KeyDown zdarzenie, Key jest ustawione na, Key.System Jeśli nacionięcia klawiszy mogą stać się częścią TextInput zdarzenia (na przykład naciśnięcie klawisza ALT + S). Umożliwia to kod w programie KeyDown obsługi zdarzeń, który ma zostać wyszukany Key.System i, w przypadku znalezienia, pozostawić przetwarzanie dla programu obsługi zdarzenia po tym TextInput zdarzeniu. W takich przypadkach różne właściwości TextCompositionEventArgs argumentu mogą służyć do określenia oryginalnych naciśnięć klawiszy. Podobnie, jeśli edytor IME jest aktywny, Key ma wartość Key.ImeProcessed i ImeProcessedKey nadaje oryginalne naciśnięcie klawiszy lub naciśnięcia klawiszy.

W poniższym przykładzie zdefiniowano procedurę obsługi dla Click zdarzenia i programu obsługi 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

Ze względu na to, że zdarzenia wejściowe są rzutowane na trasę zdarzeń, StackPanel odbiera dane wejściowe niezależnie od tego, który element ma fokus klawiatury. TextBoxKontrolka jest najpierw powiadamiana, a OnTextInputKeyDown procedura obsługi jest wywoływana tylko wtedy, gdy TextBox nie obsłuży danych wejściowych. Jeśli PreviewKeyDown zdarzenie jest używane zamiast KeyDown zdarzenia, OnTextInputKeyDown program obsługi jest wywoływany jako pierwszy.

W tym przykładzie logika obsługi jest zapisywana dwa razy — jeden raz dla klawiszy CTRL + O i ponownie dla zdarzenia kliknięcia przycisku. Można to uprościć przy użyciu poleceń, zamiast bezpośrednio obsługiwać zdarzenia wejściowe. Polecenia zostały omówione w tym przeglądzie i w omówieniu poleceń.

Dotyk i manipulowanie

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

WPF uwidacznia dwa typy zdarzeń, gdy nastąpi dotknięcie: zdarzenia dotknięcia i zdarzenia manipulowania. Zdarzenia dotknięcia zapewniają pierwotne dane dotyczące każdego palca na ekranie dotykowym i jego ruchu. Zdarzenia manipulowania interpretują dane wejściowe jako określone akcje. W tej sekcji omówiono oba typy zdarzeń.

Wymagania wstępne

Do tworzenia aplikacji, która reaguje na dotyk, potrzebne są następujące składniki.

  • Program Visual Studio 2010.

  • System Windows 7.

  • Urządzenie, takie jak ekran dotykowy, obsługujące funkcję Touch systemu Windows.

Terminologia

Poniższe terminy są używane podczas omawiania dotyku.

  • Dotyk jest typem danych wprowadzonych przez użytkownika, które są rozpoznawane przez system Windows 7. Zwykle dotyk jest inicjowany przez umieszczenie palców na ekranie dotykowym. Należy zauważyć, że urządzenia takie jak płytka dotykowa, która jest często spotykana na komputerach przenośnych, nie obsługują dotyku, jeśli urządzenie tylko przekonwertuje pozycję i przemieszczenie palca jako dane wejściowe myszy.

  • Wielodotyku jest dotknięciem, który występuje z więcej niż jednego punktu jednocześnie. System Windows 7 i WPF obsługuje wielodotyku. Za każdym razem, gdy program Touch zostanie omówiony w dokumentacji programu WPF , pojęcia dotyczą wielodotyku.

  • Manipulowanie występuje, gdy dotyk jest interpretowany jako fizyczna akcja zastosowana do obiektu. W programie WPF zdarzenia manipulowania interpretują dane wejściowe jako operacje tłumaczenia, rozwinięcia lub obrotu.

  • touch deviceReprezentuje urządzenie, które generuje dotyk dotykowy, na przykład pojedynczy palec na ekranie dotykowym.

Kontrolki, które reagują na dotyk

Następujące kontrolki można przewijać, przeciągając palecę w kontrolce, jeśli ma ona zawartość, która jest przewijana z widoku.

ScrollViewerDefiniuje ScrollViewer.PanningMode załączoną właściwość, która umożliwia określenie, czy panoramowanie dotykowe jest włączone w poziomie, w pionie, czy nie. ScrollViewer.PanningDecelerationWłaściwość określa, jak szybko przewijanie jest spowalniane, gdy użytkownik wydźwiga palca z ekranu dotykowego. ScrollViewer.PanningRatioDołączona właściwość określa stosunek przesunięcia przewijania do translacji przesunięcia manipulacji.

Zdarzenia dotknięcia

Klasy podstawowe,, UIElement UIElement3D i ContentElement , definiują zdarzenia, które można subskrybować, aby Twoja aplikacja odpowiadała na kontakt. Zdarzenia touch są przydatne, gdy aplikacja interpretuje dotyk jako coś innego niż manipulowanie obiektem. Na przykład aplikacja, która umożliwia użytkownikowi rysowanie przy użyciu co najmniej jednego palca, subskrybuje zdarzenia dotknięcia.

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 touch są zdarzeniami kierowanymi. Zdarzenia rozpoczynające się od Preview są zdarzeniami tunelowania, a zdarzenia rozpoczynające się od Touch są zdarzeniami propagacji. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Omówienie zdarzeń kierowanych. Podczas obsługi tych zdarzeń można pobrać pozycję danych wejściowych względem dowolnego elementu, wywołując GetTouchPoint GetIntermediateTouchPoints metodę or.

Aby zrozumieć interakcję między zdarzeniami dotyku, Rozważmy scenariusz, w którym użytkownik umieszcza jeden palec w elemencie, przenosi palec w elemencie, a następnie dźwig palcem z elementu. Na poniższej ilustracji przedstawiono wykonywanie zdarzeń propagacji (zdarzenia tunelowania są pomijane dla uproszczenia).

Sekwencja zdarzeń dotykowych. Zdarzenia dotknięcia

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

  1. TouchEnterZdarzenie występuje raz, gdy użytkownik umieści palca w elemencie.

  2. TouchDownZdarzenie występuje jeden raz.

  3. TouchMoveZdarzenie występuje wiele razy, gdy użytkownik przenosi palec w obrębie elementu.

  4. TouchUpZdarzenie występuje jednorazowo, gdy użytkownik wydźwiga palca z elementu.

  5. TouchLeaveZdarzenie występuje jeden raz.

Gdy używane są więcej niż dwa palców, zdarzenia są wykonywane dla każdego palca.

Zdarzenia manipulowania

W przypadku, gdy aplikacja umożliwia użytkownikowi manipulowanie obiektem, UIElement Klasa definiuje zdarzenia manipulowania. W przeciwieństwie do zdarzeń dotykowych, które po prostu raportują pozycję Touch, zdarzenia manipulowania raportują, jak można interpretować dane wejściowe. Istnieją trzy typy manipulowania, tłumaczenia, rozwijania i obrotu. Na poniższej liście opisano, jak wywołać trzy typy manipulacji.

  • Umieść palec na obiekcie i Przenieś palec na ekranie dotykowym, aby wywołać manipulowanie tłumaczeniami. Zwykle jest to przeniesienie obiektu.

  • Umieść dwa Palcy na obiekcie i przesuń je bliżej siebie lub obok siebie, aby wywołać manipulowanie ekspansją. Zwykle zmieniany jest rozmiar obiektu.

  • Umieść dwa Palcy w obiekcie i Obróć palcami wokół siebie, aby wywołać manipulowanie rotacją. Zwykle powoduje to obrócenie obiektu.

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

Gdy obiekty reagują na manipulacje, można mieć, że obiekt wydaje się być bezwładnością. Może to sprawiać, że obiekty są symulowane na świecie fizycznym. Na przykład w przypadku wypychania książki w ramach tabeli, jeśli wypchnięcie jest wystarczające, książka będzie nadal przenoszona po jej udostępnieniu. WPF umożliwia symulowanie tego zachowania przez podnoszenie poziomu zdarzeń związanych z manipulowaniem po zwolnieniu obiektu przez użytkownika.

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.

UIElementDefiniuje następujące zdarzenia manipulowania.

Domyślnie nie UIElement są odbierane te zdarzenia manipulowania. Aby otrzymywać zdarzenia manipulowania w UIElement , ustaw UIElement.IsManipulationEnabled jako true .

Ścieżka wykonywania zdarzeń manipulowania

Rozważmy scenariusz, w którym użytkownik "zgłosi" obiekt. Użytkownik umieszcza palca na obiekcie, przesuwa palec na ekranie dotykowym o krótkiej odległości, a następnie dźwiga podczas przesuwania. Wynikiem tego jest to, że obiekt zostanie przesunięty pod palcem użytkownika i będzie kontynuował pracę po wyjściu palca przez użytkownika.

Na poniższej ilustracji przedstawiono ścieżkę wykonywania zdarzeń manipulacji i ważne informacje dotyczące poszczególnych zdarzeń.

Sekwencja zdarzeń manipulowania. Zdarzenia manipulowania

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

  1. ManipulationStartingZdarzenie występuje, gdy użytkownik umieści palca w obiekcie. To zdarzenie umożliwia ustawienie ManipulationContainer właściwości. W kolejnych zdarzeniach pozycja manipulowania będzie odnosząca się do ManipulationContainer . W przypadku zdarzeń innych niż ManipulationStarting , ta 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. ManipulationStartedZdarzenie występuje dalej. To zdarzenie służy do zgłaszania pochodzenia manipulowania.

  3. ManipulationDeltaZdarzenie występuje wiele razy, gdy użytkownik przechodzi na ekran dotykowy. DeltaManipulationWłaściwość ManipulationDeltaEventArgs klasy raportuje, czy manipulacja jest interpretowana jako przesunięcia, rozwinięcia czy tłumaczenie. Jest to miejsce, w którym wykonuje się większość pracy manipulowania obiektem.

  4. ManipulationInertiaStartingZdarzenie występuje, gdy użytkownik utraci kontakt z obiektem. To zdarzenie umożliwia określenie opóźnienia manipulacji podczas bezwładności. Jest tak dlatego, że obiekt może emulować różne fizyczne miejsca lub atrybuty w przypadku wybrania opcji. Załóżmy na przykład, że aplikacja ma dwa obiekty reprezentujące elementy w świecie fizycznym, a jeden z nich jest grubszy niż drugi. Można sprawić, aby większy obiekt spowalniania szybciej niż jaśniejszy obiekt.

  5. ManipulationDeltaZdarzenie występuje wiele razy, gdy następuje bezwładności. Należy zauważyć, że to zdarzenie występuje, gdy użytkownik przechodzi przez palca na ekranie dotykowym i gdy WPF symuluje bezwładności. Inaczej mówiąc, ManipulationDelta występuje przed zdarzeniem i po nim ManipulationInertiaStarting . ManipulationDeltaEventArgs.IsInertialWłaściwość określa ManipulationDelta , czy zdarzenie występuje w czasie bezwładności, aby można było sprawdzić tę właściwość i wykonać różne akcje, w zależności od jej wartości.

  6. ManipulationCompletedZdarzenie występuje podczas manipulowania i dowolnych punktów końcowych. Oznacza to, że po ManipulationDelta wystąpieniu wszystkich zdarzeń ManipulationCompleted zdarzenie występuje do sygnalizowania, że manipulacja została zakończona.

UIElementDefiniuje również ManipulationBoundaryFeedback zdarzenie. To zdarzenie występuje, gdy ReportBoundaryFeedback Metoda jest wywoływana w ManipulationDelta zdarzeniu. ManipulationBoundaryFeedbackZdarzenie umożliwia aplikacjom i składnikom dostarczanie wizualnych informacji zwrotnych, gdy obiekt osiągnie granicę. Na przykład Window Klasa obsługuje ManipulationBoundaryFeedback zdarzenie, aby spowodować nieco przechodzenie okna po napotkaniu jego krawędzi.

Manipulowanie można anulować przez wywołanie Cancel metody dla argumentów zdarzeń w każdym zdarzeniu manipulacji z wyjątkiem ManipulationBoundaryFeedback zdarzenia. Po wywołaniu Cancel , zdarzenia manipulowania nie są już wywoływane i pojawiają się zdarzenia myszy w celu dotknięcia. W poniższej tabeli opisano relację między czasem anulowania manipulowania a zdarzeniami myszy, które wystąpiły.

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.
ManipulationDelta Zdarzenia myszy i przenoszenia kursora myszy.
ManipulationInertiaStarting i ManipulationCompleted Mysz w dół, ruch przychodzący i wskaźnik myszy.

Należy pamiętać, że w przypadku wywołania Cancel , gdy manipulacja jest w trybie bezwładności, metoda zwraca false i dane wejściowe nie powodują zdarzeń myszy.

Relacja między zdarzeniami dotykowymi i manipulowania

UIElementZawsze może odbierać zdarzenia dotknięcia. Gdy IsManipulationEnabled Właściwość jest ustawiona na true , UIElement może odbierać zarówno zdarzenia dotykowe, jak i manipulowania. Jeśli TouchDown zdarzenie nie jest obsługiwane (oznacza to, że Handled Właściwość jest false ), logika manipulowania przechwytuje element i generuje zdarzenia manipulowania. Jeśli Handled Właściwość jest ustawiona na true w TouchDown zdarzeniu, logika manipulowania nie generuje zdarzeń manipulowania. Na poniższej ilustracji przedstawiono relacje między zdarzeniami Touch i zdarzeniami manipulowania.

Relacja między zdarzeniami dotykowymi i manipulowania Zdarzenia dotykowe i manipulowania

Poniższa lista zawiera opis relacji między zdarzeniami dotyku i manipulowania, które są wyświetlane na powyższej ilustracji.

Ukierunkowanie

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

Fokus klawiatury

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

Fokus klawiatury można uzyskać, naciskając klawisz Tab do elementu lub klikając myszą na określonych elementach, takich jak TextBox . Fokus klawiatury można również uzyskać programowo przy użyciu Focus metody Keyboard klasy. Focus próbuje nadać określony fokus klawiatury elementu. Element zwracany przez Focus to element, który aktualnie ma fokus klawiatury.

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

Poniższy przykład używa Focus do ustawiania fokusu klawiatury na Button . Zalecane miejsce, aby ustawić początkowy fokus w aplikacji, znajduje się w Loaded obsłudze zdarzeń.

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 naciskania klawiatury, zobacz temat Omówienie fokusu.

Fokus logiczny

Fokus logiczny odnosi się do FocusManager.FocusedElement zakresu fokusu. Może istnieć wiele elementów mających fokus logiczny w aplikacji, ale może istnieć tylko jeden element, który ma logiczne fokus w konkretnym zakresie fokusu.

Zakres fokusu to element kontenera, który śledzi FocusedElement zakres. Gdy fokus opuszcza zakres fokusu, element skoncentrowany utraci fokus klawiatury, ale będzie utrzymywać fokus logiczny. Gdy fokus powróci do zakresu fokusu, element skoncentrowany uzyska fokus klawiatury. Pozwala to na zmianę fokusu klawiatury między wieloma zakresami fokusu, ale nie ma pewności, że element skoncentrowany w zakresie fokusu pozostaje elementem skoncentrowanym, gdy fokus jest zwracany.

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

Poniższy przykład tworzy StackPanel zakres fokusu przez ustawienie IsFocusScope dołączonej właściwości.

<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 WPF , w których domyślnie są zakresy koncentracji Window , to,, Menu ToolBar i ContextMenu .

Element, który ma fokus klawiatury, będzie również miał fokus logiczny dla zakresu fokusu, do którego należy. w związku z tym ustawienie fokusu na elemencie z Focus metodą Keyboard klasy lub klasy elementu podstawowego podejmie próbę nawiązania fokusu na klawiaturze i logicznej ostrości.

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

Aby uzyskać więcej informacji o koncentracji logicznej, zobacz temat Omówienie fokusu.

Położenie myszy

WPFInterfejs API danych wejściowych zapewnia przydatne informacje w odniesieniu do przestrzeni współrzędnych. Na przykład, koordynuje (0,0) jest współrzędną górnej krawędzi, ale w lewym górnym rogu elementu drzewa? Element, który jest obiektem docelowym wprowadzania? Do którego elementu została dołączona procedura obsługi zdarzeń? Lub coś innego? Aby uniknąć nieporozumień, WPF wejściowy interfejs API wymaga określenia ramki odwołania podczas pracy ze współrzędnymi uzyskanymi za pomocą myszy. GetPositionMetoda zwraca współrzędną wskaźnika myszy względem określonego elementu.

Przechwytywanie myszy

Urządzenia myszy mają specjalne cechy modalne znane jako przechwycenie myszy. Przechwytywanie myszy służy do zachowywania stanu przejściowego danych wejściowych podczas uruchamiania operacji przeciągania i upuszczania, dzięki czemu inne operacje obejmujące nominalną pozycję na ekranie wskaźnika myszy nie muszą być wykonywane. Podczas przeciągania użytkownik nie może kliknąć bez przerywania przeciągania i upuszczania, co sprawia, że większość mouseoverych wskaźników jest nieodpowiedni, podczas gdy przechwytywanie myszy jest przechowywane przez punkt przeciągania. System wejściowy udostępnia interfejsy API, które mogą określać stan przechwytywania myszy, a także interfejsy API, które mogą wymusić przechwycenie myszy do określonego elementu lub wyczyścić stan przechwycenia myszy. Aby uzyskać więcej informacji na temat operacji przeciągania i upuszczania, zobacz temat Przeciąganie i upuszczanie — Omówienie.

Polecenia

Polecenia umożliwiają obsługę danych wejściowych na wyższym poziomie semantycznym niż dane wejściowe urządzenia. Polecenia są prostymi dyrektywami, takimi jak Cut ,, Copy Paste , lub Open . Polecenia są przydatne do scentralizowania logiki poleceń. Do tego samego polecenia można uzyskać dostęp z Menu , w ToolBar lub za pomocą skrótu klawiaturowego. Polecenia udostępniają również mechanizm wyłączania formantów, gdy polecenie staną się niedostępne.

RoutedCommand jest WPF implementacją programu ICommand . Gdy RoutedCommand jest wykonywane, PreviewExecuted a i Executed zdarzenie są wywoływane w celu polecenia, który tunel i bąbelki przez drzewo elementu, jak inne dane wejściowe. Jeśli obiekt docelowy polecenia nie jest ustawiony, element z fokusem klawiatury będzie elementem docelowym polecenia. Logika, która wykonuje polecenie, jest dołączona do CommandBinding . Gdy Executed zdarzenie osiągnie CommandBinding dla tego konkretnego polecenia, obiekt ExecutedRoutedEventHandler CommandBinding jest wywoływany. Ta procedura obsługi wykonuje akcję polecenia.

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

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

Poniższy przykład pokazuje, jak skonfigurować program MenuItem , aby po jego kliknięciu wywoła Paste polecenie na TextBox , przy założeniu, że TextBox ma 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 programie WPF , zobacz Omówienie poleceń.

System wejściowy i elementy podstawowe

Zdarzenia wejściowe, takie jak dołączone zdarzenia zdefiniowane przez Mouse , Keyboard i Stylus klasy są wywoływane przez system wejściowy i wstrzykiwane do określonej pozycji w modelu obiektów na podstawie trafień w drzewie wizualizacji w czasie wykonywania.

Wszystkie zdarzenia Mouse , które, Keyboard i Stylus zdefiniowane jako dołączone zdarzenie, są również ponownie udostępniane przez klasy elementów podstawowych UIElement i ContentElement jako nowe zdarzenia kierowane. Zdarzenia przesyłane do elementu podstawowego są generowane przez klasy obsługujące pierwotne dołączone zdarzenie i ponownie korzystające z danych zdarzenia.

Gdy zdarzenie wejściowe stanie się skojarzone z konkretnym elementem źródłowym za pośrednictwem implementacji zdarzenia wejściowego elementu podstawowego, może być kierowane przez resztę trasy zdarzenia na podstawie kombinacji obiektów drzewa logicznego i wizualnego i być obsługiwane przez kod aplikacji. Ogólnie rzecz biorąc, łatwiej jest obsługiwać te zdarzenia wejściowe powiązane z urządzeniem przy użyciu zdarzeń kierowanych w systemach UIElement i ContentElement , ponieważ można użyć bardziej intuicyjnej składni procedury obsługi zdarzeń zarówno w programie XAML , jak i w kodzie. Zamiast tego można wybrać obsługę dołączonego zdarzenia, które zainicjowało proces, ale może wystąpić kilka problemów: dołączone zdarzenie mogą być oznaczone jako obsługiwane przez obsługę klasy elementu podstawowego i należy użyć metod dostępu zamiast prawdziwej składni zdarzeń, aby dołączyć procedury obsługi dla dołączonych zdarzeń.

Co dalej?

Teraz masz kilka technik obsługi danych wejściowych WPF . Należy również poprawić różne typy zdarzeń wejściowych i mechanizmów zdarzeń kierowanych używanych przez program WPF .

Dostępne są dodatkowe zasoby, które WPF szczegółowo objaśniają elementy struktury i routing zdarzeń. Zapoznaj się z poniższymi omówieniami, aby uzyskać więcej informacji, Omówienie poleceń, Przegląd koncentracji, Przegląd elementów podstawowych, drzewa w WPFi Informacje o rutowanych zdarzeniach.

Zobacz też