mirror of
https://github.com/greenshot/greenshot
synced 2025-08-19 13:10:00 -07:00
Changed the default window capture for Windows 11 to use User32.PrintWindow (called GDI internally), which should solve #326. The background for this can be read in #373
This commit is contained in:
parent
6b90f2c3ff
commit
4f3920d61a
4 changed files with 77 additions and 27 deletions
38
src/Greenshot.Base/Core/Enums/PrintWindowFlags.cs
Normal file
38
src/Greenshot.Base/Core/Enums/PrintWindowFlags.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
|
*
|
||||||
|
* For more information see: https://getgreenshot.org/
|
||||||
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Base.Core.Enums
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum PrintWindowFlags : uint
|
||||||
|
{
|
||||||
|
/// <summary>Render the entire window.</summary>
|
||||||
|
PW_ENTIREWINDOW = 0,
|
||||||
|
|
||||||
|
/// <summary>Only the client area of the window is copied to hdcBlt. By default, the entire window is copied.</summary>
|
||||||
|
PW_CLIENTONLY = 1,
|
||||||
|
|
||||||
|
/// <summary>Undocumented</summary>
|
||||||
|
PW_RENDERFULLCONTENT = 0x00000002,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1392,32 +1392,36 @@ namespace Greenshot.Base.Core
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return an Image representing the Window!
|
/// Return an Image representing the Window!
|
||||||
/// As GDI+ draws it, it will be without Aero borders!
|
/// For Windows 7, as GDI+ draws it, it will be without Aero borders!
|
||||||
|
/// For Windows 10+, there is an option PW_RENDERFULLCONTENT, which makes sure the capture is "as is".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Image PrintWindow()
|
public Image PrintWindow()
|
||||||
{
|
{
|
||||||
Rectangle windowRect = WindowRectangle;
|
Rectangle windowRect = WindowRectangle;
|
||||||
// Start the capture
|
// Start the capture
|
||||||
Exception exceptionOccured = null;
|
Exception exceptionOccurred = null;
|
||||||
Image returnImage;
|
Image returnImage;
|
||||||
using (Region region = GetRegion())
|
using (Region region = GetRegion())
|
||||||
{
|
{
|
||||||
|
var backgroundColor = Color.Black;
|
||||||
PixelFormat pixelFormat = PixelFormat.Format24bppRgb;
|
PixelFormat pixelFormat = PixelFormat.Format24bppRgb;
|
||||||
// Only use 32 bpp ARGB when the window has a region
|
// Only use 32 bpp ARGB when the window has a region
|
||||||
if (region != null)
|
if (region != null)
|
||||||
{
|
{
|
||||||
pixelFormat = PixelFormat.Format32bppArgb;
|
pixelFormat = PixelFormat.Format32bppArgb;
|
||||||
|
backgroundColor = Color.Transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
returnImage = new Bitmap(windowRect.Width, windowRect.Height, pixelFormat);
|
returnImage = ImageHelper.CreateEmpty(windowRect.Width, windowRect.Height, pixelFormat, backgroundColor, 96,96);
|
||||||
using Graphics graphics = Graphics.FromImage(returnImage);
|
using Graphics graphics = Graphics.FromImage(returnImage);
|
||||||
using (SafeDeviceContextHandle graphicsDc = graphics.GetSafeDeviceContext())
|
using (SafeDeviceContextHandle graphicsDc = graphics.GetSafeDeviceContext())
|
||||||
{
|
{
|
||||||
bool printSucceeded = User32.PrintWindow(Handle, graphicsDc.DangerousGetHandle(), 0x0);
|
var pwFlags = WindowsVersion.IsWindows10OrLater ? PrintWindowFlags.PW_RENDERFULLCONTENT : PrintWindowFlags.PW_ENTIREWINDOW;
|
||||||
|
bool printSucceeded = User32.PrintWindow(Handle, graphicsDc.DangerousGetHandle(), pwFlags);
|
||||||
if (!printSucceeded)
|
if (!printSucceeded)
|
||||||
{
|
{
|
||||||
// something went wrong, most likely a "0x80004005" (Acess Denied) when using UAC
|
// something went wrong, most likely a "0x80004005" (Access Denied) when using UAC
|
||||||
exceptionOccured = User32.CreateWin32Exception("PrintWindow");
|
exceptionOccurred = User32.CreateWin32Exception("PrintWindow");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1432,9 +1436,9 @@ namespace Greenshot.Base.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return null if error
|
// Return null if error
|
||||||
if (exceptionOccured != null)
|
if (exceptionOccurred != null)
|
||||||
{
|
{
|
||||||
Log.ErrorFormat("Error calling print window: {0}", exceptionOccured.Message);
|
Log.ErrorFormat("Error calling print window: {0}", exceptionOccurred.Message);
|
||||||
returnImage.Dispose();
|
returnImage.Dispose();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace Greenshot.Base.UnmanagedHelpers
|
||||||
|
|
||||||
[DllImport("user32", SetLastError = true)]
|
[DllImport("user32", SetLastError = true)]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hDc, uint nFlags);
|
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hDc, PrintWindowFlags pwFlags);
|
||||||
|
|
||||||
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
|
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
|
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
|
@ -969,26 +969,34 @@ namespace Greenshot.Helpers
|
||||||
// Take default screen
|
// Take default screen
|
||||||
windowCaptureMode = WindowCaptureMode.Screen;
|
windowCaptureMode = WindowCaptureMode.Screen;
|
||||||
|
|
||||||
// Change to GDI, if allowed
|
// In https://github.com/greenshot/greenshot/issues/373 it was shown that PrintWindow (GDI) works great with Windows 11
|
||||||
if (!windowToCapture.IsMetroApp && WindowCapture.IsGdiAllowed(process))
|
if (WindowsVersion.IsWindows11OrLater)
|
||||||
{
|
{
|
||||||
if (!dwmEnabled && IsWpf(process))
|
windowCaptureMode = WindowCaptureMode.GDI;
|
||||||
{
|
|
||||||
// do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF
|
|
||||||
Log.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
windowCaptureMode = WindowCaptureMode.GDI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Change to DWM, if enabled and allowed
|
|
||||||
if (dwmEnabled)
|
|
||||||
{
|
{
|
||||||
if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process))
|
// Change to GDI, if allowed
|
||||||
|
if (!windowToCapture.IsMetroApp && WindowCapture.IsGdiAllowed(process))
|
||||||
{
|
{
|
||||||
windowCaptureMode = WindowCaptureMode.Aero;
|
if (!dwmEnabled && IsWpf(process))
|
||||||
|
{
|
||||||
|
// do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF
|
||||||
|
Log.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
windowCaptureMode = WindowCaptureMode.GDI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change to DWM, if enabled and allowed
|
||||||
|
if (dwmEnabled)
|
||||||
|
{
|
||||||
|
if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process))
|
||||||
|
{
|
||||||
|
windowCaptureMode = WindowCaptureMode.Aero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1034,7 +1042,7 @@ namespace Greenshot.Helpers
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpCapture = windowToCapture.CaptureGdiWindow(captureForWindow);
|
tmpCapture = windowToCapture.CaptureGdiWindow(captureForWindow);
|
||||||
if (tmpCapture != null)
|
if (tmpCapture != null && !WindowsVersion.IsWindows11OrLater)
|
||||||
{
|
{
|
||||||
// check if GDI capture any good, by comparing it with the screen content
|
// check if GDI capture any good, by comparing it with the screen content
|
||||||
int blackCountGdi = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false);
|
int blackCountGdi = ImageHelper.CountColor(tmpCapture.Image, Color.Black, false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue