Fixed DWM capture to work by cutting the corners only if Windows Vista / Windows 7. This change allowed to have the redmask capture to be removed, only need to freeze processes if a transparent capture is taken. This should speedup the capture and use less memory.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2242 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-11-05 19:07:39 +00:00
commit 93d9a8cd0c

View file

@ -840,7 +840,6 @@ namespace GreenshotPlugin.Core {
} }
} }
// Prepare the displaying of the Thumbnail // Prepare the displaying of the Thumbnail
DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES(); DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES();
props.Opacity = (byte)255; props.Opacity = (byte)255;
@ -855,16 +854,11 @@ namespace GreenshotPlugin.Core {
// Destination bitmap for the capture // Destination bitmap for the capture
Bitmap capturedBitmap = null; Bitmap capturedBitmap = null;
bool frozen = false;
try { try {
this.FreezeWindow();
// Use red to make removal of the corners possible
tempForm.BackColor = Color.Red;
// Make sure everything is visible
tempForm.Refresh();
Application.DoEvents();
using (Bitmap redMask = WindowCapture.CaptureRectangle(captureRectangle)) {
// Check if we make a transparent capture // Check if we make a transparent capture
if (windowCaptureMode == WindowCaptureMode.AeroTransparent) { if (windowCaptureMode == WindowCaptureMode.AeroTransparent) {
frozen = this.FreezeWindow();
// Use white, later black to capture transparent // Use white, later black to capture transparent
tempForm.BackColor = Color.White; tempForm.BackColor = Color.White;
// Make sure everything is visible // Make sure everything is visible
@ -908,7 +902,10 @@ namespace GreenshotPlugin.Core {
// Capture from the screen // Capture from the screen
capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle); capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle);
} }
if (capturedBitmap != null && redMask != null) { if (capturedBitmap != null) {
// Not needed for Windows 8
if (!(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)) {
if (conf.WindowCaptureRemoveCorners && !Maximised) {
// Remove corners // Remove corners
if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) { if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) {
LOG.Debug("Changing pixelformat to Alpha for the RemoveCorners"); LOG.Debug("Changing pixelformat to Alpha for the RemoveCorners");
@ -916,21 +913,16 @@ namespace GreenshotPlugin.Core {
capturedBitmap.Dispose(); capturedBitmap.Dispose();
capturedBitmap = tmpBitmap; capturedBitmap = tmpBitmap;
} }
} RemoveCorners(capturedBitmap);
if (capturedBitmap != null) {
if (conf.WindowCaptureRemoveCorners && !Maximised) {
Color cornerColor = Color.Transparent;
if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) {
cornerColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B);
}
RemoveCorners(capturedBitmap, cornerColor);
} }
} }
} }
} finally { } finally {
// Make sure to ALWAYS unfreeze!! // Make sure to ALWAYS unfreeze!!
if (frozen) {
this.UnfreezeWindow(); this.UnfreezeWindow();
} }
}
capture.Image = capturedBitmap; capture.Image = capturedBitmap;
// Make sure the capture location is the location of the window, not the copy // Make sure the capture location is the location of the window, not the copy
@ -954,17 +946,19 @@ namespace GreenshotPlugin.Core {
/// <summary> /// <summary>
/// Helper method to remove the corners from a DMW capture /// Helper method to remove the corners from a DMW capture
/// </summary> /// </summary>
/// <param name="normalBitmap">The bitmap to remove the corners from.</param> /// <param name="image">The bitmap to remove the corners from.</param>
/// <param name="cornerColor">The background color</param> private void RemoveCorners(Bitmap image) {
private void RemoveCorners(Bitmap normalBitmap, Color cornerColor) { int [] cornerRange = {5,3,2,1,1};
int borderWidth = User32.GetSystemMetrics(SystemMetric.SM_CXFRAME)+2; using (BitmapBuffer buffer = new BitmapBuffer((Bitmap)image, false)) {
int borderHeight = User32.GetSystemMetrics(SystemMetric.SM_CYFRAME)+2; buffer.Lock();
IntPtr regionHandle = GDI32.CreateRoundRectRgn(0, 0, normalBitmap.Width+1, normalBitmap.Height+1, borderWidth, borderHeight); for (int y = 0; y < cornerRange.Length; y++) {
Region region = Region.FromHrgn(regionHandle); for (int x = 0; x < cornerRange[y]; x++) {
GDI32.DeleteObject(regionHandle); buffer.SetColorAt(x, y, Color.Transparent);
using (Graphics graphics = Graphics.FromImage(normalBitmap)) { buffer.SetColorAt(image.Width-1-x, y, Color.Transparent);
graphics.ExcludeClip(region); buffer.SetColorAt(image.Width-1-x, image.Height-1-y, Color.Transparent);
graphics.Clear(cornerColor); buffer.SetColorAt(x, image.Height-1-y, Color.Transparent);
}
}
} }
} }
@ -1131,28 +1125,31 @@ namespace GreenshotPlugin.Core {
/// Freezes the process belonging to the window /// Freezes the process belonging to the window
/// Warning: Use only if no other way!! /// Warning: Use only if no other way!!
/// </summary> /// </summary>
private void FreezeWindow() { private bool FreezeWindow() {
Process proc = Process.GetProcessById(this.ProcessId.ToInt32()); Process proc = Process.GetProcessById(this.ProcessId.ToInt32());
string processName = proc.ProcessName; string processName = proc.ProcessName;
if (!CanFreezeOrUnfreeze(processName)) { if (!CanFreezeOrUnfreeze(processName)) {
LOG.DebugFormat("Not freezing {0}", processName); LOG.DebugFormat("Not freezing {0}", processName);
return; return false;
} }
if (!CanFreezeOrUnfreeze(Text)) { if (!CanFreezeOrUnfreeze(Text)) {
LOG.DebugFormat("Not freezing {0}", processName); LOG.DebugFormat("Not freezing {0}", processName);
return; return false;
} }
LOG.DebugFormat("Freezing process: {0}", processName); LOG.DebugFormat("Freezing process: {0}", processName);
bool frozen = false;
foreach (ProcessThread pT in proc.Threads) { foreach (ProcessThread pT in proc.Threads) {
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id); IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero) { if (pOpenThread == IntPtr.Zero) {
break; break;
} }
frozen = true;
Kernel32.SuspendThread(pOpenThread); Kernel32.SuspendThread(pOpenThread);
} }
return frozen;
} }
/// <summary> /// <summary>