Exemple #1
0
        bool _DontBlock(bool isInjected, LPARAM extraInfo, KKey vk = 0, bool isMMove = false)
        {
            if (_pause)
            {
                return(true);
            }
            if (isInjected)
            {
                //if(DontBlockInjected || (extraInfo != default && extraInfo == DontBlockInjectedExtraInfo)) return true;
                if (DontBlockInjected)
                {
                    return(true);
                }
            }
            AWnd w;

            if (vk != 0)
            {
                //var a = DontBlockKeys;
                //if(a != null) foreach(var k in a) if(vk == k) return true;
                w = AWnd.Active;
            }
            else
            {
                w = isMMove ? AWnd.Active : AWnd.FromMouse();
                //note: don't use hook's pt, because of a bug in some OS versions.
                //note: for wheel it's better to use FromMouse.
            }
            if (w.ThreadId == _threadId)
            {
                return(true);
            }
            return(false);
        }
Exemple #2
0
        /// <summary>
        /// Adds single key to the internal collection. Allows to specify scan code and whether it is an extended key. It will be sent by <see cref="Send"/>.
        /// Returns self.
        /// </summary>
        /// <param name="key">Virtual-key code, as <see cref="KKey"/> or int like <c>(KKey)200</c>. Valid values are 1-255. Can be 0.</param>
        /// <param name="scanCode">Scan code of the physical key. Scan code values are 1-127, but this function allows 1-0xffff. Can be 0.</param>
        /// <param name="extendedKey">true if the key is an extended key.</param>
        /// <param name="down">true - key down; false - key up; null (default) - key down-up.</param>
        /// <exception cref="ArgumentException">Invalid scan code.</exception>
        public AKeys AddKey(KKey key, int scanCode, bool extendedKey, bool?down = null)
        {
            _ThrowIfSending();
            if ((uint)scanCode > 0xffff)
            {
                throw new ArgumentException("Invalid value.", nameof(scanCode));
            }
            bool isPair; _KFlags f = 0;

            if (key == 0)
            {
                f = _KFlags.Scancode;
            }
            else
            {
                //don't: if extendedKey false, set true if need. Don't do it because this func is 'raw'.
            }

            if (!(isPair = (down == null)) && !down.GetValueOrDefault())
            {
                f |= _KFlags.Up;
            }
            if (extendedKey)
            {
                f |= _KFlags.Extended;
            }

            return(_AddKey(new _KEvent(isPair, key, f, (ushort)scanCode)));
        }
Exemple #3
0
        static KKey _WaitForKey(double secondsTimeout, KKey key, bool up, bool block)
        {
            //SHOULDDO: if up and block: don't block if was down when starting to wait. Also in the Mouse func.

            KKey R = 0;

            using (WindowsHook.Keyboard(x => {
                if (key != 0 && !x.IsKey(key))
                {
                    return;
                }
                if (x.IsUp != up)
                {
                    if (up && block)                       //key down when waiting for up. If block, now block down too.
                    {
                        if (key == 0)
                        {
                            key = x.vkCode;
                        }
                        x.BlockEvent();
                    }
                    return;
                }
                R = x.vkCode;                 //info: for mod keys returns left/right
                if (block)
                {
                    x.BlockEvent();
                }
            })) wait.forMessagesAndCondition(secondsTimeout, () => R != 0);

            return(R);
        }
