mirror of
https://github.com/greenshot/greenshot
synced 2025-07-14 00:53:51 -07:00
Added multi-screen capture support! As a default the current screen under the cursor is captured. (ScreenCaptureMode.Auto)
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1806 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
54dd4614f5
commit
e687450dfc
7 changed files with 161 additions and 19 deletions
|
@ -535,7 +535,7 @@ namespace Greenshot.Drawing {
|
|||
/// </summary>
|
||||
/// <returns>true if cropped</returns>
|
||||
public bool AutoCrop() {
|
||||
Rectangle cropRectangle = ImageHelper.FindAutoCropRectangle(Image);
|
||||
Rectangle cropRectangle = ImageHelper.FindAutoCropRectangle(Image, conf.AutoCropDifference);
|
||||
if (isCropPossible(ref cropRectangle)) {
|
||||
DrawingMode = DrawingModes.Crop;
|
||||
cropContainer = new CropContainer(this);
|
||||
|
@ -637,6 +637,18 @@ namespace Greenshot.Drawing {
|
|||
newImage = ImageHelper.RotateFlip((Bitmap)Image, rotateFlipType);
|
||||
break;
|
||||
}
|
||||
// The following was added to correct any unneeded pixels, had the bad effect that sometimes everything was cropped... :(
|
||||
//Rectangle autoCropRectangle = ImageHelper.FindAutoCropRectangle(newImage, 0);
|
||||
//if (!Size.Empty.Equals(autoCropRectangle.Size) && !autoCropRectangle.Size.Equals(newImage.Size)) {
|
||||
// LOG.InfoFormat("Crop to {0}", autoCropRectangle);
|
||||
// using (Bitmap tmpImage = newImage) {
|
||||
// newImage = ImageHelper.CloneArea(newImage, autoCropRectangle, PixelFormat.DontCare);
|
||||
// }
|
||||
// // Fix offset
|
||||
// offset = new Point(offset.X - autoCropRectangle.X, offset.Y - autoCropRectangle.Y);
|
||||
//} else {
|
||||
// LOG.DebugFormat("No cropping needed!");
|
||||
//}
|
||||
|
||||
if (newImage != null) {
|
||||
// Make sure the elements move according to the offset the effect made the bitmap move
|
||||
|
@ -655,6 +667,11 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check if a crop is possible
|
||||
/// </summary>
|
||||
/// <param name="cropRectangle"></param>
|
||||
/// <returns>true if this is possible</returns>
|
||||
public bool isCropPossible(ref Rectangle cropRectangle) {
|
||||
cropRectangle = Helpers.GuiRectangle.GetGuiRectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, cropRectangle.Height);
|
||||
if (cropRectangle.Left < 0) cropRectangle = new Rectangle(0, cropRectangle.Top, cropRectangle.Width + cropRectangle.Left, cropRectangle.Height);
|
||||
|
@ -684,12 +701,16 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crop the surface
|
||||
/// </summary>
|
||||
/// <param name="cropRectangle"></param>
|
||||
/// <returns></returns>
|
||||
public bool ApplyCrop(Rectangle cropRectangle) {
|
||||
if (isCropPossible(ref cropRectangle)) {
|
||||
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
|
||||
// we should not forget to Dispose the images!!
|
||||
Bitmap tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare);
|
||||
tmpImage.SetResolution(Image.HorizontalResolution, Image.VerticalResolution);
|
||||
|
||||
Point offset = new Point(-cropRectangle.Left, -cropRectangle.Top);
|
||||
// Make undoable
|
||||
|
|
1
Greenshot/Forms/MainForm.Designer.cs
generated
1
Greenshot/Forms/MainForm.Designer.cs
generated
|
@ -132,7 +132,6 @@ namespace Greenshot {
|
|||
this.contextmenu_capturefullscreen.ShortcutKeyDisplayString = "Ctrl + Print";
|
||||
this.contextmenu_capturefullscreen.Size = new System.Drawing.Size(242, 22);
|
||||
this.contextmenu_capturefullscreen.Text = "Capture full screen";
|
||||
this.contextmenu_capturefullscreen.Click += new System.EventHandler(this.CaptureFullScreenToolStripMenuItemClick);
|
||||
//
|
||||
// toolStripSeparator4
|
||||
//
|
||||
|
|
|
@ -562,6 +562,7 @@ namespace Greenshot {
|
|||
void CaptureRegion() {
|
||||
CaptureHelper.CaptureRegion(true);
|
||||
}
|
||||
|
||||
void CaptureClipboard() {
|
||||
CaptureHelper.CaptureClipboard();
|
||||
}
|
||||
|
@ -575,15 +576,19 @@ namespace Greenshot {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureFullScreen() {
|
||||
CaptureHelper.CaptureFullscreen(true);
|
||||
CaptureHelper.CaptureFullscreen(true, conf.ScreenCaptureMode);
|
||||
}
|
||||
|
||||
void CaptureLastRegion() {
|
||||
CaptureHelper.CaptureLastRegion(true);
|
||||
}
|
||||
|
||||
void CaptureIE() {
|
||||
CaptureHelper.CaptureIE(true);
|
||||
}
|
||||
|
||||
void CaptureWindow() {
|
||||
if (conf.CaptureWindowsInteractive) {
|
||||
CaptureHelper.CaptureWindowInteractive(true);
|
||||
|
@ -609,6 +614,17 @@ namespace Greenshot {
|
|||
} catch (Exception ex) {
|
||||
LOG.WarnFormat("Problem accessing IE information: {0}", ex.Message);
|
||||
}
|
||||
|
||||
// Multi-Screen captures
|
||||
this.contextmenu_capturefullscreen.Click -= new System.EventHandler(this.CaptureFullScreenToolStripMenuItemClick);
|
||||
this.contextmenu_capturefullscreen.DropDownOpening -= new System.EventHandler(MultiScreenDropDownOpening);
|
||||
this.contextmenu_capturefullscreen.DropDownClosed -= new System.EventHandler(MultiScreenDropDownClosing);
|
||||
if (Screen.AllScreens.Length > 1) {
|
||||
this.contextmenu_capturefullscreen.DropDownOpening += new System.EventHandler(MultiScreenDropDownOpening);
|
||||
this.contextmenu_capturefullscreen.DropDownClosed += new System.EventHandler(MultiScreenDropDownClosing);
|
||||
} else {
|
||||
this.contextmenu_capturefullscreen.Click += new System.EventHandler(this.CaptureFullScreenToolStripMenuItemClick);
|
||||
}
|
||||
}
|
||||
|
||||
void ContextMenuClosing(object sender, EventArgs e) {
|
||||
|
@ -653,6 +669,56 @@ namespace Greenshot {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MultiScreenDropDownOpening is called when mouse hovers over the Capture-Screen context menu
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void MultiScreenDropDownOpening(object sender, EventArgs e) {
|
||||
ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender;
|
||||
captureScreenMenuItem.DropDownItems.Clear();
|
||||
if (Screen.AllScreens.Length > 1) {
|
||||
ToolStripMenuItem captureScreenItem;
|
||||
string allDeviceName = "";
|
||||
foreach (Screen screen in Screen.AllScreens) {
|
||||
string deviceName = screen.DeviceName;
|
||||
if (allDeviceName.Length > 0) {
|
||||
allDeviceName += " + ";
|
||||
}
|
||||
allDeviceName += deviceName.Substring(deviceName.Length - 1);
|
||||
}
|
||||
captureScreenItem = new ToolStripMenuItem(allDeviceName);
|
||||
captureScreenItem.Click += delegate {
|
||||
BeginInvoke((MethodInvoker)delegate {
|
||||
CaptureHelper.CaptureFullscreen(false, ScreenCaptureMode.FullScreen);
|
||||
});
|
||||
};
|
||||
captureScreenMenuItem.DropDownItems.Add(captureScreenItem);
|
||||
foreach (Screen screen in Screen.AllScreens) {
|
||||
Screen screenToCapture = screen;
|
||||
string deviceName = screenToCapture.DeviceName;
|
||||
deviceName = deviceName.Substring(deviceName.Length - 1);
|
||||
captureScreenItem = new ToolStripMenuItem(deviceName);
|
||||
captureScreenItem.Click += delegate {
|
||||
BeginInvoke((MethodInvoker)delegate {
|
||||
CaptureHelper.CaptureRegion(false, screenToCapture.Bounds);
|
||||
});
|
||||
};
|
||||
captureScreenMenuItem.DropDownItems.Add(captureScreenItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MultiScreenDropDownOpening is called when mouse leaves the context menu
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void MultiScreenDropDownClosing(object sender, EventArgs e) {
|
||||
ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender;
|
||||
captureScreenMenuItem.DropDownItems.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build a selectable list of windows when we enter the menu item
|
||||
/// </summary>
|
||||
|
@ -783,7 +849,7 @@ namespace Greenshot {
|
|||
|
||||
void CaptureFullScreenToolStripMenuItemClick(object sender, EventArgs e) {
|
||||
BeginInvoke((MethodInvoker)delegate {
|
||||
CaptureHelper.CaptureFullscreen(false);
|
||||
CaptureHelper.CaptureFullscreen(false, conf.ScreenCaptureMode);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace Greenshot.Helpers {
|
|||
private bool captureMouseCursor = false;
|
||||
private ICapture capture = null;
|
||||
private CaptureMode captureMode;
|
||||
private ScreenCaptureMode screenCaptureMode = ScreenCaptureMode.Auto;
|
||||
private Thread windowDetailsThread = null;
|
||||
|
||||
public static void CaptureClipboard() {
|
||||
|
@ -64,7 +65,10 @@ namespace Greenshot.Helpers {
|
|||
CaptureHelper captureHelper = new CaptureHelper(CaptureMode.Region, captureMouse, destination);
|
||||
captureHelper.MakeCapture();
|
||||
}
|
||||
public static void CaptureFullscreen(bool captureMouse) {
|
||||
public static void CaptureRegion(bool captureMouse, Rectangle region) {
|
||||
new CaptureHelper(CaptureMode.Region, captureMouse).MakeCapture(region);
|
||||
}
|
||||
public static void CaptureFullscreen(bool captureMouse, ScreenCaptureMode screenCaptureMode) {
|
||||
new CaptureHelper(CaptureMode.FullScreen, captureMouse).MakeCapture();
|
||||
}
|
||||
public static void CaptureLastRegion(bool captureMouse) {
|
||||
|
@ -103,6 +107,11 @@ namespace Greenshot.Helpers {
|
|||
this.captureMouseCursor = captureMouseCursor;
|
||||
}
|
||||
|
||||
public CaptureHelper(CaptureMode captureMode, bool captureMouseCursor, ScreenCaptureMode screenCaptureMode) : this(captureMode) {
|
||||
this.captureMouseCursor = captureMouseCursor;
|
||||
this.screenCaptureMode = screenCaptureMode;
|
||||
}
|
||||
|
||||
public CaptureHelper(CaptureMode captureMode, bool captureMouseCursor, IDestination destination) : this(captureMode, captureMouseCursor) {
|
||||
capture.CaptureDetails.AddDestination(destination);
|
||||
}
|
||||
|
@ -131,6 +140,16 @@ namespace Greenshot.Helpers {
|
|||
MakeCapture();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make Capture for region
|
||||
/// </summary>
|
||||
/// <param name="filename">filename</param>
|
||||
private void MakeCapture(Rectangle region) {
|
||||
captureRect = region;
|
||||
MakeCapture();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Make Capture with specified destinations
|
||||
/// </summary>
|
||||
|
@ -210,7 +229,32 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
case CaptureMode.FullScreen:
|
||||
// Check how we need to capture the screen
|
||||
bool captureTaken = false;
|
||||
switch (screenCaptureMode) {
|
||||
case ScreenCaptureMode.Auto:
|
||||
Point mouseLocation = WindowCapture.GetCursorLocation();
|
||||
foreach (Screen screen in Screen.AllScreens) {
|
||||
if (screen.Bounds.Contains(mouseLocation)) {
|
||||
capture = WindowCapture.CaptureRectangle(capture, screen.Bounds);
|
||||
captureTaken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ScreenCaptureMode.Fixed:
|
||||
if (conf.ScreenToCapture > 0 && conf.ScreenToCapture <= Screen.AllScreens.Length) {
|
||||
capture = WindowCapture.CaptureRectangle(capture, Screen.AllScreens[conf.ScreenToCapture].Bounds);
|
||||
captureTaken = true;
|
||||
}
|
||||
break;
|
||||
case ScreenCaptureMode.FullScreen:
|
||||
// Do nothing, we take the fullscreen capture automatically
|
||||
break;
|
||||
}
|
||||
if (!captureTaken) {
|
||||
capture = WindowCapture.CaptureScreen(capture);
|
||||
}
|
||||
HandleCapture();
|
||||
break;
|
||||
case CaptureMode.Clipboard:
|
||||
|
@ -279,19 +323,25 @@ namespace Greenshot.Helpers {
|
|||
break;
|
||||
case CaptureMode.LastRegion:
|
||||
if (!RuntimeConfig.LastCapturedRegion.IsEmpty) {
|
||||
capture = WindowCapture.CaptureScreen(capture);
|
||||
capture = WindowCapture.CaptureRectangle(capture, RuntimeConfig.LastCapturedRegion);
|
||||
if (windowDetailsThread != null) {
|
||||
windowDetailsThread.Join();
|
||||
}
|
||||
capture.Crop(RuntimeConfig.LastCapturedRegion);
|
||||
capture.CaptureDetails.AddMetaData("source", "screen");
|
||||
HandleCapture();
|
||||
}
|
||||
break;
|
||||
case CaptureMode.Region:
|
||||
// Check if a region is pre-supplied!
|
||||
if (Rectangle.Empty.Equals(captureRect)) {
|
||||
capture = WindowCapture.CaptureScreen(capture);
|
||||
capture.CaptureDetails.AddMetaData("source", "screen");
|
||||
CaptureWithFeedback();
|
||||
} else {
|
||||
capture = WindowCapture.CaptureRectangle(capture, captureRect);
|
||||
capture.CaptureDetails.AddMetaData("source", "screen");
|
||||
HandleCapture();
|
||||
}
|
||||
break;
|
||||
case CaptureMode.Video:
|
||||
capture = WindowCapture.CaptureScreen(capture);
|
||||
|
|
|
@ -71,7 +71,11 @@ namespace GreenshotPlugin.Core {
|
|||
public bool CaptureWindowsInteractive;
|
||||
[IniProperty("CaptureDelay", Description="Capture delay in millseconds.", DefaultValue="100")]
|
||||
public int CaptureDelay;
|
||||
[IniProperty("WindowCaptureMode", Description="The capture mode used to capture a Window.", DefaultValue="Auto")]
|
||||
[IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")]
|
||||
public ScreenCaptureMode ScreenCaptureMode;
|
||||
[IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")]
|
||||
public int ScreenToCapture;
|
||||
[IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")]
|
||||
public WindowCaptureMode WindowCaptureMode;
|
||||
[IniProperty("WindowCaptureAllChildLocations", Description="Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue="False")]
|
||||
public bool WindowCaptureAllChildLocations;
|
||||
|
|
|
@ -98,20 +98,20 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="buffer"></param>
|
||||
/// <param name="colorPoint"></param>
|
||||
/// <returns></returns>
|
||||
private static Rectangle FindAutoCropRectangle(BitmapBuffer buffer, Point colorPoint) {
|
||||
private static Rectangle FindAutoCropRectangle(BitmapBuffer buffer, Point colorPoint, int cropDifference) {
|
||||
Rectangle cropRectangle = Rectangle.Empty;
|
||||
Color referenceColor = buffer.GetColorAtWithoutAlpha(colorPoint.X,colorPoint.Y);
|
||||
Point min = new Point(int.MaxValue, int.MaxValue);
|
||||
Point max = new Point(int.MinValue, int.MinValue);
|
||||
|
||||
if (conf.AutoCropDifference > 0) {
|
||||
if (cropDifference > 0) {
|
||||
for(int y = 0; y < buffer.Height; y++) {
|
||||
for(int x = 0; x < buffer.Width; x++) {
|
||||
Color currentColor = buffer.GetColorAt(x, y);
|
||||
int diffR = Math.Abs(currentColor.R - referenceColor.R);
|
||||
int diffG = Math.Abs(currentColor.G - referenceColor.G);
|
||||
int diffB = Math.Abs(currentColor.B - referenceColor.B);
|
||||
if (((diffR+diffG+diffB)/3) > conf.AutoCropDifference) {
|
||||
if (((diffR + diffG + diffB) / 3) > cropDifference) {
|
||||
if (x < min.X) min.X = x;
|
||||
if (y < min.Y) min.Y = y;
|
||||
if (x > max.X) max.X = x;
|
||||
|
@ -140,12 +140,13 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
return cropRectangle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a rectangle for the image which crops the image of all colors equal to that on 0,0
|
||||
/// </summary>
|
||||
/// <param name="image"></param>
|
||||
/// <returns>Rectangle</returns>
|
||||
public static Rectangle FindAutoCropRectangle(Image image) {
|
||||
public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) {
|
||||
Rectangle cropRectangle = Rectangle.Empty;
|
||||
using (BitmapBuffer buffer = new BitmapBuffer((Bitmap)image, false)) {
|
||||
buffer.Lock();
|
||||
|
@ -162,7 +163,7 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
// find biggest area
|
||||
foreach(Point checkPoint in checkPoints) {
|
||||
currentRectangle = FindAutoCropRectangle(buffer, checkPoint);
|
||||
currentRectangle = FindAutoCropRectangle(buffer, checkPoint, cropDifference);
|
||||
if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) {
|
||||
cropRectangle = currentRectangle;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace Greenshot.Plugin {
|
|||
/// The capture mode for Greenshot
|
||||
/// </summary>
|
||||
public enum CaptureMode { None, Region, FullScreen, ActiveWindow, Window, LastRegion, Clipboard, File, IE, Video, Import };
|
||||
public enum ScreenCaptureMode { Auto, FullScreen, Fixed};
|
||||
|
||||
/// <summary>
|
||||
/// Details for the capture, like the window title and date/time etc.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue