Пример #1
0
 /// <summary>
 /// Gets window Windows Store app user model id, like "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App".
 /// Returns null if fails or if called on Windows 7.
 /// </summary>
 /// <param name="w"></param>
 /// <param name="prependShellAppsFolder">Prepend <c>@"shell:AppsFolder\"</c> (to run or get icon).</param>
 /// <param name="getExePathIfNotWinStoreApp">Get program path if it is not a Windows Store app.</param>
 /// <remarks>
 /// Windows Store app window class name can be "Windows.UI.Core.CoreWindow" or "ApplicationFrameWindow".
 /// </remarks>
 public static string GetWindowsStoreAppId(AWnd w, bool prependShellAppsFolder = false, bool getExePathIfNotWinStoreApp = false)
 {
     if (0 != Internal_.GetWindowsStoreAppId(w, out var R, prependShellAppsFolder, getExePathIfNotWinStoreApp))
     {
         return(R);
     }
     return(null);
 }
Пример #2
0
 Util.ArrayBuilder_ <AWnd> _AllChildren(AWnd wParent)
 {
     wParent.ThrowIfInvalid();
     return(Internal_.EnumWindows2(Internal_.EnumAPI.EnumChildWindows,
                                   onlyVisible: 0 == (_flags & WCFlags.HiddenToo),
                                   sortFirstVisible: true,
                                   wParent: wParent,
                                   directChild: 0 != (_flags & WCFlags.DirectChild)));
 }
Пример #3
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);
                }
Пример #4
0
        unsafe void _SendKey(_KEvent k, int i)
        {
            bool needScanCode = k.scan == 0 && !k.SIFlags.HasAny(_KFlags.Scancode | _KFlags.Unicode);
            var  opt          = _GetOptionsAndWndFocused(out var wFocus, needScanCode);

            if (needScanCode)
            {
                var hkl = Api.GetKeyboardLayout(wFocus.ThreadId);                 //most layouts have the same standard scancodes, but eg dvorak different
                k.scan = Internal_.VkToSc(k.vk, hkl);
            }

            bool isLast = i == _a.Count - 1;

            _SendKey2(k, isLast ? default : _a[i + 1], isLast, opt);
        }
Пример #5
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);
        }
Пример #6
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.
            }
        }
Пример #7
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.
        }
Пример #8
0
 /// <summary>
 /// Gets top-level windows.
 /// </summary>
 /// <param name="a">Receives window handles as <b>wnd</b>. If null, this function creates new List, else clears before adding items.</param>
 /// <param name="onlyVisible"></param>
 /// <param name="sortFirstVisible"></param>
 /// <remarks>
 /// Use this overload to avoid much garbage when calling frequently with the same List variable. Other overload always allocates new array. This overload in most cases reuses memory allocated for the list variable.
 /// </remarks>
 public static void allWindows(ref List <wnd> a, bool onlyVisible = false, bool sortFirstVisible = false)
 {
     Internal_.EnumWindows2(Internal_.EnumAPI.EnumWindows, onlyVisible, sortFirstVisible, list: a ??= new List <wnd>());
 }
Пример #9
0
 /// <summary>
 /// Gets top-level windows.
 /// </summary>
 /// <returns>Array containing window handles as <b>wnd</b>.</returns>
 /// <param name="onlyVisible">
 /// Need only visible windows.
 /// Note: this function does not check whether windows are cloaked, as it is rather slow. Use <see cref="IsCloaked"/> if need.
 /// </param>
 /// <param name="sortFirstVisible">
 /// Place hidden windows at the end of the array.
 /// Not used when <i>onlyVisible</i> is true.</param>
 /// <remarks>
 /// Calls API <msdn>EnumWindows</msdn>.
 /// Although undocumented, the API retrieves most windows as in the Z order, however places IDE windows (hidden) at the end. See also: <see cref="allWindowsZorder"/>;
 /// <note>The array can be bigger than you expect, because there are many invisible windows, tooltips, etc. See also <see cref="mainWindows"/>.</note>
 /// Skips message-only windows; use <see cref="findFast"/> if need.
 /// On Windows 8 and later may skip Windows Store app Metro-style windows (on Windows 10 few such windows exist). It happens if this program does not have disableWindowFiltering true in its manifest and is not uiAccess; to find such windows you can use <see cref="findFast"/>.
 /// Tip: To get top-level and child windows in single array: <c>var a = wnd.getwnd.root.Get.Children();</c>.
 /// </remarks>
 /// <seealso cref="Children"/>
 /// <seealso cref="findAll"/>
 public static wnd[] allWindows(bool onlyVisible = false, bool sortFirstVisible = false)
 {
     return(Internal_.EnumWindows(Internal_.EnumAPI.EnumWindows, onlyVisible, sortFirstVisible));
 }
Пример #10
0
 /// <summary>
 /// Gets child controls, including all descendants.
 /// </summary>
 /// <param name="a">Receives window handles as AWnd. If null, this function creates new List, else clears before adding items.</param>
 /// <param name="onlyVisible">Need only visible controls.</param>
 /// <param name="sortFirstVisible">Place all array elements of hidden controls at the end of the array.</param>
 /// <param name="directChild">Need only direct children, not all descendants.</param>
 /// <exception cref="AuWndException">This variable is invalid (window not found, closed, etc).</exception>
 /// <remarks>
 /// Use this overload to avoid much garbage when calling frequently with the same List variable. Other overload always allocates new array. This overload in most cases reuses memory allocated for the list variable.
 /// </remarks>
 public void Children(ref List <AWnd> a, bool onlyVisible = false, bool sortFirstVisible = false, bool directChild = false)
 {
     _w.ThrowIfInvalid();
     Internal_.EnumWindows2(Internal_.EnumAPI.EnumChildWindows, onlyVisible, sortFirstVisible, _w, directChild, list: a ??= new List <AWnd>());
 }
Пример #11
0
 /// <summary>
 /// Gets child controls, including all descendants.
 /// Returns array containing 0 or more control handles as AWnd.
 /// </summary>
 /// <param name="onlyVisible">Need only visible controls.</param>
 /// <param name="sortFirstVisible">Place all array elements of hidden controls at the end of the array.</param>
 /// <param name="directChild">Need only direct children, not all descendants.</param>
 /// <exception cref="AuWndException">This variable is invalid (window not found, closed, etc).</exception>
 /// <remarks>
 /// Calls API <msdn>EnumChildWindows</msdn>.
 /// </remarks>
 /// <seealso cref="ChildAll"/>
 public AWnd[] Children(bool onlyVisible = false, bool sortFirstVisible = false, bool directChild = false)
 {
     _w.ThrowIfInvalid();
     return(Internal_.EnumWindows(Internal_.EnumAPI.EnumChildWindows, onlyVisible, sortFirstVisible, _w, directChild));
 }