Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Symulowanie i automatyzowanie danych wejściowych użytkownika z urządzeń, takich jak klawiatura, mysz, dotyk, pióro i gamepad w aplikacjach systemu Windows.
Ważne interfejsy API: Windows.UI.Input.Preview.Injection
Przegląd
Iniekcja danych wejściowych umożliwia aplikacji systemu Windows symulowanie danych wejściowych z różnych urządzeń wejściowych i kierowanie tych danych wejściowych w dowolnym miejscu, w tym poza obszarem klienta aplikacji (nawet do aplikacji uruchomionych z uprawnieniami administratora, takich jak Edytor rejestru).
Iniekcja danych wejściowych jest przydatna w przypadku aplikacji i narzędzi systemu Windows, które muszą zapewniać funkcje, które obejmują ułatwienia dostępu, testowanie (ad hoc, zautomatyzowane) oraz funkcje dostępu zdalnego i obsługi technicznej.
Konfiguracja
Aby użyć API wprowadzania danych w aplikacji systemu Windows, należy dodać następujący kod do manifestu aplikacji:
- Kliknij prawym przyciskiem myszy plik Package.appxmanifest i wybierz pozycję Wyświetl kod.
- Wstaw następujące elementy do węzła
Package:xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"IgnorableNamespaces="rescap"
- Wstaw następujące elementy do węzła
Capabilities:<rescap:Capability Name="inputInjectionBrokered" />
Zduplikowane dane wejściowe użytkownika
|
|---|
| Przykład wstrzykiwania wejścia dotykowego |
W tym przykładzie pokazano, jak używać interfejsów API iniekcji danych wejściowych (Windows.UI.Input.Preview.Injection), aby nasłuchiwać zdarzeń wprowadzania myszy w jednym regionie aplikacji i symulować odpowiednie zdarzenia wejściowe dotyku w innym regionie.
Pobierz ten przykład z przykładu iniekcji danych wejściowych (mysz do dotyku)
Najpierw skonfigurujemy interfejs użytkownika (MainPage.xaml).
Mamy dwa obszary Grid (jeden dla danych wejściowych myszy i jeden dla wstrzykiwania danych dotykowych), każdy z czterema przyciskami.
Uwaga / Notatka
Tło siatki musi mieć przypisaną wartość (
Transparentw tym przypadku), w przeciwnym razie zdarzenia wskaźnika nie są wykrywane.Po wykryciu jakichkolwiek kliknięć myszy w obszarze wejściowym odpowiednie zdarzenie dotykowe jest wstrzykiwane do obszaru iniekcji wejściowej. Kliknięcia przycisku z wprowadzanie danych wejściowych są zgłaszane w obszarze tytułu.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Margin="10"> <TextBlock Style="{ThemeResource TitleTextBlockStyle}" Name="titleText" Text="Touch input injection" HorizontalTextAlignment="Center" /> <TextBlock Style="{ThemeResource BodyTextBlockStyle}" Name="statusText" HorizontalTextAlignment="Center" /> </StackPanel> <Grid HorizontalAlignment="Center" Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Grid.Row="0" Style="{ThemeResource CaptionTextBlockStyle}" Text="User mouse input area"/> <!-- Background must be set to something, otherwise pointer events are not detected. --> <Grid Name="ContainerInput" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" Background="Transparent" BorderBrush="Green" BorderThickness="2" MinHeight="100" MinWidth="300" Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Button Name="B1" Grid.Column="0" HorizontalAlignment="Center" Width="50" Height="50" Content="B1" /> <Button Name="B2" Grid.Column="1" HorizontalAlignment="Center" Width="50" Height="50" Content="B2" /> <Button Name="B3" Grid.Column="2" HorizontalAlignment="Center" Width="50" Height="50" Content="B3" /> <Button Name="B4" Grid.Column="3" HorizontalAlignment="Center" Width="50" Height="50" Content="B4" /> </Grid> <TextBlock Grid.Column="1" Grid.Row="0" Style="{ThemeResource CaptionTextBlockStyle}" Text="Injected touch input area"/> <Grid Name="ContainerInject" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" BorderBrush="Red" BorderThickness="2" MinHeight="100" MinWidth="300" Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Button Name="B1i" Click="Button_Click_Injected" Content="B1i" Grid.Column="0" HorizontalAlignment="Center" Width="50" Height="50" /> <Button Name="B2i" Click="Button_Click_Injected" Content="B2i" Grid.Column="1" HorizontalAlignment="Center" Width="50" Height="50" /> <Button Name="B3i" Click="Button_Click_Injected" Content="B3i" Grid.Column="2" HorizontalAlignment="Center" Width="50" Height="50" /> <Button Name="B4i" Click="Button_Click_Injected" Content="B4i" Grid.Column="3" HorizontalAlignment="Center" Width="50" Height="50" /> </Grid> </Grid> </Grid>Następnie zainicjujemy naszą aplikację.
W tym fragmencie kodu deklarujemy nasze obiekty globalne i deklarujemy odbiorniki dla zdarzeń wskaźnika (AddHandler) w obszarze wprowadzania myszy, które mogą być oznaczone jako obsługiwane w zdarzeniach kliknięcia przycisku.
Obiekt InputInjector reprezentuje wirtualne urządzenie wejściowe do wysyłania danych wejściowych.
W programie obsługującym
ContainerInput_PointerPressedwywołujemy funkcję wstrzykiwania dotyku.W obsłudze
ContainerInput_PointerReleasedwywołujemy metodę UninitializeTouchInjection, aby zamknąć obiekt InputInjector.public sealed partial class MainPage : Page { /// <summary> /// The virtual input device. /// </summary> InputInjector _inputInjector; /// <summary> /// Initialize the app, set the window size, /// and add pointer input handlers for the container. /// </summary> public MainPage() { this.InitializeComponent(); ApplicationView.PreferredLaunchViewSize = new Size(600, 200); ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize; // Button handles PointerPressed/PointerReleased in // the Tapped routed event, but we need the container Grid // to handle them also. Add a handler for both // PointerPressedEvent and PointerReleasedEvent on the input Grid // and set handledEventsToo to true. ContainerInput.AddHandler(PointerPressedEvent, new PointerEventHandler(ContainerInput_PointerPressed), true); ContainerInput.AddHandler(PointerReleasedEvent, new PointerEventHandler(ContainerInput_PointerReleased), true); } /// <summary> /// PointerReleased handler for all pointer conclusion events. /// PointerPressed and PointerReleased events do not always occur /// in pairs, so your app should listen for and handle any event that /// might conclude a pointer down (such as PointerExited, PointerCanceled, /// and PointerCaptureLost). /// </summary> /// <param name="sender">Source of the click event</param> /// <param name="e">Event args for the button click routed event</param> private void ContainerInput_PointerReleased( object sender, PointerRoutedEventArgs e) { // Prevent most handlers along the event route from handling event again. e.Handled = true; // Shut down the virtual input device. _inputInjector.UninitializeTouchInjection(); } /// <summary> /// PointerPressed handler. /// PointerPressed and PointerReleased events do not always occur /// in pairs. Your app should listen for and handle any event that /// might conclude a pointer down (such as PointerExited, /// PointerCanceled, and PointerCaptureLost). /// </summary> /// <param name="sender">Source of the click event</param> /// <param name="e">Event args for the button click routed event</param> private void ContainerInput_PointerPressed( object sender, PointerRoutedEventArgs e) { // Prevent most handlers along the event route from // handling the same event again. e.Handled = true; InjectTouchForMouse(e.GetCurrentPoint(ContainerInput)); } ... }Oto funkcja wstrzykiwania dotykowego wejścia.
Najpierw wywołujemy metodę TryCreate, aby utworzyć wystąpienie obiektu InputInjector.
Następnie wywołujemy InitializeTouchInjection z InjectedInputVisualizationMode
Default.Po obliczeniu punktu iniekcji wywołujemy metodę InjectedInputTouchInfo , aby zainicjować listę punktów dotykowych do wstrzykiwania (w tym przykładzie tworzymy jeden punkt dotykowy odpowiadający wskaźnikowi wejściowemu myszy).
Na koniec dwukrotnie wywołujemy funkcję InjectTouchInput , pierwszą dla wskaźnika w dół i drugą dla wskaźnika w górę.
/// <summary> /// Inject touch input on injection target corresponding /// to mouse click on input target. /// </summary> /// <param name="pointerPoint">The mouse click pointer.</param> private void InjectTouchForMouse(PointerPoint pointerPoint) { // Create the touch injection object. _inputInjector = InputInjector.TryCreate(); if (_inputInjector != null) { _inputInjector.InitializeTouchInjection( InjectedInputVisualizationMode.Default); // Create a unique pointer ID for the injected touch pointer. // Multiple input pointers would require more robust handling. uint pointerId = pointerPoint.PointerId + 1; // Get the bounding rectangle of the app window. Rect appBounds = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds; // Get the top left screen coordinates of the app window rect. Point appBoundsTopLeft = new Point(appBounds.Left, appBounds.Top); // Get a reference to the input injection area. GeneralTransform injectArea = ContainerInject.TransformToVisual(Window.Current.Content); // Get the top left screen coordinates of the input injection area. Point injectAreaTopLeft = injectArea.TransformPoint(new Point(0, 0)); // Get the screen coordinates (relative to the input area) // of the input pointer. int pointerPointX = (int)pointerPoint.Position.X; int pointerPointY = (int)pointerPoint.Position.Y; // Create the point for input injection and calculate its screen location. Point injectionPoint = new Point( appBoundsTopLeft.X + injectAreaTopLeft.X + pointerPointX, appBoundsTopLeft.Y + injectAreaTopLeft.Y + pointerPointY); // Create a touch data point for pointer down. // Each element in the touch data list represents a single touch contact. // For this example, we're mirroring a single mouse pointer. List<InjectedInputTouchInfo> touchData = new List<InjectedInputTouchInfo> { new InjectedInputTouchInfo { Contact = new InjectedInputRectangle { Left = 30, Top = 30, Bottom = 30, Right = 30 }, PointerInfo = new InjectedInputPointerInfo { PointerId = pointerId, PointerOptions = InjectedInputPointerOptions.PointerDown | InjectedInputPointerOptions.InContact | InjectedInputPointerOptions.New, TimeOffsetInMilliseconds = 0, PixelLocation = new InjectedInputPoint { PositionX = (int)injectionPoint.X , PositionY = (int)injectionPoint.Y } }, Pressure = 1.0, TouchParameters = InjectedInputTouchParameters.Pressure | InjectedInputTouchParameters.Contact } }; // Inject the touch input. _inputInjector.InjectTouchInput(touchData); // Create a touch data point for pointer up. touchData = new List<InjectedInputTouchInfo> { new InjectedInputTouchInfo { PointerInfo = new InjectedInputPointerInfo { PointerId = pointerId, PointerOptions = InjectedInputPointerOptions.PointerUp } } }; // Inject the touch input. _inputInjector.InjectTouchInput(touchData); } }Na koniec obsługujemy wszystkie zdarzenia kliknięte przyciskiem w obszarze wstrzykiwania danych wejściowych i aktualizujemy interfejs użytkownika przy użyciu nazwy klikniętego przycisku.
Zobacz także
Przykłady tematów
Windows developer