Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Simulare e automatizzare l'input dell'utente da dispositivi come tastiera, mouse, tocco, penna e game pad nelle applicazioni Windows.
API Importanti: Windows.UI.Input.Preview.Injection
Informazioni generali
L'inserimento di input consente alla tua applicazione Windows di simulare l'input da un'ampia gamma di dispositivi di input e indirizzare quell'input ovunque, anche al di fuori dell'area client dell'app (persino alle app in esecuzione con privilegi amministrativi, come l'Editor del Registro di sistema).
L'inserimento di input è utile per le app e gli strumenti di Windows che devono fornire funzionalità che includono accessibilità, test (ad hoc, automatizzato) e funzionalità di accesso remoto e supporto.
Configurazione
Per usare le API di input injection nell'app di Windows, dovrai aggiungere quanto segue al manifesto dell'app:
- Fare clic con il pulsante destro del mouse sul file Package.appxmanifest e selezionare Visualizza codice.
- Inserire quanto segue nel nodo
Package
:xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="rescap"
- Inserire quanto segue nel nodo
Capabilities
:<rescap:Capability Name="inputInjectionBrokered" />
Input utente duplicato
![]() |
---|
esempio di inserimento dell'input tocco |
In questo esempio viene illustrato come usare le API di input injection (Windows.UI.Input.Preview.Injection) per ascoltare gli eventi di input del mouse in un'area di un'app e simulare gli eventi di input tocco corrispondenti in un'altra area.
Scaricare questo esempio da esempio di inserimento di input (da mouse a tocco)
Prima di tutto, impostiamo l'interfaccia utente (MainPage.xaml).
Abbiamo due aree Griglia (una per l'input del mouse e una per l'input tattile iniettato), ognuna con quattro pulsanti.
Annotazioni
Allo sfondo griglia deve essere assegnato un valore (
Transparent
, in questo caso), altrimenti gli eventi puntatore non vengono rilevati.Quando vengono rilevati clic del mouse nell'area di input, un evento tocco corrispondente viene inserito nell'area di inserimento dell'input. I clic del pulsante dall'input iniettato vengono riportati nell'area del titolo.
<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>
A questo punto, inizializziamo l'app.
In questo frammento di codice dichiariamo gli oggetti globali e dichiariamo i listener per gli eventi del puntatore (AddHandler) all'interno dell'area di input del mouse che potrebbe essere contrassegnata come gestita negli eventi di clic del pulsante.
L'oggetto InputInjector rappresenta il dispositivo di input virtuale per l'invio dei dati di input.
Nel gestore
ContainerInput_PointerPressed
chiamiamo la funzione di iniezione di tocco.Nel gestore
ContainerInput_PointerReleased
chiamiamo UninitializeTouchInjection per interrompere l'oggetto 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)); } ... }
Ecco la funzione di iniezione del tocco di input.
Prima di tutto, chiamiamo TryCreate per creare un'istanza dell'oggetto InputInjector.
Viene quindi chiamato InitializeTouchInjection con un InjectedInputVisualizationMode di
Default
.Dopo aver calcolato il punto di inserimento, chiamiamo InjectedInputTouchInfo per inizializzare l'elenco dei punti di tocco da inserire (per questo esempio creiamo un punto di tocco corrispondente al puntatore di input del mouse).
Infine, chiamiamo InjectTouchInput due volte, il primo per un puntatore verso il basso e il secondo per un puntatore verso l'alto.
/// <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); } }
Infine, gestiamo qualsiasi evento instradato di clic sul pulsante Click nell'area di inserimento dell'input e aggiorniamo l'interfaccia utente con il nome del pulsante cliccato.