コード例 #1
0
        /// <summary>
        ///     Get a location where this window would be visible
        ///     * if none is found return false, formLocation = the original location
        ///     * if something is found, return true and formLocation = new location
        /// </summary>
        /// <param name="interopWindow">IInteropWindow, the window to find a location for</param>
        /// <param name="formLocation">NativePoint with the location where the window will fit</param>
        /// <returns>true if a location if found, and the formLocation is also set</returns>
        public static bool GetVisibleLocation(this IInteropWindow interopWindow, out NativePoint formLocation)
        {
            bool doesWindowFit   = false;
            var  windowRectangle = interopWindow.GetInfo().Bounds;

            // assume own location
            formLocation = windowRectangle.Location;
            var primaryDisplay = User32Api.AllDisplays().First(x => x.IsPrimary);

            using (var workingArea = new Region(primaryDisplay.Bounds))
            {
                // Create a region with the screens working area
                foreach (var display in User32Api.AllDisplays())
                {
                    if (!display.IsPrimary)
                    {
                        workingArea.Union(display.Bounds);
                    }
                }

                // If the formLocation is not inside the visible area
                if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
                {
                    // If none found we find the biggest screen
                    foreach (var display in User32Api.AllDisplays())
                    {
                        var newWindowRectangle = new Rectangle(display.WorkingArea.Location, windowRectangle.Size);
                        if (!workingArea.AreRectangleCornersVisisble(newWindowRectangle))
                        {
                            continue;
                        }
                        formLocation  = display.Bounds.Location;
                        doesWindowFit = true;
                        break;
                    }
                }
                else
                {
                    doesWindowFit = true;
                }
            }
            return(doesWindowFit);
        }
コード例 #2
0
        /// <summary>
        ///     This method will capture the current Cursor by using User32 Code
        /// </summary>
        /// <returns>A Capture Object with the Mouse Cursor information in it.</returns>
        public static ICapture CaptureCursor(ICapture capture)
        {
            Log.Debug().WriteLine("Capturing the mouse cursor.");
            if (capture == null)
            {
                capture = new Capture();
            }

            var cursorInfo = CursorInfo.Create();

            if (!NativeCursorMethods.GetCursorInfo(ref cursorInfo))
            {
                return(capture);
            }
            if (cursorInfo.Flags != CursorInfoFlags.Showing)
            {
                return(capture);
            }
            using (var safeIcon = NativeIconMethods.CopyIcon(cursorInfo.CursorHandle))
            {
                if (!NativeIconMethods.GetIconInfo(safeIcon, out var iconInfo))
                {
                    return(capture);
                }
                using (iconInfo.BitmaskBitmapHandle)
                    using (iconInfo.ColorBitmapHandle)
                    {
                        var cursorLocation = User32Api.GetCursorLocation();
                        // Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
                        var x = cursorLocation.X - iconInfo.Hotspot.X - capture.ScreenBounds.X;
                        var y = cursorLocation.Y - iconInfo.Hotspot.Y - capture.ScreenBounds.Y;
                        // Set the location
                        capture.CursorLocation = new NativePoint(x, y);

                        using (var icon = Icon.FromHandle(safeIcon.DangerousGetHandle()))
                        {
                            capture.Cursor = icon;
                        }
                    }
            }
            return(capture);
        }
コード例 #3
0
        /// <summary>
        ///     Enumerate the windows / child windows (this is NOT lazy)
        /// </summary>
        /// <param name="parent">IInteropWindow with the hwnd of the parent, or null for all</param>
        /// <param name="wherePredicate">Func for the where</param>
        /// <param name="takeWhileFunc">Func which can decide to stop enumerating, the second argument is the current count</param>
        /// <returns>IEnumerable with InteropWindow</returns>
        public static IEnumerable <IInteropWindow> EnumerateWindows(IInteropWindow parent = null, Func <IInteropWindow, bool> wherePredicate = null, Func <IInteropWindow, int, bool> takeWhileFunc = null)
        {
            var result = new List <IInteropWindow>();

            bool EnumWindowsProc(IntPtr hwnd, IntPtr param)
            {
                // check if we should continue
                var interopWindow = InteropWindowFactory.CreateFor(hwnd);

                if (wherePredicate == null || wherePredicate(interopWindow))
                {
                    result.Add(interopWindow);
                }

                return(takeWhileFunc == null || takeWhileFunc(interopWindow, result.Count));
            }

            User32Api.EnumChildWindows(parent?.Handle ?? IntPtr.Zero, EnumWindowsProc, IntPtr.Zero);
            return(result);
        }
