/// <summary>
        ///     Go to the previous "page"
        /// </summary>
        /// <returns>bool if this worked</returns>
        public bool Previous()
        {
            var result        = false;
            var hasScrollInfo = TryRetrievePosition(out var scrollInfoBefore);

            switch (ScrollMode)
            {
            case ScrollModes.KeyboardPageUpDown:
                result = KeyboardInputGenerator.KeyPresses(VirtualKeyCode.Prior) == 2;
                break;

            case ScrollModes.WindowsMessage:
                result = SendScrollMessage(ScrollBarCommands.SB_PAGEUP);
                break;

            case ScrollModes.AbsoluteWindowMessage:
                if (!hasScrollInfo)
                {
                    return(false);
                }
                // Calculate previous position, clone the scrollInfoBefore
                var scrollInfoForPrevious = scrollInfoBefore;
                scrollInfoForPrevious.Position = Math.Max(scrollInfoBefore.Minimum, scrollInfoBefore.Position - (int)scrollInfoBefore.PageSize);
                result = ApplyPosition(ref scrollInfoForPrevious);
                break;

            case ScrollModes.MouseWheel:
                var bounds      = ScrollingWindow.GetInfo().Bounds;
                var middlePoint = new NativePoint(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2);
                result = MouseInputGenerator.MoveMouseWheel(WheelDelta, middlePoint) == 1;
                break;
            }
            return(result);
        }
Exemple #2
0
        private async Task TestInput()
        {
            // Start a process to test against
            using (var process = Process.Start("notepad.exe"))
            {
                // Make sure it's started
                Assert.NotNull(process);
                // Wait until the process started it's message pump (listening for input)
                process.WaitForInputIdle();

                User32Api.SetWindowText(process.MainWindowHandle, "TestInput");

                // Find the belonging window
                var notepadWindow = await WindowsEnumerator.EnumerateWindowsAsync()
                                    .Where(interopWindow =>
                {
                    User32Api.GetWindowThreadProcessId(interopWindow.Handle, out var processId);
                    return(processId == process.Id);
                })
                                    .FirstOrDefaultAsync();

                Assert.NotNull(notepadWindow);

                // Send input
                var sentInputs = KeyboardInputGenerator.KeyPresses(VirtualKeyCode.KeyR, VirtualKeyCode.KeyO, VirtualKeyCode.KeyB, VirtualKeyCode.KeyI, VirtualKeyCode.KeyN);
                // Test if we indead sent 10 inputs (5 x down & up)
                Assert.Equal((uint)10, sentInputs);

                // Kill the process
                process.Kill();
            }
        }
Exemple #3
0
        /// <summary>
        ///     Set the window as foreground window
        /// </summary>
        /// <param name="interopWindow">The window to bring to the foreground</param>
        /// <param name="workaround">bool with true to use a trick (press Alt) to really bring the window to the foreground</param>
        public static async ValueTask ToForegroundAsync(this IInteropWindow interopWindow, bool workaround = true)
        {
            // Nothing we can do if it's not visible!
            if (!interopWindow.IsVisible())
            {
                return;
            }
            // Window is already the foreground window
            if (User32Api.GetForegroundWindow() == interopWindow.Handle)
            {
                return;
            }
            if (interopWindow.IsMinimized())
            {
                interopWindow.Restore();
                while (interopWindow.IsMinimized())
                {
                    await Task.Delay(50).ConfigureAwait(false);
                }
            }

            // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx
            if (workaround)
            {
                // Simulate an "ALT" key press, make it double to remove menu activation
                KeyboardInputGenerator.KeyPresses(VirtualKeyCode.Menu, VirtualKeyCode.Menu);
            }
            // Show window in foreground.
            User32Api.BringWindowToTop(interopWindow.Handle);
            User32Api.SetForegroundWindow(interopWindow.Handle);
        }
