csharp WPF对指定控件发送按键

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp WPF对指定控件发送按键相关的知识,希望对你有一定的参考价值。

using System.Collections.Generic;namespace System.Windows.Input.Test{    internal class SendKeysParser    {        private string text;        private int current = 0;        private bool insideParentheses = false;        private ModifierKeys currentModifiers = ModifierKeys.None;        private List<KeyPressInfo> result = new List<KeyPressInfo>();        public static IEnumerable<KeyPressInfo> Parse(string text)        {            return new SendKeysParser().ParseSendKeysString(text);        }        public IEnumerable<KeyPressInfo> ParseSendKeysString(string text)        {            this.text = text;            current = 0;            int oldCurrent = current;            while (current < text.Length)            {                if (CurrentChar == '{')                {                    ParseCurly();                    if (!insideParentheses && currentModifiers != ModifierKeys.None)                    {                        currentModifiers = ModifierKeys.None;                    }                }                else if (CurrentChar == '~')                {                    current++;                    Add(Key.Return);                    if (!insideParentheses && currentModifiers != ModifierKeys.None)                    {                        currentModifiers = ModifierKeys.None;                    }                }                else if (CurrentChar == '+')                {                    currentModifiers = currentModifiers | ModifierKeys.Shift;                    current++;                }                else if (CurrentChar == '^')                {                    currentModifiers = currentModifiers | ModifierKeys.Control;                    current++;                }                else if (CurrentChar == '%')                {                    currentModifiers = currentModifiers | ModifierKeys.Alt;                    current++;                }                else if (CurrentChar == '(')                {                    if (insideParentheses)                    {                        Error("Unbalanced parentheses: unexpected second (");                    }                    insideParentheses = true;                    current++;                }                else if (CurrentChar == ')')                {                    if (!insideParentheses)                    {                        Error("Unbalanced parentheses: unexpected closing )");                    }                    insideParentheses = false;                    currentModifiers = ModifierKeys.None;                    current++;                }                else if (IsPrintableChar())                {                    ParseChar();                    if (!insideParentheses && currentModifiers != ModifierKeys.None)                    {                        currentModifiers = ModifierKeys.None;                    }                }                else                {                    Error("Unexpected character: '" + CurrentChar + "'");                }                if (oldCurrent == current)                {                    Error("Didn't advance forward, stuck at parsing character '" + CurrentChar + "'");                }                oldCurrent = current;            }            return result;        }        private void Error(string p)        {            throw new Exception(p + Environment.NewLine + " at position " + current);        }        private Dictionary<string, KeyPressInfo> specialValues = new Dictionary<string, KeyPressInfo>()        {            {"+", new KeyPressInfo(Key.OemPlus, ModifierKeys.Shift)},            {"^", new KeyPressInfo(Key.D6, ModifierKeys.Shift)},            {"%", new KeyPressInfo(Key.D5, ModifierKeys.Shift)},            {"{", new KeyPressInfo(Key.OemOpenBrackets, ModifierKeys.Shift)},            {"}", new KeyPressInfo(Key.Oem6, ModifierKeys.Shift)},            {"[", new KeyPressInfo(Key.OemOpenBrackets)},            {"]", new KeyPressInfo(Key.Oem6)},            {"(", new KeyPressInfo(Key.D9, ModifierKeys.Shift)},            {")", new KeyPressInfo(Key.D0, ModifierKeys.Shift)},            {"~", new KeyPressInfo(Key.Oem3, ModifierKeys.Shift)},            {"BACKSPACE", new KeyPressInfo(Key.Back)},            {"BS", new KeyPressInfo(Key.Back)},            {"BKSP", new KeyPressInfo(Key.Back)},            {"CAPSLOCK", new KeyPressInfo(Key.CapsLock)},            {"DEL", new KeyPressInfo(Key.Delete)},            {"DELETE", new KeyPressInfo(Key.Delete)},            {"DOWN", new KeyPressInfo(Key.Down)},            {"END", new KeyPressInfo(Key.End)},            {"ENTER", new KeyPressInfo(Key.Enter)},            {"ESC", new KeyPressInfo(Key.Escape)},            {"HELP", new KeyPressInfo(Key.Help)},            {"HOME", new KeyPressInfo(Key.Home)},            {"INSERT", new KeyPressInfo(Key.Insert)},            {"INS", new KeyPressInfo(Key.Insert)},            {"LEFT", new KeyPressInfo(Key.Left)},            {"NUMLOCK", new KeyPressInfo(Key.NumLock)},            {"PGDN", new KeyPressInfo(Key.PageDown)},            {"PGUP", new KeyPressInfo(Key.PageUp)},            {"PRTSC", new KeyPressInfo(Key.PrintScreen)},            {"RIGHT", new KeyPressInfo(Key.Right)},            {"SCROLLOCK", new KeyPressInfo(Key.Scroll)},            {"TAB", new KeyPressInfo(Key.Tab)},            {"UP", new KeyPressInfo(Key.Up)},            {"F1", new KeyPressInfo(Key.F1)},            {"F2", new KeyPressInfo(Key.F2)},            {"F3", new KeyPressInfo(Key.F3)},            {"F4", new KeyPressInfo(Key.F4)},            {"F5", new KeyPressInfo(Key.F5)},            {"F6", new KeyPressInfo(Key.F6)},            {"F7", new KeyPressInfo(Key.F7)},            {"F8", new KeyPressInfo(Key.F8)},            {"F9", new KeyPressInfo(Key.F9)},            {"F10", new KeyPressInfo(Key.F10)},            {"F11", new KeyPressInfo(Key.F11)},            {"F12", new KeyPressInfo(Key.F12)},            {"F13", new KeyPressInfo(Key.F13)},            {"F14", new KeyPressInfo(Key.F14)},            {"F15", new KeyPressInfo(Key.F15)},            {"F16", new KeyPressInfo(Key.F16)},        };        private void ParseCurly()        {            foreach (var specialValue in specialValues)            {                var name = specialValue.Key;                if (current + name.Length + 2 > text.Length)                {                    continue;                }                if (text.Substring(current + 1, name.Length + 1).Equals(name + "}", StringComparison.OrdinalIgnoreCase))                {                    current += name.Length + 2;                    var gesture = specialValue.Value;                    Add(gesture);                    return;                }            }            int closing = text.IndexOf('}', current);            if (closing == -1)            {                Error("Closing curly missing");            }            Error("Unknown key: " + text.Substring(current, closing - current + 1));        }        private void Add(KeyPressInfo gesture)        {            if (currentModifiers != ModifierKeys.None)            {                gesture = new KeyPressInfo(gesture.Key, gesture.Modifiers | currentModifiers);            }            result.Add(gesture);        }        private void Add(Key key)        {            Add(new KeyPressInfo(key));        }        private void ParseChar()        {            var key = Key.None;            var modifiers = ModifierKeys.None;            var ch = CurrentChar.ToString();            KeyPressInfo knownKeyPress = KeyboardLayout.Instance.GetKeyGestureForChar(ch[0]);            if (knownKeyPress != null)            {                key = knownKeyPress.Key;                modifiers = knownKeyPress.Modifiers;            }            else            {                if (char.IsUpper(ch, 0))                {                    ch = ch.ToLower();                    modifiers = ModifierKeys.Shift;                }                key = (Key)new KeyConverter().ConvertFromInvariantString(ch);            }            if (key != Key.None)            {                Add(new KeyPressInfo(key, modifiers));                current++;            }        }        private bool IsPrintableChar()        {            return char.IsLetterOrDigit(CurrentChar)                || KeyboardLayout.Instance.GetKeyGestureForChar(CurrentChar) != null;        }        private char CurrentChar        {            get            {                return text[current];            }        }    }}
using System.Runtime.InteropServices;using System.Text;using System.Windows.Forms;namespace System.Windows.Input.Test{    internal class SendKeys    {        public static void Send(UIElement element, string text)        {            var sequence = SendKeysParser.Parse(text);            foreach (var keyPressInfo in sequence)            {                Send(element, keyPressInfo.Key, keyPressInfo.Modifiers);            }        }        public static void Send(UIElement element, Key key, ModifierKeys modifiers)        {            KeyboardDevice keyboardDevice = InputManager.Current.PrimaryKeyboardDevice;            if (modifiers != ModifierKeys.None)            {                MockKeyboardDevice mockKeyboardDevice = MockKeyboardDevice.Instance;                mockKeyboardDevice.Modifiers = modifiers;                keyboardDevice = mockKeyboardDevice;            }            RaiseKeyEvent(element, key, modifiers, keyboardDevice);        }        public static void SendInput(UIElement element, string text)        {            InputManager inputManager = InputManager.Current;            InputDevice inputDevice = inputManager.PrimaryKeyboardDevice;            TextComposition composition = new TextComposition(inputManager, element, text);            TextCompositionEventArgs args = new TextCompositionEventArgs(inputDevice, composition);            args.RoutedEvent = UIElement.PreviewTextInputEvent;            element.RaiseEvent(args);            args.RoutedEvent = UIElement.TextInputEvent;            element.RaiseEvent(args);        }        private static void RaiseKeyEvent(UIElement element, Key key, ModifierKeys modifiers, KeyboardDevice keyboardDevice)        {            PresentationSource presentationSource = PresentationSource.FromVisual(element);            int timestamp = Environment.TickCount;            KeyEventArgs args = new KeyEventArgs(keyboardDevice, presentationSource, timestamp, key);            // 1) PreviewKeyDown            args.RoutedEvent = Keyboard.PreviewKeyDownEvent;            element.RaiseEvent(args);            // 2) KeyDown            args.RoutedEvent = Keyboard.KeyDownEvent;            element.RaiseEvent(args);            // 3) TextInput            SendInputIfNecessary(element, key, modifiers, keyboardDevice);            // 4) PreviewKeyUp            args.RoutedEvent = Keyboard.PreviewKeyUpEvent;            element.RaiseEvent(args);            // 5) KeyUp            args.RoutedEvent = Keyboard.KeyUpEvent;            element.RaiseEvent(args);        }        private static void SendInputIfNecessary(UIElement element, Key key, ModifierKeys modifiers, KeyboardDevice keyboardDevice)        {            if (modifiers.HasFlag(ModifierKeys.Control) || modifiers.HasFlag(ModifierKeys.Alt))            {                return;            }            string input = "";            input = KeyboardLayout.Instance.GetInputForGesture(new KeyPressInfo(key, modifiers));            if (input == "")            {                input = GetInputFromKey(key);            }            if (string.IsNullOrEmpty(input))            {                return;            }            if (modifiers == ModifierKeys.Shift)            {                input = input.ToUpperInvariant();            }            else            {                input = input.ToLowerInvariant();            }            SendInput(element, input);        }        private static string GetInputFromKey(Key key)        {            switch (key)            {                case Key.Left:                case Key.Up:                case Key.Right:                case Key.Down:                case Key.Home:                case Key.End:                case Key.Insert:                case Key.Delete:                case Key.PageUp:                case Key.PageDown:                case Key.Back:                case Key.Escape:                case Key.Enter:                case Key.Tab:                case Key.Space:                    return "";            }            return ToAscii((Keys)KeyInterop.VirtualKeyFromKey(key));        }        [DllImport("user32.dll")]        public static extern int ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, [Out]StringBuilder lpwTransKey, uint fuState);        private static string ToAscii(Keys key)        {            string keystring = key.ToString();            var keyState = new byte[256];            var outputBuilder = new StringBuilder(2);            int result = ToAscii((uint)key, 0, keyState,                  outputBuilder, 0);            if (result == 1)            {                if (outputBuilder.Length > 0)                {                    keystring = outputBuilder[0].ToString();                }            }            return keystring.ToUpper();        }    }}
using System.Reflection;namespace System.Windows.Input.Test{    /// <summary>    /// This serves to mock the state of the modifier keys Shift, Alt and Ctrl.    /// We pass this keyboard device to KeyEventArgs, so that whenever the user    /// says args.KeyboardDevice.Modifiers, we can provide our own Modifiers value    /// instead of going to the operating system and fetching the actual key states    /// from the driver (normally done by KeyboardDevice and Win32KeyboardDevice).    /// </summary>    /// <remarks>    /// An unfortunate side effect of creating our own derived KeyboardDevice is    /// that we'll have to call the KeyboardDevice's protected ctor, which does    /// a lot of damage by subscribing itself to a whole bunch of static events.    /// Not only will these events prevent our MockKeyboardDevice from ever being    /// collected, but also every instance of us will start "typing" whenever real    /// input from the user comes into the system. For example, by merely creating    /// an instance of MockKeyboardDevice, we achieve the effect that when the user    /// types a key such as w, it will be duplicated and all the events will be called    /// twice, resulting in a 'ww' on the screen.    /// </remarks>    internal class MockKeyboardDevice : KeyboardDevice    {        /// <summary>        /// Fake state of the Shift, Alt and Ctrl keys desired by the test        /// </summary>        public new ModifierKeys Modifiers { get; set; }        private static MockKeyboardDevice mInstance;        public static MockKeyboardDevice Instance        {            get            {                if (mInstance == null)                {                    mInstance = new MockKeyboardDevice();                }                return mInstance;            }        }        /// <summary>        /// To prevent contaminating the system with test side effects        /// (basically, to prevent our MockKeyboardDevice from listening and reacting to real        /// keyboard input), we need to undo the damage done by the        /// base KeyboardDevice's constructor where it subscribes to some events.        /// By unsubscribing from these events we make sure our KeyboardDevice        /// won't respond to real input and will be used solely to provide the        /// desired state of the Shift, Alt and Ctrl modifier keys when asked for.        /// </summary>        private MockKeyboardDevice()            : base(InputManager.Current)        {            // There's only one global input manager in the system            InputManager inputManager = InputManager.Current;            // First, unsubscribe our 3 handlers from the InputManager.            // 1)            // Undo the effect of the following line in the KeyboardDevice ctor:            // this._inputManager.Value.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);            PreProcessInputEventHandler preProcessInputHandler =                GetDelegateForMethod<PreProcessInputEventHandler>(this, "PreProcessInput");            inputManager.PreProcessInput -= preProcessInputHandler;            // 2)            // Undo the effect of the following line in the KeyboardDevice ctor:            // this._inputManager.Value.PreNotifyInput += new NotifyInputEventHandler(this.PreNotifyInput);            NotifyInputEventHandler preNotifyInputHandler =                GetDelegateForMethod<NotifyInputEventHandler>(this, "PreNotifyInput");            inputManager.PreNotifyInput -= preNotifyInputHandler;            // 3)            // Undo the effect of the following line in the KeyboardDevice ctor:            // this._inputManager.Value.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);            ProcessInputEventHandler postProcessInputHandler =                GetDelegateForMethod<ProcessInputEventHandler>(this, "PostProcessInput");            inputManager.PostProcessInput -= postProcessInputHandler;            // Now undo the damage done by creating a new TextServicesManager            // this._TsfManager = new SecurityCriticalDataClass<TextServicesManager>(new TextServicesManager(inputManager));            var textServicesManager = this.GetFieldValue("_TsfManager").GetFieldValue("_value");            // this._inputManager.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);            preProcessInputHandler = GetDelegateForMethod<PreProcessInputEventHandler>(textServicesManager, "PreProcessInput");            inputManager.PreProcessInput -= preProcessInputHandler;            // this._inputManager.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);            postProcessInputHandler = GetDelegateForMethod<ProcessInputEventHandler>(textServicesManager, "PostProcessInput");            inputManager.PostProcessInput -= postProcessInputHandler;            // And finally, revert the changes done by creating a new TextCompositionManager            // this._textcompositionManager = new SecurityCriticalData<TextCompositionManager>(new TextCompositionManager(inputManager));            var textCompositionManager = this.GetFieldValue("_textcompositionManager").GetFieldValue("_value");            // this._inputManager.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);            preProcessInputHandler = GetDelegateForMethod<PreProcessInputEventHandler>(textCompositionManager, "PreProcessInput");            inputManager.PreProcessInput -= preProcessInputHandler;            // his._inputManager.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);            postProcessInputHandler = GetDelegateForMethod<ProcessInputEventHandler>(textCompositionManager, "PostProcessInput");            inputManager.PostProcessInput -= postProcessInputHandler;        }        private T GetDelegateForMethod<T>(object target, string methodName)        {            object result = Delegate.CreateDelegate(typeof(T), target, methodName);            return (T)result;        }        protected override KeyStates GetKeyStatesFromSystem(Key key)        {            return GetKeyStatesCore(key, this.Modifiers);        }        private KeyStates GetKeyStatesCore(Key key, ModifierKeys Modifiers)        {            switch (key)            {                case Key.LeftAlt:                case Key.RightAlt:                    return (Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt ? KeyStates.Down : KeyStates.None;                case Key.LeftCtrl:                case Key.RightCtrl:                    return (Modifiers & ModifierKeys.Control) == ModifierKeys.Control ? KeyStates.Down : KeyStates.None;                case Key.LeftShift:                case Key.RightShift:                    return (Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift ? KeyStates.Down : KeyStates.None;            }            return KeyStates.None;        }    }    internal static class ReflectionExtensions    {        public static object GetFieldValue(this object instance, string fieldName)        {            Type type = instance.GetType();            FieldInfo fieldInfo = null;            while (type != null)            {                fieldInfo = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);                if (fieldInfo != null)                {                    break;                }                type = type.BaseType;            }            if (fieldInfo == null)            {                throw new FieldAccessException("Field " + fieldName + " was not found on type " + type.ToString());            }            object result = fieldInfo.GetValue(instance);            return result; // you can place a breakpoint here (for debugging purposes)        }    }}
using System.Collections.Generic;namespace System.Windows.Input.Test{    internal class KeyboardLayout    {        public static readonly KeyboardLayout Instance = new KeyboardLayout();        public KeyPressInfo GetKeyGestureForChar(char index)        {            KeyPressInfo result = null;            printableChars.TryGetValue(index, out result);            return result;        }        public string GetInputForGesture(KeyPressInfo gesture)        {            foreach (var item in printableChars)            {                if (item.Value.Key == gesture.Key && item.Value.Modifiers == gesture.Modifiers)                {                    return item.Key.ToString();                }            }            return "";        }        private static readonly Dictionary<char, KeyPressInfo> printableChars = new Dictionary<char, KeyPressInfo>        {            {' ', new KeyPressInfo(Key.Space)},            {',', new KeyPressInfo(Key.OemComma)},            {'<', new KeyPressInfo(Key.OemComma, ModifierKeys.Shift)},            {'.', new KeyPressInfo(Key.OemPeriod)},            {'>', new KeyPressInfo(Key.OemPeriod, ModifierKeys.Shift)},            {'/', new KeyPressInfo(Key.OemQuestion)},            {'?', new KeyPressInfo(Key.OemQuestion, ModifierKeys.Shift)},            {'-', new KeyPressInfo(Key.OemMinus)},            {'_', new KeyPressInfo(Key.OemMinus, ModifierKeys.Shift)},            {'=', new KeyPressInfo(Key.OemPlus)},            {'+', new KeyPressInfo(Key.OemPlus, ModifierKeys.Shift)},            {'[', new KeyPressInfo(Key.OemOpenBrackets)},            {'{', new KeyPressInfo(Key.OemOpenBrackets, ModifierKeys.Shift)},            {']', new KeyPressInfo(Key.Oem6)},            {'}', new KeyPressInfo(Key.Oem6, ModifierKeys.Shift)},            {'\\', new KeyPressInfo(Key.Oem5)},            {'|', new KeyPressInfo(Key.Oem5, ModifierKeys.Shift)},            {';', new KeyPressInfo(Key.Oem1)},            {':', new KeyPressInfo(Key.Oem1, ModifierKeys.Shift)},            {'`', new KeyPressInfo(Key.Oem3)},            {'~', new KeyPressInfo(Key.Oem3, ModifierKeys.Shift)},            {'\'', new KeyPressInfo(Key.OemQuotes)},            {'"', new KeyPressInfo(Key.OemQuotes, ModifierKeys.Shift)},            {'!', new KeyPressInfo(Key.D1, ModifierKeys.Shift)},            {'@', new KeyPressInfo(Key.D2, ModifierKeys.Shift)},            {'#', new KeyPressInfo(Key.D3, ModifierKeys.Shift)},            {'$', new KeyPressInfo(Key.D4, ModifierKeys.Shift)},            {'%', new KeyPressInfo(Key.D5, ModifierKeys.Shift)},            {'^', new KeyPressInfo(Key.D6, ModifierKeys.Shift)},            {'&', new KeyPressInfo(Key.D7, ModifierKeys.Shift)},            {'*', new KeyPressInfo(Key.D8, ModifierKeys.Shift)},            {'(', new KeyPressInfo(Key.D9, ModifierKeys.Shift)},            {')', new KeyPressInfo(Key.D0, ModifierKeys.Shift)},        };    }}
namespace System.Windows.Input.Test{    internal class KeyPressInfo    {        public KeyPressInfo(Key key)        {            this.Key = key;            this.Modifiers = ModifierKeys.None;        }        public KeyPressInfo(Key key, ModifierKeys modifierKeys)        {            this.Key = key;            this.Modifiers = modifierKeys;        }        public Key Key { get; set; }        public ModifierKeys Modifiers { get; set; }        public override string ToString()        {            var result = Key.ToString();            if (Modifiers != ModifierKeys.None)            {                result = Modifiers.ToString() + " + " + result;            }            return result;        }    }}

以上是关于csharp WPF对指定控件发送按键的主要内容,如果未能解决你的问题,请参考以下文章

csharp 在WPF VisualTree中按名称查找控件

wpf 控件注意事项

csharp 【WPF】【】MVVM MVVMでの控制焦点を指定する。

为 WPF WebBrowser 控件指定用户代理

WPF控件动态移动问题

WPF: 实现 ScrollViewer 滚动到指定控件处