private static void NormalizeCoordinates(ref int x, ref int y) { int vScreenWidth = MySendKeys.GetSystemMetrics(MySendKeys.SMCxvirtualscreen); int vScreenHeight = MySendKeys.GetSystemMetrics(MySendKeys.SMCyvirtualscreen); int vScreenLeft = MySendKeys.GetSystemMetrics(MySendKeys.SMXvirtualscreen); int vScreenTop = MySendKeys.GetSystemMetrics(MySendKeys.SMYvirtualscreen); // Absolute input requires that input is in 'normalized' coords - with the entire // desktop being (0,0)...(65536,65536). Need to convert input x,y coords to this // first. // // In this normalized world, any pixel on the screen corresponds to a block of values // of normalized coords - eg. on a 1024x768 screen, // y pixel 0 corresponds to range 0 to 85.333, // y pixel 1 corresponds to range 85.333 to 170.666, // y pixel 2 correpsonds to range 170.666 to 256 - and so on. // Doing basic scaling math - (x-top)*65536/Width - gets us the start of the range. // However, because int math is used, this can end up being rounded into the wrong // pixel. For example, if we wanted pixel 1, we'd get 85.333, but that comes out as // 85 as an int, which falls into pixel 0's range - and that's where the pointer goes. // To avoid this, we add on half-a-"screen pixel"'s worth of normalized coords - to // push us into the middle of any given pixel's range - that's the 65536/(Width*2) // part of the formula. So now pixel 1 maps to 85+42 = 127 - which is comfortably // in the middle of that pixel's block. // The key ting here is that unlike points in coordinate geometry, pixels take up // space, so are often better treated like rectangles - and if you want to target // a particular pixel, target its rectangle's midpoint, not its edge. x = ((x - vScreenLeft) * 65536) / vScreenWidth + 65536 / (vScreenWidth * 2); y = ((y - vScreenTop) * 65536) / vScreenHeight + 65536 / (vScreenHeight * 2); }
private static void SendMouseInput(int x, int y, int data, MySendKeys.SendMouseInputFlags flags) { PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted); permissions.Demand(); int intflags = (int)flags; if ((intflags & (int)MySendKeys.SendMouseInputFlags.Absolute) != 0) { // Absolute position requires normalized coordinates. NormalizeCoordinates(ref x, ref y); intflags |= MySendKeys.MouseeventfVirtualdesk; } MySendKeys.INPUT mi = new MySendKeys.INPUT(); mi.type = MySendKeys.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 (MySendKeys.SendInput(1, ref mi, Marshal.SizeOf(mi)) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
public static bool GetCapsLockStatus() { //if ((MySendKeys.GetKeyState(0x20) & 0x8000)!=0) return true; bool CapsLock = (((ushort)MySendKeys.GetKeyState(0x14)) & 0xffff) != 0; return(CapsLock); }
private static void SendKeyboardInput(Key key, bool press) { PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted); permissions.Demand(); MySendKeys.INPUT ki = new MySendKeys.INPUT(); ki.type = MySendKeys.InputKeyboard; ki.union.keyboardInput.wVk = (short)KeyInterop.VirtualKeyFromKey(key); ki.union.keyboardInput.wScan = (short)MySendKeys.MapVirtualKey(ki.union.keyboardInput.wVk, 0); int dwFlags = 0; if (ki.union.keyboardInput.wScan > 0) { dwFlags |= MySendKeys.KeyeventfScancode; } if (!press) { dwFlags |= MySendKeys.KeyeventfKeyup; } ki.union.keyboardInput.dwFlags = dwFlags; if (ExtendedKeys.Contains(key)) { ki.union.keyboardInput.dwFlags |= MySendKeys.KeyeventfExtendedkey; } ki.union.keyboardInput.time = 0; ki.union.keyboardInput.dwExtraInfo = new IntPtr(0); if (MySendKeys.SendInput(1, ref ki, Marshal.SizeOf(ki)) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Types the specified text. /// </summary> /// <param name="text">The text to type.</param> public static void Type(string text) { foreach (char c in text) { // We get the vKey value for the character via a Win32 API. We then use bit masks to pull the // upper and lower bytes to get the shift state and key information. We then use WPF KeyInterop // to go from the vKey key info into a System.Windows.Input.Key data structure. This work is // necessary because Key doesn't distinguish between upper and lower case, so we have to wrap // the key type inside a shift press/release if necessary. int vKeyValue = MySendKeys.VkKeyScan(c); bool keyIsShifted = (vKeyValue & MySendKeys.VKeyShiftMask) == MySendKeys.VKeyShiftMask; Key key = KeyInterop.KeyFromVirtualKey(vKeyValue & MySendKeys.VKeyCharMask); if (keyIsShifted) { Type(key, new Key[] { Key.LeftShift }); } else { Type(key); } } }