Exemple #4
0
 /// <summary>
 /// Waits for key-down or key-up event of the specified key.
 /// </summary>
 /// <returns>Returns true. On timeout returns false if <i>secondsTimeout</i> is negative; else exception.</returns>
 /// <param name="secondsTimeout">Timeout, seconds. Can be 0 (infinite), &gt;0 (exception) or &lt;0 (no exception). More info: [](xref:wait_timeout).</param>
 /// <param name="key">Wait for this key.</param>
 /// <param name="up">Wait for key-up event.</param>
 /// <param name="block">Make the event invisible for other apps. If <i>up</i> is true, makes the down event invisible too, if it comes while waiting for the up event.</param>
 /// <exception cref="ArgumentException"><i>key</i> is 0.</exception>
 /// <exception cref="TimeoutException"><i>secondsTimeout</i> time has expired (if &gt; 0).</exception>
 /// <remarks>
 /// Waits for key event, not for key state.
 /// Uses low-level keyboard hook. Can wait for any single key. See also <see cref="waitForHotkey"/>.
 /// Ignores key events injected by functions of this library.
 /// </remarks>
 /// <example>
 /// <code><![CDATA[
 /// keys.waitForKey(0, KKey.Ctrl, up: false, block: true);
 /// print.it("Ctrl");
 /// ]]></code>
 /// </example>
 public static bool waitForKey(double secondsTimeout, KKey key, bool up = false, bool block = false)
 {
     if (key == 0)
     {
         throw new ArgumentException();
     }
     return(0 != _WaitForKey(secondsTimeout, key, up, block));
 }
Exemple #5
0
 /// <summary>
 /// Returns true if the specified key or mouse button is pressed.
 /// In UI code use <see cref="keys.gui"/> instead.
 /// </summary>
 /// <remarks>
 /// Uses API <msdn>GetAsyncKeyState</msdn>.
 /// </remarks>
 public static bool isPressed(KKey key)
 {
     if ((key == KKey.MouseLeft || key == KKey.MouseRight) && 0 != Api.GetSystemMetrics(Api.SM_SWAPBUTTON))
     {
         key = (KKey)((int)key ^ 3);                                                                                                                //makes this func 3 times slower, eg 2 -> 6 mcs when cold CPU. But much faster when called next time without a delay; for example mouse.isPressed(Left|Right) is not slower than mouse.isPressed(Left), although calls this func 2 times.
     }
     return(Api.GetAsyncKeyState((int)key) < 0);
 }
Exemple #6
0
                /// <summary>
                /// Presses Ctrl+key. Does not release.
                /// If enter is true, Release will press Enter.
                /// </summary>
                public void Press(KKey key, OptKey opt, AWnd wFocus, bool enter = false)
                {
                    _scan  = VkToSc(_vk = key, Api.GetKeyboardLayout(wFocus.ThreadId));
                    _enter = enter;
                    _opt   = opt;

                    SendCtrl(true);
                    Internal_.Sleep(opt.KeySpeedClipboard);                     //need 1 ms for IE address bar, 100 ms for BlueStacks
                    SendKeyEventRaw(_vk, _scan, 0);
                }
Exemple #7
0
            [FieldOffset(2)] internal ushort ch;      //character if IsChar

            //Event type KeyEvent or KeyPair.
            internal _KEvent(bool pair, KKey vk, _KFlags siFlags, ushort scan = 0) : this()
            {
                this.vk = vk;
                var f = (byte)siFlags; if (pair)

                {
                    f |= 16;
                }
                _flags = f;

                this.scan = scan;
            }
Exemple #8
0
        /// <summary>
        /// Converts keys string to <see cref="KKey"/> array.
        /// </summary>
        /// <param name="keys_">String containing one or more key names, like with <see cref="keys.send"/>. Operators are not supported.</param>
        /// <exception cref="ArgumentException">Error in <i>keys_</i> string.</exception>
        public static KKey[] parseKeysString(string keys_)
        {
            var a = new List <KKey>();

            foreach (var g in _SplitKeysString(keys_ ?? ""))
            {
                KKey k = _KeynameToKey(keys_, g.Start, g.Length);
                if (k == 0)
                {
                    throw _ArgumentException_ErrorInKeysString(keys_, g.Start, g.Length);
                }
                a.Add(k);
            }
            return(a.ToArray());
        }
Exemple #9
0
                /// <summary>
                /// Releases keys.
                /// Does nothing if already released.
                /// </summary>
                public void Release()
                {
                    if (_vk == 0)
                    {
                        return;
                    }

                    SendKeyEventRaw(_vk, _scan, Api.KEYEVENTF_KEYUP);
                    SendCtrl(false);
                    _vk = 0;
                    if (_enter)
                    {
                        Enter(_opt);
                    }
                }