コード例 #4
0
        public MainWindow()
        {
            InitializeComponent();
            this.AttachDpiHandler();

            this.WinProcMessages()
            .Where(m => m.Message == WindowsMessages.WM_DESTROY)
            .Subscribe(m => { MessageBox.Show($"{m.Message}"); });

            DeviceNotification.OnVolumeAdded().Subscribe(volumeInfo => Debug.WriteLine($"Drives {volumeInfo.Volume.Drives} were added"));
            DeviceNotification.OnVolumeRemoved().Subscribe(volumeInfo => Debug.WriteLine($"Drives {volumeInfo.Volume.Drives} were removed"));

            DeviceNotification
            .OnDeviceArrival()
            .Subscribe(deviceInterfaceChangeInfo => Debug.WriteLine("Device added: {0}, for more information goto {1}", deviceInterfaceChangeInfo.Device.FriendlyDeviceName, deviceInterfaceChangeInfo.Device.UsbDeviceInfoUri));

            // A small example to lock the PC when a YubiKey is removed
            DeviceNotification.OnDeviceRemoved()
            .Where(deviceInterfaceChangeInfo => deviceInterfaceChangeInfo.Device.Name.Contains("Yubi"))
            .Subscribe(deviceInterfaceChangeInfo => User32Api.LockWorkStation());
        }
コード例 #5
0
        /// <summary>
        ///     Get the Windows caption (title)
        /// </summary>
        /// <param name="interopWindow">InteropWindow</param>
        /// <param name="forceUpdate">set to true to make sure the value is updated</param>
        /// <returns>string with the caption</returns>
        public static string GetCaption(this IInteropWindow interopWindow, bool forceUpdate = false)
        {
            if (interopWindow.Caption != null && !forceUpdate)
            {
                return(interopWindow.Caption);
            }

            // Calling User32Api.GetText (GetWindowText) for the current Process will hang, deadlock, this should be ignored
            if (interopWindow.IsOwnedByCurrentThread())
            {
                // TODO: it might have a value, but can't get it. Returning null would be bad... so return empty
                interopWindow.Caption = string.Empty;
                Log.Warn().WriteLine("Do not call GetWindowText for a Window ({0}) which belongs the current thread! An empty string is returned.", interopWindow.Handle);
            }
            else
            {
                var caption = User32Api.GetText(interopWindow.Handle);
                interopWindow.Caption = caption;
            }
            return(interopWindow.Caption);
        }
コード例 #6
0
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) //使用冒泡事件
        {
            if (_direction != Direction.NONE)
            {
                var pos     = this.PointToScreen(Mouse.GetPosition(this));   //鼠标屏幕坐标
                var leftTop = this.PointToScreen(new Point(0, 0));           //左上
                var right   = this.PointToScreen(new Point(this.Width, 0));  //右
                var bottom  = this.PointToScreen(new Point(0, this.Height)); //下

                if (pos.X - leftTop.X <= 2)                                  //左
                {
                    User32Api.SetCursorPos((int)pos.X + 1, (int)pos.Y);
                }
                else if (pos.Y - leftTop.Y <= 2) //上
                {
                    User32Api.SetCursorPos((int)pos.X, (int)pos.Y + 1);
                }
                else if (right.X - pos.X <= 2) //右
                {
                    User32Api.SetCursorPos((int)pos.X - 1, (int)pos.Y);
                }
                else if (bottom.Y - pos.Y <= 2) //下
                {
                    User32Api.SetCursorPos((int)pos.X, (int)pos.Y - 1);
                }
            }
            else if (e.ClickCount == 2 && Mouse.GetPosition(this).Y <= this._headHeight) //双击最大化
            {
                if (this.WindowState == WindowState.Normal)
                {
                    this.WindowState = WindowState.Maximized;
                }
                else
                {
                    this.WindowState = WindowState.Normal;
                }
                e.Handled = true;
            }
            base.OnMouseLeftButtonDown(e);
        }
コード例 #7
0
        private async Task TestWinEventHook()
        {
            // This takes care of having a WinProc handler, to make sure the messages arrive
            var winProcHandler = WinProcHandler.Instance;
            // This buffers the observable
            var replaySubject = new ReplaySubject <IInteropWindow>();

            var winEventObservable = WinEventHook.WindowTileChangeObservable()
                                     .Select(info => InteropWindowFactory.CreateFor(info.Handle).Fill())
                                     .Where(interopWindow => !string.IsNullOrEmpty(interopWindow?.Caption))
                                     .Subscribe(interopWindow =>
            {
                Log.Debug().WriteLine("Window title change: Process ID {0} - Title: {1}", interopWindow.Handle, interopWindow.Caption);
                replaySubject.OnNext(interopWindow);
            }, exception => Log.Error().WriteLine("An error occured", exception));
            await Task.Delay(100);

            // Start a process to test against
            using (var process = Process.Start("notepad.exe"))
            {
                try
                {
                    // 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, "TestWinEventHook - Test");

                    // Find the belonging window
                    var notepadWindow = await replaySubject.Where(info => info != null && info.ProcessId == process.Id).FirstAsync();

                    Assert.Equal(process.Id, notepadWindow?.ProcessId);
                }
                finally
                {
                    winEventObservable.Dispose();
                    process?.Kill();
                }
            }
        }
