コード例 #1
0
        private AttachedThreadInputScope()
        {
            s_current.Value?.Dispose();
            s_current.Value = this;

            _foregroundWindow   = WinApi.GetForegroundWindow();
            _currentThreadId    = WinApi.GetCurrentThreadId();
            _foregroundThreadId = WinApi.GetWindowThreadProcessId(_foregroundWindow, out var _);

            if (_currentThreadId != _foregroundThreadId)
            {
                // attach to the foreground thread
                if (!WinApi.AttachThreadInput(_currentThreadId, _foregroundThreadId, true))
                {
                    // unable to attach, see if the window is a Win10 Console Window
                    var className = new StringBuilder(capacity: 256);
                    WinApi.GetClassName(_foregroundWindow, className, className.Capacity - 1);
                    if (String.CompareOrdinal("ConsoleWindowClass", className.ToString()) != 0)
                    {
                        return;
                    }
                    // consider attached to a console window
                }
            }

            _attached = true;
        }
コード例 #2
0
ファイル: Utilities.cs プロジェクト: hpenney2/devcomrade
        public static bool TryGetThirdPartyForgroundWindow(out IntPtr hwnd)
        {
            hwnd = IntPtr.Zero;
            var foregroundWindow = WinApi.GetForegroundWindow();
            var currentThreadId  = WinApi.GetCurrentThreadId();
            var foregroundThread = WinApi.GetWindowThreadProcessId(foregroundWindow, out var _);

            if (currentThreadId == foregroundThread)
            {
                return(false);
            }
            else
            {
                var hwndRoot = WinApi.GetAncestor(foregroundWindow, WinApi.GA_ROOT);
                if (hwndRoot != IntPtr.Zero)
                {
                    foregroundWindow = hwndRoot;
                }

                var className = new StringBuilder(capacity: 256);
                WinApi.GetClassName(foregroundWindow, className, className.Capacity - 1);
                if (className.ToString().CompareTo("Shell_TrayWnd") == 0)
                {
                    return(false);
                }

                hwnd = foregroundWindow;
                return(true);
            }
        }
コード例 #3
0
        public static async Task <bool> FeedTextAsync(string text, CancellationToken token)
        {
            await s_asyncLock.WaitAsync(token);

            try
            {
                var foregroundWindow = WinApi.GetForegroundWindow();
                WinApi.BlockInput(true);
                try
                {
                    var size  = Marshal.SizeOf <WinApi.INPUT>();
                    var input = new WinApi.INPUT[1];

                    // feed each character individually and asynchronously
                    foreach (var c in text)
                    {
                        token.ThrowIfCancellationRequested();

                        if (WinApi.GetForegroundWindow() != foregroundWindow ||
                            IsAnyKeyPressed())
                        {
                            break;
                        }

                        if (c == '\n' || c == '\r')
                        {
                            // we need this for correctly handling line breaks
                            // when pasting into Chromium's <textarea>
                            SimulateKeyDown(WinApi.VK_RETURN);
                            SimulateKeyUp(WinApi.VK_RETURN);
                        }
                        else
                        {
                            CharToKeyboardInput(c, ref input[0]);
                            if (WinApi.SendInput((uint)input.Length, input, size) == 0)
                            {
                                break;
                            }
                        }

                        if (InputHelpers.AnyInputMessage(WinApi.QS_ALLINPUT))
                        {
                            await InputHelpers.TimerYield(token : token);
                        }
                    }
                    return(true);
                }
                finally
                {
                    WinApi.BlockInput(false);
                }
            }
            finally
            {
                s_asyncLock.Release();
            }
        }
コード例 #4
0
        public static async Task <bool> FeedTextAsync(string text, CancellationToken token)
        {
            await s_asyncLock.WaitAsync(token);

            try
            {
                var foregroundWindow = WinApi.GetForegroundWindow();
                WinApi.BlockInput(true);
                try
                {
                    var size  = Marshal.SizeOf <WinApi.INPUT>();
                    var input = new WinApi.INPUT[1];

                    // feed each character individually and asynchronously
                    foreach (var c in text)
                    {
                        token.ThrowIfCancellationRequested();

                        if (WinApi.GetForegroundWindow() != foregroundWindow ||
                            IsAnyKeyPressed())
                        {
                            break;
                        }

                        CharToKeyboardInput(c, ref input[0]);
                        if (WinApi.SendInput((uint)input.Length, input, size) == 0)
                        {
                            break;
                        }

                        if (InputHelpers.AnyInputMessage(WinApi.QS_ALLINPUT))
                        {
                            await InputHelpers.TimerYield(token : token);
                        }
                    }
                    return(true);
                }
                finally
                {
                    WinApi.BlockInput(false);
                }
            }
            finally
            {
                s_asyncLock.Release();
            }
        }
