Fixed some capture issues, when trying to capture or show thumbnails of Windows that are iconized the size calculations are wrong.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2206 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-10-26 18:07:55 +00:00
parent 4d41fc0a43
commit 4a3161a281
5 changed files with 147 additions and 142 deletions

View file

@ -1125,7 +1125,6 @@ namespace Greenshot {
capture.CaptureDetails.DpiX = graphics.DpiY; capture.CaptureDetails.DpiX = graphics.DpiY;
capture.CaptureDetails.DpiY = graphics.DpiY; capture.CaptureDetails.DpiY = graphics.DpiY;
} }
windowToCapture.Restore();
windowToCapture = CaptureHelper.SelectCaptureWindow(windowToCapture); windowToCapture = CaptureHelper.SelectCaptureWindow(windowToCapture);
if (windowToCapture != null) { if (windowToCapture != null) {
capture = CaptureHelper.CaptureWindow(windowToCapture, capture, coreConf.WindowCaptureMode); capture = CaptureHelper.CaptureWindow(windowToCapture, capture, coreConf.WindowCaptureMode);

View file

@ -631,12 +631,11 @@ namespace Greenshot.Helpers {
// Nothing to capture, code up in the stack will capture the full screen // Nothing to capture, code up in the stack will capture the full screen
return false; return false;
} }
if (selectedCaptureWindow != null && selectedCaptureWindow.Iconic) { if (!presupplied && selectedCaptureWindow != null && selectedCaptureWindow.Iconic) {
// Restore the window making sure it's visible! // Restore the window making sure it's visible!
// This is done mainly for a screen capture, but some applications like Excel and TOAD have weird behaviour! // This is done mainly for a screen capture, but some applications like Excel and TOAD have weird behaviour!
selectedCaptureWindow.Restore(); selectedCaptureWindow.Restore();
} }
selectedCaptureWindow.ToForeground();
selectedCaptureWindow = SelectCaptureWindow(selectedCaptureWindow); selectedCaptureWindow = SelectCaptureWindow(selectedCaptureWindow);
if (selectedCaptureWindow == null) { if (selectedCaptureWindow == null) {
LOG.Warn("No window to capture, after SelectCaptureWindow!"); LOG.Warn("No window to capture, after SelectCaptureWindow!");
@ -657,7 +656,7 @@ namespace Greenshot.Helpers {
/// <returns>WindowDetails with the target Window OR a replacement</returns> /// <returns>WindowDetails with the target Window OR a replacement</returns>
public static WindowDetails SelectCaptureWindow(WindowDetails windowToCapture) { public static WindowDetails SelectCaptureWindow(WindowDetails windowToCapture) {
Rectangle windowRectangle = windowToCapture.WindowRectangle; Rectangle windowRectangle = windowToCapture.WindowRectangle;
if (windowToCapture.Iconic || windowRectangle.Width == 0 || windowRectangle.Height == 0) { if (windowRectangle.Width == 0 || windowRectangle.Height == 0) {
LOG.WarnFormat("Window {0} has nothing to capture, using workaround to find other window of same process.", windowToCapture.Text); LOG.WarnFormat("Window {0} has nothing to capture, using workaround to find other window of same process.", windowToCapture.Text);
// Trying workaround, the size 0 arrises with e.g. Toad.exe, has a different Window when minimized // Trying workaround, the size 0 arrises with e.g. Toad.exe, has a different Window when minimized
WindowDetails linkedWindow = WindowDetails.GetLinkedWindow(windowToCapture); WindowDetails linkedWindow = WindowDetails.GetLinkedWindow(windowToCapture);
@ -706,10 +705,6 @@ namespace Greenshot.Helpers {
captureForWindow = new Capture(); captureForWindow = new Capture();
} }
Rectangle windowRectangle = windowToCapture.WindowRectangle; Rectangle windowRectangle = windowToCapture.WindowRectangle;
if (windowToCapture.Iconic) {
// Restore the window making sure it's visible!
windowToCapture.Restore();
}
// When Vista & DWM (Aero) enabled // When Vista & DWM (Aero) enabled
bool dwmEnabled = DWM.isDWMEnabled(); bool dwmEnabled = DWM.isDWMEnabled();
@ -769,40 +764,52 @@ namespace Greenshot.Helpers {
bool captureTaken = false; bool captureTaken = false;
// Try to capture // Try to capture
while (!captureTaken) { while (!captureTaken) {
if (windowCaptureMode == WindowCaptureMode.GDI) { ICapture tmpCapture = null;
ICapture tmpCapture = null; switch (windowCaptureMode) {
if (WindowCapture.isGDIAllowed(process)) { case WindowCaptureMode.GDI:
tmpCapture = windowToCapture.CaptureWindow(captureForWindow); if (WindowCapture.isGDIAllowed(process)) {
} if (windowToCapture.Iconic) {
if (tmpCapture != null) { // Restore the window making sure it's visible!
captureForWindow = tmpCapture; windowToCapture.Restore();
captureTaken = true; }
} else { tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow);
// A problem, try Screen }
windowCaptureMode = WindowCaptureMode.Screen; if (tmpCapture != null) {
} captureForWindow = tmpCapture;
} else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { captureTaken = true;
ICapture tmpCapture = null; } else {
if (WindowCapture.isDWMAllowed(process)) { // A problem, try Screen
tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode); windowCaptureMode = WindowCaptureMode.Screen;
} }
if (tmpCapture != null) { break;
captureForWindow = tmpCapture; case WindowCaptureMode.Aero:
captureTaken = true; case WindowCaptureMode.AeroTransparent:
} else { if (WindowCapture.isDWMAllowed(process)) {
// A problem, try GDI tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode);
windowCaptureMode = WindowCaptureMode.GDI; }
} if (tmpCapture != null) {
} else { captureForWindow = tmpCapture;
// Screen capture captureTaken = true;
windowRectangle.Intersect(captureForWindow.ScreenBounds); } else {
try { // A problem, try GDI
captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle); windowCaptureMode = WindowCaptureMode.GDI;
captureTaken = true; }
} catch (Exception e) { break;
LOG.Error("Problem capturing", e); default:
return null; // Screen capture
} if (windowToCapture.Iconic) {
// Restore the window making sure it's visible!
windowToCapture.Restore();
}
windowRectangle.Intersect(captureForWindow.ScreenBounds);
try {
captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle);
captureTaken = true;
} catch (Exception e) {
LOG.Error("Problem capturing", e);
return null;
}
break;
} }
} }
@ -835,11 +842,11 @@ namespace Greenshot.Helpers {
// Take the captureRect, this already is specified as bitmap coordinates // Take the captureRect, this already is specified as bitmap coordinates
capture.Crop(captureRect); capture.Crop(captureRect);
// save for re-capturing later and show recapture context menu option // save for re-capturing later and show recapture context menu option
// Important here is that the location needs to be offsetted back to screen coordinates! // Important here is that the location needs to be offsetted back to screen coordinates!
Rectangle tmpRectangle = captureRect.Clone(); Rectangle tmpRectangle = captureRect.Clone();
tmpRectangle.Offset(capture.ScreenBounds.Location.X, capture.ScreenBounds.Location.Y); tmpRectangle.Offset(capture.ScreenBounds.Location.X, capture.ScreenBounds.Location.Y);
RuntimeConfig.LastCapturedRegion = tmpRectangle; RuntimeConfig.LastCapturedRegion = tmpRectangle;
HandleCapture(); HandleCapture();
} }
} }

View file

@ -26,92 +26,93 @@ using System.Drawing;
using GreenshotPlugin.UnmanagedHelpers; using GreenshotPlugin.UnmanagedHelpers;
namespace GreenshotPlugin.Controls { namespace GreenshotPlugin.Controls {
/// <summary> /// <summary>
/// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture. /// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture.
/// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform. /// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform.
/// </summary> /// </summary>
public class ThumbnailForm : FormWithoutActivation { public class ThumbnailForm : FormWithoutActivation {
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>(); private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private IntPtr thumbnailHandle = IntPtr.Zero; private IntPtr thumbnailHandle = IntPtr.Zero;
private Rectangle parentMenuBounds = Rectangle.Empty; private Rectangle parentMenuBounds = Rectangle.Empty;
public ThumbnailForm() { public ThumbnailForm() {
ShowInTaskbar = false; ShowInTaskbar = false;
FormBorderStyle = FormBorderStyle.None; FormBorderStyle = FormBorderStyle.None;
TopMost = false; TopMost = false;
Enabled = false; Enabled = false;
if (conf.WindowCaptureMode == WindowCaptureMode.Auto || conf.WindowCaptureMode == WindowCaptureMode.Aero) { if (conf.WindowCaptureMode == WindowCaptureMode.Auto || conf.WindowCaptureMode == WindowCaptureMode.Aero) {
BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B); BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B);
} else { } else {
BackColor = Color.White; BackColor = Color.White;
} }
// cleanup at close // cleanup at close
this.FormClosing += delegate { this.FormClosing += delegate {
UnregisterThumbnail(); UnregisterThumbnail();
}; };
} }
public new void Hide() { public new void Hide() {
UnregisterThumbnail(); UnregisterThumbnail();
base.Hide(); base.Hide();
} }
private void UnregisterThumbnail() { private void UnregisterThumbnail() {
if (thumbnailHandle != IntPtr.Zero) { if (thumbnailHandle != IntPtr.Zero) {
DWM.DwmUnregisterThumbnail(thumbnailHandle); DWM.DwmUnregisterThumbnail(thumbnailHandle);
thumbnailHandle = IntPtr.Zero; thumbnailHandle = IntPtr.Zero;
} }
} }
/// <summary> /// <summary>
/// Show the thumbnail of the supplied window above (or under) the parent Control /// Show the thumbnail of the supplied window above (or under) the parent Control
/// </summary> /// </summary>
/// <param name="window">WindowDetails</param> /// <param name="window">WindowDetails</param>
/// <param name="parentControl">Control</param> /// <param name="parentControl">Control</param>
public void ShowThumbnail(WindowDetails window, Control parentControl) { public void ShowThumbnail(WindowDetails window, Control parentControl) {
UnregisterThumbnail(); UnregisterThumbnail();
DWM.DwmRegisterThumbnail(Handle, window.Handle, out thumbnailHandle); DWM.DwmRegisterThumbnail(Handle, window.Handle, out thumbnailHandle);
if (thumbnailHandle != IntPtr.Zero) { if (thumbnailHandle != IntPtr.Zero) {
Rectangle windowRectangle = window.WindowRectangle; SIZE sourceSize;
int thumbnailHeight = 200; DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize);
int thumbnailWidth = (int)(thumbnailHeight * ((float)windowRectangle.Width / (float)windowRectangle.Height)); int thumbnailHeight = 200;
if (parentControl != null && thumbnailWidth > parentControl.Width) { int thumbnailWidth = (int)(thumbnailHeight * ((float)sourceSize.width / (float)sourceSize.height));
thumbnailWidth = parentControl.Width; if (parentControl != null && thumbnailWidth > parentControl.Width) {
thumbnailHeight = (int)(thumbnailWidth * ((float)windowRectangle.Height / (float)windowRectangle.Width)); thumbnailWidth = parentControl.Width;
} thumbnailHeight = (int)(thumbnailWidth * ((float)sourceSize.height / (float)sourceSize.width));
Width = thumbnailWidth; }
Height = thumbnailHeight; Width = thumbnailWidth;
// Prepare the displaying of the Thumbnail Height = thumbnailHeight;
DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES(); // Prepare the displaying of the Thumbnail
props.Opacity = (byte)255; DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES();
props.Visible = true; props.Opacity = (byte)255;
props.SourceClientAreaOnly = false; props.Visible = true;
props.Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight); props.SourceClientAreaOnly = false;
DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); props.Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight);
if (parentControl != null) { DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props);
AlignToControl(parentControl); if (parentControl != null) {
} AlignToControl(parentControl);
}
if (!Visible) { if (!Visible) {
Show(); Show();
} }
// Make sure it's on "top"! // Make sure it's on "top"!
if (parentControl != null) { if (parentControl != null) {
User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE);
} }
} }
} }
public void AlignToControl(Control alignTo) { public void AlignToControl(Control alignTo) {
Rectangle screenBounds = WindowCapture.GetScreenBounds(); Rectangle screenBounds = WindowCapture.GetScreenBounds();
if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) { if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) {
Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height); Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height);
} else { } else {
Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Bottom); Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Bottom);
} }
} }
} }
} }