コード例 #8
0
        /// <summary>
        ///     Used to access system folder icons.
        /// </summary>
        /// <param name="size">Specify large or small icons.</param>
        /// <param name="folderType">Specify open or closed FolderType.</param>
        /// <returns>System.Drawing.Icon</returns>
        public static TIcon GetFolderIcon <TIcon>(IconSize size, FolderType folderType) where TIcon : class
        {
            // Need to add size check, although errors generated at present!
            var flags = ShellGetFileInfoFlags.Icon | ShellGetFileInfoFlags.UseFileAttributes;

            if (FolderType.Open == folderType)
            {
                flags |= ShellGetFileInfoFlags.OpenIcon;
            }

            if (IconSize.Small == size)
            {
                flags |= ShellGetFileInfoFlags.SmallIcon;
            }
            else
            {
                flags |= ShellGetFileInfoFlags.LargeIcon;
            }

            // Get the folder icon
            var shellFileInfo = new ShellFileInfo();

            SHGetFileInfo(null, FILE_ATTRIBUTE_DIRECTORY, ref shellFileInfo, (uint)Marshal.SizeOf(shellFileInfo), flags);

            //Icon.FromHandle(shfi.hIcon);	// Load the icon from an HICON handle
            // Now clone the icon, so that it can be successfully stored in an ImageList
            try
            {
                return(IconHelper.IconHandleTo <TIcon>(shellFileInfo.IconHandle));
            }
            finally
            {
                if (shellFileInfo.IconHandle != IntPtr.Zero)
                {
                    // Cleanup
                    User32Api.DestroyIcon(shellFileInfo.IconHandle);
                }
            }
        }
コード例 #9
0
        /// <summary>
        ///     Returns an icon for a given file extension - indicated by the name parameter.
        ///     See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179(v=vs.85).aspx
        /// </summary>
        /// <param name="filename">Filename</param>
        /// <param name="size">Large or small</param>
        /// <param name="linkOverlay">Whether to include the link icon</param>
        /// <returns>System.Drawing.Icon</returns>
        public static TIcon GetFileExtensionIcon <TIcon>(string filename, IconSize size, bool linkOverlay) where TIcon : class
        {
            var shfi = new ShellFileInfo();
            // UseFileAttributes makes it simulate, just gets the icon for the extension
            var flags = ShellGetFileInfoFlags.Icon | ShellGetFileInfoFlags.UseFileAttributes;

            if (linkOverlay)
            {
                flags |= ShellGetFileInfoFlags.LinkOverlay;
            }

            // Check the size specified for return.
            if (IconSize.Small == size)
            {
                flags |= ShellGetFileInfoFlags.SmallIcon;
            }
            else
            {
                flags |= ShellGetFileInfoFlags.LargeIcon;
            }

            SHGetFileInfo(Path.GetFileName(filename), FILE_ATTRIBUTE_NORMAL, ref shfi, (uint)Marshal.SizeOf(shfi), flags);

            // TODO: Fix bad practise for cleanup, and use generics to allow the user to specify if it's an icon/bitmap/-source
            // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
            try
            {
                return(IconHelper.IconHandleTo <TIcon>(shfi.IconHandle));
            }
            finally
            {
                if (shfi.IconHandle != IntPtr.Zero)
                {
                    // Cleanup
                    User32Api.DestroyIcon(shfi.IconHandle);
                }
            }
        }
コード例 #10
0
        /// <summary>
        ///     Method to set the ScrollbarInfo, if we can get it
        /// </summary>
        /// <param name="forceUpdate">set to true to force an update, default is false</param>
        /// <returns>ScrollBarInfo?</returns>
        public ScrollBarInfo?GetScrollbarInfo(bool forceUpdate = false)
        {
            // Prevent updates, if there is already a value
            if (ScrollBar.HasValue && !forceUpdate)
            {
                return(ScrollBar);
            }
            var objectId = ObjectIdentifiers.Client;

            switch (ScrollBarType)
            {
            case ScrollBarTypes.Control:
                objectId = ObjectIdentifiers.Client;
                break;

            case ScrollBarTypes.Vertical:
                objectId = ObjectIdentifiers.VerticalScrollbar;
                break;

            case ScrollBarTypes.Horizontal:
                objectId = ObjectIdentifiers.HorizontalScrollbar;
                break;
            }
            var scrollbarInfo    = ScrollBarInfo.Create();
            var hasScrollbarInfo = User32Api.GetScrollBarInfo(ScrollBarWindow.Handle, objectId, ref scrollbarInfo);

            if (!hasScrollbarInfo)
            {
                var error = Win32.GetLastErrorCode();
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Error retrieving Scrollbar info : {0}", Win32.GetMessage(error));
                }
                return(null);
            }
            ScrollBar = scrollbarInfo;
            return(scrollbarInfo);
        }
コード例 #11
0
        /// <summary>
        ///     Get the WindowInfo
        /// </summary>
        /// <param name="interopWindow">InteropWindow</param>
        /// <param name="forceUpdate">set to true to make sure the value is updated</param>
        /// <returns>WindowInfo</returns>
        public static WindowInfo GetInfo(this IInteropWindow interopWindow, bool forceUpdate = false)
        {
            if (interopWindow.Info.HasValue && !forceUpdate)
            {
                return(interopWindow.Info.Value);
            }
            var windowInfo = WindowInfo.Create();

            User32Api.GetWindowInfo(interopWindow.Handle, ref windowInfo);

            // Now correct the bounds, for Windows 10
            if (Dwm.IsDwmEnabled)
            {
                NativeRect extendedFrameBounds;
                bool       gotFrameBounds = Dwm.GetExtendedFrameBounds(interopWindow.Handle, out extendedFrameBounds);
                if (gotFrameBounds && (interopWindow.IsApp() || WindowsVersion.IsWindows10OrLater && !interopWindow.IsMaximized()))
                {
                    windowInfo.Bounds = extendedFrameBounds;
                }
            }
            interopWindow.Info = windowInfo;
            return(interopWindow.Info.Value);
        }
