/// <summary> /// Sends key events added by AInputBlocker -> AddRaw_. /// Simply calls Api.SendInput. No options, no sleep, etc. /// If new events added while sending, sends them too, until there are no new events added. /// </summary> /// <param name="onlyUp">Send only 'up' events.</param> internal unsafe void SendBlocked_(bool onlyUp) { g1: int n = 0; var a = new Api.INPUTK[_a.Count]; for (int i = 0; i < _a.Count; i++) { var k = _a[i]; if (onlyUp && !k.IsUp) { continue; } a[n++].Set(k.vk, k.scan, (uint)k.SIFlags); } _a.Clear(); if (n == 0) { return; fixed(Api.INPUTK *p = a) Api.SendInput(p, n); //ATime.DoEvents(); //sometimes catches one more event, but not necessary if (_a.Count > 0) { goto g1; //the hook proc is called while in SendInput. If we don't retry, new blocked keys are lost. } }
//Caller should set k.scan; this func doesn't. unsafe static void _SendKey2(_KEvent k, _KEvent kNext, bool isLast, OptKey opt) { var ki = new Api.INPUTK(k.vk, k.scan, (uint)k.SIFlags); int count = 1, sleep = opt.KeySpeed; if (isLast) { if (!k.IsPair) { sleep = Internal_.LimitSleepTime(sleep) - opt.SleepFinally; } } else { if (kNext.IsRepeat) { count = kNext.repeat; } else if (!k.IsPair) { //If this is pair, sleep between down and up, and don't sleep after up. //Else if repeat, sleep always. //Else in most cases don't need to sleep. In some cases need, but can limit the time. // For example, in Ctrl+C normally would not need to sleep after Ctrl down and Ctrl up. // However some apps/controls then may not work. Maybe they process mod and nonmod keys somehow async. // For example, Ctrl+C in IE address bar often does not work if there is no sleep after Ctrl down. Always works if 1 ms. sleep = Internal_.LimitSleepTime(sleep); if (kNext.IsKey) { bool thisMod = KeyTypes_.IsMod(k.vk), nextMod = KeyTypes_.IsMod(kNext.vk); if (!k.IsUp) { if (kNext.IsUp) { sleep = opt.KeySpeed; } else if (thisMod == nextMod) { sleep = 0; } } else { if (!thisMod || nextMod) { sleep = 0; } } } else if (kNext.IsSleep) { sleep = sleep - kNext.sleep; } } } if (sleep < 0) { sleep = 0; } //var s = (k.vk).ToString(); //if(k.IsPair) AOutput.Write($"{s}<{sleep}>"); //else { var ud = k.IsUp ? '-' : '+'; if(sleep > 0) AOutput.Write($"{s}{ud} {sleep}"); else AOutput.Write($"{s}{ud}"); } for (int r = 0; r < count; r++) { //APerf.First(); Api.SendInput(&ki); //APerf.Next(); if (sleep > 0) { Internal_.Sleep(sleep); } if (k.IsPair) { ki.dwFlags |= Api.KEYEVENTF_KEYUP; Api.SendInput(&ki); ki.dwFlags &= ~Api.KEYEVENTF_KEYUP; } //APerf.NW(); //speed: min 400 mcs for each event. Often > 1000. Does not depend on whether all events sent by single SendInput call. } }
/// <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); }