Exemple #10
0
        void _Add(Action <HotkeyTriggerArgs> action, KKey key, KMod mod, KMod modAny, TKFlags flags, string paramsString)
        {
            if (mod == 0 && flags.HasAny((TKFlags.LeftMod | TKFlags.RightMod)))
            {
                throw new ArgumentException("Invalid flags.");
            }
            _triggers.ThrowIfRunning_();
            //actually could safely add triggers while running.
            //	Currently would need just lock(_d) in several places. Also some triggers of this type must be added before starting, else we would not have the hook etc.
            //	But probably not so useful. Makes programming more difficult. If need, can Stop, add triggers, then Run again.

            //AOutput.Write($"key={key}, mod={mod}, modAny={modAny}");
            var t = new HotkeyTrigger(_triggers, action, mod, modAny, flags, paramsString);

            t.DictAdd(_d, (int)key);
            _lastAdded = t;
        }
Exemple #11
0
        /// <summary>
        /// Adds a hotkey trigger.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="modKeys">
        /// Modifier keys, like with the <see cref="AKeys.Key"/> function.
        /// Examples: "Ctrl", "Ctrl+Shift+Alt+Win".
        /// To ignore modifiers: "?". Then the trigger works with any combination of modifiers.
        /// To ignore a modifier: "Ctrl?". Then the trigger works with or without the modifier. More examples: "Ctrl?+Shift?", "Ctrl+Shift?".
        /// </param>
        /// <param name="flags"></param>
        /// <exception cref="ArgumentException">Invalid modKeys string or flags.</exception>
        /// <exception cref="InvalidOperationException">Cannot add triggers after <c>Triggers.Run</c> was called, until it returns.</exception>
        public Action <HotkeyTriggerArgs> this[KKey key, string modKeys, TKFlags flags = 0] {
            set {
                var ps = key.ToString(); if (AChar.IsAsciiDigit(ps[0]))
                {
                    ps = "VK" + ps;
                }
                if (!modKeys.NE())
                {
                    ps = modKeys + "+" + ps;
                }

                if (!AKeys.More.ParseHotkeyTriggerString_(modKeys, out var mod, out var modAny, out _, true))
                {
                    throw new ArgumentException("Invalid modKeys string.");
                }
                _Add(value, key, mod, modAny, flags, ps);
            }
        }
Exemple #12
0
        /// <summary>
        /// Waits for keyboard events using callback function.
        /// </summary>
        /// <returns>
        /// Returns the key code. On timeout returns 0 if <i>secondsTimeout</i> is negative; else exception.
        /// For modifier keys returns the left or right key code, for example LCtrl/RCtrl, not Ctrl.
        /// </returns>
        /// <param name="secondsTimeout">Timeout, seconds. Can be 0 (infinite), &gt;0 (exception) or &lt;0 (no exception). More info: [](xref:wait_timeout).</param>
        /// <param name="f">Callback function that receives key down and up events. Let it return true to stop waiting.</param>
        /// <param name="block">Make the key down event invisible for other apps (when the callback function returns true).</param>
        /// <remarks>
        /// Waits for key event, not for key state.
        /// Uses low-level keyboard hook.
        /// Ignores key events injected by functions of this library.
        /// </remarks>
        /// <example>
        /// Wait for F3 or Esc.
        /// <code><![CDATA[
        /// var k = keys.waitForKeys(0, k => !k.IsUp && k.Key is KKey.F3 or KKey.Escape, block: true);
        /// print.it(k);
        /// ]]></code>
        /// </example>
        public static KKey waitForKeys(double secondsTimeout, Func <HookData.Keyboard, bool> f, bool block = false)
        {
            KKey R = 0;

            using (WindowsHook.Keyboard(x => {
                if (!f(x))
                {
                    return;
                }
                R = x.vkCode;                 //info: for mod keys returns left/right
                if (block && !x.IsUp)
                {
                    x.BlockEvent();
                }
            })) wait.forMessagesAndCondition(secondsTimeout, () => R != 0);

            return(R);
        }
