public void Send(IEnumerable <KeyEventArgs> sequence) { var inputs = sequence.Select(arg => new INPUT { U = new INPUT_UNION { ki = new KEYBDINPUT { dwFlags = arg.Action == KeyAction.KeyUp ? KEYEVENTF.KEYUP : 0, wVk = _mapper.Map <Key, VIRTUAL_KEY_CODE>(arg.Key) } }, type = INPUT_TYPE.INPUT_KEYBOARD }).ToArray(); var size = Marshal.SizeOf(inputs[0]); var result = SendInputInterop.SendInput((uint)inputs.Length, inputs, size); if (result != inputs.Length) { throw new InvalidOperationException(); } }
public void Send(IEnumerable <KeyEventArgs> sequence) { var inputs = sequence.Select(arg => new INPUT { type = INPUT_TYPE.INPUT_KEYBOARD, U = new INPUT_UNION { ki = new KEYBDINPUT { dwFlags = arg.KeyState == KeyState.KeyUp ? KEYEVENTF.KEYUP : 0, wVk = (VIRTUAL_KEY_CODE)KeyInterop.VirtualKeyFromKey(arg.Key) } } }).ToArray(); var size = Marshal.SizeOf(inputs[0]); var result = SendInputInterop.SendInput((uint)inputs.Length, inputs, size); if (result != inputs.Length) { throw new InvalidOperationException(); } }
/// <summary> /// Plays back ink data to a specified control /// </summary> /// <param name="destinationControl"> /// The control to play the Ink Data to.</param> /// <param name="destinationRenderer"> /// The Ink Renderer used to convert ink data to display coordinates</param> /// <param name="keepDestinationAspectRatio"> /// Specified whether to keep original aspect ratio of ink when scaling</param> /// <param name="playbackRate"> /// The rate at which to play back the Ink Data</param> protected void PlaybackRecordedData(Control destinationControl, bool keepDestinationAspectRatio, PacketPlaybackRate playbackRate, System.Drawing.Drawing2D.Matrix iTrans) { if (null != PlaybackInk) { System.Drawing.Graphics g = destinationControl.CreateGraphics(); Microsoft.Ink.Renderer destinationRenderer = new Microsoft.Ink.Renderer(); destinationRenderer.SetViewTransform(iTrans); // Set whether or not to keep ink aspect ratio in the display window bool keepAspectRatio = keepDestinationAspectRatio; // Declare scaling factors float scaleFactorX = 1.0f; float scaleFactorY = 1.0f; // Get the size of the display window System.Drawing.Size displayWindowSize = destinationControl.ClientSize; // Get ink bounding box in ink space; convert the box's size to pixel; System.Drawing.Rectangle inkBoundingBox = PlaybackInk.GetBoundingBox(); // Set the size and offset of the destination input System.Drawing.Point inkBoundingBoxSize = new System.Drawing.Point(inkBoundingBox.Width, inkBoundingBox.Height); // Convert the inkspace coordinate to pixels destinationRenderer.InkSpaceToPixel(g, ref inkBoundingBoxSize); // Get the offset of ink System.Drawing.Point inkOffset = inkBoundingBox.Location; // Determine what the scaling factor of the destination control is so // we know how to correctly resize the ink data getDisplayWindowScalingFactor(new System.Drawing.Size(inkBoundingBoxSize), displayWindowSize, keepAspectRatio, ref scaleFactorX, ref scaleFactorY); // Iterate through all ink strokes and extract the packet data foreach (Microsoft.Ink.Stroke currentStroke in PlaybackInk.Strokes) { // Convert the stroke's packet data to INPUT structs INPUT[] inputs = SendInputInterop.StrokeToInputs(currentStroke, destinationRenderer, g, scaleFactorX, scaleFactorY, destinationControl, inkOffset); if (null != inputs) { // Iterate through all the extracted INPUT data in order to send to destination control for (int i = 0; i < inputs.Length; i++) { // Use the Win32 SendInput API to send the ink data point to the control // Note that all playback will use the upper left of the destination control // as the origin SendInputInterop.SendInput(1, new INPUT[] { inputs[i] }, System.Runtime.InteropServices.Marshal.SizeOf(inputs[i])); // Determine the delay between packets (within a stroke) switch (playbackRate) { case PacketPlaybackRate.Default: default: System.Threading.Thread.Sleep(5); break; case PacketPlaybackRate.Slow: System.Threading.Thread.Sleep(100); break; case PacketPlaybackRate.Fast: break; } } } // Reset the focus to the destination control in case it has been changed if (destinationControl.InvokeRequired) { GenericVoidCallback func = new GenericVoidCallback(delegate { destinationControl.Focus(); }); destinationControl.Invoke(func); } else { destinationControl.Focus(); } // Create a delay between each stroke if (0 != InterStrokeDelay) { System.Threading.Thread.Sleep((int)(InterStrokeDelay)); } } // dispose the graphics object g.Dispose(); } }