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;
        }
Beispiel #2
0
        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);
            }
        }
        public static IntPtr FindProcessWindow(string processName)
        {
            var hwndFound = IntPtr.Zero;

            bool enumWindowsProc(IntPtr hwnd, IntPtr lparam)
            {
                if (!WinApi.IsWindowVisible(hwnd))
                {
                    return(true);
                }

                WinApi.GetWindowThreadProcessId(hwnd, out var pid);
                if (pid == 0)
                {
                    return(true);
                }

                var hProcess = WinApi.OpenProcess(WinApi.PROCESS_QUERY_LIMITED_INFORMATION, false, pid);

                if (hProcess == IntPtr.Zero)
                {
                    return(true);
                }
                try
                {
                    var buffer = new StringBuilder(1024);
                    int size   = buffer.Capacity;
                    if (WinApi.QueryFullProcessImageName(hProcess, 0, buffer, out size))
                    {
                        var path     = buffer.ToString();
                        var fileName = System.IO.Path.GetFileNameWithoutExtension(path);
                        if (String.Compare(fileName, processName, ignoreCase: true) == 0)
                        {
                            hwndFound = hwnd;
                            return(false);
                        }
                    }
                }
                finally
                {
                    WinApi.CloseHandle(hProcess);
                }
                return(true);
            }

            WinApi.EnumDesktopWindows(IntPtr.Zero, enumWindowsProc, IntPtr.Zero);
            return(hwndFound);
        }
Beispiel #4
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;
        }
Beispiel #5
0
        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();
            }
        }