Exemple #13
0
        /// <summary>
        /// Converts string to <see cref="KKey"/> and <see cref="KMod"/>.
        /// For example, if s is "Ctrl+Left", sets mod=KMod.Ctrl, key=KKey.Left.
        /// Returns false if the string is invalid.
        /// </summary>
        /// <remarks>
        /// Key names are like with <see cref="keys.send"/>.
        /// Must be single non-modifier key, preceded by zero or more of modifier keys Ctrl, Shift, Alt, Win, all joined with +.
        /// Valid hotkey examples: <c>"A"</c>, <c>"a"</c>, <c>"7"</c>, <c>"F12"</c>, <c>"."</c>, <c>"End"</c>, <c>"Ctrl+D"</c>, <c>"Ctrl+Alt+Shift+Win+Left"</c>, <c>" Ctrl + U "</c>.
        /// Invalid hotkey examples: null, "", <c>"A+B"</c>, <c>"Ctrl+A+K"</c>, <c>"A+Ctrl"</c>, <c>"Ctrl+Shift"</c>, <c>"Ctrl+"</c>, <c>"NoSuchKey"</c>, <c>"tab"</c>.
        /// </remarks>
        public static bool parseHotkeyString(string s, out KMod mod, out KKey key)
        {
            key = 0; mod = 0;
            if (s == null)
            {
                return(false);
            }
            int i = 0;

            foreach (var g in _SplitKeysString(s))
            {
                if (key != 0)
                {
                    return(false);
                }
                if ((i++ & 1) == 0)
                {
                    KKey k = _KeynameToKey(s, g.Start, g.Length);
                    if (k == 0)
                    {
                        return(false);
                    }
                    var m = Internal_.KeyToMod(k);
                    if (m != 0)
                    {
                        if ((m & mod) != 0)
                        {
                            return(false);
                        }
                        mod |= m;
                    }
                    else
                    {
                        key = k;
                    }
                }
                else if (g.Length != 1 || s[g.Start] != '+')
                {
                    return(false);
                }
            }
            return(key != 0 && key != KKey.Packet);
        }
Exemple #14
0
            /// <summary>
            /// Sends key.
            /// Not used for keys whose scancode can depend on keyboard layout. To get scancode, uses keyboard layout of current thread.
            /// </summary>
            /// <param name="k"></param>
            /// <param name="downUp">1 down, 2 up, 0 down-up.</param>
            internal static void SendKey(KKey k, int downUp = 0)
            {
                uint f = 0;

                if (KeyTypes_.IsExtended(k))
                {
                    f |= Api.KEYEVENTF_EXTENDEDKEY;
                }
                ushort scan = VkToSc(k);

                if (0 == (downUp & 2))
                {
                    SendKeyEventRaw(k, scan, f);
                }
                if (0 == (downUp & 1))
                {
                    SendKeyEventRaw(k, scan, f | Api.KEYEVENTF_KEYUP);
                }
            }
Exemple #15
0
        /// <summary>
        /// Adds single key, specified as <see cref="KKey"/>, to the internal collection. It will be sent by <see cref="Send"/>.
        /// Returns self.
        /// </summary>
        /// <param name="key">Virtual-key code, as <see cref="KKey"/> or int like <c>(KKey)200</c>. Valid values are 1-255.</param>
        /// <param name="down">true - key down; false - key up; null (default) - key down-up.</param>
        /// <exception cref="ArgumentException">Invalid <i>key</i> (0).</exception>
        public AKeys AddKey(KKey key, bool?down = null)
        {
            _ThrowIfSending();
            if (key == 0)
            {
                throw new ArgumentException("Invalid value.", nameof(key));
            }

            bool isPair; _KFlags f = 0;

            if (!(isPair = (down == null)) && !down.GetValueOrDefault())
            {
                f |= _KFlags.Up;
            }
            if (KeyTypes_.IsExtended(key))
            {
                f |= _KFlags.Extended;
            }

            return(_AddKey(new _KEvent(isPair, key, f)));
        }