Exemple #4
0
        private async Task TestKeyHandler_Slow_Subscriber()
        {
            int       pressCount        = 0;
            const int pressHandlingTime = 500;
            // Wait 2x press plus overhead
            const int waitForPressHandling = (int)((pressHandlingTime * 2) * 1.1);

            var sequenceHandler = new KeyCombinationHandler(VirtualKeyCode.Shift, VirtualKeyCode.KeyA)
            {
                IgnoreInjected = false
            };

            using (KeyboardHook.KeyboardEvents.Where(sequenceHandler).Subscribe(keyboardHookEventArgs =>
            {
                Log.Info().WriteLine("Key combination was pressed, slow handling!", null);
                Thread.Sleep(pressHandlingTime);
                Log.Info().WriteLine("Key combination was pressed, finished!", null);
                pressCount++;
            }))
            {
                Log.Info().WriteLine("Pressing key combination", null);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyA);
                Log.Info().WriteLine("Pressed key combination", null);
                Log.Info().WriteLine("Pressing key combination", null);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyA);
                Log.Info().WriteLine("Pressed key combination", null);
                await Task.Delay(waitForPressHandling);

                Assert.Equal(2, pressCount);
            }
        }
Exemple #5
0
        private async Task TestKeyHandler_Sequence_InputGenerator()
        {
            int pressCount      = 0;
            var sequenceHandler = new KeySequenceHandler(
                new KeyCombinationHandler(VirtualKeyCode.Print)
            {
                IgnoreInjected = false
            },
                new KeyCombinationHandler(VirtualKeyCode.Shift, VirtualKeyCode.KeyA)
            {
                IgnoreInjected = false
            });


            using (KeyboardHook.KeyboardEvents.Where(sequenceHandler).Subscribe(keyboardHookEventArgs => pressCount++))
            {
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Print);
                await Task.Delay(20);

                Assert.True(pressCount == 0);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyB);
                await Task.Delay(20);

                Assert.True(pressCount == 0);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Print);
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyA);
                await Task.Delay(20);

                Assert.True(pressCount == 1);
            }
        }
        private async Task TestKeyHandler_SingleCombination()
        {
            int pressCount = 0;
            var keyHandler = new KeyCombinationHandler(VirtualKeyCode.Back, VirtualKeyCode.RightShift)
            {
                IgnoreInjected = false,
                IsPassThrough  = false
            };

            using (KeyboardHook.KeyboardEvents.Where(keyHandler).Subscribe(keyboardHookEventArgs => pressCount++))
            {
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Back, VirtualKeyCode.RightShift);
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Back, VirtualKeyCode.RightShift);
                await Task.Delay(20);
            }
            Assert.True(pressCount == 2);
            KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Back, VirtualKeyCode.RightShift);
            await Task.Delay(20);

            Assert.True(pressCount == 2);
        }
Exemple #7
0
        private async Task TestKeyHandler_SequenceWithOptionalKeys_KeyboardInputGenerator()
        {
            int pressCount      = 0;
            var sequenceHandler = new KeySequenceHandler(
                new KeyCombinationHandler(VirtualKeyCode.Print)
            {
                IgnoreInjected = false
            },
                new KeyOrCombinationHandler(
                    new KeyCombinationHandler(VirtualKeyCode.Shift, VirtualKeyCode.KeyA)
            {
                IgnoreInjected = false
            },
                    new KeyCombinationHandler(VirtualKeyCode.Shift, VirtualKeyCode.KeyB)
            {
                IgnoreInjected = false
            })
                )
            {
                // Timeout for test
                Timeout = TimeSpan.FromMilliseconds(200)
            };

            using (KeyboardHook.KeyboardEvents.Where(sequenceHandler).Subscribe(keyboardHookEventArgs => pressCount++))
            {
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Print);
                await Task.Delay(20);

                Assert.Equal(0, pressCount);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyB);
                await Task.Delay(20);

                Assert.Equal(1, pressCount);
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Print);
                await Task.Delay(20);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyA);
                await Task.Delay(20);

                Assert.Equal(2, pressCount);

                // Test with timeout, waiting to long
                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Print);
                await Task.Delay(400);

                KeyboardInputGenerator.KeyCombinationPress(VirtualKeyCode.Shift, VirtualKeyCode.KeyA);
                await Task.Delay(20);

                Assert.Equal(2, pressCount);
            }
        }
        /// <summary>
        ///     Move to the start
        /// </summary>
        /// <returns>bool if this worked</returns>
        public bool Start()
        {
            var result        = false;
            var hasScrollInfo = TryRetrievePosition(out var scrollInfoBefore);

            switch (ScrollMode)
            {
            case ScrollModes.KeyboardPageUpDown:
                KeyboardInputGenerator.KeyDown(VirtualKeyCode.Control);
                KeyboardInputGenerator.KeyPresses(VirtualKeyCode.Home);
                KeyboardInputGenerator.KeyUp(VirtualKeyCode.Control);
                result = true;
                break;

            case ScrollModes.WindowsMessage:
                result = SendScrollMessage(ScrollBarCommands.SB_TOP);
                break;

            case ScrollModes.AbsoluteWindowMessage:
                result = hasScrollInfo;
                if (hasScrollInfo)
                {
                    // Calculate start position, clone the scrollInfoBefore
                    var scrollInfoForStart = scrollInfoBefore;
                    scrollInfoForStart.Position = scrollInfoBefore.Minimum;
                    result = ApplyPosition(ref scrollInfoForStart);
                }
                break;

            case ScrollModes.MouseWheel:
                result = true;
                while (!IsAtStart)
                {
                    if (!Previous())
                    {
                        break;
                    }
                }
                break;
            }
            return(result);
        }