コード例 #12
0
        /// <summary>
        ///     Extension method to create a WindowScroller
        /// </summary>
        /// <param name="interopWindow">IInteropWindow</param>
        /// <param name="scrollBarType">ScrollBarTypes</param>
        /// <param name="forceUpdate">true to force a retry, even if the previous check failed</param>
        /// <returns>WindowScroller or null</returns>
        public static WindowScroller GetWindowScroller(this IInteropWindow interopWindow, ScrollBarTypes scrollBarType = ScrollBarTypes.Vertical, bool forceUpdate = false)
        {
            if (!forceUpdate && interopWindow.CanScroll.HasValue && !interopWindow.CanScroll.Value)
            {
                return(null);
            }
            var initialScrollInfo = ScrollInfo.Create(ScrollInfoMask.All);

            if (User32Api.GetScrollInfo(interopWindow.Handle, scrollBarType, ref initialScrollInfo) && initialScrollInfo.Minimum != initialScrollInfo.Maximum)
            {
                var windowScroller = new WindowScroller
                {
                    ScrollingWindow   = interopWindow,
                    ScrollBarWindow   = interopWindow,
                    ScrollBarType     = scrollBarType,
                    InitialScrollInfo = initialScrollInfo,
                    WheelDelta        = (int)(120 * (initialScrollInfo.PageSize / WindowScroller.ScrollWheelLinesFromRegistry))
                };
                interopWindow.CanScroll = true;
                return(windowScroller);
            }
            if (User32Api.GetScrollInfo(interopWindow.Handle, ScrollBarTypes.Control, ref initialScrollInfo) && initialScrollInfo.Minimum != initialScrollInfo.Maximum)
            {
                var windowScroller = new WindowScroller
                {
                    ScrollingWindow   = interopWindow,
                    ScrollBarWindow   = interopWindow,
                    ScrollBarType     = ScrollBarTypes.Control,
                    InitialScrollInfo = initialScrollInfo,
                    WheelDelta        = (int)(120 * (initialScrollInfo.PageSize / WindowScroller.ScrollWheelLinesFromRegistry))
                };
                interopWindow.CanScroll = true;
                return(windowScroller);
            }
            interopWindow.CanScroll = false;
            return(null);
        }
コード例 #13
0
ファイル: AppQuery.cs プロジェクト: molongwudi/Dapplo.Windows
        /// <summary>
        ///     Check if a Windows Store App (WinRT) is visible
        /// </summary>
        /// <param name="windowBounds"></param>
        /// <returns>true if an app, covering the supplied rect, is visisble</returns>
        public static bool AppVisible(NativeRect windowBounds)
        {
            if (AppVisibility == null)
            {
                return(true);
            }

            foreach (var screen in User32Api.AllDisplays())
            {
                if (!screen.Bounds.Contains(windowBounds))
                {
                    continue;
                }

                if (windowBounds.Equals(screen.Bounds))
                {
                    // Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes
                    // Although it might be the other App, this is not "very" important
                    var rect    = screen.Bounds;
                    var monitor = User32Api.MonitorFromRect(ref rect, MonitorFrom.DefaultToNearest);
                    if (monitor != IntPtr.Zero)
                    {
                        var monitorAppVisibility = AppVisibility.ComObject.GetAppVisibilityOnMonitor(monitor);
                        if (monitorAppVisibility == MonitorAppVisibility.MAV_APP_VISIBLE)
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    // Is only partly on the screen, when this happens the app is allways visible!
                    return(true);
                }
            }
            return(false);
        }
コード例 #14
0
        /// <summary>
        ///     Get the WindowInfo
        /// </summary>
        /// <param name="interopWindow">InteropWindow</param>
        /// <param name="forceUpdate">set to true to make sure the value is updated</param>
        /// <param name="autoCorrect">enable auto correction, e,g, have the bounds cropped to the parent(s)</param>
        /// <returns>WindowInfo</returns>
        public static WindowInfo GetInfo(this IInteropWindow interopWindow, bool forceUpdate = false, bool autoCorrect = true)
        {
            if (interopWindow.Info.HasValue && !forceUpdate)
            {
                return(interopWindow.Info.Value);
            }

            var windowInfo = WindowInfo.Create();

            User32Api.GetWindowInfo(interopWindow.Handle, ref windowInfo);

            // Test if we need to correct some values
            if (autoCorrect)
            {
                // Correct the bounds, for Windows 8+
                if (Dwm.IsDwmEnabled)
                {
                    // This only works for top level windows, otherwise a access denied is returned
                    bool gotFrameBounds = Dwm.GetExtendedFrameBounds(interopWindow.Handle, out var extendedFrameBounds);
                    if (gotFrameBounds && (interopWindow.IsApp() || WindowsVersion.IsWindows10OrLater && !interopWindow.IsMaximized()))
                    {
                        windowInfo.Bounds = extendedFrameBounds;
                    }
                }

                var parentWindow = interopWindow.GetParentWindow();
                if (interopWindow.HasParent)
                {
                    var parentInfo = parentWindow.GetInfo(forceUpdate, true);
                    windowInfo.Bounds       = windowInfo.Bounds.Intersect(parentInfo.Bounds);
                    windowInfo.ClientBounds = windowInfo.ClientBounds.Intersect(parentInfo.ClientBounds);
                }
            }

            interopWindow.Info = windowInfo;
            return(windowInfo);
        }
コード例 #15
0
        /// <summary>
        ///     Default constructor, this opens the input destop with GENERIC_ALL
        ///     This is needed to support marshalling!!
        /// </summary>
        public SafeCurrentInputDesktopHandle() : base(true)
        {
            var hDesktop = User32Api.OpenInputDesktop(0, true, DesktopAccessRight.GENERIC_ALL);

            if (hDesktop != IntPtr.Zero)
            {
                // Got desktop, store it as handle for the ReleaseHandle
                SetHandle(hDesktop);
                if (User32Api.SetThreadDesktop(hDesktop))
                {
                    Log.Debug().WriteLine("Switched to desktop {0}", hDesktop);
                }
                else
                {
                    Log.Warn().WriteLine("Couldn't switch to desktop {0}", hDesktop);
                    Log.Error().WriteLine(User32Api.CreateWin32Exception("SetThreadDesktop"));
                }
            }
            else
            {
                Log.Warn().WriteLine("Couldn't get current desktop.");
                Log.Error().WriteLine(User32Api.CreateWin32Exception("OpenInputDesktop"));
            }
        }
コード例 #16
0
ファイル: WinIoHelp.cs プロジェクト: oujunke/Help
        /// <summary>
        /// 按键按下
        /// </summary>
        /// <param name="vKeyCoad"></param>
        public static void MykeyDown(VKKey vKeyCoad)
        {
            if (!IsInitialize)
            {
                return;
            }

            Thread.Sleep(100);
            int btScancode = 0;

            btScancode = User32Api.MapVirtualKey((uint)vKeyCoad, 0);

            KBCWait4IBE();

            SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1);

            KBCWait4IBE();

            SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);

            KBCWait4IBE();

            SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);
        }