Exemple #16
0
            /// <summary>
            /// If k is Shift, Ctrl, Alt or Win or their left/right versions, returns it as modifier flag, eg KMod.Shift.
            /// Else returns 0.
            /// </summary>
            internal static KMod KeyToMod(KKey k)
            {
                switch (k)
                {
                case KKey.Shift:
                case KKey.LShift:
                case KKey.RShift: return(KMod.Shift);

                case KKey.Ctrl:
                case KKey.LCtrl:
                case KKey.RCtrl: return(KMod.Ctrl);

                case KKey.Alt:
                case KKey.LAlt:
                case KKey.RAlt: return(KMod.Alt);

                case KKey.Win:
                case KKey.RWin: return(KMod.Win);
                }
                return(0);
            }
Exemple #17
0
    public bool OnCmdKey(KKey key)
    {
        if (_popup.IsVisible)
        {
            switch (key)
            {
            case KKey.Escape:
                Hide();
                return(true);

            case KKey.Down:
            case KKey.Up:
            case KKey.PageDown:
            case KKey.PageUp:
            case KKey.Home:
            case KKey.End:
                _tv.ProcessKey(keys.more.KKeyToWpf(key));
                return(true);
            }
        }
        return(false);
    }
Exemple #18
0
            /// <summary>
            /// Gets scan code from virtual-key code.
            /// </summary>
            /// <param name="vk"></param>
            /// <param name="hkl">Keyboard layout. If default(LPARAM), uses of current thread.</param>
            internal static ushort VkToSc(KKey vk, LPARAM hkl = default)
            {
                if (hkl == default)
                {
                    hkl = Api.GetKeyboardLayout(0);
                }
                uint sc = Api.MapVirtualKeyEx((uint)vk, 0, hkl);                 //MAPVK_VK_TO_VSC

                //fix Windows bugs
                if (vk == KKey.PrintScreen && sc == 0x54)
                {
                    sc = 0x37;
                }
                if (vk == KKey.Pause && sc == 0)
                {
                    sc = 0x45;
                }

                return((ushort)sc);

                //tested: LCtrl, RCtrl etc are correctly sent, although MSDN does not mention that SendInput supports it.
            }
Exemple #19
0
 ///
 public KHotkey(KMod mod, KKey key)
 {
     Mod = mod; Key = key;
 }
Exemple #20
0
 public KKeyScan(KKey vk, bool extendedKey)
 {
     this.vk = vk; this.scanCode = 0; this.extendedKey = extendedKey;
 }
Exemple #21
0
 public KKeyScan(ushort scanCode, bool extendedKey)
 {
     vk = 0; this.scanCode = scanCode; this.extendedKey = extendedKey;
 }
