Beispiel #1
0
        private static bool ClearTypeEnabled()
        {
            int sv = 0;

            /* Call to systemparametersinfo to get the font smoothing value. */
            WindowsApi.SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, ref sv, 0);

            int stv = 0;

            /* Call to systemparametersinfo to get the font smoothing Type value. */
            WindowsApi.SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, ref stv, 0);

            if (sv > 0 && stv == 2) //if smoothing is on, and is set to cleartype
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #2
0
        internal static void CaptureWindow(ref ScreenshotTask data)
        {
            IntPtr start   = WindowsApi.FindWindow("Button", "Start");
            IntPtr taskbar = WindowsApi.FindWindow("Shell_TrayWnd", null);

            if (data.ClipboardNotDisk || Directory.Exists(data.DiskSaveDirectory))
            {
                try
                {
                    // Hide the taskbar, just incase it gets in the way
                    if (data.WindowHandle != start &&
                        data.WindowHandle != taskbar)
                    {
                        WindowsApi.ShowWindow(start, 0);
                        WindowsApi.ShowWindow(taskbar, 0);
                        Application.DoEvents();
                    }
                    bool ClearTypeToggled = false;
                    if (data.DisableClearType && ClearTypeEnabled())
                    {
                        WindowsApi.SystemParametersInfo(SPI_SETFONTSMOOTHINGTYPE, 0, FE_FONTSMOOTHINGSTANDARD, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
                        WindowsApi.RedrawWindow(data.WindowHandle, IntPtr.Zero, IntPtr.Zero, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
                        ClearTypeToggled = true;
                    }
                    WindowsApi.SetForegroundWindow(data.WindowHandle);

                    bool AeroColorToggled = false;
                    WindowsApi.DWM_COLORIZATION_PARAMS originalParameters;
                    WindowsApi.DwmGetColorizationParameters(out originalParameters);
                    if (data.CustomGlass && AeroEnabled())
                    {
                        // Original colorization parameters
                        originalParameters.clrGlassReflectionIntensity = 50;

                        // Custom colorization parameters
                        WindowsApi.DWM_COLORIZATION_PARAMS parameters;
                        WindowsApi.DwmGetColorizationParameters(out parameters);
                        parameters.clrAfterGlowBalance = 2;
                        parameters.clrBlurBalance      = 29;
                        parameters.clrColor            = ColorToBgra(data.AeroColor);
                        parameters.nIntensity          = 69;

                        // Call the DwmSetColorizationParameters to make the change take effect.
                        WindowsApi.DwmSetColorizationParameters(ref parameters, false);
                        AeroColorToggled = true;
                    }

                    bool ShadowToggled = false;
                    if (data.DisableShadow && ShadowEnabled())
                    {
                        WindowsApi.SystemParametersInfo(SPI_SETDROPSHADOW, 0, false, 0);
                        ShadowToggled = true;
                    }

                    var r = new WindowsRect(0);
                    if (data.DoResize)
                    {
                        SmartResizeWindow(ref data, out r);
                        Thread.Sleep(100);
                    }

                    int length = WindowsApi.GetWindowTextLength(data.WindowHandle);
                    var sb     = new StringBuilder(length + 1);
                    WindowsApi.GetWindowText(data.WindowHandle, sb, sb.Capacity);

                    string name = sb.ToString();

                    foreach (char inv in Path.GetInvalidFileNameChars())
                    {
                        name = name.Replace(inv.ToString(), string.Empty);
                    }

                    Bitmap s = CaptureCompositeScreenshot(ref data);

                    if (AeroColorToggled)
                    {
                        WindowsApi.DwmSetColorizationParameters(ref originalParameters, false);
                    }

                    if (ClearTypeToggled)
                    {
                        WindowsApi.SystemParametersInfo(SPI_SETFONTSMOOTHINGTYPE, 0, FE_FONTSMOOTHINGCLEARTYPE, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
                        WindowsApi.RedrawWindow(data.WindowHandle, IntPtr.Zero, IntPtr.Zero, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
                    }

                    if (ShadowToggled)
                    {
                        WindowsApi.SystemParametersInfo(SPI_SETDROPSHADOW, 0, true, 0);
                    }

                    // Show the taskbar again
                    if (data.WindowHandle != start &&
                        data.WindowHandle != taskbar)
                    {
                        WindowsApi.ShowWindow(start, 1);
                        WindowsApi.ShowWindow(taskbar, 1);
                    }

                    if (s == null)
                    {
                        MessageBox.Show("The screenshot taken was blank, it will not be saved.",
                                        "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                    else
                    {
                        if (data.ClipboardNotDisk && data.Background !=
                            ScreenshotTask.BackgroundType.Transparent)
                        {
                            // Screenshot is already opaque, don't need to modify it
                            Clipboard.SetImage(s);
                        }
                        else if (data.ClipboardNotDisk)
                        {
                            var whiteS = new Bitmap(s.Width, s.Height, PixelFormat.Format24bppRgb);
                            using (Graphics graphics = Graphics.FromImage(whiteS))
                            {
                                graphics.Clear(Color.White);
                                graphics.DrawImage(s, 0, 0, s.Width, s.Height);
                            }
                            using (var stream = new MemoryStream())
                            {
                                // Save screenshot in clipboard as PNG which some applications support (eg. Microsoft Office)
                                s.Save(stream, ImageFormat.Png);
                                var pngClipboardData = new DataObject("PNG", stream);

                                // Add fallback for applications that don't support PNG from clipboard (eg. Photoshop or Paint)
                                pngClipboardData.SetData(DataFormats.Bitmap, whiteS);
                                Clipboard.Clear();
                                Clipboard.SetDataObject(pngClipboardData, true);
                            }
                            whiteS.Dispose();
                        }
                        else
                        {
                            name = name.Trim();
                            if (name == string.Empty)
                            {
                                name = "AeroShot";
                            }
                            string path = Path.Combine(data.DiskSaveDirectory, name + ".png");

                            if (File.Exists(path))
                            {
                                for (int i = 1; i < 9999; i++)
                                {
                                    path = Path.Combine(data.DiskSaveDirectory, name + " " + i + ".png");
                                    if (!File.Exists(path))
                                    {
                                        break;
                                    }
                                }
                            }
                            s.Save(path, ImageFormat.Png);
                        }
                        s.Dispose();
                    }

                    if (data.DoResize)
                    {
                        if ((WindowsApi.GetWindowLong(data.WindowHandle, GWL_STYLE) & WS_SIZEBOX) == WS_SIZEBOX)
                        {
                            WindowsApi.SetWindowPos(data.WindowHandle, (IntPtr)0, r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top, SWP_SHOWWINDOW);
                        }
                    }
                }
                catch (Exception)
                {
                    if (data.WindowHandle != start && data.WindowHandle != taskbar)
                    {
                        WindowsApi.ShowWindow(start, 1);
                        WindowsApi.ShowWindow(taskbar, 1);
                    }
                    MessageBox.Show("An error occurred while trying to take a screenshot.\r\n\r\nPlease make sure you have selected a valid window.",
                                    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Invalid directory chosen.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Beispiel #3
0
        private static unsafe Bitmap[] CaptureCompositeScreenshot(ref ScreenshotTask data)
        {
            // Generate a rectangle with the size of all monitors combined
            Rectangle totalSize = Rectangle.Empty;

            foreach (Screen s in Screen.AllScreens)
            {
                totalSize = Rectangle.Union(totalSize, s.Bounds);
            }

            var rct = new WindowsRect();

            if (WindowsApi.DwmGetWindowAttribute(data.WindowHandle, DwmWindowAttribute.ExtendedFrameBounds, ref rct, sizeof(WindowsRect)) != 0)
            {
                // DwmGetWindowAttribute() failed, usually means Aero is disabled so we fall back to GetWindowRect()
                WindowsApi.GetWindowRect(data.WindowHandle, ref rct);
            }
            else
            {
                // DwmGetWindowAttribute() succeeded
            }

            // Get DPI of the window (this only works properly on Win 10 1607+) but it is not really needed until Win 11 anyway
            int DPI = 96;

            try
            {
                DPI = WindowsApi.GetDpiForWindow(data.WindowHandle);
            }
            catch { }

            // Adjust margin for DPI
            double scalingFactor  = DPI / 96;
            int    backdropOffset = Convert.ToInt32(100 * scalingFactor);

            // Add a 100px margin for window shadows. Excess transparency is trimmed out later
            rct.Left   -= backdropOffset;
            rct.Right  += backdropOffset;
            rct.Top    -= backdropOffset;
            rct.Bottom += backdropOffset;

            // These next 4 checks handle if the window is outside of the visible screen
            if (rct.Left < totalSize.Left)
            {
                rct.Left = totalSize.Left;
            }
            if (rct.Right > totalSize.Right)
            {
                rct.Right = totalSize.Right;
            }
            if (rct.Top < totalSize.Top)
            {
                rct.Top = totalSize.Top;
            }
            if (rct.Bottom > totalSize.Bottom)
            {
                rct.Bottom = totalSize.Bottom;
            }

            // Spawning backdrop
            // Handling as much as possible in the constructor makes this easier to render, which makes capture less likely to fail on underpowered PCs
            Color tmpColor = Color.White;
            var   backdrop = new Form
            {
                BackColor       = tmpColor,
                FormBorderStyle = FormBorderStyle.None,
                ShowInTaskbar   = false,
                //Opacity = 0,
                Size          = new Size(rct.Right - rct.Left, rct.Bottom - rct.Top),
                StartPosition = FormStartPosition.Manual,
                Location      = new Point(rct.Left, rct.Top)
            };

            WindowsApi.ShowWindow(backdrop.Handle, 4);
            if (!WindowsApi.SetWindowPos(backdrop.Handle, data.WindowHandle, rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top, SWP_NOACTIVATE))
            {
                // We are unable to put backdrop directly behind the window, so we will put it into the foreground and then put the original window on top of it
                // This likely happens because the program we're trying to capture is running as administrator
                WindowsApi.SetWindowPos(backdrop.Handle, IntPtr.Zero, rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top, SWP_NOACTIVATE);
                WindowsApi.SetForegroundWindow(data.WindowHandle).ToString();
            }

            RefreshBackdrop();

            // Capture screenshot with white background
            Bitmap whiteShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

            backdrop.BackColor = Color.Black;
            RefreshBackdrop();

            // Capture screenshot with black background
            Bitmap blackShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

            Bitmap transparentImage;
            Bitmap transparentInactiveImage            = null;
            Bitmap transparentWhiteImage               = null;
            Bitmap transparentWhiteInactiveImage       = null;
            Bitmap transparentMaskImage                = null;
            Bitmap transparentTransparentImage         = null;
            Bitmap transparentTransparentInactiveImage = null;

            transparentImage = DifferentiateAlpha(whiteShot, blackShot, false);
            if (data.SaveActiveLight)
            {
                transparentWhiteImage = DifferentiateAlpha(whiteShot, blackShot, true);
            }

            whiteShot.Dispose();
            blackShot.Dispose();

            //Capture black mask screenshot
            if (data.SaveMask)
            {
                int  minAlpha      = 0;
                bool isCompositing = false;
                bool ShadowToggled = false;
                bool ColorToggled  = false;

                try
                {
                    WindowsApi.DwmIsCompositionEnabled(out isCompositing);
                }
                catch (Exception)
                {
                    //OS doesn't have a supported version of DWM
                }

                //We can't disable shadows on Vista without disabling DWM, which would cause the mask to be inaccurate
                UInt32 ColorizationColor = 0;
                bool   fOpaque           = true;
                if (isCompositing && (VersionHelpers.IsWindowsVista() || VersionHelpers.IsWindows11()))
                {
                    minAlpha = 254;

                    WindowsApi.DwmGetColorizationColor(out ColorizationColor, out fOpaque);

                    if (fOpaque == false)
                    {
                        WindowsApi.DwmpSetColorization(ColorizationColor, true, 0xFF);
                        ColorToggled = true;
                    }
                }
                else if (ShadowEnabled())
                {
                    WindowsApi.SystemParametersInfo(SPI_SETDROPSHADOW, 0, false, 0);
                    ShadowToggled = true;
                }

                backdrop.BackColor = Color.White;
                RefreshBackdrop();
                Bitmap whiteMaskShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                backdrop.BackColor = Color.Black;
                RefreshBackdrop();
                Bitmap blackMaskShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                transparentMaskImage = CreateMask(DifferentiateAlpha(whiteMaskShot, blackMaskShot, false), minAlpha);

                if (ShadowToggled)
                {
                    WindowsApi.SystemParametersInfo(SPI_SETDROPSHADOW, 0, true, 0);
                }

                if (ColorToggled)
                {
                    WindowsApi.DwmpSetColorization(ColorizationColor, fOpaque, 0xFF);
                }

                whiteMaskShot.Dispose();
                blackMaskShot.Dispose();
            }

            //Capture active fully transparent
            if (data.SaveActiveTransparent)
            {
                try
                {
                    //win 7
                    WindowsApi.DWM_COLORIZATION_PARAMS parameters, originalParameters = new WindowsApi.DWM_COLORIZATION_PARAMS();
                    //win vista
                    UInt32 ColorizationColor = 0;
                    bool   fOpaque           = true;


                    if (VersionHelpers.IsWindowsVista())
                    {
                        WindowsApi.DwmGetColorizationColor(out ColorizationColor, out fOpaque);

                        if (fOpaque == false)
                        {
                            WindowsApi.DwmpSetColorization(0xFFFFFF, false, 0xFF);
                        }
                    }
                    else
                    {
                        WindowsApi.DwmGetColorizationParameters(out parameters);
                        WindowsApi.DwmGetColorizationParameters(out originalParameters);

                        //Set custom fully transparent parameters
                        parameters.clrAfterGlowBalance = 0;
                        parameters.clrBlurBalance      = 100;
                        parameters.nIntensity          = 0;

                        // Call the DwmSetColorizationParameters to make the change take effect.
                        WindowsApi.DwmSetColorizationParameters(ref parameters, false);
                    }


                    backdrop.BackColor = Color.White;
                    RefreshBackdrop();
                    Bitmap whiteTransparentShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                    backdrop.BackColor = Color.Black;
                    RefreshBackdrop();
                    Bitmap blackTransparentShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                    transparentTransparentImage = DifferentiateAlpha(whiteTransparentShot, blackTransparentShot, false);
                    whiteTransparentShot.Dispose();
                    blackTransparentShot.Dispose();

                    if (VersionHelpers.IsWindowsVista())
                    {
                        WindowsApi.DwmpSetColorization(ColorizationColor, fOpaque, 0xFF);
                    }
                    else
                    {
                        WindowsApi.DwmSetColorizationParameters(ref originalParameters, false);
                    }
                }
                catch (Exception)
                {
                    transparentTransparentImage = new Bitmap(transparentImage);
                }
            }

            //Show form to steal focus
            var emptyForm = new Form
            {
                FormBorderStyle = FormBorderStyle.None,
                ShowInTaskbar   = false,
                Opacity         = 0,
            };

            WindowsApi.ShowWindow(emptyForm.Handle, 5);
            WindowsApi.SetWindowPos(emptyForm.Handle, data.WindowHandle, rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top, 0);
            WindowsApi.SetForegroundWindow(emptyForm.Handle);

            // Capture inactive screenshots
            if (data.SaveInactiveDark || data.SaveInactiveLight)
            {
                backdrop.BackColor = Color.White;
                RefreshBackdrop();

                // Capture inactive screenshot with white background
                Bitmap whiteInactiveShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                backdrop.BackColor = Color.Black;
                RefreshBackdrop();

                // Capture inactive screenshot with black background
                Bitmap blackInactiveShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));


                if (data.SaveInactiveDark)
                {
                    transparentInactiveImage = DifferentiateAlpha(whiteInactiveShot, blackInactiveShot, false);
                }
                if (data.SaveInactiveLight)
                {
                    transparentWhiteInactiveImage = DifferentiateAlpha(whiteInactiveShot, blackInactiveShot, true);
                }

                whiteInactiveShot.Dispose();
                blackInactiveShot.Dispose();
            }

            //Capture inactive fully transparent
            if (data.SaveInactiveTransparent)
            {
                try
                {
                    //Get original colorization parameters
                    WindowsApi.DWM_COLORIZATION_PARAMS parameters, originalParameters;
                    WindowsApi.DwmGetColorizationParameters(out parameters);
                    WindowsApi.DwmGetColorizationParameters(out originalParameters);

                    //Set custom fully transparent parameters
                    parameters.clrAfterGlowBalance = 0;
                    parameters.clrBlurBalance      = 100;
                    parameters.nIntensity          = 0;

                    // Call the DwmSetColorizationParameters to make the change take effect.
                    WindowsApi.DwmSetColorizationParameters(ref parameters, false);

                    backdrop.BackColor = Color.White;
                    RefreshBackdrop();
                    Bitmap whiteTransparentInactiveShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                    backdrop.BackColor = Color.Black;
                    RefreshBackdrop();
                    Bitmap blackTransparentInactiveShot = CaptureScreenRegion(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));

                    transparentTransparentInactiveImage = DifferentiateAlpha(whiteTransparentInactiveShot, blackTransparentInactiveShot, false);
                    whiteTransparentInactiveShot.Dispose();
                    blackTransparentInactiveShot.Dispose();

                    WindowsApi.DwmSetColorizationParameters(ref originalParameters, false);
                }
                catch (Exception)
                {
                    transparentTransparentInactiveImage = new Bitmap(transparentInactiveImage);
                }
            }

            backdrop.Dispose();
            emptyForm.Dispose();

            if (data.CaptureMouse)
            {
                DrawCursorToBitmap(transparentImage, new Point(rct.Left, rct.Top));
            }
            Bitmap[] final = CropEmptyEdges(new[] { transparentImage, transparentInactiveImage, transparentWhiteImage, transparentWhiteInactiveImage, transparentMaskImage, transparentTransparentImage, transparentTransparentInactiveImage }, Color.FromArgb(0, 0, 0, 0), ref data);

            // Returns a bitmap with transparency, calculated by differentiating the white and black screenshots
            return(final);
        }