コード例 #17
0
ファイル: IconHelper.cs プロジェクト: galri/Dapplo.Windows
        /// <summary>
        ///     See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx
        /// </summary>
        /// <typeparam name="TIcon"></typeparam>
        /// <param name="location">The file (EXE or DLL) to get the icon from</param>
        /// <param name="index">Index of the icon</param>
        /// <param name="useLargeIcon">true if the large icon is wanted</param>
        /// <returns>Icon</returns>
        public static TIcon ExtractAssociatedIcon <TIcon>(string location, int index = 0, bool useLargeIcon = true) where TIcon : class
        {
            IntPtr large;
            IntPtr small;

            NativeInvokes.ExtractIconEx(location, index, out large, out small, 1);
            TIcon returnIcon = null;

            try
            {
                if (useLargeIcon && !IntPtr.Zero.Equals(large))
                {
                    returnIcon = IconHandleTo <TIcon>(large);
                }
                else if (!IntPtr.Zero.Equals(small))
                {
                    returnIcon = IconHandleTo <TIcon>(small);
                }
                else if (!IntPtr.Zero.Equals(large))
                {
                    returnIcon = IconHandleTo <TIcon>(large);
                }
            }
            finally
            {
                if (!IntPtr.Zero.Equals(small))
                {
                    User32Api.DestroyIcon(small);
                }
                if (!IntPtr.Zero.Equals(large))
                {
                    User32Api.DestroyIcon(large);
                }
            }
            return(returnIcon);
        }
コード例 #18
0
 /// <summary>
 ///     Minimize the Window
 /// </summary>
 /// <param name="interopWindow">InteropWindow</param>
 /// <returns>IInteropWindow for fluent calls</returns>
 public static IInteropWindow Minimize(this IInteropWindow interopWindow)
 {
     User32Api.ShowWindow(interopWindow.Handle, ShowWindowCommands.Minimize);
     interopWindow.IsMinimized = true;
     return(interopWindow);
 }
コード例 #19
0
 protected override bool ReleaseHandle()
 {
     return(User32Api.CloseDesktop(handle));
 }
コード例 #20
0
 /// <summary>
 /// Move the specified window to a new location
 /// </summary>
 /// <param name="interopWindow">IInteropWindow</param>
 /// <param name="location">NativePoint with the offset</param>
 /// <returns>IInteropWindow for fluent calls</returns>
 public static IInteropWindow MoveTo(this IInteropWindow interopWindow, NativePoint location)
 {
     User32Api.SetWindowPos(interopWindow.Handle, IntPtr.Zero, location.X, location.Y, 0, 0, WindowPos.SWP_NOSIZE | WindowPos.SWP_SHOWWINDOW | WindowPos.SWP_NOACTIVATE | WindowPos.SWP_NOZORDER);
     interopWindow.Info = null;
     return(interopWindow);
 }