Exemple #22
0
        internal bool HookProc(HookData.Keyboard k, TriggerHookContext thc)
        {
            //AOutput.Write(k.vkCode, !k.IsUp);
            Debug.Assert(!k.IsInjectedByAu);             //server must ignore

            KKey key = k.vkCode;
            KMod mod = thc.Mod;
            bool up  = k.IsUp;

            if (!up)
            {
                _UpClear();
            }

            if (thc.ModThis != 0)
            {
                if (_upTrigger != null && mod == 0 && _upKey == 0)
                {
                    _UpTriggered(thc);
                }
            }
            else if (up)
            {
                if (key == _upKey)
                {
                    _upKey = 0;
                    if (_upTrigger != null && mod == 0)
                    {
                        _UpTriggered(thc);
                    }
                }
                if (key == _eatUp)
                {
                    _eatUp = 0;
                    return(true);
                    //To be safer, could return false if AKeys.IsPressed(_eatUp), but then can interfere with the trigger action.
                }
                //CONSIDER: _upTimeout.
            }
            else
            {
                //if(key == _eatUp) _eatUp = 0;
                _eatUp = 0;

                if (_d.TryGetValue((int)key, out var v))
                {
                    HotkeyTriggerArgs args = null;
                    for (; v != null; v = v.next)
                    {
                        var x = v as HotkeyTrigger;
                        if ((mod & x.modMask) != x.modMasked)
                        {
                            continue;
                        }

                        switch (x.flags & (TKFlags.LeftMod | TKFlags.RightMod))
                        {
                        case TKFlags.LeftMod: if (thc.ModL != mod)
                            {
                                continue;
                            }
                            break;

                        case TKFlags.RightMod: if (thc.ModR != mod)
                            {
                                continue;
                            }
                            break;
                        }

                        if (v.DisabledThisOrAll)
                        {
                            continue;
                        }

                        if (args == null)
                        {
                            thc.args = args = new HotkeyTriggerArgs(x, thc.Window, key, mod);                                      //may need for scope callbacks too
                        }
                        else
                        {
                            args.Trigger = x;
                        }

                        if (!x.MatchScopeWindowAndFunc(thc))
                        {
                            continue;
                        }

                        if (x.action != null)
                        {
                            if (0 != (x.flags & TKFlags.KeyModUp))
                            {
                                _upTrigger = x;
                                _upArgs    = args;
                                _upKey     = key;
                            }
                            else
                            {
                                thc.trigger = x;
                            }
                        }

                        //AOutput.Write(key, mod);
                        if (0 != (x.flags & TKFlags.ShareEvent))
                        {
                            return(false);
                        }

                        if (thc.trigger == null)                          //KeyModUp or action==null
                        {
                            if (mod == KMod.Alt || mod == KMod.Win || mod == (KMod.Alt | KMod.Win))
                            {
                                //AOutput.Write("need Ctrl");
                                ThreadPool.QueueUserWorkItem(o => AKeys.Internal_.SendKey(KKey.Ctrl));                                 //disable Alt/Win menu
                            }
                        }
                        else if (mod != 0)
                        {
                            if (0 == (x.flags & TKFlags.NoModOff))
                            {
                                thc.muteMod = TriggerActionThreads.c_modRelease;
                            }
                            else if (mod == KMod.Alt || mod == KMod.Win || mod == (KMod.Alt | KMod.Win))
                            {
                                thc.muteMod = TriggerActionThreads.c_modCtrl;
                            }
                        }

                        _eatUp = key;
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #23
0
            /// <summary>
            /// Sends one key event.
            /// Just calls API SendInput with raw parameters.
            /// </summary>
            internal static unsafe void SendKeyEventRaw(KKey vk, ushort scan, uint flags)
            {
                var ki = new Api.INPUTK(vk, scan, flags);

                Api.SendInput(&ki);
            }
Exemple #24
0
 /// <summary>
 /// Returns true if the specified key or mouse button is pressed.
 /// </summary>
 /// <remarks>
 /// Can be used for mouse buttons too. Example: <c>keys.gui.isPressed(KKey.MouseLeft)</c>. When mouse left and right buttons are swapped, gets logical state, not physical.
 /// </remarks>
 public static bool isPressed(KKey key) => getKeyState(key) < 0;
Exemple #25
0
        /// <summary>
        /// Converts part of string to <see cref="KKey"/>.
        /// The substring should contain single key name, eg "Esc", "A", "=".
        /// Returns 0 if invalid key name.
        /// </summary>
        static unsafe KKey _KeynameToKey(string s, int i, int len)
        {
            //AOutput.Write(s, i, len);
            if (len < 1)
            {
                return(0);
            }

            char c = s[i];

            //character keys, like K, 9, -
            if (len == 1)
            {
                if (c >= 'a' && c <= 'z')
                {
                    return((KKey)(c - 32));
                }
                if (c >= 'A' && c <= 'Z')
                {
                    return((KKey)c);
                }
                if (c >= '0' && c <= '9')
                {
                    return((KKey)c);
                }
                switch (c)
                {
                case '=': return(KKey.OemPlus);

                case '`':
                case '~': return(KKey.OemTilde);

                case '-':
                case '_': return(KKey.OemMinus);

                case '[':
                case '{': return(KKey.OemOpenBrackets);

                case ']':
                case '}': return(KKey.OemCloseBrackets);

                case '\\':
                case '|': return(KKey.OemPipe);

                case ';':
                case ':': return(KKey.OemSemicolon);

                case '\'':
                case '\"': return(KKey.OemQuotes);

                case ',':
                case '<': return(KKey.OemComma);

                case '.':
                case '>': return(KKey.OemPeriod);

                case '/':
                case '?': return(KKey.OemQuestion);
                }
                return(0);

                //special
                //+ //eg Ctrl+A
                //* //*nTimes, *down, *up
                //( //eg Alt+(A F)
                //)
                //# //numpad keys, eg #5, #*
                //$ //Shift+

                //reserved
                //! @ % ^ &
            }

            //numpad keys
            if (c == '#')
            {
                if (len == 2)
                {
                    switch (s[i + 1])
                    {
                    case '.': return(KKey.Decimal);

                    case '+': return(KKey.Add);

                    case '/': return(KKey.Divide);

                    case '*': return(KKey.Multiply);

                    case '-': return(KKey.Subtract);

                    case '0': return(KKey.NumPad0);

                    case '1': return(KKey.NumPad1);

                    case '2': return(KKey.NumPad2);

                    case '3': return(KKey.NumPad3);

                    case '4': return(KKey.NumPad4);

                    case '5': return(KKey.NumPad5);

                    case '6': return(KKey.NumPad6);

                    case '7': return(KKey.NumPad7);

                    case '8': return(KKey.NumPad8);

                    case '9': return(KKey.NumPad9);
                    }
                }
                return(0);
            }

            //F keys
            if (c == 'F' && AChar.IsAsciiDigit(s[i + 1]))
            {
                int n = s.ToInt(i + 1, out int e, STIFlags.NoHex);
                if (n > 0 && n <= 24 && e == i + len)
                {
                    return((KKey)(0x6F + n));
                }
            }

            //named keys
            //names start with an uppercase letter and must have at least 2 other anycase letters, except: Up, AltG (RAl), PageU (PgU), PageD (PgD), some alternative names (PU, PD, PB, PS, HM, SL, CL, NL, BS).
            KKey k  = 0;
            char c1 = Char.ToLowerInvariant(s[i + 1]),             //note: Util.Tables_.LowerCase would make startup slow
                 c2 = len > 2 ? Char.ToLowerInvariant(s[i + 2]) : ' ',
                 c3 = len > 3 ? Char.ToLowerInvariant(s[i + 3]) : ' ',
                 c4 = len > 4 ? Char.ToLowerInvariant(s[i + 4]) : ' ';
            uint u  = (uint)c1 << 16 | c2;

            switch (c)
            {
            case 'A':
                if (_U('l', 't'))
                {
                    k = c3 == 'g' ? KKey.RAlt : KKey.Alt;
                }
                else if (_U('p', 'p'))
                {
                    k = KKey.Apps;
                }
                break;

            case 'B':
                if (_U('a', 'c') || _U('s', ' '))
                {
                    k = KKey.Back;
                }
                break;

            case 'C':
                if (_U('t', 'r'))
                {
                    k = KKey.Ctrl;
                }
                else if (_U('a', 'p') || _U('l', ' '))
                {
                    k = KKey.CapsLock;
                }
                break;

            case 'D':
                if (_U('e', 'l'))
                {
                    k = KKey.Delete;
                }
                else if (_U('o', 'w'))
                {
                    k = KKey.Down;
                }
                break;

            case 'E':
                if (_U('n', 't'))
                {
                    k = KKey.Enter;
                }
                else if (_U('n', 'd'))
                {
                    k = KKey.End;
                }
                else if (_U('s', 'c'))
                {
                    k = KKey.Escape;
                }
                break;

            case 'H':
                if (_U('o', 'm') || _U('m', ' '))
                {
                    k = KKey.Home;
                }
                break;

            case 'I':
                if (_U('n', 's'))
                {
                    k = KKey.Insert;
                }
                break;

            case 'L':
                if (_U('e', 'f'))
                {
                    k = KKey.Left;
                }
                //don't need LShift etc
                break;

            case 'M':
                if (_U('e', 'n'))
                {
                    k = KKey.Apps;
                }
                break;

            case 'N':
                if (_U('u', 'm') || _U('l', ' '))
                {
                    k = KKey.NumLock;
                }
                //for NumEnter use AKeys.Key((KKey.Enter, 0, true))
                break;

            case 'P':
                if (_U('a', 'g') && c3 == 'e')
                {
                    k = c4 == 'u' ? KKey.PageUp : (c4 == 'd' ? KKey.PageDown : 0);
                }
                else if (_U('g', 'u') || _U('u', ' '))
                {
                    k = KKey.PageUp;
                }
                else if (_U('g', 'd') || _U('d', ' '))
                {
                    k = KKey.PageDown;
                }
                else if (_U('a', 'u') || _U('b', ' '))
                {
                    k = KKey.Pause;
                }
                else if (_U('r', 'i') || _U('r', 't') || _U('s', ' '))
                {
                    k = KKey.PrintScreen;
                }
                break;

            case 'R':
                if (_U('i', 'g'))
                {
                    k = KKey.Right;
                }
                else if (_U('a', 'l'))
                {
                    k = KKey.RAlt;
                }
                else if (_U('c', 't'))
                {
                    k = KKey.RCtrl;
                }
                else if (_U('s', 'h'))
                {
                    k = KKey.RShift;
                }
                else if (_U('w', 'i'))
                {
                    k = KKey.RWin;
                }
                break;

            case 'S':
                if (_U('h', 'i'))
                {
                    k = KKey.Shift;
                }
                else if (_U('p', 'a'))
                {
                    k = KKey.Space;
                }
                else if (_U('c', 'r') || _U('l', ' '))
                {
                    k = KKey.ScrollLock;
                }
                //SysRq not used on Windows
                break;

            case 'T':
                if (_U('a', 'b'))
                {
                    k = KKey.Tab;
                }
                break;

            case 'U':
                if (c1 == 'p')
                {
                    k = KKey.Up;
                }
                break;

            case 'V':
                if (c1 == 'k')
                {
                    int v = s.ToInt(i + 2, out int end, STIFlags.DontSkipSpaces);
                    if (end != i + len || (uint)v > 255)
                    {
                        v = 0;
                    }
                    return((KKey)v);
                }
                break;

            case 'W':
                if (_U('i', 'n'))
                {
                    k = KKey.Win;
                }
                break;
            }
            if (k != 0)
            {
                for (int i2 = i + len; i < i2; i++)
                {
                    if (!AChar.IsAsciiAlpha(s[i]))
                    {
                        return(0);
                    }
                }
                return(k);
            }

            if (c >= 'A' && c <= 'Z')
            {
                var s1 = s.Substring(i, len);
#if false
                if (Enum.TryParse(s1, true, out KKey r1))
                {
                    return(r1);
                }
                //if(Enum.TryParse(s1, true, out System.Windows.Forms.Keys r2) && (uint)r2 <= 0xff) return (KKey)r2;
#else //20-50 times faster and less garbage. Good JIT speed.
                return(_FindKeyInEnums(s1));
#endif
            }
            return(0);

            bool _U(char cc1, char cc2)
            {
                return(u == ((uint)cc1 << 16 | cc2));
            }
        }
Exemple #26
0
 /// <summary>
 /// Returns true if the specified key or mouse button is toggled.
 /// </summary>
 /// <remarks>
 /// Works only with CapsLock, NumLock, ScrollLock and several other keys, as well as mouse buttons.
 /// </remarks>
 public static bool isToggled(KKey key) => 0 != (getKeyState(key) & 1);
Exemple #27
0
 /// <summary>
 /// Adds key down or up event.
 /// </summary>
 /// <param name="vk"></param>
 /// <param name="scan"></param>
 /// <param name="siFlags">SendInput flags.</param>
 internal AKeys AddRaw_(KKey vk, ushort scan, byte siFlags)
 {
     _ThrowIfSending();
     return(_AddKey(new _KEvent(false, vk, (_KFlags)(siFlags & 0xf), scan)));
 }
Exemple #28
0
 void _UpClear()
 {
     _upTrigger = null;
     _upArgs    = null;
     _upKey     = 0;
 }
Exemple #29
0
 public KKeyScan(KKey vk, ushort scanCode, bool extendedKey)
 {
     this.vk = vk; this.scanCode = scanCode; this.extendedKey = extendedKey;
 }
Exemple #30
0
 ///
 public HotkeyTriggerArgs(HotkeyTrigger trigger, AWnd w, KKey key, KMod mod)
 {
     Trigger = trigger;
     Window  = w; Key = key; Mod = mod;
 }