/// <summary> /// Presses or releases one or more modifier keys. /// Sends in this order: Ctrl, Alt, Shift, Win. /// </summary> /// <param name="press"></param> /// <param name="mod">Modifier keys. Does nothing if 0.</param> internal static unsafe void ModPressRelease(bool press, KMod mod) { if (mod == 0) { return; } var a = stackalloc Api.INPUTK[4]; int n = 0; uint f = press ? 0 : Api.KEYEVENTF_KEYUP; if (0 != (mod & KMod.Ctrl)) { a[n++].Set(KKey.Ctrl, 0x1D, f); } if (0 != (mod & KMod.Alt)) { a[n++].Set(KKey.Alt, 0x38, f); } if (0 != (mod & KMod.Shift)) { a[n++].Set(KKey.Shift, 0x2A, f); } if (0 != (mod & KMod.Win)) { a[n++].Set(KKey.Win, 0x5B, f); } Api.SendInput(a, n); }
void _ResetUp() { _upTrigger = null; _upArgs = null; _upEvent = 0; _upMod = 0; }
internal HotkeyTrigger(ActionTriggers triggers, Action <HotkeyTriggerArgs> action, KMod mod, KMod modAny, TKFlags flags, string paramsString) : base(triggers, action, true) { const KMod csaw = KMod.Ctrl | KMod.Shift | KMod.Alt | KMod.Win; modMask = ~modAny & csaw; modMasked = mod & modMask; this.flags = flags; _paramsString = flags == 0 ? paramsString : paramsString + " (" + flags.ToString() + ")"; //AOutput.Write(_paramsString); }
internal MouseTrigger(ActionTriggers triggers, Action <MouseTriggerArgs> action, KMod mod, KMod modAny, TMFlags flags, TMScreen screen, string paramsString) : base(triggers, action, true) { const KMod csaw = KMod.Ctrl | KMod.Shift | KMod.Alt | KMod.Win; modMask = ~modAny & csaw; modMasked = mod & modMask; this.flags = flags; this.screenIndex = screen; _paramsString = paramsString; }
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; }
void _SetTempKeybHook() { //AOutput.Write(". hook"); if (_keyHook == null) { _keyHook = AHookWin.Keyboard(k => { if (ATime.WinMilliseconds >= _keyHookTimeout) { _ResetUpAndUnhookTempKeybHook(); ADebug.Print("hook timeout"); } else { var mod = k.Mod; if (0 != (mod & _upMod) && k.IsUp) { _upMod &= ~mod; if (_upMod == 0 && _upEvent == 0 && _upTrigger != null) { _triggers.RunAction_(_upTrigger, _upArgs); _ResetUp(); } } if (0 != (mod & _eatMod)) { //AOutput.Write(k); k.BlockEvent(); if (k.IsUp) { _eatMod &= ~mod; } } if (0 == (_upMod | _eatMod)) { _UnhookTempKeybHook(); } } }, setNow: false); } if (!_keyHook.IsSet) { _keyHook.Hook(); } _keyHookTimeout = _keyHook.IgnoreModInOtherHooks_(5000); }
/// <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> /// Returns true if some modifier keys are pressed. /// </summary> /// <param name="mod">Return true if some of these keys are pressed. Default: Ctrl, Shift or Alt.</param> /// <remarks> /// By default does not check the Win key, as it is not used in UI, but you can include it in <i>mod</i> if need. /// </remarks> public static bool isMod(KMod mod = KMod.Ctrl | KMod.Shift | KMod.Alt) { if (0 != (mod & KMod.Ctrl) && isCtrl) { return(true); } if (0 != (mod & KMod.Shift) && isShift) { return(true); } if (0 != (mod & KMod.Alt) && isAlt) { return(true); } if (0 != (mod & KMod.Win) && isWin) { return(true); } return(false); }
/// <summary> /// Gets flags indicating which modifier keys are pressed: Ctrl, Shift, Alt, Win. Calls <see cref="isPressed"/>. /// In UI code use <see cref="keys.gui"/> instead. /// </summary> /// <param name="mod">Check only these keys. Default - all four.</param> public static KMod getMod(KMod mod = KMod.Ctrl | KMod.Shift | KMod.Alt | KMod.Win) { KMod R = 0; if (0 != (mod & KMod.Ctrl) && isCtrl) { R |= KMod.Ctrl; } if (0 != (mod & KMod.Shift) && isShift) { R |= KMod.Shift; } if (0 != (mod & KMod.Alt) && isAlt) { R |= KMod.Alt; } if (0 != (mod & KMod.Win) && isWin) { R |= KMod.Win; } return(R); }
/// <summary> /// Gets left and right modifiers. Uses AKeys.IsPressed. /// Returns modL | modR. /// </summary> public static KMod GetModLR(out KMod modL, out KMod modR) { KMod L = 0, R = 0; if (AKeys.IsPressed(KKey.LCtrl)) { L |= KMod.Ctrl; } if (AKeys.IsPressed(KKey.LShift)) { L |= KMod.Shift; } if (AKeys.IsPressed(KKey.LAlt)) { L |= KMod.Alt; } if (AKeys.IsPressed(KKey.Win)) { L |= KMod.Win; } if (AKeys.IsPressed(KKey.RCtrl)) { R |= KMod.Ctrl; } if (AKeys.IsPressed(KKey.RShift)) { R |= KMod.Shift; } if (AKeys.IsPressed(KKey.RAlt)) { R |= KMod.Alt; } if (AKeys.IsPressed(KKey.RWin)) { R |= KMod.Win; } modL = L; modR = R; return(L | R); }
/// public KHotkey(KMod mod, KKey key) { Mod = mod; Key = key; }
public static extern void SetModState(KMod modstate);
/// <summary> /// Waits while some modifier keys (Ctrl, Shift, Alt, Win) or mouse buttons are pressed. /// </summary> /// <param name="secondsTimeout">Timeout, seconds. Can be 0 (infinite), >0 (exception) or <0 (no exception). More info: [](xref:wait_timeout).</param> /// <param name="mod">Check only these keys. Default: all.</param> /// <param name="buttons">Check only these buttons. Default: all.</param> /// <returns>Returns true. On timeout returns false if <i>secondsTimeout</i> is negative; else exception.</returns> /// <exception cref="TimeoutException"><i>secondsTimeout</i> time has expired (if > 0).</exception> /// <seealso cref="isMod"/> /// <seealso cref="mouse.isPressed"/> /// <seealso cref="mouse.waitForNoButtonsPressed"/> public static bool waitForNoModifierKeysAndMouseButtons(double secondsTimeout = 0.0, KMod mod = KMod.Ctrl | KMod.Shift | KMod.Alt | KMod.Win, MButtons buttons = MButtons.Left | MButtons.Right | MButtons.Middle | MButtons.X1 | MButtons.X2) { var to = new wait.Loop(secondsTimeout, new OWait(period: 2)); for (; ;) { if (!isMod(mod) && !mouse.isPressed(buttons)) { return(true); } if (!to.Sleep()) { return(false); } } }
void _ResetUpAndUnhookTempKeybHook() { _ResetUp(); _eatMod = 0; _UnhookTempKeybHook(); }
internal MouseTrigger(ActionTriggers triggers, Action <MouseTriggerArgs> action, TMKind kind, byte data, KMod mod, KMod modAny, TMFlags flags, TMScreen screenIndex, string paramsString, (string, int) source) : base(triggers, action, true, source)
internal HotkeyTrigger(ActionTriggers triggers, Action <HotkeyTriggerArgs> action, KMod mod, KMod modAny, TKFlags flags, string paramsString, (string, int) source)
MouseTrigger _Add(Action <MouseTriggerArgs> f, ESubtype subtype, string modKeys, TMFlags flags, byte data, TMScreen screen, string sData) { _triggers.ThrowIfRunning_(); bool noMod = modKeys.NE(); string ps; using (new Util.StringBuilder_(out var b)) { b.Append(subtype.ToString()).Append(' ').Append(sData); b.Append(" + ").Append(noMod ? "none" : (modKeys == "?" ? "any" : modKeys)); if (flags != 0) { b.Append(" (").Append(flags.ToString()).Append(')'); } if (subtype == ESubtype.Edge || subtype == ESubtype.Move) { if (screen == 0) { b.Append(", primary screen"); } else if (screen > 0) { b.Append(", non-primary screen ").Append((int)screen); } else if (screen == TMScreen.Any) { b.Append(", any screen"); } else if (screen == TMScreen.OfActiveWindow) { b.Append(", screen of the active window"); } else { throw new ArgumentException(); } } ps = b.ToString(); //AOutput.Write(ps); } KMod mod = 0, modAny = 0; if (noMod) { if (flags.HasAny(subtype == ESubtype.Click ? TMFlags.LeftMod | TMFlags.RightMod : TMFlags.LeftMod | TMFlags.RightMod | TMFlags.ButtonModUp)) { throw new ArgumentException("Invalid flags."); } } else { if (!AKeys.More.ParseHotkeyTriggerString_(modKeys, out mod, out modAny, out _, true)) { throw new ArgumentException("Invalid modKeys string."); } } var t = new MouseTrigger(_triggers, f, mod, modAny, flags, screen, ps); t.DictAdd(_d, _DictKey(subtype, data)); _lastAdded = t; UsedHookEvents_ |= HooksThread.UsedEvents.Mouse; //just sets the hook switch (subtype) { case ESubtype.Click: UsedHookEvents_ |= HooksThread.UsedEvents.MouseClick; break; case ESubtype.Wheel: UsedHookEvents_ |= HooksThread.UsedEvents.MouseWheel; break; default: UsedHookEvents_ |= HooksThread.UsedEvents.MouseEdgeMove; break; } return(t); }
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> /// Waits while some modifier keys (Ctrl, Shift, Alt, Win) are pressed. See <see cref="isMod"/>. /// </summary> /// <param name="secondsTimeout">Timeout, seconds. Can be 0 (infinite), >0 (exception) or <0 (no exception). More info: [](xref:wait_timeout).</param> /// <param name="mod">Check only these keys. Default: all.</param> /// <returns>Returns true. On timeout returns false if <i>secondsTimeout</i> is negative; else exception.</returns> /// <exception cref="TimeoutException"><i>secondsTimeout</i> time has expired (if > 0).</exception> public static bool waitForNoModifierKeys(double secondsTimeout = 0.0, KMod mod = KMod.Ctrl | KMod.Shift | KMod.Alt | KMod.Win) { return(waitForNoModifierKeysAndMouseButtons(secondsTimeout, mod, 0)); }
/// public HotkeyTriggerArgs(HotkeyTrigger trigger, AWnd w, KKey key, KMod mod) { Trigger = trigger; Window = w; Key = key; Mod = mod; }