コード例 #21
0
 /// <summary>
 /// Tests if the interopWindow still exists
 /// </summary>
 /// <param name="interopWindow">IInteropWindow</param>
 /// <returns>True if it's still there.
 /// Because window handles are recycled the handle could point to a different window!
 /// </returns>
 public static bool Exists(this IInteropWindow interopWindow)
 {
     return(User32Api.IsWindow(interopWindow.Handle));
 }
コード例 #22
0
 /// <summary>
 ///     Set the WindowPlacement
 /// </summary>
 /// <param name="interopWindow">InteropWindow</param>
 /// <param name="placement">WindowPlacement</param>
 /// <returns>IInteropWindow for fluent calls</returns>
 public static IInteropWindow SetPlacement(this IInteropWindow interopWindow, WindowPlacement placement)
 {
     User32Api.SetWindowPlacement(interopWindow.Handle, ref placement);
     interopWindow.Placement = placement;
     return(interopWindow);
 }
コード例 #23
0
 /// <summary>
 ///     Set the WindowStyle
 /// </summary>
 /// <param name="interopWindow">InteropWindow</param>
 /// <param name="windowStyleFlags">WindowStyleFlags</param>
 /// <returns>IInteropWindow for fluent calls</returns>
 public static IInteropWindow SetStyle(this IInteropWindow interopWindow, WindowStyleFlags windowStyleFlags)
 {
     User32Api.SetWindowLongWrapper(interopWindow.Handle, WindowLongIndex.GWL_STYLE, new IntPtr((uint)windowStyleFlags));
     interopWindow.Info = null;
     return(interopWindow);
 }
コード例 #24
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();
            }
        }
コード例 #25
0
        /// <summary>
        ///     Get current position
        /// </summary>
        /// <returns>SCROLLINFO</returns>
        public bool GetPosition(out ScrollInfo scrollInfo)
        {
            scrollInfo = ScrollInfo.Create(ScrollInfoMask.All);

            return(User32Api.GetScrollInfo(ScrollBarWindow.Handle, ScrollBarType, ref scrollInfo));
        }
コード例 #26
0
ファイル: CaptureForm.cs プロジェクト: Vistritium/greenshot
 /// <summary>
 ///     The mouse move handler of the capture form
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void OnMouseMove(object sender, MouseEventArgs e)
 {
     // Make sure the mouse coordinates are fixed, when pressing shift
     _mouseMovePos = FixMouseCoordinates(User32Api.GetCursorLocation());
     _mouseMovePos = WindowCapture.GetLocationRelativeToScreenBounds(_mouseMovePos);
 }