View file

@ -705,7 +705,9 @@ namespace GreenshotPlugin.Core {
User32.BringWindowToTop(this.hWnd); User32.BringWindowToTop(this.hWnd);
User32.SetForegroundWindow(this.hWnd); User32.SetForegroundWindow(this.hWnd);
// Make sure windows has time to perform the action // Make sure windows has time to perform the action
Application.DoEvents(); while(Iconic) {
Application.DoEvents();
}
} }
public WindowStyleFlags WindowStyle { public WindowStyleFlags WindowStyle {
@ -738,7 +740,7 @@ namespace GreenshotPlugin.Core {
/// </summary> /// </summary>
/// <param name="capture">The capture to fill</param> /// <param name="capture">The capture to fill</param>
/// <returns>ICapture</returns> /// <returns>ICapture</returns>
public ICapture CaptureWindow(ICapture capture) { public ICapture CaptureGDIWindow(ICapture capture) {
Image capturedImage = PrintWindow(); Image capturedImage = PrintWindow();
if (capturedImage != null) { if (capturedImage != null) {
capture.Image = capturedImage; capture.Image = capturedImage;
@ -772,7 +774,7 @@ namespace GreenshotPlugin.Core {
SIZE sourceSize; SIZE sourceSize;
DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize); DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize);
if (sourceSize.cx <= 0 || sourceSize.cy <= 0) { if (sourceSize.width <= 0 || sourceSize.height <= 0) {
return null; return null;
} }
@ -819,7 +821,7 @@ namespace GreenshotPlugin.Core {
tempForm.Size = sourceSize.ToSize(); tempForm.Size = sourceSize.ToSize();
// Prepare rectangle to capture from the screen. // Prepare rectangle to capture from the screen.
Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.cx, sourceSize.cy); Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.width, sourceSize.height);
if (Maximised) { if (Maximised) {
// Correct capture size for maximized window by offsetting the X,Y with the border size // Correct capture size for maximized window by offsetting the X,Y with the border size
captureRectangle.X += borderSize.Width; captureRectangle.X += borderSize.Width;
@ -838,14 +840,12 @@ namespace GreenshotPlugin.Core {
} }
} }
// Make sure the to be captured window is active, important for the close/resize buttons
this.Restore();
// 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;
props.Visible = true; props.Visible = true;
props.Destination = new RECT(0, 0, sourceSize.cx, sourceSize.cy); props.Destination = new RECT(0, 0, sourceSize.width, sourceSize.height);
DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props);
tempForm.Show(); tempForm.Show();
tempFormShown = true; tempFormShown = true;
@ -1322,9 +1322,7 @@ namespace GreenshotPlugin.Core {
/// As GDI+ draws it, it will be without Aero borders! /// As GDI+ draws it, it will be without Aero borders!
/// </summary> /// </summary>
public Image PrintWindow() { public Image PrintWindow() {
Rectangle windowRect = Rectangle.Empty; Rectangle windowRect = WindowRectangle;
GetWindowRect(out windowRect);
// Start the capture // Start the capture
Exception exceptionOccured = null; Exception exceptionOccured = null;
Image returnImage = null; Image returnImage = null;

View file

@ -25,17 +25,17 @@ using System.Runtime.InteropServices;
namespace GreenshotPlugin.UnmanagedHelpers { namespace GreenshotPlugin.UnmanagedHelpers {
[StructLayout(LayoutKind.Sequential), Serializable()] [StructLayout(LayoutKind.Sequential), Serializable()]
public struct SIZE { public struct SIZE {
public int cx; public int width;
public int cy; public int height;
public SIZE(Size size) : this(size.Width, size.Height) { public SIZE(Size size) : this(size.Width, size.Height) {
} }
public SIZE(int cx, int cy) { public SIZE(int width, int height) {
this.cx = cx; this.width = width;
this.cy = cy; this.height = height;
} }
public Size ToSize() { public Size ToSize() {
return new Size(cx, cy); return new Size(width, height);
} }
} }