/// <summary> /// Send text to client as keypresses. Restores and activates window. /// </summary> /// <param name="client">Target client.</param> /// <param name="text">String to send.</param> /// <returns>True if all text was successfully sent.</returns> public static bool SendText(int client, string text) { if (string.IsNullOrEmpty(text)) return false; ClientInfo ci; if (ClientInfoCollection.GetClient(client, out ci)) { if (!ci.PrepareWindowForInput()) { ci.DetachFromWindow(); return false; } NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[text.Length * 2]; NativeMethods.KEYBDINPUT kbi = new NativeMethods.KEYBDINPUT(); for (int x = 0; x < text.Length; x++) { kbi.wScan = text[x]; kbi.dwFlags = NativeMethods.KEYEVENTF_UNICODE; inputs[x * 2].mkhi.ki = kbi; inputs[x * 2].type = NativeMethods.INPUT_KEYBOARD; kbi.dwFlags = NativeMethods.KEYEVENTF_KEYUP | NativeMethods.KEYEVENTF_UNICODE; inputs[x * 2 + 1].mkhi.ki = kbi; inputs[x * 2 + 1].type = NativeMethods.INPUT_KEYBOARD; } uint success = NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(inputs[0])); ci.DetachFromWindow(); return success == inputs.Length; } return false; }
private static void processKey(uint keyToPressCode) { try { byte virtualKeyCode = (byte)keyToPressCode; // low byte contains virtual key code ushort scanCode = (ushort)NativeMethods.MapVirtualKey(virtualKeyCode, NativeMethods.MAPVK_VK_TO_VSC); uint shiftState = GetShiftState(keyToPressCode); bool midKeyPress = false; int inputIndex = 0; NativeMethods.INPUT[] input = new NativeMethods.INPUT[4]; if (((shiftState > 0) && (shiftState <= 8)) && !midKeyPress && processShiftState(shiftState, input, inputIndex, midKeyPress)) { midKeyPress = true; inputIndex++; } // KEYDOWN input[inputIndex].type = NativeMethods.INPUT_KEYBOARD; input[inputIndex].ki.wVk = (ushort)virtualKeyCode; input[inputIndex].ki.wScan = scanCode; inputIndex++; // KEYUP input[inputIndex].type = NativeMethods.INPUT_KEYBOARD; input[inputIndex].ki.wVk = (ushort)virtualKeyCode; input[inputIndex].ki.dwFlags = NativeMethods.KEYEVENTF_KEYUP; input[inputIndex].ki.wScan = scanCode; inputIndex++; if (((shiftState > 0) && (shiftState <= 8)) && midKeyPress && processShiftState(shiftState, input, inputIndex, midKeyPress)) { midKeyPress = false; inputIndex++; } if (curWindowHandle == null || curWindowHandle == IntPtr.Zero) throw new Exception("Unable to press keys becuase the current window handle is not set"); DateTime endTime = DateTime.Now.AddSeconds(15); while (DateTime.Now < endTime) { NativeMethods.SetForegroundWindow(curWindowHandle); if (NativeMethods.GetForegroundWindow() == curWindowHandle) { NativeMethods.SendInput(4, input, System.Runtime.InteropServices.Marshal.SizeOf(input[0])); break; } } } catch (Exception e) { throw (e); } }
public static void Action(double x, double y, MouseAction buttonState) { Point point = new Point((int)x, (int)y); Cursor.Position = point; NativeMethods.INPUT[] input = new NativeMethods.INPUT[1]; NativeMethods.MOUSEINPUT mi = new NativeMethods.MOUSEINPUT(); mi.dx = 0; mi.dy = 0; if (buttonState == MouseAction.LeftDown) mi.dwFlags = NativeMethods.MOUSEEVENTF_LEFTDOWN | NativeMethods.MOUSEEVENTF_ABSOLUTE; else if (buttonState == MouseAction.LeftUp) mi.dwFlags = NativeMethods.MOUSEEVENTF_LEFTUP | NativeMethods.MOUSEEVENTF_ABSOLUTE; else if (buttonState == MouseAction.RightDown) mi.dwFlags = NativeMethods.MOUSEEVENTF_RIGHTDOWN | NativeMethods.MOUSEEVENTF_ABSOLUTE; else if (buttonState == MouseAction.RightUp) mi.dwFlags = NativeMethods.MOUSEEVENTF_RIGHTUP | NativeMethods.MOUSEEVENTF_ABSOLUTE; input[0] = new NativeMethods.INPUT(); input[0].mi = mi; NativeMethods.SendInput((uint)input.Length, input, Marshal.SizeOf(input[0])); }
public void WriteText(string characters) { NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[2 * characters.Length]; for (int i = 0; i < inputs.Length; i++) { var ki = new NativeMethods.KEYBDINPUT(); ki.dwFlags = NativeMethods.KEYEVENTF.UNICODE; if (i % 2 == 1) ki.dwFlags |= NativeMethods.KEYEVENTF.KEYUP; ki.wScan = (short)characters[i / 2]; var input = new NativeMethods.INPUT(); input.type = NativeMethods.INPUT_KEYBOARD; input.U.ki = ki; inputs[i] = input; } if (NativeMethods.SendInput((uint)inputs.Length, inputs, NativeMethods.INPUT.Size) == 0) throw new Win32Exception(); }
private void PressOrReleaseKey(VirtualKeyShort keyCode, bool down) { var ki = new NativeMethods.KEYBDINPUT(); ki.wVk = keyCode; if (!down) ki.dwFlags = NativeMethods.KEYEVENTF.KEYUP; var input = new NativeMethods.INPUT(); input.type = NativeMethods.INPUT_KEYBOARD; input.U.ki = ki; NativeMethods.INPUT[] inputs = { input }; if (NativeMethods.SendInput((uint)inputs.Length, inputs, NativeMethods.INPUT.Size) == 0) throw new Win32Exception(); }
private void DoMouseInput(int x, int y, bool absoluteCoordinates, bool? mouseDown) { // TODO: Maybe we should instead send WM_MOUSEMOVE, WM_LBUTTONDOWN etc. // messages directly to the destination window so that we don't need to // position the mouse cursor which makes it harder e.g. to // click on the "Stop" button of the simulator. // Convert the screen coordinates into mouse coordinates. Coordinates cs = new Coordinates(x, y); cs = GetMouseCoordinatesFromScreenCoordinates(cs); var mi = new NativeMethods.MOUSEINPUT(); mi.dx = cs.X; mi.dy = cs.Y; if (absoluteCoordinates) mi.dwFlags |= NativeMethods.MOUSEEVENTF.ABSOLUTE; if (!(!absoluteCoordinates && x == 0 && y == 0)) { // A movement occured. mi.dwFlags |= NativeMethods.MOUSEEVENTF.MOVE; } if (mouseDown.HasValue) { mi.dwFlags |= mouseDown.Value ? NativeMethods.MOUSEEVENTF.LEFTDOWN : NativeMethods.MOUSEEVENTF.LEFTUP; } var input = new NativeMethods.INPUT(); input.type = NativeMethods.INPUT_MOUSE; input.U.mi = mi; NativeMethods.INPUT[] inputs = { input }; if (NativeMethods.SendInput(1, inputs, NativeMethods.INPUT.Size) == 0) throw new Win32Exception(); }
private static void DoMouse( NativeMethods.MOUSEEVENTF flags, Point newPoint, int scrollSize = 0 ) { NativeMethods.INPUT input = new NativeMethods.INPUT(); NativeMethods.MOUSEINPUT mi = new NativeMethods.MOUSEINPUT(); input.dwType = NativeMethods.InputType.Mouse; input.mi = mi; input.mi.dwExtraInfo = IntPtr.Zero; // mouse co-ords: top left is (0,0), bottom right is (65535, 65535) // convert screen co-ord to mouse co-ords... input.mi.dx = newPoint.X * 65535 / Screen.PrimaryScreen.Bounds.Width; input.mi.dy = newPoint.Y * 65535 / Screen.PrimaryScreen.Bounds.Height; input.mi.time = 0; input.mi.mouseData = scrollSize * 120; // can be used for WHEEL event see msdn input.mi.dwFlags = flags; int cbSize = Marshal.SizeOf( typeof ( NativeMethods.INPUT ) ); int result = NativeMethods.SendInput( 1, ref input, cbSize ); // if ( result == 0 ) // Debug.WriteLine( Marshal.GetLastWin32Error() ); }
private static void SendKeyboardInput(Key key, bool press) { PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted); permissions.Demand(); NativeMethods.INPUT ki = new NativeMethods.INPUT(); ki.type = NativeMethods.InputKeyboard; ki.union.keyboardInput.wVk = (short)KeyInterop.VirtualKeyFromKey(key); ki.union.keyboardInput.wScan = (short)NativeMethods.MapVirtualKey(ki.union.keyboardInput.wVk, 0); int dwFlags = 0; if (ki.union.keyboardInput.wScan > 0) { dwFlags |= NativeMethods.KeyeventfScancode; } if (!press) { dwFlags |= NativeMethods.KeyeventfKeyup; } ki.union.keyboardInput.dwFlags = dwFlags; ki.union.keyboardInput.time = 0; ki.union.keyboardInput.dwExtraInfo = new IntPtr(0); if (NativeMethods.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
// Uses User32 SendInput to send keystrokes private static void SendInput(byte[] oldKeyboardState) //, Queue previousEvents) { NativeMethods.INPUT[] currentInput = new NativeMethods.INPUT[1]; // all events are Keyboard events currentInput[0].type = NativeMethods.INPUT_KEYBOARD; // initialize unused members currentInput[0].inputUnion.ki.dwExtraInfo = IntPtr.Zero; currentInput[0].inputUnion.ki.time = 0; // send each of our SKEvents using SendInput int INPUTSize = Marshal.SizeOf(typeof(NativeMethods.INPUT)); // need these outside the lock below uint eventsSent = 0; int eventsTotal; // A lock here will allow multiple threads to SendInput at the same time. lock (events.SyncRoot) { // block keyboard and mouse input events from reaching applications. bool blockInputSuccess = UnsafeNativeMethods.BlockInput(true); try { eventsTotal = events.Count; for (int i = 0; i < eventsTotal; i++) { SKEvent skEvent = (SKEvent)events.Dequeue(); currentInput[0].inputUnion.ki.dwFlags = 0; // just need to send currentInput[0] for skEvent currentInput[0].inputUnion.ki.wScan = skEvent.sc; // add KeyUp flag if we have a KeyUp if (skEvent.wm == BaseUtils.Win32Constants.WM.KEYUP || skEvent.wm == BaseUtils.Win32Constants.WM.SYSKEYUP) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_KEYUP; } // Sets KEYEVENTF_EXTENDEDKEY flag if necessary if (skEvent.extkey) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_EXTENDEDKEY; } currentInput[0].inputUnion.ki.wVk = skEvent.vkey; System.Diagnostics.Debug.WriteLine("Send " + currentInput[0].inputUnion.ki.wVk + " " + currentInput[0].inputUnion.ki.wScan.ToString("2X") + " " + currentInput[0].inputUnion.ki.dwFlags); // send only currentInput[0] eventsSent += UnsafeNativeMethods.SendInput(1, currentInput, INPUTSize); System.Threading.Thread.Sleep(skEvent.delay > 0 ? skEvent.delay : 1); } } finally { SetKeyboardState(oldKeyboardState); // unblock input if it was previously blocked if (blockInputSuccess) { UnsafeNativeMethods.BlockInput(false); } } } // check to see if we sent the number of events we're supposed to if (eventsSent != eventsTotal) { // calls Marshal.GetLastWin32Error and sets it in the exception throw new Win32Exception(); } }
internal static extern int SendInput(int nInputs, ref NativeMethods.INPUT ki, int cbSize);
// Uses User32 SendInput to send keystrokes private static void SendInput(byte[] oldKeyboardState, Queue previousEvents) { // Should be a No-Opt most of the time AddCancelModifiersForPreviousEvents(previousEvents); // SKEvents are sent as sent as 1 or 2 inputs // currentInput[0] represents the SKEvent // currentInput[1] is a KeyUp to prevent all identical WM_CHARs to be sent as one message NativeMethods.INPUT[] currentInput = new NativeMethods.INPUT[2]; // all events are Keyboard events currentInput[0].type = NativeMethods.INPUT_KEYBOARD; currentInput[1].type = NativeMethods.INPUT_KEYBOARD; // set KeyUp values for currentInput[1] currentInput[1].inputUnion.ki.wVk = (short)0; currentInput[1].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_UNICODE | NativeMethods.KEYEVENTF_KEYUP; // initialize unused members currentInput[0].inputUnion.ki.dwExtraInfo = IntPtr.Zero; currentInput[0].inputUnion.ki.time = 0; currentInput[1].inputUnion.ki.dwExtraInfo = IntPtr.Zero; currentInput[1].inputUnion.ki.time = 0; // send each of our SKEvents using SendInput int INPUTSize = Marshal.SizeOf <NativeMethods.INPUT>(); // need these outside the lock below uint eventsSent = 0; int eventsTotal; // A lock here will allow multiple threads to SendInput at the same time. // This mimics the JournalHook method of using the message loop to mitigate // threading issues. There is still a theoretical thread issue with adding // to the events Queue (both JournalHook and SendInput), but we do not want // to alter the timings of the existing shipped behavior. I did not run into // problems with 2 threads on a multiproc machine lock (events.SyncRoot) { // block keyboard and mouse input events from reaching applications. bool blockInputSuccess = UnsafeNativeMethods.BlockInput(true); try { eventsTotal = events.Count; ClearGlobalKeys(); for (int i = 0; i < eventsTotal; i++) { SKEvent skEvent = (SKEvent)events.Dequeue(); currentInput[0].inputUnion.ki.dwFlags = 0; if (skEvent.wm == WindowMessages.WM_CHAR) { // for WM_CHAR, send a KEYEVENTF_UNICODE instead of a Keyboard event // to support extended ascii characters with no keyboard equivalent. // send currentInput[1] in this case currentInput[0].inputUnion.ki.wVk = (short)0; currentInput[0].inputUnion.ki.wScan = (short)skEvent.paramL; currentInput[0].inputUnion.ki.dwFlags = NativeMethods.KEYEVENTF_UNICODE; currentInput[1].inputUnion.ki.wScan = (short)skEvent.paramL; // call SendInput, increment the eventsSent but subtract 1 for the extra one sent eventsSent += UnsafeNativeMethods.SendInput(2, currentInput, INPUTSize) - 1; } else { // just need to send currentInput[0] for skEvent currentInput[0].inputUnion.ki.wScan = 0; // add KeyUp flag if we have a KeyUp if (skEvent.wm == WindowMessages.WM_KEYUP || skEvent.wm == WindowMessages.WM_SYSKEYUP) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_KEYUP; } // Sets KEYEVENTF_EXTENDEDKEY flag if necessary if (IsExtendedKey(skEvent)) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_EXTENDEDKEY; } currentInput[0].inputUnion.ki.wVk = (short)skEvent.paramL; // send only currentInput[0] eventsSent += UnsafeNativeMethods.SendInput(1, currentInput, INPUTSize); CheckGlobalKeys(skEvent); } // We need this slight delay here for Alt-Tab to work on Vista when the Aero theme // is running. Although this does not look good, a delay // here actually more closely resembles the old JournalHook that processes each // event individually in the hook callback. System.Threading.Thread.Sleep(1); } // reset the keyboard back to what it was before inputs were sent, SendInupt modifies // the global lights on the keyboard (caps, scroll..) so we need to call it again to // undo those changes ResetKeyboardUsingSendInput(INPUTSize); } finally { SetKeyboardState(oldKeyboardState); // unblock input if it was previously blocked if (blockInputSuccess) { UnsafeNativeMethods.BlockInput(false); } } } // check to see if we sent the number of events we're supposed to if (eventsSent != eventsTotal) { // calls Marshal.GetLastWin32Error and sets it in the exception throw new Win32Exception(); } }
private static void SendMouseInput (int x, int y, int data, NativeMethods.SendMouseInputFlags flags) { PermissionSet permissions = new PermissionSet (PermissionState.Unrestricted); permissions.Demand (); int intflags = (int)flags; if ((intflags & (int)NativeMethods.SendMouseInputFlags.Absolute) != 0) { // Absolute position requires normalized coordinates. NormalizeCoordinates (ref x, ref y); intflags |= NativeMethods.MouseeventfVirtualdesk; } NativeMethods.INPUT mi = new NativeMethods.INPUT (); mi.type = NativeMethods.InputMouse; mi.union.mouseInput.dx = x; mi.union.mouseInput.dy = y; mi.union.mouseInput.mouseData = data; mi.union.mouseInput.dwFlags = intflags; mi.union.mouseInput.time = 0; mi.union.mouseInput.dwExtraInfo = new IntPtr (0); if (NativeMethods.SendInput (1, ref mi, Marshal.SizeOf (mi)) == 0) { throw new Win32Exception (Marshal.GetLastWin32Error ()); } }
// Uses User32 SendInput to send keystrokes private static void SendInput() { byte[] keystate = new byte[256]; UnsafeNativeMethods.GetKeyboardState(keystate); NativeMethods.INPUT[] currentInput = new NativeMethods.INPUT[1]; // all events are Keyboard events currentInput[0].type = NativeMethods.INPUT_KEYBOARD; // initialize unused members currentInput[0].inputUnion.ki.dwExtraInfo = IntPtr.Zero; currentInput[0].inputUnion.ki.time = 0; // send each of our SKEvents using SendInput int INPUTSize = Marshal.SizeOf(typeof(NativeMethods.INPUT)); // A lock here will allow multiple threads to SendInput at the same time. lock (events) { // block keyboard and mouse input events from reaching applications. bool blockInputSuccess = UnsafeNativeMethods.BlockInput(true); try { int eventsTotal = events.Count; for (int i = 0; i < eventsTotal; i++) { EnhancedSendKeysParser.SKEvent skEvent = (EnhancedSendKeysParser.SKEvent)events.Dequeue(); currentInput[0].inputUnion.ki.dwFlags = 0; // just need to send currentInput[0] for skEvent currentInput[0].inputUnion.ki.wScan = skEvent.sc; // add KeyUp flag if we have a KeyUp if (skEvent.wm == BaseUtils.Win32Constants.WM.KEYUP || skEvent.wm == BaseUtils.Win32Constants.WM.SYSKEYUP) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_KEYUP; } // Sets KEYEVENTF_EXTENDEDKEY flag if necessary if (skEvent.extkey) { currentInput[0].inputUnion.ki.dwFlags |= NativeMethods.KEYEVENTF_EXTENDEDKEY; } currentInput[0].inputUnion.ki.wVk = (short)skEvent.vkey; System.Diagnostics.Debug.WriteLine(Environment.TickCount % 10000 + " Send " + skEvent.vkey.VKeyToString() + " " + currentInput[0].inputUnion.ki.wScan.ToString("2X") + " " + currentInput[0].inputUnion.ki.dwFlags); // send only currentInput[0] UnsafeNativeMethods.SendInput(1, currentInput, INPUTSize); System.Threading.Thread.Sleep(skEvent.delay > 0 ? skEvent.delay : 1); } } finally { UnsafeNativeMethods.SetKeyboardState(keystate); // unblock input if it was previously blocked if (blockInputSuccess) { UnsafeNativeMethods.BlockInput(false); } } } }