コード例 #27
0
        /// <summary>
        ///     This method will use User32 code to capture the specified captureBounds from the screen
        /// </summary>
        /// <param name="captureBounds">NativeRect with the bounds to capture</param>
        /// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
        public static Bitmap CaptureRectangle(NativeRect captureBounds)
        {
            Bitmap returnBitmap = null;

            if (captureBounds.Height <= 0 || captureBounds.Width <= 0)
            {
                Log.Warn().WriteLine("Nothing to capture, ignoring!");
                return(null);
            }
            Log.Debug().WriteLine("CaptureRectangle Called!");

            // .NET GDI+ Solution, according to some post this has a GDI+ leak...
            // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen
            // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height);
            // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) {
            //	graphics.CopyFromScreen(captureBounds.Location, NativePoint.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt);
            // }
            // capture.Image = capturedBitmap;
            // capture.Location = captureBounds.Location;

            using (var desktopDcHandle = SafeWindowDcHandle.FromDesktop())
            {
                if (desktopDcHandle.IsInvalid)
                {
                    // Get Exception before the error is lost
                    var exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds);
                    // throw exception
                    throw exceptionToThrow;
                }

                // create a device context we can copy to
                using (var safeCompatibleDcHandle = Gdi32Api.CreateCompatibleDC(desktopDcHandle))
                {
                    // Check if the device context is there, if not throw an error with as much info as possible!
                    if (safeCompatibleDcHandle.IsInvalid)
                    {
                        // Get Exception before the error is lost
                        var exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
                        // throw exception
                        throw exceptionToThrow;
                    }
                    // Create BITMAPINFOHEADER for CreateDIBSection
                    var bmi = BitmapInfoHeader.Create(captureBounds.Width, captureBounds.Height, 24);

                    // TODO: Enable when the function is available again
                    // Make sure the last error is set to 0
                    Win32.SetLastError(0);

                    // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
                    IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
                    // TODO: Change the usage to an enum?
                    using (var safeDibSectionHandle = Gdi32Api.CreateDIBSection(desktopDcHandle, ref bmi, 0, out bits0, IntPtr.Zero, 0))
                    {
                        if (safeDibSectionHandle.IsInvalid)
                        {
                            // Get Exception before the error is lost
                            var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
                            exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32());
                            exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32());

                            // Throw so people can report the problem
                            throw exceptionToThrow;
                        }
                        // select the bitmap object and store the old handle
                        using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle))
                        {
                            // bitblt over (make copy)
                            // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
                            Gdi32Api.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y,
                                            RasterOperations.SourceCopy | RasterOperations.CaptureBlt);
                        }

                        // get a .NET image object for it
                        // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
                        var success = false;
                        ExternalException exception = null;
                        for (var i = 0; i < 3; i++)
                        {
                            try
                            {
                                // Collect all screens inside this capture
                                var screensInsideCapture = new List <Screen>();
                                foreach (var screen in Screen.AllScreens)
                                {
                                    if (screen.Bounds.IntersectsWith(captureBounds))
                                    {
                                        screensInsideCapture.Add(screen);
                                    }
                                }
                                // Check all all screens are of an equal size
                                bool offscreenContent;
                                using (var captureRegion = new Region(captureBounds))
                                {
                                    // Exclude every visible part
                                    foreach (var screen in screensInsideCapture)
                                    {
                                        captureRegion.Exclude(screen.Bounds);
                                    }
                                    // If the region is not empty, we have "offscreenContent"
                                    using (var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow()))
                                    {
                                        offscreenContent = !captureRegion.IsEmpty(screenGraphics);
                                    }
                                }
                                // Check if we need to have a transparent background, needed for offscreen content
                                if (offscreenContent)
                                {
                                    using (var tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()))
                                    {
                                        // Create a new bitmap which has a transparent background
                                        returnBitmap = BitmapFactory.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution,
                                                                                 tmpBitmap.VerticalResolution);
                                        // Content will be copied here
                                        using (var graphics = Graphics.FromImage(returnBitmap))
                                        {
                                            // For all screens copy the content to the new bitmap
                                            foreach (var screen in Screen.AllScreens)
                                            {
                                                // Make sure the bounds are offsetted to the capture bounds
                                                var screenBounds = screen.Bounds;
                                                screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
                                                graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    // All screens, which are inside the capture, are of equal size
                                    // assign image to Capture, the image will be disposed there..
                                    returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
                                }
                                // We got through the capture without exception
                                success = true;
                                break;
                            }
                            catch (ExternalException ee)
                            {
                                Log.Warn().WriteLine(ee, "Problem getting bitmap at try " + i + " : ");
                                exception = ee;
                            }
                        }
                        if (!success)
                        {
                            Log.Error().WriteLine(null, "Still couldn't create Bitmap!");
                            if (exception != null)
                            {
                                throw exception;
                            }
                        }
                    }
                }
            }
            return(returnBitmap);
        }
コード例 #28
0
        /// <summary>
        ///     Message handler of the Per_Monitor_DPI_Aware window.
        ///     The handles the WM_DPICHANGED message and adjusts window size, graphics and text based on the DPI of the monitor.
        ///     The window message provides the new window size (lparam) and new DPI (wparam)
        ///     See
        ///     <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx">WM_DPICHANGED message</a>
        /// </summary>
        /// <param name="windowMessageInfo">WindowMessageInfo</param>
        /// <returns>IntPtr</returns>
        internal bool HandleWindowMessages(WindowMessageInfo windowMessageInfo)
        {
            bool handled      = false;
            var  currentDpi   = DefaultScreenDpi;
            bool isDpiMessage = false;

            switch (windowMessageInfo.Message)
            {
            // Handle the WM_NCCREATE for Forms / controls, for WPF this is done differently
            case WindowsMessages.WM_NCCREATE:
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Processing {0} event, enabling DPI scaling for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle);
                }

                TryEnableNonClientDpiScaling(windowMessageInfo.Handle);
                break;

            // Handle the WM_CREATE, this is where we can get the DPI via system calls
            case WindowsMessages.WM_CREATE:
                isDpiMessage = true;
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Processing {0} event, retrieving DPI for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle);
                }

                currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle);
                _scopedThreadDpiAwarenessContext.Dispose();
                break;

            // Handle the DPI change message, this is where it's supplied
            case WindowsMessages.WM_DPICHANGED:
                isDpiMessage = true;
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Processing {0} event, resizing / positioning window {1}", windowMessageInfo.Message, windowMessageInfo.Handle);
                }

                // Retrieve the adviced location
                var lprNewRect = (NativeRect)Marshal.PtrToStructure(windowMessageInfo.LongParam, typeof(NativeRect));
                // Move the window to it's location, and resize
                User32Api.SetWindowPos(windowMessageInfo.Handle,
                                       IntPtr.Zero,
                                       lprNewRect.Left,
                                       lprNewRect.Top,
                                       lprNewRect.Width,
                                       lprNewRect.Height,
                                       WindowPos.SWP_NOZORDER | WindowPos.SWP_NOOWNERZORDER | WindowPos.SWP_NOACTIVATE);
                currentDpi = (uint)windowMessageInfo.WordParam & 0xFFFF;
                // specify that the message was handled
                handled = true;
                break;

            case WindowsMessages.WM_PAINT:
                // This is a workaround for non DPI aware applications, these don't seem to get a WM_CREATE
                if (Dpi == 0)
                {
                    isDpiMessage = true;
                    currentDpi   = NativeDpiMethods.GetDpi(windowMessageInfo.Handle);
                }
                break;

            case WindowsMessages.WM_SETICON:
                // This is a workaround for handling WinProc outside of the class
                if (_needsListenerWorkaround)
                {
                    isDpiMessage = true;
                    // disable workaround
                    _needsListenerWorkaround = false;
                    currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle);
                }

                break;

            case WindowsMessages.WM_DPICHANGED_BEFOREPARENT:
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Dpi changed on {0} before parent", windowMessageInfo.Handle);
                }
                break;

            case WindowsMessages.WM_DPICHANGED_AFTERPARENT:
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Dpi changed on {0} after parent", windowMessageInfo.Handle);
                }
                break;

            case WindowsMessages.WM_DESTROY:
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Completing the observable for {0}", windowMessageInfo.Handle);
                }

                // If the window is destroyed, we complete the subject
                _onDpiChanged.OnCompleted();
                // Dispose all resources
                Dispose();
                break;
            }

            // Check if the DPI was changed, if so call the action (if any)
            if (!isDpiMessage)
            {
                return(false);
            }

            if (Dpi != currentDpi)
            {
                var beforeDpi = Dpi;
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Changing DPI from {0} to {1}", beforeDpi, currentDpi);
                }
                Dpi = currentDpi;
                _onDpiChanged.OnNext(new DpiChangeInfo(beforeDpi, currentDpi));
            }
            else if (Log.IsVerboseEnabled())
            {
                Log.Verbose().WriteLine("DPI was unchanged from {0}", Dpi);
            }

            return(handled);
        }
