Beispiel #1
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);
                }
Beispiel #2
0
        //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.
            }
        }
Beispiel #3
0
        /// <summary>
        /// Sends keys, text and executes other events added with the <b>AddX</b> functions.
        /// </summary>
        /// <param name="canSendAgain">Don't clear the internal collection. If true, this function then can be called again (eg in loop) to send/execute the same keys etc. If false (default), clears the added keys etc; then you can call <b>AddX</b> functions and <b>Send</b> again.</param>
        /// <exception cref="ArgumentException"><i>canSendAgain</i> is true and keys end with + or (.</exception>
        public void Send(bool canSendAgain = false)
        {
            _ThrowIfSending();
            if (_a.Count == 0)
            {
                return;
            }
            if (canSendAgain)
            {
                if (_pstate.paren || _pstate.plus)
                {
                    throw new ArgumentException("canSendAgain cannot be true if keys ends with + or (");
                }
            }

            //AOutput.Write("-- _parsing.mod --");
            //AOutput.Write(_parsing.mod);

            _AddModUp();             //add mod-up events if need, eg Ctrl-up after "Ctrl+A"

            //AOutput.Write("-- _a --");
            //AOutput.Write(_a);

            //APerf.First();
            int  sleepFinally    = 0;
            bool restoreCapsLock = false;
            var  bi = new AInputBlocker()
            {
                ResendBlockedKeys = true
            };

            try {
                _sending = true;
                //AOutput.Write("{");
                if (!Options.NoBlockInput)
                {
                    bi.Start(BIEvents.Keys);
                }
                restoreCapsLock = Internal_.ReleaseModAndCapsLock(Options);
                //APerf.Next();
                for (int i = 0; i < _a.Count; i++)
                {
                    var k = _a[i];
                    switch (k.Type)
                    {
                    case _KType.Sleep:
                        if (i == _a.Count - 1)
                        {
                            sleepFinally = k.sleep;
                        }
                        else
                        {
                            Internal_.Sleep(k.sleep);
                        }
                        break;

                    case _KType.Repeat:
                        Debug.Assert(i > 0 && _a[i - 1].IsKey);
                        break;

                    case _KType.Callback:
                        (_GetData(k.data) as Action)();
                        break;

                    case _KType.Text:
                        _SendText(k);
                        break;

                    default:
                        _SendKey(k, i);
                        break;
                    }
                }
                //APerf.Next();
                sleepFinally += _GetOptionsAndWndFocused(out _, false).SleepFinally;
            }
            finally {
                if (restoreCapsLock)
                {
                    Internal_.SendKey(KKey.CapsLock);
                }
                _sending = false;
                bi.Dispose();
                //APerf.NW();
                //AOutput.Write("}");

                //if canSendAgain, can be used like: AddX(); for(...) Send();
                //else can be used like: AddX(); Send(); AddX(); Send();
                if (!canSendAgain)
                {
                    _a.Clear();
                    _data = null;
                    _sstate.Clear();
                    //and don't clear _pstate
                }
            }

            if (sleepFinally > 0)
            {
                Internal_.Sleep(sleepFinally);
            }

            //_SyncWait();
            //CONSIDER: instead of SleepFinally use TimeSyncFinally, default 100 ms. Eg send a sync key and wait max TimeSyncFinally ms.
            //	Don't sync after each (or some) sent key. Usually it does not make sense. The final sync/sleep is useful if next statement is not an input function.
            //Sync problems:
            //	Tried many ways, nothing is good enough. The test code now is in the "Unused" project.
            //	The best would be non-LL keyboard hook that sets event when receives our sent special key-up. Especially when combined with 'get thread CPU usage' while waiting for the event. However these hooks don't work eg in Store apps.
            //Better add a Sync function (AKeys.Sync) or/and special key name, let users do it explicitly where need.
        }