Пример #1
0
        /// <summary>
        ///     Capture DWM Window
        /// </summary>
        /// <param name="interopWindow">IInteropWindow</param>
        /// <param name="capture">Capture to fill</param>
        /// <param name="windowCaptureMode">Wanted WindowCaptureModes</param>
        /// <param name="autoMode">True if auto modus is used</param>
        /// <returns>ICapture with the capture</returns>
        public static ICapture CaptureDwmWindow(this IInteropWindow interopWindow, ICapture capture, WindowCaptureModes windowCaptureMode, bool autoMode)
        {
            var  thumbnailHandle = IntPtr.Zero;
            Form tempForm        = null;
            var  tempFormShown   = false;

            try
            {
                tempForm = new Form
                {
                    ShowInTaskbar   = false,
                    FormBorderStyle = FormBorderStyle.None,
                    TopMost         = true
                };

                // Register the Thumbnail
                Dwm.DwmRegisterThumbnail(tempForm.Handle, interopWindow.Handle, out thumbnailHandle);

                // Get the original size
                Dwm.DwmQueryThumbnailSourceSize(thumbnailHandle, out var sourceSize);

                if (sourceSize.Width <= 0 || sourceSize.Height <= 0)
                {
                    return(null);
                }

                // Calculate the location of the temp form
                var windowRectangle = interopWindow.GetInfo().Bounds;
                var formLocation    = windowRectangle.Location;
                var borderSize      = new Size();
                var doesCaptureFit  = false;
                if (!interopWindow.IsMaximized())
                {
                    // Assume using it's own location
                    formLocation = windowRectangle.Location;
                    using (var workingArea = new Region(Screen.PrimaryScreen.Bounds))
                    {
                        // Find the screen where the window is and check if it fits
                        foreach (var screen in Screen.AllScreens)
                        {
                            if (!Equals(screen, Screen.PrimaryScreen))
                            {
                                workingArea.Union(screen.Bounds);
                            }
                        }

                        // If the formLocation is not inside the visible area
                        if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
                        {
                            // If none found we find the biggest screen
                            foreach (var screen in Screen.AllScreens)
                            {
                                var newWindowRectangle = new NativeRect(screen.WorkingArea.Location, windowRectangle.Size);
                                if (workingArea.AreRectangleCornersVisisble(newWindowRectangle))
                                {
                                    formLocation   = screen.Bounds.Location;
                                    doesCaptureFit = true;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            doesCaptureFit = true;
                        }
                    }
                }
                else if (!WindowsVersion.IsWindows8OrLater)
                {
                    //GetClientRect(out windowRectangle);
                    borderSize   = interopWindow.GetInfo().BorderSize;
                    formLocation = new NativePoint(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height);
                }

                tempForm.Location = formLocation;
                tempForm.Size     = sourceSize;

                // Prepare rectangle to capture from the screen.
                var captureRectangle = new NativeRect(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height);
                if (interopWindow.IsMaximized())
                {
                    // Correct capture size for maximized window by offsetting the X,Y with the border size
                    // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing)
                    captureRectangle = captureRectangle.Inflate(borderSize.Width, borderSize.Height);
                }
                else
                {
                    // TODO: Also 8.x?
                    if (WindowsVersion.IsWindows10)
                    {
                        captureRectangle = captureRectangle.Inflate(CoreConfiguration.Win10BorderCrop.Width, CoreConfiguration.Win10BorderCrop.Height);
                    }

                    if (autoMode)
                    {
                        // check if the capture fits
                        if (!doesCaptureFit)
                        {
                            // if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
                            using (var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId()))
                            {
                                if (!interopWindow.IsApp() && WindowCapture.IsGdiAllowed(thisWindowProcess))
                                {
                                    // we return null which causes the capturing code to try another method.
                                    return(null);
                                }
                            }
                        }
                    }
                }
                // Prepare the displaying of the Thumbnail
                var props = new DwmThumbnailProperties
                {
                    Opacity     = 255,
                    Visible     = true,
                    Destination = new NativeRect(0, 0, sourceSize.Width, sourceSize.Height)
                };
                Dwm.DwmUpdateThumbnailProperties(thumbnailHandle, ref props);
                tempForm.Show();
                tempFormShown = true;

                // Intersect with screen
                captureRectangle = captureRectangle.Intersect(capture.ScreenBounds);

                // Destination bitmap for the capture
                Bitmap capturedBitmap = null;
                // Check if we make a transparent capture
                if (windowCaptureMode == WindowCaptureModes.AeroTransparent)
                {
                    // Use white, later black to capture transparent
                    tempForm.BackColor = Color.White;
                    // Make sure everything is visible
                    tempForm.Refresh();
                    Application.DoEvents();

                    try
                    {
                        using (var whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle))
                        {
                            // Apply a white color
                            tempForm.BackColor = Color.Black;
                            // Make sure everything is visible
                            tempForm.Refresh();
                            if (!interopWindow.IsApp())
                            {
                                // Make sure the application window is active, so the colors & buttons are right
                                // TODO: Await?
                                interopWindow.ToForegroundAsync();
                            }
                            // Make sure all changes are processed and visible
                            Application.DoEvents();
                            using (var blackBitmap = WindowCapture.CaptureRectangle(captureRectangle))
                            {
                                capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Warn().WriteLine(e, "Exception: ");
                        // Some problem occurred, cleanup and make a normal capture
                        if (capturedBitmap != null)
                        {
                            capturedBitmap.Dispose();
                            capturedBitmap = null;
                        }
                    }
                }
                // If no capture up till now, create a normal capture.
                if (capturedBitmap == null)
                {
                    // Remove transparency, this will break the capturing
                    if (!autoMode)
                    {
                        tempForm.BackColor = Color.FromArgb(255, CoreConfiguration.DWMBackgroundColor.R, CoreConfiguration.DWMBackgroundColor.G, CoreConfiguration.DWMBackgroundColor.B);
                    }
                    else
                    {
                        var colorizationColor = Dwm.ColorizationSystemDrawingColor;
                        // Modify by losing the transparency and increasing the intensity (as if the background color is white)
                        colorizationColor  = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1);
                        tempForm.BackColor = colorizationColor;
                    }
                    // Make sure everything is visible
                    tempForm.Refresh();
                    if (!interopWindow.IsApp())
                    {
                        // Make sure the application window is active, so the colors & buttons are right
                        interopWindow.ToForegroundAsync();
                    }
                    // Make sure all changes are processed and visible
                    Application.DoEvents();
                    // Capture from the screen
                    capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle);
                }
                if (capturedBitmap != null)
                {
                    // Not needed for Windows 8
                    if (!WindowsVersion.IsWindows8OrLater)
                    {
                        // Only if the Inivalue is set, not maximized and it's not a tool window.
                        if (CoreConfiguration.WindowCaptureRemoveCorners && !interopWindow.IsMaximized() &&
                            !interopWindow.GetInfo().ExtendedStyle.HasFlag(ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW))
                        {
                            // Remove corners
                            if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat))
                            {
                                Log.Debug().WriteLine("Changing pixelformat to Alpha for the RemoveCorners");
                                var tmpBitmap = capturedBitmap.CloneBitmap(PixelFormat.Format32bppArgb) as Bitmap;
                                capturedBitmap.Dispose();
                                capturedBitmap = tmpBitmap;
                            }
                            RemoveCorners(capturedBitmap);
                        }
                    }
                }

                capture.Bitmap = capturedBitmap;
                // Make sure the capture location is the location of the window, not the copy
                capture.Location = interopWindow.GetInfo().Bounds.Location;
            }
            finally
            {
                if (thumbnailHandle != IntPtr.Zero)
                {
                    // Unregister (cleanup), as we are finished we don't need the form or the thumbnail anymore
                    Dwm.DwmUnregisterThumbnail(thumbnailHandle);
                }
                if (tempForm != null)
                {
                    if (tempFormShown)
                    {
                        tempForm.Close();
                    }
                    tempForm.Dispose();
                    tempForm = null;
                }
            }

            return(capture);
        }
Пример #2
0
        /// <summary>
        ///     Extension method to capture a bitmap of the screen area where the InteropWindow is located
        /// </summary>
        /// <param name="interopWindow">InteropWindow</param>
        /// <param name="clientBounds">true to use the client bounds</param>
        /// <returns>Bitmap</returns>
        public static Bitmap CaptureFromScreen(this IInteropWindow interopWindow, bool clientBounds = false)
        {
            var bounds = clientBounds ? interopWindow.GetInfo().ClientBounds: interopWindow.GetInfo().Bounds;

            return(WindowCapture.CaptureRectangle(bounds));
        }