コード例 #29
0
 /// <summary>
 ///     Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
 ///     can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
 /// </summary>
 /// <returns>
 ///     NativePoint with cursor location, relative to the top left corner of the monitor setup (which itself might actually not
 ///     be on any screen)
 /// </returns>
 public static NativePoint GetCursorLocationRelativeToScreenBounds()
 {
     return(GetLocationRelativeToScreenBounds(User32Api.GetCursorLocation()));
 }
コード例 #30
0
        /// <summary>
        /// Start the capture
        /// </summary>
        /// <returns>Bitmap</returns>
        public Bitmap Capture()
        {
            if (_windowScroller.NeedsFocus())
            {
                User32Api.SetForegroundWindow(_windowScroller.ScrollBarWindow.Handle);
                Application.DoEvents();
                Thread.Sleep(Delay);
                Application.DoEvents();
            }

            // Find the area which is scrolling

            // 1. Take the client bounds
            var clientBounds = _windowScroller.ScrollBarWindow.GetInfo().ClientBounds;

            // Use a region for steps 2 and 3
            using (var region = new Region(clientBounds))
            {
                // 2. exclude the children, if any
                foreach (var interopWindow in _windowScroller.ScrollBarWindow.GetChildren())
                {
                    region.Exclude(interopWindow.GetInfo().Bounds);
                }
                // 3. exclude the scrollbar, if it can be found
                if (_windowScroller.ScrollBar.HasValue)
                {
                    region.Exclude(_windowScroller.ScrollBar.Value.Bounds);
                }
                // Get the bounds of the region
                using (var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow()))
                {
                    var rectangleF = region.GetBounds(screenGraphics);
                    clientBounds = new NativeRect((int)rectangleF.X, (int)rectangleF.Y, (int)rectangleF.Width, (int)rectangleF.Height);
                }
            }

            if (clientBounds.Width * clientBounds.Height <= 0)
            {
                return(null);
            }
            // Move the window to the start
            _windowScroller.Start();

            // Register a keyboard hook to make it possible to ESC the capturing
            var breakScroll  = false;
            var keyboardHook = KeyboardHook.KeyboardEvents
                               .Where(args => args.Key == VirtualKeyCodes.ESCAPE)
                               .Subscribe(args =>
            {
                args.Handled = true;
                breakScroll  = true;
            });
            Bitmap resultImage = null;

            try
            {
                // A delay to make the window move
                Application.DoEvents();
                Thread.Sleep(Delay);
                Application.DoEvents();

                if (_windowScroller.IsAtStart)
                {
                    using (var bitmapStitcher = new BitmapStitcher())
                    {
                        bitmapStitcher.AddBitmap(WindowCapture.CaptureRectangle(clientBounds));

                        // Loop as long as we are not at the end yet
                        while (!_windowScroller.IsAtEnd && !breakScroll)
                        {
                            // Next "page"
                            _windowScroller.Next();
                            // Wait a bit, so the window can update
                            Application.DoEvents();
                            Thread.Sleep(Delay);
                            Application.DoEvents();
                            // Capture inside loop
                            bitmapStitcher.AddBitmap(WindowCapture.CaptureRectangle(clientBounds));
                        }
                        resultImage = bitmapStitcher.Result();
                    }
                }
                else
                {
                    resultImage = WindowCapture.CaptureRectangle(clientBounds);
                }
            }
            catch (Exception ex)
            {
                Log.Error().WriteLine(ex);
            }
            finally
            {
                // Remove hook for escape
                keyboardHook.Dispose();
                // Try to reset location
                _windowScroller.Reset();
            }

            return(resultImage);
        }