コード例 #5
0
        private AttachedThreadInputScope()
        {
            s_current.Value?.Dispose();
            s_current.Value = this;

            _foregroundWindow   = WinApi.GetForegroundWindow();
            _currentThreadId    = WinApi.GetCurrentThreadId();
            _foregroundThreadId = WinApi.GetWindowThreadProcessId(_foregroundWindow, out var _);

            if (_currentThreadId != _foregroundThreadId)
            {
                // attach to the foreground thread
                if (!WinApi.AttachThreadInput(_foregroundThreadId, _currentThreadId, true))
                {
                    return;
                }
            }

            _attached = true;
        }
コード例 #6
0
ファイル: Utilities.cs プロジェクト: hpenney2/devcomrade
        public static IntPtr GetPrevActiveWindow()
        {
            var foregroundWindow = WinApi.GetAncestor(WinApi.GetForegroundWindow(), WinApi.GA_ROOT);

            var hwndPrev  = IntPtr.Zero;
            var hwndFound = IntPtr.Zero;

            bool enumWindowsProc(IntPtr hwnd, IntPtr lparam)
            {
                if (WinApi.IsWindowVisible(hwnd))
                {
                    if (hwndPrev == foregroundWindow)
                    {
                        hwndFound = hwnd;
                        return(false);
                    }
                    hwndPrev = hwnd;
                }
                return(true);
            }

            WinApi.EnumDesktopWindows(IntPtr.Zero, enumWindowsProc, IntPtr.Zero);
            return(hwndFound);
        }
コード例 #7
0
ファイル: Diagnostics.cs プロジェクト: hpenney2/devcomrade
        private async static ValueTask <(bool left, bool right)> GetLeftRightCtrlStateAsync(uint delay, CancellationToken token)
        {
            // this is used purely for debugging and so we utilize
            // native CreateTimerQueueTimer with WT_EXECUTEINPERSISTENTTHREAD
            // for keyboard polling here, because we don't want
            // to pollute ThreadPool threads with AttachThreadInput other user32 calls
            var tcs = new TaskCompletionSource <(bool, bool)>(TaskCreationOptions.RunContinuationsAsynchronously);

            using var rego = token.Register(() => tcs.SetCanceled(), useSynchronizationContext: false);
            WinApi.WaitOrTimerCallbackProc timerCallback = delegate
            {
                try
                {
                    // attach the to the foreground thread to read the keyboard status
                    var currentThread    = WinApi.GetCurrentThreadId();
                    var foregroundWindow = WinApi.GetForegroundWindow();
                    var foregroundThread = WinApi.GetWindowThreadProcessId(foregroundWindow, out uint foregroundProcess);

                    var attached = WinApi.AttachThreadInput(foregroundThread, currentThread, true);
                    try
                    {
                        var leftCtrl  = (WinApi.GetAsyncKeyState(WinApi.VK_LCONTROL) & 0x8000) != 0;
                        var rightCtrl = (WinApi.GetAsyncKeyState(WinApi.VK_RCONTROL) & 0x8000) != 0;
                        tcs.TrySetResult((leftCtrl, rightCtrl));
                    }
                    finally
                    {
                        if (attached)
                        {
                            WinApi.AttachThreadInput(foregroundThread, currentThread, false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    tcs.TrySetException(ex);
                }
            };

            var    gcHandle    = GCHandle.Alloc(timerCallback);
            IntPtr timerHandle = IntPtr.Zero;

            try
            {
                if (!WinApi.CreateTimerQueueTimer(
                        out timerHandle,
                        IntPtr.Zero,
                        timerCallback,
                        IntPtr.Zero, delay, 0,
                        (UIntPtr)(WinApi.WT_EXECUTEINPERSISTENTTHREAD | WinApi.WT_EXECUTEONLYONCE)))
                {
                    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
                }

                return(await tcs.Task);
            }
            finally
            {
                if (timerHandle != IntPtr.Zero)
                {
                    WinApi.DeleteTimerQueueTimer(IntPtr.Zero, timerHandle, IntPtr.Zero);
                }
                gcHandle.Free();
            }
        }