Exemple #9
0
        /// <summary>
        ///     Test scrolling a window
        /// </summary>
        /// <returns></returns>
        //[StaFact]
        private async Task TestScrollingAsync()
        {
            var breakScroll = false;

            IDisposable keyboardhook = null;

            try
            {
                keyboardhook = KeyboardHook.KeyboardEvents.Where(args => args.Key == VirtualKeyCode.Escape).Subscribe(args => breakScroll = true);
                // Start a process to test against
                using (var process = Process.Start("notepad.exe", "C:\\Windows\\setupact.log"))
                {
                    // Make sure it's started
                    Assert.NotNull(process);
                    // Wait until the process started it's message pump (listening for input)
                    process.WaitForInputIdle();

                    try
                    {
                        // Find the belonging window, by the process id
                        var notepadWindow = WindowsEnumerator.EnumerateWindows()
                                            .FirstOrDefault(interopWindow =>
                        {
                            User32Api.GetWindowThreadProcessId(interopWindow.Handle, out var processId);
                            return(processId == process.Id);
                        });
                        Assert.NotNull(notepadWindow);

                        // Create a WindowScroller
                        var scroller = notepadWindow.GetChildren().Select(window => window.GetWindowScroller()).FirstOrDefault();

                        Assert.NotNull(scroller);
                        // Notepad should have ScrollBarInfo
                        scroller.GetScrollbarInfo();
                        Assert.True(scroller.ScrollBar.HasValue);

                        Log.Info().WriteLine("Scrollbar info: {0}", scroller.ScrollBar.Value);

                        User32Api.SetForegroundWindow(scroller.ScrollingWindow.Handle);
                        await Task.Delay(1000);

                        // Just make sure the window is changed
                        KeyboardInputGenerator.KeyPresses(VirtualKeyCode.Next, VirtualKeyCode.Down);
                        await Task.Delay(2000);

                        scroller.ScrollMode  = ScrollModes.WindowsMessage;
                        scroller.ShowChanges = false;
                        // Move the window to the start
                        Assert.True(scroller.Start());
                        // A delay to make the window move
                        await Task.Delay(2000);

                        // Check if it did move to the start
                        Assert.True(scroller.IsAtStart);

                        // Loop
                        do
                        {
                            if (breakScroll)
                            {
                                break;
                            }
                            // Next "page"
                            Assert.True(scroller.Next());
                            // Wait a bit, so the window can update
                            await Task.Delay(300);

                            // Loop as long as we are not at the end yet
                        } while (!scroller.IsAtEnd);
                        scroller.Reset();
                    }
                    finally
                    {
                        // Kill the process
                        process.Kill();
                    }
                }
            }
            finally
            {
                keyboardhook?.Dispose();
            }
        }