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); }
/// <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))); }
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); }
/// <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), >0 (exception) or <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 > 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)); }
/// <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); }
/// <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); }
[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; }
/// <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()); }
/// <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); } }
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; }
/// <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); } }
/// <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), >0 (exception) or <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); }
/// <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); }
/// <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); } }
/// <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))); }
/// <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); }
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); }
/// <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. }
/// public KHotkey(KMod mod, KKey key) { Mod = mod; Key = key; }
public KKeyScan(KKey vk, bool extendedKey) { this.vk = vk; this.scanCode = 0; this.extendedKey = extendedKey; }
public KKeyScan(ushort scanCode, bool extendedKey) { vk = 0; this.scanCode = scanCode; this.extendedKey = extendedKey; }
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); }
/// <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); }
/// <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;
/// <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)); } }
/// <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);
/// <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))); }
void _UpClear() { _upTrigger = null; _upArgs = null; _upKey = 0; }
public KKeyScan(KKey vk, ushort scanCode, bool extendedKey) { this.vk = vk; this.scanCode = scanCode; this.extendedKey = extendedKey; }
/// public HotkeyTriggerArgs(HotkeyTrigger trigger, AWnd w, KKey key, KMod mod) { Trigger = trigger; Window = w; Key = key; Mod = mod; }