Update Greenshot to latest version

Greenshot updated from 1.2 branch at commit
e9ab99c5acc99785cc5045b4b5493c9b6504d016

This solves #1341 and #1079 for allowing support high DPI monitors.
Additionally, the following were implemented:
- #748 - Objects can be saved to file and loaded from file via menu
- #676 - Keyboard shortcuts added for 'Save and close' (Alt+S), 'Close'
(Alt+W), and 'Close and cancel tasks' (Alt+C)
- #1189 - Editor opens sized to image. Can be disabled via Greenshot ini
with `MatchSizeToCapture=False`
This commit is contained in:
Brian 2016-03-13 12:07:53 -04:00
parent beadb58dcf
commit ee88e25b2f
166 changed files with 5825 additions and 2044 deletions

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -23,15 +23,17 @@
using Greenshot.Plugin;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace GreenshotPlugin.Core
{
public enum ClipboardFormat
{
PNG, DIB, HTML, HTMLDATAURL, BITMAP
PNG, DIB, HTML, HTMLDATAURL, BITMAP, DIBV5
}
public enum OutputFormat
{
@ -62,8 +64,10 @@ public enum ClickActions
/// Description of CoreConfiguration.
/// </summary>
[IniSection("Core", Description = "Greenshot core configuration")]
public class CoreConfiguration : IniSection
public class CoreConfiguration : IniSection, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")]
public string Language;
@ -118,8 +122,10 @@ public class CoreConfiguration : IniSection
public OutputFormat OutputFileFormat = OutputFormat.png;
[IniProperty("OutputFileReduceColors", Description = "If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue = "false")]
public bool OutputFileReduceColors;
[IniProperty("OutputFileAutoReduceColors", Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "true")]
[IniProperty("OutputFileAutoReduceColors", Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "false")]
public bool OutputFileAutoReduceColors;
[IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")]
public int OutputFileReduceColorsTo;
[IniProperty("OutputFileCopyPathToClipboard", Description = "When saving a screenshot, copy the path to the clipboard?", DefaultValue = "true")]
public bool OutputFileCopyPathToClipboard;
@ -172,7 +178,7 @@ public class CoreConfiguration : IniSection
public List<string> IncludePlugins;
[IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")]
public List<string> ExcludePlugins;
[IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.", DefaultValue = "OneNote")]
[IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")]
public List<string> ExcludeDestinations;
[IniProperty("UpdateCheckInterval", Description = "How many days between every update check? (0=no checks)", DefaultValue = "1")]
@ -192,9 +198,9 @@ public class CoreConfiguration : IniSection
[IniProperty("ThumnailPreview", Description = "Enable/disable thumbnail previews", DefaultValue = "True")]
public bool ThumnailPreview;
[IniProperty("NoGDICaptureForProduct", Description = "List of products for which GDI capturing doesn't work.", DefaultValue = "IntelliJ,IDEA")]
[IniProperty("NoGDICaptureForProduct", Description = "List of productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")]
public List<string> NoGDICaptureForProduct;
[IniProperty("NoDWMCaptureForProduct", Description = "List of products for which DWM capturing doesn't work.", DefaultValue = "Citrix,ICA,Client")]
[IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")]
public List<string> NoDWMCaptureForProduct;
[IniProperty("OptimizeForRDP", Description = "Make some optimizations for usage with remote desktop", DefaultValue = "False")]
@ -234,6 +240,8 @@ public class CoreConfiguration : IniSection
[IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")]
public bool ZoomerEnabled;
[IniProperty("ZoomerOpacity", Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", DefaultValue = "1")]
public float ZoomerOpacity;
[IniProperty("MaxMenuItemLength", Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")]
public int MaxMenuItemLength;
@ -245,8 +253,98 @@ public class CoreConfiguration : IniSection
[IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
public string MailApiBCC;
// Specifies what THIS build is
public BuildStates BuildState = BuildStates.UNSTABLE;
[IniProperty("OptimizePNGCommand", Description = "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", DefaultValue = "")]
public string OptimizePNGCommand;
[IniProperty("OptimizePNGCommandArguments", Description = "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", DefaultValue = "\"{0}\"")]
public string OptimizePNGCommandArguments;
[IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")]
public string LastSaveWithVersion;
[IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", DefaultValue = "True")]
public bool ProcessEXIFOrientation;
[IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")]
public Rectangle LastCapturedRegion;
private Size _iconSize;
[IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")]
public Size IconSize
{
get
{
return _iconSize;
}
set
{
Size newSize = value;
if (newSize != Size.Empty)
{
if (newSize.Width < 16)
{
newSize.Width = 16;
}
else if (newSize.Width > 256)
{
newSize.Width = 256;
}
newSize.Width = (newSize.Width / 16) * 16;
if (newSize.Height < 16)
{
newSize.Height = 16;
}
else if (IconSize.Height > 256)
{
newSize.Height = 256;
}
newSize.Height = (newSize.Height / 16) * 16;
}
if (_iconSize != newSize)
{
_iconSize = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IconSize"));
}
}
}
}
[IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")]
public int WebRequestTimeout;
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
public int WebRequestReadWriteTimeout;
/// <summary>
/// Specifies what THIS build is
/// </summary>
public BuildStates BuildState
{
get
{
string informationalVersion = Application.ProductVersion;
if (informationalVersion != null)
{
if (informationalVersion.ToLowerInvariant().Contains("-rc"))
{
return BuildStates.RELEASE_CANDIDATE;
}
if (informationalVersion.ToLowerInvariant().Contains("-unstable"))
{
return BuildStates.UNSTABLE;
}
}
return BuildStates.RELEASE;
}
}
public bool UseLargeIcons
{
get
{
return IconSize.Width >= 32 || IconSize.Height >= 32;
}
}
/// <summary>
/// A helper method which returns true if the supplied experimental feature is enabled
@ -353,6 +451,21 @@ public override string PreCheckValue(string propertyName, string propertyValue)
return base.PreCheckValue(propertyName, propertyValue);
}
/// <summary>
/// This method will be called before writing the configuration
/// </summary>
public override void BeforeSave()
{
try
{
// Store version, this can be used later to fix settings after an update
LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
}
catch
{
}
}
/// <summary>
/// This method will be called after reading the configuration, so eventually some corrections can be made
/// </summary>
@ -361,6 +474,34 @@ public override void AfterLoad()
// Comment with releases
// CheckForUnstable = true;
if (string.IsNullOrEmpty(LastSaveWithVersion))
{
try
{
// Store version, this can be used later to fix settings after an update
LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
}
catch
{
}
// Disable the AutoReduceColors as it causes issues with Mozzila applications and some others
OutputFileAutoReduceColors = false;
}
// Enable OneNote if upgrading from 1.1
if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote"))
{
if (LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1"))
{
ExcludeDestinations.Remove("OneNote");
}
else
{
// TODO: Remove with the release
ExcludeDestinations.Remove("OneNote");
}
}
if (OutputDestinations == null)
{
OutputDestinations = new List<string>();
@ -391,11 +532,12 @@ public override void AfterLoad()
if (NoGDICaptureForProduct != null)
{
// Fix error in configuration
if (NoGDICaptureForProduct.Count == 1)
if (NoGDICaptureForProduct.Count >= 2)
{
if ("intellij idea".Equals(NoGDICaptureForProduct[0]))
if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1]))
{
NoGDICaptureForProduct[0] = "intellij,idea";
NoGDICaptureForProduct.RemoveRange(0, 2);
NoGDICaptureForProduct.Add("Intellij Idea");
IsDirty = true;
}
}
@ -407,11 +549,12 @@ public override void AfterLoad()
if (NoDWMCaptureForProduct != null)
{
// Fix error in configuration
if (NoDWMCaptureForProduct.Count == 1)
if (NoDWMCaptureForProduct.Count >= 3)
{
if ("citrix ica client".Equals(NoDWMCaptureForProduct[0]))
if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2]))
{
NoDWMCaptureForProduct[0] = "citrix,ica,client";
NoDWMCaptureForProduct.RemoveRange(0, 3);
NoDWMCaptureForProduct.Add("Citrix ICA Client");
IsDirty = true;
}
}
@ -429,6 +572,23 @@ public override void AfterLoad()
{
AutoCropDifference = 255;
}
if (OutputFileReduceColorsTo < 2)
{
OutputFileReduceColorsTo = 2;
}
if (OutputFileReduceColorsTo > 256)
{
OutputFileReduceColorsTo = 256;
}
if (WebRequestTimeout <= 10)
{
WebRequestTimeout = 100;
}
if (WebRequestReadWriteTimeout < 1)
{
WebRequestReadWriteTimeout = 100;
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Greenshot.Core;
using Greenshot.Drawing.Fields;
using Greenshot.IniFile;
using GreenshotPlugin.UnmanagedHelpers;
@ -50,16 +51,30 @@ public class EditorConfiguration : IniSection
public Point WindowMinPosition;
[IniProperty("WindowMaxPosition", Description = "Position of maximized window", DefaultValue = "-1,-1")]
public Point WindowMaxPosition;
[IniProperty("WindowNormalPosition", Description = "Position of normal window", DefaultValue = "100,100,600,500")]
[IniProperty("WindowNormalPosition", Description = "Position of normal window", DefaultValue = "100,100,400,400")]
public Rectangle WindowNormalPosition;
[IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")]
public bool ReuseEditor;
[IniProperty("FreehandSensitivity", Description = "The smaller this number, the less smoothing is used. Decrease for detailed drawing, e.g. when using a pen. Increase for smoother lines. e.g. when you want to draw a smooth line.", DefaultValue = "3")]
public int FreehandSensitivity;
[IniProperty("SuppressSaveDialogAtClose", Description = "Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue = "False")]
public bool SuppressSaveDialogAtClose;
[IniProperty("DropShadowEffectSettings", Description = "Settings for the drop shadow effect.")]
public DropShadowEffect DropShadowEffectSettings;
[IniProperty("TornEdgeEffectSettings", Description = "Settings for the torn edge effect.")]
public TornEdgeEffect TornEdgeEffectSettings;
public override void AfterLoad()
{
base.AfterLoad();
if (RecentColors == null)
{
RecentColors = new List<Color>();
}
}
/// <param name="requestingType">Type of the class for which to create the field</param>
/// <param name="fieldType">FieldType of the field to construct</param>
/// <param name="scope">FieldType of the field to construct</param>

View file

@ -1,141 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.UnmanagedHelpers;
using System;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Extend this Form to have the possibility for animations on your form
/// </summary>
internal class AnimatingForm : GreenshotForm
{
private const int DEFAULT_VREFRESH = 60;
private int vRefresh = 0;
private Timer timer = null;
/// <summary>
/// This flag specifies if any animation is used
/// </summary>
protected bool EnableAnimation
{
get;
set;
}
/// <summary>
/// Vertical Refresh Rate
/// </summary>
protected int VRefresh
{
get
{
if (vRefresh == 0)
{
// get te hDC of the desktop to get the VREFRESH
using (SafeWindowDCHandle desktopHandle = SafeWindowDCHandle.fromDesktop())
{
vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
}
}
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
// As there is currently no know way to get the default, we guess it.
if (vRefresh <= 1)
{
vRefresh = DEFAULT_VREFRESH;
}
return vRefresh;
}
}
/// <summary>
/// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections
/// </summary>
protected bool isTerminalServerSession
{
get
{
return coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession;
}
}
/// <summary>
/// Calculate the amount of frames that an animation takes
/// </summary>
/// <param name="milliseconds"></param>
/// <returns>Number of frames, 1 if in Terminal Server Session</returns>
protected int FramesForMillis(int milliseconds)
{
// If we are in a Terminal Server Session we return 1
if (isTerminalServerSession)
{
return 1;
}
return milliseconds / VRefresh;
}
/// <summary>
/// Initialize the animation
/// </summary>
protected AnimatingForm()
{
Load += delegate
{
if (EnableAnimation)
{
timer = new Timer();
timer.Interval = 1000 / VRefresh;
timer.Tick += timer_Tick;
timer.Start();
}
};
// Unregister at close
FormClosing += delegate
{
if (timer != null)
{
timer.Stop();
}
};
}
/// <summary>
/// The tick handler initiates the animation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
Animate();
}
/// <summary>
/// This method will be called every frame, so implement your animation/redraw logic here.
/// </summary>
protected virtual void Animate()
{
throw new NotImplementedException();
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -43,7 +43,7 @@ public static BackgroundForm ShowAndWait(string title, string text)
{
BackgroundForm backgroundForm = new BackgroundForm(title, text);
// Show form in background thread
Thread backgroundTask = new Thread(backgroundForm.BackgroundShowDialog);
Thread backgroundTask = new Thread(new ThreadStart(backgroundForm.BackgroundShowDialog));
backgroundForm.Name = "Background form";
backgroundTask.IsBackground = true;
backgroundTask.SetApartmentState(ApartmentState.STA);

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -40,8 +40,7 @@ public string LanguageKey
set;
}
public BindableToolStripButton()
: base()
public BindableToolStripButton() : base()
{
CheckedChanged += BindableToolStripButton_CheckedChanged;
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -40,8 +40,7 @@ public string LanguageKey
set;
}
public BindableToolStripComboBox()
: base()
public BindableToolStripComboBox() : base()
{
SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -27,7 +27,7 @@ namespace Greenshot.Controls
{
/// <summary>
/// A simple ToolStripDropDownButton implementing INotifyPropertyChanged for data binding.
/// Also, when a DropDownItem is selected, the DropDownButton adops its Tag and Image.
/// Also, when a DropDownItem is selected, the DropDownButton adopts its Tag and Image.
/// The selected tag can be accessed via SelectedTag property.
/// </summary>
internal class BindableToolStripDropDownButton : ToolStripDropDownButton, INotifyPropertyChanged, IGreenshotLanguageBindable

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -0,0 +1,79 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Windows.Forms;
namespace Greenshot.Controls
{
/// <summary>
/// Prevent having a gradient background in the toolstrip, and the overflow button
/// See: http://stackoverflow.com/a/16926979
/// </summary>
internal class CustomProfessionalColorTable : ProfessionalColorTable
{
public override Color ToolStripGradientBegin
{
get { return SystemColors.Control; }
}
public override Color ToolStripGradientMiddle
{
get { return SystemColors.Control; }
}
public override Color ToolStripGradientEnd
{
get { return SystemColors.Control; }
}
public override Color OverflowButtonGradientBegin
{
get { return SystemColors.Control; }
}
public override Color OverflowButtonGradientMiddle
{
get { return SystemColors.Control; }
}
public override Color OverflowButtonGradientEnd
{
get { return SystemColors.Control; }
}
}
/// <summary>
/// ToolStripProfessionalRenderer without having a visual artifact
/// See: http://stackoverflow.com/a/16926979 and http://stackoverflow.com/a/13418840
/// </summary>
internal class CustomToolStripProfessionalRenderer : ToolStripProfessionalRenderer
{
public CustomToolStripProfessionalRenderer() : base(new CustomProfessionalColorTable())
{
RoundedEdges = false;
}
/// <summary>
/// By overriding the OnRenderToolStripBorder we can make the ToolStrip without border
/// </summary>
/// <param name="e"></param>
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
// Don't draw a border
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -49,8 +49,7 @@ public FontFamily FontFamily
}
}
public FontFamilyComboBox()
: base()
public FontFamilyComboBox() : base()
{
ComboBox.DataSource = FontFamily.Families;
ComboBox.DisplayMember = "Name";
@ -69,40 +68,61 @@ private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
if (e.Index > -1)
{
FontFamily fontFamily = Items[e.Index] as FontFamily;
FontStyle fs = FontStyle.Regular;
FontStyle fontStyle = FontStyle.Regular;
if (!fontFamily.IsStyleAvailable(FontStyle.Regular))
{
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
{
fs = FontStyle.Bold;
fontStyle = FontStyle.Bold;
}
else if (fontFamily.IsStyleAvailable(FontStyle.Italic))
{
fs = FontStyle.Italic;
fontStyle = FontStyle.Italic;
}
else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout))
{
fs = FontStyle.Strikeout;
fontStyle = FontStyle.Strikeout;
}
else if (fontFamily.IsStyleAvailable(FontStyle.Underline))
{
fs = FontStyle.Underline;
fontStyle = FontStyle.Underline;
}
}
using (Font font = new Font(fontFamily, this.Font.Size + 5, fs, GraphicsUnit.Pixel))
try
{
// Make sure the text is visible by centering it in the line
using (StringFormat stringFormat = new StringFormat())
{
stringFormat.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(fontFamily.Name, font, Brushes.Black, e.Bounds, stringFormat);
}
DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name);
}
catch
{
// If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular'
DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name);
}
}
// Uncomment this if you actually like the way the focus rectangle looks
//e.DrawFocusRectangle ();
}
/// <summary>
/// Helper method to draw the string
/// </summary>
/// <param name="graphics"></param>
/// <param name="fontFamily"></param>
/// <param name="fontStyle"></param>
/// <param name="bounds"></param>
/// <param name="text"></param>
private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text)
{
using (Font font = new Font(fontFamily, this.Font.Size + 5, fontStyle, GraphicsUnit.Pixel))
{
// Make sure the text is visible by centering it in the line
using (StringFormat stringFormat = new StringFormat())
{
stringFormat.LineAlignment = StringAlignment.Center;
graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
}
}
}
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (PropertyChanged != null)

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -38,9 +38,9 @@ public class GreenshotForm : Form, IGreenshotLanguageBindable
protected static CoreConfiguration coreConfiguration;
private static IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
private IComponentChangeService m_changeService;
private bool storeFieldsManually = false;
private IDictionary<string, Control> designTimeControls;
private IDictionary<string, ToolStripItem> designTimeToolStripItems;
private bool _storeFieldsManually = false;
private IDictionary<string, Control> _designTimeControls;
private IDictionary<string, ToolStripItem> _designTimeToolStripItems;
static GreenshotForm()
{
@ -73,14 +73,23 @@ protected bool ManualStoreFields
{
get
{
return storeFieldsManually;
return _storeFieldsManually;
}
set
{
storeFieldsManually = value;
_storeFieldsManually = value;
}
}
/// <summary>
/// When this is set, the form will be brought to the foreground as soon as it is shown.
/// </summary>
protected bool ToFront
{
get;
set;
}
/// <summary>
/// Code to initialize the language etc during design time
/// </summary>
@ -88,13 +97,16 @@ protected void InitializeForDesigner()
{
if (DesignMode)
{
designTimeControls = new Dictionary<string, Control>();
designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
_designTimeControls = new Dictionary<string, Control>();
_designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
}
}
protected override void OnLoad(EventArgs e)
{
// Every GreenshotForm should have it's default icon
// And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important
Icon = GreenshotResources.getGreenshotIcon();
if (!DesignMode)
{
FillFields();
@ -108,13 +120,26 @@ protected override void OnLoad(EventArgs e)
}
}
/// <summary>
/// Make sure the form is visible, if this is wanted
/// </summary>
/// <param name="e">EventArgs</param>
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
if (ToFront)
{
WindowDetails.ToForeground(Handle);
}
}
/// <summary>
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
/// </summary>
/// <param name="e"></param>
protected override void OnClosed(EventArgs e)
{
if (!DesignMode && !storeFieldsManually)
if (!DesignMode && !_storeFieldsManually)
{
if (DialogResult == DialogResult.OK)
{
@ -159,7 +184,7 @@ private void ClearChangeNotifications()
// Clear our the component change events to prepare for re-siting.
if (m_changeService != null)
{
m_changeService.ComponentAdded -= OnComponentAdded;
m_changeService.ComponentAdded -= new ComponentEventHandler(OnComponentAdded);
}
}
@ -168,7 +193,7 @@ private void RegisterChangeNotifications()
// Register the event handlers for the IComponentChangeService events
if (m_changeService != null)
{
m_changeService.ComponentAdded += OnComponentAdded;
m_changeService.ComponentAdded += new ComponentEventHandler(OnComponentAdded);
}
}
@ -179,25 +204,25 @@ private void OnComponentAdded(object sender, ComponentEventArgs ce)
Control control = ce.Component as Control;
if (control != null)
{
if (!designTimeControls.ContainsKey(control.Name))
if (!_designTimeControls.ContainsKey(control.Name))
{
designTimeControls.Add(control.Name, control);
_designTimeControls.Add(control.Name, control);
}
else
{
designTimeControls[control.Name] = control;
_designTimeControls[control.Name] = control;
}
}
else if (ce.Component is ToolStripItem)
{
ToolStripItem item = ce.Component as ToolStripItem;
if (!designTimeControls.ContainsKey(item.Name))
if (!_designTimeControls.ContainsKey(item.Name))
{
designTimeToolStripItems.Add(item.Name, item);
_designTimeToolStripItems.Add(item.Name, item);
}
else
{
designTimeToolStripItems[item.Name] = item;
_designTimeToolStripItems[item.Name] = item;
}
}
}
@ -254,7 +279,7 @@ protected void FillFields()
IniValue iniValue = null;
if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue))
{
LOG.WarnFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name);
LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name);
continue;
}
@ -276,6 +301,17 @@ protected void FillFields()
TextBox textBox = controlObject as TextBox;
if (textBox != null)
{
HotkeyControl hotkeyControl = controlObject as HotkeyControl;
if (hotkeyControl != null)
{
string hotkeyValue = (string)iniValue.Value;
if (!string.IsNullOrEmpty(hotkeyValue))
{
hotkeyControl.SetHotkey(hotkeyValue);
hotkeyControl.Enabled = !iniValue.IsFixed;
}
continue;
}
textBox.Text = iniValue.ToString();
textBox.Enabled = !iniValue.IsFixed;
continue;
@ -345,6 +381,13 @@ protected void StoreFields()
TextBox textBox = controlObject as TextBox;
if (textBox != null)
{
HotkeyControl hotkeyControl = controlObject as HotkeyControl;
if (hotkeyControl != null)
{
iniValue.Value = hotkeyControl.ToString();
iniDirty = true;
continue;
}
iniValue.UseValueOrDefault(textBox.Text);
iniDirty = true;
continue;

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -0,0 +1,709 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.Plugin;
using GreenshotPlugin.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// A simple control that allows the user to select pretty much any valid hotkey combination
/// See: http://www.codeproject.com/KB/buttons/hotkeycontrol.aspx
/// But is modified to fit in Greenshot, and have localized support
/// </summary>
internal class HotkeyControl : GreenshotTextBox
{
private static EventDelay eventDelay = new EventDelay(TimeSpan.FromMilliseconds(600).Ticks);
private static bool isWindows7OrOlder = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1;
// Holds the list of hotkeys
private static Dictionary<int, HotKeyHandler> keyHandlers = new Dictionary<int, HotKeyHandler>();
private static int hotKeyCounter = 1;
private const uint WM_HOTKEY = 0x312;
private static IntPtr hotkeyHWND;
// static HotkeyControl() {
// StringBuilder keyName = new StringBuilder();
// for(uint sc = 0; sc < 500; sc++) {
// if (GetKeyNameText(sc << 16, keyName, 100) != 0) {
// LOG.DebugFormat("SC {0} = {1}", sc, keyName);
// }
// }
// }
public enum Modifiers : uint
{
NONE = 0,
ALT = 1,
CTRL = 2,
SHIFT = 4,
WIN = 8,
NO_REPEAT = 0x4000
}
private enum MapType : uint
{
MAPVK_VK_TO_VSC = 0, //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0.
MAPVK_VSC_TO_VK = 1, //The uCode parameter is a scan code and is translated into a virtual-key code that does not distinguish between left- and right-hand keys. If there is no translation, the function returns 0.
MAPVK_VK_TO_CHAR = 2, //The uCode parameter is a virtual-key code and is translated into an unshifted character value in the low order word of the return value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, the function returns 0.
MAPVK_VSC_TO_VK_EX = 3, //The uCode parameter is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand keys. If there is no translation, the function returns 0.
MAPVK_VK_TO_VSC_EX = 4 //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If the scan code is an extended scan code, the high byte of the uCode value can contain either 0xe0 or 0xe1 to specify the extended scan code. If there is no translation, the function returns 0.
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
// These variables store the current hotkey and modifier(s)
private Keys _hotkey = Keys.None;
private Keys _modifiers = Keys.None;
// ArrayLists used to enforce the use of proper modifiers.
// Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing.
private ArrayList needNonShiftModifier = null;
private ArrayList needNonAltGrModifier = null;
private ContextMenu dummy = new ContextMenu();
/// <summary>
/// Used to make sure that there is no right-click menu available
/// </summary>
public override ContextMenu ContextMenu
{
get
{
return dummy;
}
set
{
base.ContextMenu = dummy;
}
}
/// <summary>
/// Forces the control to be non-multiline
/// </summary>
public override bool Multiline
{
get
{
return base.Multiline;
}
set
{
// Ignore what the user wants; force Multiline to false
base.Multiline = false;
}
}
/// <summary>
/// Creates a new HotkeyControl
/// </summary>
public HotkeyControl()
{
ContextMenu = dummy; // Disable right-clicking
Text = "None";
// Handle events that occurs when keys are pressed
KeyPress += new KeyPressEventHandler(HotkeyControl_KeyPress);
KeyUp += new KeyEventHandler(HotkeyControl_KeyUp);
KeyDown += new KeyEventHandler(HotkeyControl_KeyDown);
// Fill the ArrayLists that contain all invalid hotkey combinations
needNonShiftModifier = new ArrayList();
needNonAltGrModifier = new ArrayList();
PopulateModifierLists();
}
/// <summary>
/// Populates the ArrayLists specifying disallowed hotkeys
/// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc
/// </summary>
private void PopulateModifierLists()
{
// Shift + 0 - 9, A - Z
for (Keys k = Keys.D0; k <= Keys.Z; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Numpad keys
for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Misc (,;<./ etc)
for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Space, PgUp, PgDn, End, Home
for (Keys k = Keys.Space; k <= Keys.Home; k++)
{
needNonShiftModifier.Add((int)k);
}
// Misc keys that we can't loop through
needNonShiftModifier.Add((int)Keys.Insert);
needNonShiftModifier.Add((int)Keys.Help);
needNonShiftModifier.Add((int)Keys.Multiply);
needNonShiftModifier.Add((int)Keys.Add);
needNonShiftModifier.Add((int)Keys.Subtract);
needNonShiftModifier.Add((int)Keys.Divide);
needNonShiftModifier.Add((int)Keys.Decimal);
needNonShiftModifier.Add((int)Keys.Return);
needNonShiftModifier.Add((int)Keys.Escape);
needNonShiftModifier.Add((int)Keys.NumLock);
needNonShiftModifier.Add((int)Keys.Scroll);
needNonShiftModifier.Add((int)Keys.Pause);
// Ctrl+Alt + 0 - 9
for (Keys k = Keys.D0; k <= Keys.D9; k++)
{
needNonAltGrModifier.Add((int)k);
}
}
/// <summary>
/// Resets this hotkey control to None
/// </summary>
public new void Clear()
{
Hotkey = Keys.None;
HotkeyModifiers = Keys.None;
}
/// <summary>
/// Fires when a key is pushed down. Here, we'll want to update the text in the box
/// to notify the user what combination is currently pressed.
/// </summary>
private void HotkeyControl_KeyDown(object sender, KeyEventArgs e)
{
// Clear the current hotkey
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
{
ResetHotkey();
return;
}
else
{
_modifiers = e.Modifiers;
_hotkey = e.KeyCode;
Redraw();
}
}
/// <summary>
/// Fires when all keys are released. If the current hotkey isn't valid, reset it.
/// Otherwise, do nothing and keep the text and hotkey as it was.
/// </summary>
private void HotkeyControl_KeyUp(object sender, KeyEventArgs e)
{
// Somehow the PrintScreen only comes as a keyup, therefore we handle it here.
if (e.KeyCode == Keys.PrintScreen)
{
_modifiers = e.Modifiers;
_hotkey = e.KeyCode;
Redraw();
}
if (_hotkey == Keys.None && ModifierKeys == Keys.None)
{
ResetHotkey();
return;
}
}
/// <summary>
/// Prevents the letter/whatever entered to show up in the TextBox
/// Without this, a "A" key press would appear as "aControl, Alt + A"
/// </summary>
private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
/// <summary>
/// Handles some misc keys, such as Ctrl+Delete and Shift+Insert
/// </summary>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete))
{
ResetHotkey();
return true;
}
// Paste
if (keyData == (Keys.Shift | Keys.Insert))
{
return true; // Don't allow
}
// Allow the rest
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// Clears the current hotkey and resets the TextBox
/// </summary>
public void ResetHotkey()
{
_hotkey = Keys.None;
_modifiers = Keys.None;
Redraw();
}
/// <summary>
/// Used to get/set the hotkey (e.g. Keys.A)
/// </summary>
public Keys Hotkey
{
get
{
return _hotkey;
}
set
{
_hotkey = value;
Redraw(true);
}
}
/// <summary>
/// Used to get/set the hotkey (e.g. Keys.A)
/// </summary>
public void SetHotkey(string hotkey)
{
_hotkey = HotkeyFromString(hotkey);
_modifiers = HotkeyModifiersFromString(hotkey);
Redraw(true);
}
/// <summary>
/// Used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control)
/// </summary>
public Keys HotkeyModifiers
{
get
{
return _modifiers;
}
set
{
_modifiers = value;
Redraw(true);
}
}
/// <summary>
/// Helper function
/// </summary>
private void Redraw()
{
Redraw(false);
}
/// <summary>
/// Redraws the TextBox when necessary.
/// </summary>
/// <param name="bCalledProgramatically">Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.</param>
private void Redraw(bool bCalledProgramatically)
{
// No hotkey set
if (_hotkey == Keys.None)
{
Text = "";
return;
}
// LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0)
if (_hotkey == Keys.LWin || _hotkey == Keys.RWin)
{
Text = "";
return;
}
// Only validate input if it comes from the user
if (bCalledProgramatically == false)
{
// No modifier or shift only, AND a hotkey that needs another modifier
if ((_modifiers == Keys.Shift || _modifiers == Keys.None) && needNonShiftModifier.Contains((int)_hotkey))
{
if (_modifiers == Keys.None)
{
// Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work...
if (needNonAltGrModifier.Contains((int)_hotkey) == false)
{
_modifiers = Keys.Alt | Keys.Control;
}
else
{
// ... in that case, use Shift+Alt instead.
_modifiers = Keys.Alt | Keys.Shift;
}
}
else
{
// User pressed Shift and an invalid key (e.g. a letter or a number),
// that needs another set of modifier keys
_hotkey = Keys.None;
Text = "";
return;
}
}
// Check all Ctrl+Alt keys
if ((_modifiers == (Keys.Alt | Keys.Control)) && needNonAltGrModifier.Contains((int)_hotkey))
{
// Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
_hotkey = Keys.None;
Text = "";
return;
}
}
// I have no idea why this is needed, but it is. Without this code, pressing only Ctrl
// will show up as "Control + ControlKey", etc.
if (_hotkey == Keys.Menu /* Alt */ || _hotkey == Keys.ShiftKey || _hotkey == Keys.ControlKey)
{
_hotkey = Keys.None;
}
Text = HotkeyToLocalizedString(_modifiers, _hotkey);
}
public override string ToString()
{
return HotkeyToString(HotkeyModifiers, Hotkey);
}
public static string GetLocalizedHotkeyStringFromString(string hotkeyString)
{
Keys virtualKeyCode = HotkeyFromString(hotkeyString);
Keys modifiers = HotkeyModifiersFromString(hotkeyString);
return HotkeyToLocalizedString(modifiers, virtualKeyCode);
}
public static string HotkeyToString(Keys modifierKeyCode, Keys virtualKeyCode)
{
return HotkeyModifiersToString(modifierKeyCode) + virtualKeyCode.ToString();
}
public static string HotkeyModifiersToString(Keys modifierKeyCode)
{
StringBuilder hotkeyString = new StringBuilder();
if ((modifierKeyCode & Keys.Alt) > 0)
{
hotkeyString.Append("Alt").Append(" + ");
}
if ((modifierKeyCode & Keys.Control) > 0)
{
hotkeyString.Append("Ctrl").Append(" + ");
}
if ((modifierKeyCode & Keys.Shift) > 0)
{
hotkeyString.Append("Shift").Append(" + ");
}
if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin)
{
hotkeyString.Append("Win").Append(" + ");
}
return hotkeyString.ToString();
}
public static string HotkeyToLocalizedString(Keys modifierKeyCode, Keys virtualKeyCode)
{
return HotkeyModifiersToLocalizedString(modifierKeyCode) + GetKeyName(virtualKeyCode);
}
public static string HotkeyModifiersToLocalizedString(Keys modifierKeyCode)
{
StringBuilder hotkeyString = new StringBuilder();
if ((modifierKeyCode & Keys.Alt) > 0)
{
hotkeyString.Append(GetKeyName(Keys.Alt)).Append(" + ");
}
if ((modifierKeyCode & Keys.Control) > 0)
{
hotkeyString.Append(GetKeyName(Keys.Control)).Append(" + ");
}
if ((modifierKeyCode & Keys.Shift) > 0)
{
hotkeyString.Append(GetKeyName(Keys.Shift)).Append(" + ");
}
if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin)
{
hotkeyString.Append("Win").Append(" + ");
}
return hotkeyString.ToString();
}
public static Keys HotkeyModifiersFromString(string modifiersString)
{
Keys modifiers = Keys.None;
if (!string.IsNullOrEmpty(modifiersString))
{
if (modifiersString.ToLower().Contains("alt"))
{
modifiers |= Keys.Alt;
}
if (modifiersString.ToLower().Contains("ctrl"))
{
modifiers |= Keys.Control;
}
if (modifiersString.ToLower().Contains("shift"))
{
modifiers |= Keys.Shift;
}
if (modifiersString.ToLower().Contains("win"))
{
modifiers |= Keys.LWin;
}
}
return modifiers;
}
public static Keys HotkeyFromString(string hotkey)
{
Keys key = Keys.None;
if (!string.IsNullOrEmpty(hotkey))
{
if (hotkey.LastIndexOf('+') > 0)
{
hotkey = hotkey.Remove(0, hotkey.LastIndexOf('+') + 1).Trim();
}
key = (Keys)Keys.Parse(typeof(Keys), hotkey);
}
return key;
}
public static void RegisterHotkeyHWND(IntPtr hWnd)
{
hotkeyHWND = hWnd;
}
public static int RegisterHotKey(string hotkey, HotKeyHandler handler)
{
return RegisterHotKey(HotkeyModifiersFromString(hotkey), HotkeyFromString(hotkey), handler);
}
/// <summary>
/// Register a hotkey
/// </summary>
/// <param name="hWnd">The window which will get the event</param>
/// <param name="modifierKeyCode">The modifier, e.g.: Modifiers.CTRL, Modifiers.NONE or Modifiers.ALT</param>
/// <param name="virtualKeyCode">The virtual key code</param>
/// <param name="handler">A HotKeyHandler, this will be called to handle the hotkey press</param>
/// <returns>the hotkey number, -1 if failed</returns>
public static int RegisterHotKey(Keys modifierKeyCode, Keys virtualKeyCode, HotKeyHandler handler)
{
if (virtualKeyCode == Keys.None)
{
LOG.Warn("Trying to register a Keys.none hotkey, ignoring");
return 0;
}
// Convert Modifiers to fit HKM_SETHOTKEY
uint modifiers = 0;
if ((modifierKeyCode & Keys.Alt) > 0)
{
modifiers |= (uint)Modifiers.ALT;
}
if ((modifierKeyCode & Keys.Control) > 0)
{
modifiers |= (uint)Modifiers.CTRL;
}
if ((modifierKeyCode & Keys.Shift) > 0)
{
modifiers |= (uint)Modifiers.SHIFT;
}
if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin)
{
modifiers |= (uint)Modifiers.WIN;
}
// Disable repeating hotkey for Windows 7 and beyond, as described in #1559
if (isWindows7OrOlder)
{
modifiers |= (uint)Modifiers.NO_REPEAT;
}
if (RegisterHotKey(hotkeyHWND, hotKeyCounter, modifiers, (uint)virtualKeyCode))
{
keyHandlers.Add(hotKeyCounter, handler);
return hotKeyCounter++;
}
else
{
LOG.Warn(String.Format("Couldn't register hotkey modifier {0} virtualKeyCode {1}", modifierKeyCode, virtualKeyCode));
return -1;
}
}
public static void UnregisterHotkeys()
{
foreach (int hotkey in keyHandlers.Keys)
{
UnregisterHotKey(hotkeyHWND, hotkey);
}
// Remove all key handlers
keyHandlers.Clear();
}
public static void UnregisterHotkey(int hotkey)
{
bool removeHotkey = false;
foreach (int availableHotkey in keyHandlers.Keys)
{
if (availableHotkey == hotkey)
{
UnregisterHotKey(hotkeyHWND, hotkey);
removeHotkey = true;
}
}
if (removeHotkey)
{
// Remove key handler
keyHandlers.Remove(hotkey);
}
}
/// <summary>
/// Handle WndProc messages for the hotkey
/// </summary>
/// <param name="m"></param>
/// <returns>true if the message was handled</returns>
public static bool HandleMessages(ref Message m)
{
if (m.Msg == WM_HOTKEY)
{
// Call handler
if (isWindows7OrOlder)
{
keyHandlers[(int)m.WParam]();
}
else
{
if (eventDelay.Check())
{
keyHandlers[(int)m.WParam]();
}
}
return true;
}
return false;
}
public static string GetKeyName(Keys givenKey)
{
StringBuilder keyName = new StringBuilder();
const uint NUMPAD = 55;
Keys virtualKey = givenKey;
string keyString = "";
// Make VC's to real keys
switch (virtualKey)
{
case Keys.Alt:
virtualKey = Keys.LMenu;
break;
case Keys.Control:
virtualKey = Keys.ControlKey;
break;
case Keys.Shift:
virtualKey = Keys.LShiftKey;
break;
case Keys.Multiply:
GetKeyNameText(NUMPAD << 16, keyName, 100);
keyString = keyName.ToString().Replace("*", "").Trim().ToLower();
if (keyString.IndexOf("(") >= 0)
{
return "* " + keyString;
}
keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower();
return keyString + " *";
case Keys.Divide:
GetKeyNameText(NUMPAD << 16, keyName, 100);
keyString = keyName.ToString().Replace("*", "").Trim().ToLower();
if (keyString.IndexOf("(") >= 0)
{
return "/ " + keyString;
}
keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower();
return keyString + " /";
}
uint scanCode = MapVirtualKey((uint)virtualKey, (uint)MapType.MAPVK_VK_TO_VSC);
// because MapVirtualKey strips the extended bit for some keys
switch (virtualKey)
{
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down: // arrow keys
case Keys.Prior:
case Keys.Next: // page up and page down
case Keys.End:
case Keys.Home:
case Keys.Insert:
case Keys.Delete:
case Keys.NumLock:
LOG.Debug("Modifying Extended bit");
scanCode |= 0x100; // set extended bit
break;
case Keys.PrintScreen: // PrintScreen
scanCode = 311;
break;
case Keys.Pause: // PrintScreen
scanCode = 69;
break;
}
scanCode |= 0x200;
if (GetKeyNameText(scanCode << 16, keyName, 100) != 0)
{
string visibleName = keyName.ToString();
if (visibleName.Length > 1)
{
visibleName = visibleName.Substring(0, 1) + visibleName.Substring(1).ToLower();
}
return visibleName;
}
else
{
return givenKey.ToString();
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -18,85 +18,90 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class PleaseWaitForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
namespace GreenshotPlugin.Controls {
partial class PleaseWaitForm {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent() {
this.label_pleasewait = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label_pleasewait
//
this.label_pleasewait.AutoSize = true;
this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
this.label_pleasewait.Name = "label_pleasewait";
this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
this.label_pleasewait.TabIndex = 0;
this.label_pleasewait.Text = "Please wait...";
this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.label_pleasewait.UseWaitCursor = true;
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(38, 41);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(94, 23);
this.cancelButton.TabIndex = 1;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.UseWaitCursor = true;
this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
//
// PleaseWaitForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(169, 76);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.label_pleasewait);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "PleaseWaitForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Greenshot";
this.UseWaitCursor = true;
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Label label_pleasewait;
}
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label_pleasewait = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label_pleasewait
//
this.label_pleasewait.AutoSize = true;
this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
this.label_pleasewait.Name = "label_pleasewait";
this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
this.label_pleasewait.TabIndex = 0;
this.label_pleasewait.Text = "Please wait...";
this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.label_pleasewait.UseWaitCursor = true;
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(38, 41);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(94, 23);
this.cancelButton.TabIndex = 1;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.UseWaitCursor = true;
this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
//
// PleaseWaitForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(169, 76);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.label_pleasewait);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "PleaseWaitForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Greenshot";
this.UseWaitCursor = true;
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Label label_pleasewait;
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -45,13 +45,13 @@ public QualityDialog(SurfaceOutputSettings outputSettings)
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
Icon = GreenshotResources.getGreenshotIcon();
checkBox_reduceColors.Checked = Settings.ReduceColors;
trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
trackBarJpegQuality.Value = Settings.JPGQuality;
textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
ToFront = true;
}
private void Button_okClick(object sender, EventArgs e)

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -18,132 +18,135 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class QualityDialog
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
namespace GreenshotPlugin.Controls {
partial class QualityDialog {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
this.SuspendLayout();
//
// label_choosejpegquality
//
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
this.SuspendLayout();
//
// label_choosejpegquality
//
this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47);
this.label_choosejpegquality.Name = "label_choosejpegquality";
this.label_choosejpegquality.Name = "label_choosejpegquality";
this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19);
this.label_choosejpegquality.TabIndex = 15;
this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality";
//
// textBoxJpegQuality
//
this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69);
this.textBoxJpegQuality.Name = "textBoxJpegQuality";
this.textBoxJpegQuality.ReadOnly = true;
this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20);
this.textBoxJpegQuality.TabIndex = 16;
this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// trackBarJpegQuality
//
this.trackBarJpegQuality.LargeChange = 10;
this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69);
this.trackBarJpegQuality.Maximum = 100;
this.trackBarJpegQuality.Name = "trackBarJpegQuality";
this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45);
this.trackBarJpegQuality.TabIndex = 14;
this.trackBarJpegQuality.TickFrequency = 10;
this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll);
//
// checkbox_dontaskagain
//
this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106);
this.checkbox_dontaskagain.Name = "checkbox_dontaskagain";
this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain";
this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37);
this.checkbox_dontaskagain.TabIndex = 17;
this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.UseVisualStyleBackColor = true;
//
// button_ok
//
this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button_ok.Location = new System.Drawing.Point(205, 149);
this.button_ok.Name = "button_ok";
this.button_ok.Size = new System.Drawing.Size(75, 23);
this.button_ok.TabIndex = 18;
this.button_ok.LanguageKey = "OK";
this.button_ok.UseVisualStyleBackColor = true;
this.button_ok.Click += new System.EventHandler(this.Button_okClick);
//
// checkBox_reduceColors
//
this.checkBox_reduceColors.AutoSize = true;
this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11);
this.checkBox_reduceColors.Name = "checkBox_reduceColors";
this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17);
this.checkBox_reduceColors.TabIndex = 19;
this.checkBox_reduceColors.Text = "settings_reducecolors";
this.checkBox_reduceColors.UseVisualStyleBackColor = true;
//
this.label_choosejpegquality.TabIndex = 15;
this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality";
//
// textBoxJpegQuality
//
this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69);
this.textBoxJpegQuality.Name = "textBoxJpegQuality";
this.textBoxJpegQuality.ReadOnly = true;
this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20);
this.textBoxJpegQuality.TabIndex = 16;
this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// trackBarJpegQuality
//
this.trackBarJpegQuality.LargeChange = 10;
this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69);
this.trackBarJpegQuality.Maximum = 100;
this.trackBarJpegQuality.Name = "trackBarJpegQuality";
this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45);
this.trackBarJpegQuality.TabIndex = 14;
this.trackBarJpegQuality.TickFrequency = 10;
this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll);
//
// checkbox_dontaskagain
//
this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106);
this.checkbox_dontaskagain.Name = "checkbox_dontaskagain";
this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain";
this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37);
this.checkbox_dontaskagain.TabIndex = 17;
this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft;
this.checkbox_dontaskagain.UseVisualStyleBackColor = true;
//
// button_ok
//
this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button_ok.Location = new System.Drawing.Point(205, 149);
this.button_ok.Name = "button_ok";
this.button_ok.Size = new System.Drawing.Size(75, 23);
this.button_ok.TabIndex = 18;
this.button_ok.LanguageKey = "OK";
this.button_ok.UseVisualStyleBackColor = true;
this.button_ok.Click += new System.EventHandler(this.Button_okClick);
//
// checkBox_reduceColors
//
this.checkBox_reduceColors.AutoSize = true;
this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11);
this.checkBox_reduceColors.Name = "checkBox_reduceColors";
this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17);
this.checkBox_reduceColors.TabIndex = 19;
this.checkBox_reduceColors.Text = "settings_reducecolors";
this.checkBox_reduceColors.UseVisualStyleBackColor = true;
//
// QualityDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(299, 184);
this.ControlBox = false;
this.Controls.Add(this.checkBox_reduceColors);
this.Controls.Add(this.button_ok);
this.Controls.Add(this.checkbox_dontaskagain);
this.Controls.Add(this.label_choosejpegquality);
this.Controls.Add(this.textBoxJpegQuality);
this.Controls.Add(this.trackBarJpegQuality);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "QualityDialog";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.LanguageKey = "qualitydialog_title";
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(299, 184);
this.ControlBox = false;
this.Controls.Add(this.checkBox_reduceColors);
this.Controls.Add(this.button_ok);
this.Controls.Add(this.checkbox_dontaskagain);
this.Controls.Add(this.label_choosejpegquality);
this.Controls.Add(this.textBoxJpegQuality);
this.Controls.Add(this.trackBarJpegQuality);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "QualityDialog";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.LanguageKey = "qualitydialog_title";
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
private GreenshotPlugin.Controls.GreenshotButton button_ok;
private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain;
private System.Windows.Forms.TrackBar trackBarJpegQuality;
private System.Windows.Forms.TextBox textBoxJpegQuality;
private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality;
private System.Windows.Forms.CheckBox checkBox_reduceColors;
}
}
private GreenshotPlugin.Controls.GreenshotButton button_ok;
private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain;
private System.Windows.Forms.TrackBar trackBarJpegQuality;
private System.Windows.Forms.TextBox textBoxJpegQuality;
private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality;
private System.Windows.Forms.CheckBox checkBox_reduceColors;
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -104,11 +104,13 @@ private void applyFilterOptions()
prepareFilterOptions();
string fdf = "";
int preselect = 0;
var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat);
for (int i = 0; i < filterOptions.Length; i++)
{
FilterOption fo = filterOptions[i];
fdf += fo.Label + "|*." + fo.Extension + "|";
if (conf.OutputFileAsFullpath.EndsWith(fo.Extension, StringComparison.CurrentCultureIgnoreCase)) preselect = i;
if (outputFileFormatAsString == fo.Extension)
preselect = i;
}
fdf = fdf.Substring(0, fdf.Length - 1);
saveFileDialog.Filter = fdf;

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -31,8 +31,7 @@ internal class ToolStripNumericUpDown : ToolStripControlHost, INotifyPropertyCha
{
public event PropertyChangedEventHandler PropertyChanged;
public ToolStripNumericUpDown()
: base(new NumericUpDown())
public ToolStripNumericUpDown() : base(new NumericUpDown())
{
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -49,8 +49,7 @@ public Cache()
/// Initialize the cache
/// </summary>
/// <param name="expiredCallback"></param>
public Cache(CacheObjectExpired expiredCallback)
: this()
public Cache(CacheObjectExpired expiredCallback) : this()
{
this.expiredCallback = expiredCallback;
}
@ -59,8 +58,7 @@ public Cache(CacheObjectExpired expiredCallback)
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
public Cache(int secondsToExpire)
: this()
public Cache(int secondsToExpire) : this()
{
this.secondsToExpire = secondsToExpire;
}
@ -70,8 +68,7 @@ public Cache(int secondsToExpire)
/// </summary>
/// <param name="secondsToExpire"></param>
/// <param name="expiredCallback"></param>
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback)
: this(expiredCallback)
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback)
{
this.secondsToExpire = secondsToExpire;
}

View file

@ -0,0 +1,47 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
namespace GreenshotPlugin.Core
{
/// <summary>
/// This is the method signature which is used to capture a rectangle from the screen.
/// </summary>
/// <param name="captureBounds"></param>
/// <returns>Captured Bitmap</returns>
public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
/// <summary>
/// This is a hack to experiment with different screen capture routines
/// </summary>
public static class CaptureHandler
{
/// <summary>
/// By changing this value, null is default
/// </summary>
public static CaptureScreenRectangleHandler CaptureScreenRectangle
{
get;
set;
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -26,6 +26,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
@ -44,11 +45,13 @@ public static class ClipboardHelper
private static readonly string FORMAT_FILECONTENTS = "FileContents";
private static readonly string FORMAT_PNG = "PNG";
private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art";
private static readonly string FORMAT_17 = "Format17";
private static readonly string FORMAT_JPG = "JPG";
private static readonly string FORMAT_JFIF = "JFIF";
private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art";
private static readonly string FORMAT_GIF = "GIF";
private static readonly string FORMAT_BITMAP_PLACEHOLDER = "_BITMAP_";
private static readonly string FORMAT_BITMAP = "System.Drawing.Bitmap";
//private static readonly string FORMAT_HTML = "HTML Format";
private static IntPtr nextClipboardViewer = IntPtr.Zero;
// Template for the HTML Text on the clipboard
@ -103,22 +106,24 @@ private static string GetClipboardOwner()
IntPtr hWnd = User32.GetClipboardOwner();
if (hWnd != IntPtr.Zero)
{
IntPtr pid = IntPtr.Zero;
IntPtr tid = User32.GetWindowThreadProcessId(hWnd, out pid);
Process me = Process.GetCurrentProcess();
Process ownerProcess = Process.GetProcessById(pid.ToInt32());
// Exclude myself
if (ownerProcess != null && me.Id != ownerProcess.Id)
int pid;
User32.GetWindowThreadProcessId(hWnd, out pid);
using (Process me = Process.GetCurrentProcess())
using (Process ownerProcess = Process.GetProcessById(pid))
{
// Get Process Name
owner = ownerProcess.ProcessName;
// Try to get the starting Process Filename, this might fail.
try
{
owner = ownerProcess.Modules[0].FileName;
}
catch (Exception)
// Exclude myself
if (ownerProcess != null && me.Id != ownerProcess.Id)
{
// Get Process Name
owner = ownerProcess.ProcessName;
// Try to get the starting Process Filename, this might fail.
try
{
owner = ownerProcess.Modules[0].FileName;
}
catch (Exception)
{
}
}
}
}
@ -140,7 +145,7 @@ private static void SetDataObject(IDataObject ido, bool copy)
{
lock (clipboardLockObject)
{
int retryCount = 2;
int retryCount = 5;
while (retryCount >= 0)
{
try
@ -272,6 +277,7 @@ public static bool ContainsImage(IDataObject dataObject)
|| dataObject.GetDataPresent(DataFormats.Tiff)
|| dataObject.GetDataPresent(DataFormats.EnhancedMetafile)
|| dataObject.GetDataPresent(FORMAT_PNG)
|| dataObject.GetDataPresent(FORMAT_17)
|| dataObject.GetDataPresent(FORMAT_JPG)
|| dataObject.GetDataPresent(FORMAT_GIF))
{
@ -390,113 +396,121 @@ private static Image GetImage(IDataObject dataObject)
{
// Outlook ??
LOG.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
retrieveFormats = new string[] { DataFormats.Dib, FORMAT_BITMAP_PLACEHOLDER, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
retrieveFormats = new string[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
}
else
{
retrieveFormats = new string[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP_PLACEHOLDER, FORMAT_FILECONTENTS, FORMAT_GIF };
retrieveFormats = new string[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF };
}
foreach (string currentFormat in retrieveFormats)
{
if (FORMAT_BITMAP_PLACEHOLDER.Equals(currentFormat))
{
LOG.Info("Using default .NET Clipboard.GetImage()");
try
{
returnImage = Clipboard.GetImage();
if (returnImage != null)
{
return returnImage;
}
else
{
LOG.Info("Clipboard.GetImage() didn't return an image.");
}
}
catch (Exception ex)
{
LOG.Error("Problem retrieving Image via Clipboard.GetImage(): ", ex);
}
}
else if (formats.Contains(currentFormat))
if (formats.Contains(currentFormat))
{
LOG.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
if (currentFormat == DataFormats.Dib)
{
returnImage = GetDIBImage(dataObject);
}
else
{
returnImage = GetImageFormat(currentFormat, dataObject);
}
if (returnImage != null)
{
return returnImage;
}
returnImage = GetImageForFormat(currentFormat, dataObject);
}
else
{
LOG.DebugFormat("Couldn't find format {0}.", currentFormat);
}
if (returnImage != null)
{
ImageHelper.Orientate(returnImage);
return returnImage;
}
}
}
return null;
}
/// <summary>
/// Helper method to try to get an image in the specified format from the dataObject
/// the DIB readed should solve the issue reported here: https://sourceforge.net/projects/greenshot/forums/forum/676083/topic/6354353/index/page/1
/// It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591
/// </summary>
/// <returns>Image</returns>
private static Image GetDIBImage(IDataObject dataObejct)
/// <param name="format">string with the format</param>
/// <param name="dataObject">IDataObject</param>
/// <returns>Image or null</returns>
private static Image GetImageForFormat(string format, IDataObject dataObject)
{
try
object clipboardObject = GetFromDataObject(dataObject, format);
MemoryStream imageStream = clipboardObject as MemoryStream;
if (!isValidStream(imageStream))
{
// TODO: add "HTML Format" support here...
return clipboardObject as Image;
}
else
{
// If the EnableSpecialDIBClipboardReader flag in the config is set, use the code from:
// http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/
// to read the DeviceIndependentBitmap from the clipboard, this might fix bug 3576125
if (config.EnableSpecialDIBClipboardReader)
{
MemoryStream dibStream = GetFromDataObject(dataObejct, DataFormats.Dib) as MemoryStream;
if (isValidStream(dibStream))
if (format == FORMAT_17 || format == DataFormats.Dib)
{
LOG.Info("Found valid DIB stream, trying to process it.");
byte[] dibBuffer = new byte[dibStream.Length];
dibStream.Read(dibBuffer, 0, dibBuffer.Length);
BitmapInfoHeader infoHeader = BinaryStructHelper.FromByteArray<BitmapInfoHeader>(dibBuffer);
// Only use this code, when the biCommpression != 0 (BI_RGB)
if (infoHeader.biCompression != 0)
LOG.Info("Found DIB stream, trying to process it.");
try
{
LOG.InfoFormat("Using special DIB format reader for biCompression {0}", infoHeader.biCompression);
int fileHeaderSize = Marshal.SizeOf(typeof(BitmapFileHeader));
uint infoHeaderSize = infoHeader.biSize;
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
BitmapFileHeader fileHeader = new BitmapFileHeader();
fileHeader.bfType = BitmapFileHeader.BM;
fileHeader.bfSize = fileSize;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4);
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray<BitmapFileHeader>(fileHeader);
using (MemoryStream bitmapStream = new MemoryStream())
byte[] dibBuffer = new byte[imageStream.Length];
imageStream.Read(dibBuffer, 0, dibBuffer.Length);
BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADER>(dibBuffer);
if (!infoHeader.IsDibV5)
{
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
bitmapStream.Seek(0, SeekOrigin.Begin);
using (Image tmpImage = Image.FromStream(bitmapStream))
LOG.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
uint infoHeaderSize = infoHeader.biSize;
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
BITMAPFILEHEADER fileHeader = new BITMAPFILEHEADER();
fileHeader.bfType = BITMAPFILEHEADER.BM;
fileHeader.bfSize = fileSize;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4);
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray<BITMAPFILEHEADER>(fileHeader);
using (MemoryStream bitmapStream = new MemoryStream())
{
if (tmpImage != null)
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
bitmapStream.Seek(0, SeekOrigin.Begin);
using (Image tmpImage = Image.FromStream(bitmapStream))
{
return ImageHelper.Clone(tmpImage);
if (tmpImage != null)
{
return ImageHelper.Clone(tmpImage);
}
}
}
}
else
{
LOG.Info("Using special DIBV5 / Format17 format reader");
// CF_DIBV5
IntPtr gcHandle = IntPtr.Zero;
try
{
GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
gcHandle = GCHandle.ToIntPtr(handle);
return new Bitmap(infoHeader.biWidth, infoHeader.biHeight, -(int)(infoHeader.biSizeImage / infoHeader.biHeight),
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels + (infoHeader.biHeight - 1) * (int)(infoHeader.biSizeImage / infoHeader.biHeight)));
}
catch (Exception ex)
{
LOG.Error("Problem retrieving Format17 from clipboard.", ex);
}
finally
{
if (gcHandle == IntPtr.Zero)
{
GCHandle.FromIntPtr(gcHandle).Free();
}
}
}
}
else
catch (Exception dibEx)
{
LOG.InfoFormat("Skipping special DIB format reader for biCompression {0}", infoHeader.biCompression);
LOG.Error("Problem retrieving DIB from clipboard.", dibEx);
}
}
}
@ -504,31 +518,8 @@ private static Image GetDIBImage(IDataObject dataObejct)
{
LOG.Info("Skipping special DIB format reader as it's disabled in the configuration.");
}
}
catch (Exception dibEx)
{
LOG.Error("Problem retrieving DIB from clipboard.", dibEx);
}
return null;
}
/// <summary>
/// Helper method to try to get an image in the specified format from the dataObject
/// </summary>
/// <param name="format">string with the format</param>
/// <param name="dataObject">IDataObject</param>
/// <returns>Image or null</returns>
private static Image GetImageFormat(string format, IDataObject dataObject)
{
MemoryStream imageStream = GetFromDataObject(dataObject, format) as MemoryStream;
if (isValidStream(imageStream))
{
try
{
using (FileStream fs = new FileStream(@"C:\Localdata\test.png", FileMode.OpenOrCreate))
{
imageStream.WriteTo(fs);
}
imageStream.Seek(0, SeekOrigin.Begin);
using (Image tmpImage = Image.FromStream(imageStream, true, true))
{
@ -585,7 +576,7 @@ private static string getHTMLString(ISurface surface, string filename)
string utf8EncodedHTMLString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HTML_CLIPBOARD_STRING));
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${width}", surface.Image.Width.ToString());
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${height}", surface.Image.Height.ToString());
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${file}", filename);
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${file}", filename.Replace("\\", "/"));
StringBuilder sb = new StringBuilder();
sb.Append(utf8EncodedHTMLString);
sb.Replace("<<<<<<<1", (utf8EncodedHTMLString.IndexOf("<HTML>") + "<HTML>".Length).ToString("D8"));
@ -611,6 +602,218 @@ private static string getHTMLDataURLString(ISurface surface, MemoryStream pngStr
return sb.ToString();
}
/// <summary>
/// Set an Image to the clipboard
/// This method will place images to the clipboard depending on the ClipboardFormats setting.
/// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice
/// because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661
/// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003!
/// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left!
/// For this problem the user should not use the direct paste (=Dib), but select Bitmap
/// </summary>
private const int BITMAPFILEHEADER_LENGTH = 14;
public static void SetClipboardData(ISurface surface)
{
DataObject dataObject = new DataObject();
// This will work for Office and most other applications
//ido.SetData(DataFormats.Bitmap, true, image);
MemoryStream dibStream = null;
MemoryStream dibV5Stream = null;
MemoryStream pngStream = null;
Image imageToSave = null;
bool disposeImage = false;
try
{
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
// Create the image which is going to be saved so we don't create it multiple times
disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave);
try
{
// Create PNG stream
if (config.ClipboardFormats.Contains(ClipboardFormat.PNG))
{
pngStream = new MemoryStream();
// PNG works for e.g. Powerpoint
SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings);
pngStream.Seek(0, SeekOrigin.Begin);
// Set the PNG stream
dataObject.SetData(FORMAT_PNG, false, pngStream);
}
}
catch (Exception pngEX)
{
LOG.Error("Error creating PNG for the Clipboard.", pngEX);
}
try
{
if (config.ClipboardFormats.Contains(ClipboardFormat.DIB))
{
using (MemoryStream tmpBmpStream = new MemoryStream())
{
// Save image as BMP
SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false);
ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings);
dibStream = new MemoryStream();
// Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14
dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int)tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH);
}
// Set the DIB to the clipboard DataObject
dataObject.SetData(DataFormats.Dib, true, dibStream);
}
}
catch (Exception dibEx)
{
LOG.Error("Error creating DIB for the Clipboard.", dibEx);
}
// CF_DibV5
try
{
if (config.ClipboardFormats.Contains(ClipboardFormat.DIBV5))
{
// Create the stream for the clipboard
dibV5Stream = new MemoryStream();
// Create the BITMAPINFOHEADER
BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32);
// Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
header.biCompression = BI_COMPRESSION.BI_BITFIELDS;
// Create a byte[] to write
byte[] headerBytes = BinaryStructHelper.ToByteArray<BITMAPINFOHEADER>(header);
// Write the BITMAPINFOHEADER to the stream
dibV5Stream.Write(headerBytes, 0, headerBytes.Length);
// As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added
BitfieldColorMask colorMask = new BitfieldColorMask();
// Make sure the values are set
colorMask.InitValues();
// Create the byte[] from the struct
byte[] colorMaskBytes = BinaryStructHelper.ToByteArray<BitfieldColorMask>(colorMask);
Array.Reverse(colorMaskBytes);
// Write to the stream
dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length);
// Create the raw bytes for the pixels only
byte[] bitmapBytes = BitmapToByteArray((Bitmap)imageToSave);
// Write to the stream
dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length);
// Set the DIBv5 to the clipboard DataObject
dataObject.SetData(FORMAT_17, true, dibV5Stream);
}
}
catch (Exception dibEx)
{
LOG.Error("Error creating DIB for the Clipboard.", dibEx);
}
// Set the HTML
if (config.ClipboardFormats.Contains(ClipboardFormat.HTML))
{
string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null);
string html = getHTMLString(surface, tmpFile);
dataObject.SetText(html, TextDataFormat.Html);
}
else if (config.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL))
{
string html;
using (MemoryStream tmpPNGStream = new MemoryStream())
{
SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
// Do not allow to reduce the colors, some applications dislike 256 color images
// reported with bug #3594681
pngOutputSettings.DisableReduceColors = true;
// Check if we can use the previously used image
if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed)
{
ImageOutput.SaveToStream(imageToSave, surface, tmpPNGStream, pngOutputSettings);
}
else
{
ImageOutput.SaveToStream(surface, tmpPNGStream, pngOutputSettings);
}
html = getHTMLDataURLString(surface, tmpPNGStream);
}
dataObject.SetText(html, TextDataFormat.Html);
}
}
finally
{
// we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone!
// Check if Bitmap is wanted
if (config.ClipboardFormats.Contains(ClipboardFormat.BITMAP))
{
dataObject.SetImage(imageToSave);
// Place the DataObject to the clipboard
SetDataObject(dataObject, true);
}
else
{
// Place the DataObject to the clipboard
SetDataObject(dataObject, true);
}
if (pngStream != null)
{
pngStream.Dispose();
pngStream = null;
}
if (dibStream != null)
{
dibStream.Dispose();
dibStream = null;
}
if (dibV5Stream != null)
{
dibV5Stream.Dispose();
dibV5Stream = null;
}
// cleanup if needed
if (disposeImage && imageToSave != null)
{
imageToSave.Dispose();
}
}
}
/// <summary>
/// Helper method so get the bitmap bytes
/// See: http://stackoverflow.com/a/6570155
/// </summary>
/// <param name="bitmap">Bitmap</param>
/// <returns>byte[]</returns>
private static byte[] BitmapToByteArray(Bitmap bitmap)
{
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
int absStride = Math.Abs(bmpData.Stride);
int bytes = absStride * bitmap.Height;
long ptr = bmpData.Scan0.ToInt32();
// Declare an array to hold the bytes of the bitmap.
byte[] rgbValues = new byte[bytes];
for (int i = 0; i < bitmap.Height; i++)
{
IntPtr pointer = new IntPtr(ptr + (bmpData.Stride * i));
Marshal.Copy(pointer, rgbValues, absStride * (bitmap.Height - i - 1), absStride);
}
// Unlock the bits.
bitmap.UnlockBits(bmpData);
return rgbValues;
}
/// <summary>
/// Set Object with type Type to the clipboard
/// </summary>

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -22,9 +22,12 @@
using GreenshotPlugin;
using GreenshotPlugin.Core;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.Text;
namespace Greenshot.Core
{
@ -33,19 +36,30 @@ namespace Greenshot.Core
/// </summary>
public interface IEffect
{
/// <summary>
/// Apply this IEffect to the supplied sourceImage.
/// In the process of applying the supplied matrix will be modified to represent the changes.
/// </summary>
/// <param name="sourceImage">Image to apply the effect to</param>
/// <param name="matrix">Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas</param>
/// <returns>new image with applied effect</returns>
Image Apply(Image sourceImage, Matrix matrix);
/// <summary>
/// Reset all values to their defaults
/// </summary>
void Reset();
}
/// <summary>
/// DropShadowEffect
/// </summary>
[TypeConverter(typeof(EffectConverter))]
public class DropShadowEffect : IEffect
{
public DropShadowEffect()
{
Darkness = 0.6f;
ShadowSize = 7;
ShadowOffset = new Point(-1, -1);
Reset();
}
public float Darkness
@ -64,6 +78,13 @@ public Point ShadowOffset
set;
}
public virtual void Reset()
{
Darkness = 0.6f;
ShadowSize = 7;
ShadowOffset = new Point(-1, -1);
}
public virtual Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb);
@ -73,17 +94,12 @@ public virtual Image Apply(Image sourceImage, Matrix matrix)
/// <summary>
/// TornEdgeEffect extends on DropShadowEffect
/// </summary>
[TypeConverter(typeof(EffectConverter))]
public class TornEdgeEffect : DropShadowEffect
{
public TornEdgeEffect()
: base()
public TornEdgeEffect() : base()
{
ShadowSize = 7;
ToothHeight = 12;
HorizontalToothRange = 20;
VerticalToothRange = 20;
Edges = new bool[] { true, true, true, true };
GenerateShadow = true;
Reset();
}
public int ToothHeight
@ -112,6 +128,17 @@ public bool GenerateShadow
set;
}
public override void Reset()
{
base.Reset();
ShadowSize = 7;
ToothHeight = 12;
HorizontalToothRange = 20;
VerticalToothRange = 20;
Edges = new bool[] { true, true, true, true };
GenerateShadow = true;
}
public override Image Apply(Image sourceImage, Matrix matrix)
{
Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange, Edges);
@ -135,6 +162,11 @@ public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateGrayscale(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
/// <summary>
@ -150,6 +182,11 @@ public MonochromeEffect(byte threshold)
this.threshold = threshold;
}
public void Reset()
{
// TODO: Modify the threshold to have a default, which is reset here
}
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateMonochrome(sourceImage, threshold);
@ -161,12 +198,9 @@ public Image Apply(Image sourceImage, Matrix matrix)
/// </summary>
public class AdjustEffect : IEffect
{
public AdjustEffect()
: base()
public AdjustEffect() : base()
{
Contrast = 1f;
Brightness = 1f;
Gamma = 1f;
Reset();
}
public float Contrast
@ -185,6 +219,13 @@ public float Gamma
set;
}
public void Reset()
{
Contrast = 1f;
Brightness = 1f;
Gamma = 1f;
}
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma);
@ -196,10 +237,9 @@ public Image Apply(Image sourceImage, Matrix matrix)
/// </summary>
public class ReduceColorsEffect : IEffect
{
public ReduceColorsEffect()
: base()
public ReduceColorsEffect() : base()
{
Colors = 256;
Reset();
}
public int Colors
@ -208,6 +248,11 @@ public int Colors
set;
}
public void Reset()
{
Colors = 256;
}
public Image Apply(Image sourceImage, Matrix matrix)
{
using (WuQuantizer quantizer = new WuQuantizer((Bitmap)sourceImage))
@ -238,6 +283,11 @@ public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateNegative(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
/// <summary>
@ -247,8 +297,7 @@ public class BorderEffect : IEffect
{
public BorderEffect()
{
Width = 2;
Color = Color.Black;
Reset();
}
public Color Color
@ -262,6 +311,12 @@ public int Width
set;
}
public void Reset()
{
Width = 2;
Color = Color.Black;
}
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, matrix);
@ -284,6 +339,11 @@ public int Angle
set;
}
public void Reset()
{
// Angle doesn't have a default value
}
public Image Apply(Image sourceImage, Matrix matrix)
{
RotateFlipType flipType;
@ -335,6 +395,11 @@ public bool MaintainAspectRatio
set;
}
public void Reset()
{
// values don't have a default value
}
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height, matrix);
@ -352,7 +417,7 @@ public ResizeCanvasEffect(int left, int right, int top, int bottom)
Right = right;
Top = top;
Bottom = bottom;
BackgroundColor = Color.Empty; // Uses the default background color depending on the format
BackgroundColor = Color.Empty; // Uses the default background color depending on the format
}
public int Left
@ -381,9 +446,227 @@ public Color BackgroundColor
set;
}
public void Reset()
{
// values don't have a default value
}
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom, matrix);
}
}
public class EffectConverter : TypeConverter
{
// Fix to prevent BUG-1753
private NumberFormatInfo numberFormatInfo = new NumberFormatInfo();
public EffectConverter() : base()
{
numberFormatInfo.NumberDecimalSeparator = ".";
numberFormatInfo.NumberGroupSeparator = ",";
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
if (destinationType == typeof(DropShadowEffect))
{
return true;
}
if (destinationType == typeof(TornEdgeEffect))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
// to string
if (destinationType == typeof(string))
{
StringBuilder sb = new StringBuilder();
if (value.GetType() == typeof(DropShadowEffect))
{
DropShadowEffect effect = value as DropShadowEffect;
RetrieveDropShadowEffectValues(effect, sb);
return sb.ToString();
}
if (value.GetType() == typeof(TornEdgeEffect))
{
TornEdgeEffect effect = value as TornEdgeEffect;
RetrieveDropShadowEffectValues(effect, sb);
sb.Append("|");
RetrieveTornEdgeEffectValues(effect, sb);
return sb.ToString();
}
}
// from string
if (value.GetType() == typeof(string))
{
string settings = value as string;
if (destinationType == typeof(DropShadowEffect))
{
DropShadowEffect effect = new DropShadowEffect();
ApplyDropShadowEffectValues(settings, effect);
return effect;
}
if (destinationType == typeof(TornEdgeEffect))
{
TornEdgeEffect effect = new TornEdgeEffect();
ApplyDropShadowEffectValues(settings, effect);
ApplyTornEdgeEffectValues(settings, effect);
return effect;
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value != null && value.GetType() == typeof(string))
{
string settings = value as string;
if (settings.Contains("ToothHeight"))
{
return ConvertTo(context, culture, value, typeof(TornEdgeEffect));
}
else
{
return ConvertTo(context, culture, value, typeof(DropShadowEffect));
}
}
return base.ConvertFrom(context, culture, value);
}
private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect)
{
string[] values = valuesString.Split('|');
foreach (string nameValuePair in values)
{
string[] pair = nameValuePair.Split(':');
switch (pair[0])
{
case "Darkness":
float darkness;
// Fix to prevent BUG-1753
if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, numberFormatInfo, out darkness))
{
if (darkness <= 1.0)
{
effect.Darkness = darkness;
}
}
break;
case "ShadowSize":
int shadowSize;
if (int.TryParse(pair[1], out shadowSize))
{
effect.ShadowSize = shadowSize;
}
break;
case "ShadowOffset":
Point shadowOffset = new Point();
int shadowOffsetX;
int shadowOffsetY;
string[] coordinates = pair[1].Split(',');
if (int.TryParse(coordinates[0], out shadowOffsetX))
{
shadowOffset.X = shadowOffsetX;
}
if (int.TryParse(coordinates[1], out shadowOffsetY))
{
shadowOffset.Y = shadowOffsetY;
}
effect.ShadowOffset = shadowOffset;
break;
}
}
}
private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect)
{
string[] values = valuesString.Split('|');
foreach (string nameValuePair in values)
{
string[] pair = nameValuePair.Split(':');
switch (pair[0])
{
case "GenerateShadow":
bool generateShadow;
if (bool.TryParse(pair[1], out generateShadow))
{
effect.GenerateShadow = generateShadow;
}
break;
case "ToothHeight":
int toothHeight;
if (int.TryParse(pair[1], out toothHeight))
{
effect.ToothHeight = toothHeight;
}
break;
case "HorizontalToothRange":
int horizontalToothRange;
if (int.TryParse(pair[1], out horizontalToothRange))
{
effect.HorizontalToothRange = horizontalToothRange;
}
break;
case "VerticalToothRange":
int verticalToothRange;
if (int.TryParse(pair[1], out verticalToothRange))
{
effect.VerticalToothRange = verticalToothRange;
}
break;
case "Edges":
string[] edges = pair[1].Split(',');
bool edge;
if (bool.TryParse(edges[0], out edge))
{
effect.Edges[0] = edge;
}
if (bool.TryParse(edges[1], out edge))
{
effect.Edges[1] = edge;
}
if (bool.TryParse(edges[2], out edge))
{
effect.Edges[2] = edge;
}
if (bool.TryParse(edges[3], out edge))
{
effect.Edges[3] = edge;
}
break;
}
}
}
private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb)
{
// Fix to prevent BUG-1753 is to use the numberFormatInfo
sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, effect.ShadowOffset.Y);
}
private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb)
{
sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]);
}
}
}

View file

@ -1,101 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace GreenshotPlugin.Core
{
public static class EncryptionHelper
{
private const string RGBIV = "dlgjowejgogkklwj";
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
/// <summary>
/// A simply rijndael aes encryption, can be used to store passwords
/// </summary>
/// <param name="ClearText">the string to call upon</param>
/// <returns>an encryped string in base64 form</returns>
public static string Encrypt(this string ClearText)
{
string returnValue = ClearText;
try
{
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
using (MemoryStream ms = new MemoryStream())
{
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
byte[] key = Encoding.ASCII.GetBytes(KEY);
CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
cs.Close();
returnValue = Convert.ToBase64String(ms.ToArray());
}
}
catch (Exception ex)
{
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
}
return returnValue;
}
/// <summary>
/// A simply rijndael aes decryption, can be used to store passwords
/// </summary>
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
/// <returns>Decrypeted text</returns>
public static string Decrypt(this string EncryptedText)
{
string returnValue = EncryptedText;
try
{
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
using (MemoryStream ms = new MemoryStream())
{
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
byte[] key = Encoding.ASCII.GetBytes(KEY);
CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV),
CryptoStreamMode.Write);
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
cs.Close();
returnValue = Encoding.ASCII.GetString(ms.ToArray());
}
}
catch (Exception ex)
{
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
}
return returnValue;
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -0,0 +1,47 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace GreenshotPlugin.Core
{
public class EventDelay
{
private long lastCheck = 0;
private long waitTime;
public EventDelay(long ticks)
{
this.waitTime = ticks;
}
public bool Check()
{
lock (this)
{
long now = DateTime.Now.Ticks;
bool isPassed = now - lastCheck > waitTime;
lastCheck = now;
return isPassed;
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -828,8 +828,7 @@ public unsafe class FastChunkyBitmap : FastBitmap
private Color[] colorEntries;
private Dictionary<Color, byte> colorCache = new Dictionary<Color, byte>();
public FastChunkyBitmap(Bitmap source, Rectangle area)
: base(source, area)
public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area)
{
colorEntries = bitmap.Palette.Entries;
}
@ -930,8 +929,7 @@ public override void SetColorAt(int x, int y, Color color)
/// </summary>
public unsafe class Fast24RGBBitmap : FastBitmap
{
public Fast24RGBBitmap(Bitmap source, Rectangle area)
: base(source, area)
public Fast24RGBBitmap(Bitmap source, Rectangle area) : base(source, area)
{
}
@ -997,8 +995,7 @@ public override void SetColorAt(int x, int y, byte[] color)
/// </summary>
public unsafe class Fast32RGBBitmap : FastBitmap
{
public Fast32RGBBitmap(Bitmap source, Rectangle area)
: base(source, area)
public Fast32RGBBitmap(Bitmap source, Rectangle area) : base(source, area)
{
}
@ -1053,7 +1050,7 @@ public override void GetColorAt(int x, int y, byte[] color)
public override void SetColorAt(int x, int y, byte[] color)
{
int offset = (x * 4) + (y * stride);
pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R
pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R
pointer[PIXELFORMAT_INDEX_G + offset] = color[COLOR_INDEX_G];
pointer[PIXELFORMAT_INDEX_B + offset] = color[COLOR_INDEX_B];
}
@ -1078,8 +1075,7 @@ public Color BackgroundBlendColor
set;
}
public Fast32ARGBBitmap(Bitmap source, Rectangle area)
: base(source, area)
public Fast32ARGBBitmap(Bitmap source, Rectangle area) : base(source, area)
{
BackgroundBlendColor = Color.White;
}
@ -1136,7 +1132,7 @@ public override void GetColorAt(int x, int y, byte[] color)
public override void SetColorAt(int x, int y, byte[] color)
{
int offset = (x * 4) + (y * stride);
pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R
pointer[PIXELFORMAT_INDEX_R + offset] = color[COLOR_INDEX_R]; // R
pointer[PIXELFORMAT_INDEX_G + offset] = color[COLOR_INDEX_G];
pointer[PIXELFORMAT_INDEX_B + offset] = color[COLOR_INDEX_B];
pointer[PIXELFORMAT_INDEX_A + offset] = color[COLOR_INDEX_A];

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -23,6 +23,7 @@
using Greenshot.Plugin;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
@ -31,7 +32,14 @@ namespace GreenshotPlugin.Core
{
public static class FilenameHelper
{
// Specify the regular expression for the filename formatting:
// Starting with ${
// than the varname, which ends with a : or }
// If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters.
// The parameter format is a single alpha followed by the value belonging to the parameter, e.g. :
// ${capturetime:d"yyyy-MM-dd HH_mm_ss"}
private static readonly Regex VAR_REGEXP = new Regex(@"\${(?<variable>[^:}]+)[:]?(?<parameters>[^}]*)}", RegexOptions.Compiled);
private static readonly Regex SPLIT_REGEXP = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled);
private const int MAX_TITLE_LENGTH = 80;
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
@ -158,7 +166,7 @@ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails cap
int endIndex = 0;
char padChar = ' ';
string dateFormat = "yyyy-MM-dd HH-mm-ss";
IDictionary<string, string> replacements = new Dictionary<string, string>();
string replaceValue = "";
string variable = match.Groups["variable"].Value;
string parameters = match.Groups["parameters"].Value;
@ -170,6 +178,7 @@ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails cap
{
switch (parameter.Substring(0, 1))
{
// Padding p<width>[,pad-character]
case "p":
string[] padParams = parameter.Substring(1).Split(new char[] { ',' });
try
@ -184,6 +193,17 @@ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails cap
padChar = padParams[1][0];
}
break;
// replace
// r<old string>,<new string>
case "r":
string[] replaceParameters = parameter.Substring(1).Split(new char[] { ',' });
if (replaceParameters != null && replaceParameters.Length == 2)
{
replacements.Add(replaceParameters[0], replaceParameters[1]);
}
break;
// Dateformat d<format>
// Format can be anything that is used in C# date formatting
case "d":
dateFormat = parameter.Substring(1);
if (dateFormat.StartsWith("\""))
@ -195,6 +215,8 @@ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails cap
dateFormat = dateFormat.Substring(0, dateFormat.Length - 1);
}
break;
// Substring:
// s<start>[,length]
case "s":
string range = parameter.Substring(1);
string[] rangelist = range.Split(new char[] { ',' });
@ -436,6 +458,14 @@ private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails cap
}
}
// new for feature #697
if (replacements.Count > 0)
{
foreach (string oldValue in replacements.Keys)
{
replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]);
}
}
return replaceValue;
}
@ -478,10 +508,10 @@ public static string FillVariables(string pattern, bool filenameSafeMode)
}
return VAR_REGEXP.Replace(pattern,
delegate (Match m)
new MatchEvaluator(delegate (Match m)
{
return MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode);
}
})
);
}
@ -489,7 +519,7 @@ public static string FillVariables(string pattern, bool filenameSafeMode)
/// Fill the pattern wit the supplied details
/// </summary>
/// <param name="pattern">Pattern</param>
/// <param name="captureDetails">CaptureDetails</param>
/// <param name="captureDetails">CaptureDetails, can be null</param>
/// <param name="filenameSafeMode">Should the result be made "filename" safe?</param>
/// <returns>Filled pattern</returns>
public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode)
@ -527,19 +557,58 @@ public static string FillPattern(string pattern, ICaptureDetails captureDetails,
try
{
return VAR_REGEXP.Replace(pattern,
delegate (Match m)
new MatchEvaluator(delegate (Match m)
{
return MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode);
}
})
);
}
catch (Exception e)
{
// adding additional data for bug tracking
e.Data.Add("title", captureDetails.Title);
if (captureDetails != null)
{
e.Data.Add("title", captureDetails.Title);
}
e.Data.Add("pattern", pattern);
throw;
}
}
/// <summary>
/// Checks whether a directory name is valid in the current file system
/// </summary>
/// <param name="directoryName">directory name (not path!)</param>
/// <returns>true if directory name is valid</returns>
public static bool IsDirectoryNameValid(string directoryName)
{
var forbiddenChars = Path.GetInvalidPathChars();
foreach (var forbiddenChar in forbiddenChars)
{
if (directoryName == null || directoryName.Contains(forbiddenChar.ToString()))
{
return false;
}
}
return true;
}
/// <summary>
/// Checks whether a filename is valid in the current file system
/// </summary>
/// <param name="filename">name of the file</param>
/// <returns>true if filename is valid</returns>
public static bool IsFilenameValid(string filename)
{
var forbiddenChars = Path.GetInvalidFileNameChars();
foreach (var forbiddenChar in forbiddenChars)
{
if (filename == null || filename.Contains(forbiddenChar.ToString()))
{
return false;
}
}
return true;
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -972,7 +972,7 @@ public static Bitmap CreateShadow(Image sourceBitmap, float darkness, int shadow
{
shadowSize++;
}
bool useGDIBlur = GDIplus.IsBlurPossible(shadowSize);
bool useGDIBlur = GDIplus.isBlurPossible(shadowSize);
// Create "mask" for the shadow
ColorMatrix maskMatrix = new ColorMatrix();
maskMatrix.Matrix00 = 0;
@ -1643,12 +1643,18 @@ public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, boo
if (maintainAspectRatio && canvasUseNewSize)
{
newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
matrix.Scale((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height, MatrixOrder.Append);
if (matrix != null)
{
matrix.Scale((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height, MatrixOrder.Append);
}
}
else
{
newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
matrix.Scale((float)destWidth / sourceImage.Width, (float)destHeight / sourceImage.Height, MatrixOrder.Append);
if (matrix != null)
{
matrix.Scale((float)destWidth / sourceImage.Width, (float)destHeight / sourceImage.Height, MatrixOrder.Append);
}
}
using (Graphics graphics = Graphics.FromImage(newImage))

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -23,6 +23,7 @@
using Greenshot.Plugin;
using GreenshotPlugin.Controls;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
@ -204,6 +205,10 @@ public static void SaveToStream(Image imageToSave, ISurface surface, Stream stre
AddTag(imageToSave);
// Added for OptiPNG
bool processed = false;
if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(conf.OptimizePNGCommand))
{
processed = ProcessPNGImageExternally(imageToSave, targetStream);
}
if (!processed)
{
imageToSave.Save(targetStream, imageFormat);
@ -247,6 +252,83 @@ public static void SaveToStream(Image imageToSave, ISurface surface, Stream stre
}
}
/// <summary>
/// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream
/// </summary>
/// <param name="imageToProcess">Image to pass to the external process</param>
/// <param name="targetStream">stream to write the processed image to</param>
/// <returns></returns>
private static bool ProcessPNGImageExternally(Image imageToProcess, Stream targetStream)
{
if (string.IsNullOrEmpty(conf.OptimizePNGCommand))
{
return false;
}
if (!File.Exists(conf.OptimizePNGCommand))
{
LOG.WarnFormat("Can't find 'OptimizePNGCommand' {0}", conf.OptimizePNGCommand);
return false;
}
string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png");
try
{
using (FileStream tmpStream = File.Create(tmpFileName))
{
LOG.DebugFormat("Writing png to tmp file: {0}", tmpFileName);
imageToProcess.Save(tmpStream, ImageFormat.Png);
if (LOG.IsDebugEnabled)
{
LOG.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length);
}
}
if (LOG.IsDebugEnabled)
{
LOG.DebugFormat("Starting : {0}", conf.OptimizePNGCommand);
}
ProcessStartInfo processStartInfo = new ProcessStartInfo(conf.OptimizePNGCommand);
processStartInfo.Arguments = string.Format(conf.OptimizePNGCommandArguments, tmpFileName);
processStartInfo.CreateNoWindow = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.UseShellExecute = false;
using (Process process = Process.Start(processStartInfo))
{
if (process != null)
{
process.WaitForExit();
if (process.ExitCode == 0)
{
if (LOG.IsDebugEnabled)
{
LOG.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length);
LOG.DebugFormat("Reading back tmp file: {0}", tmpFileName);
}
byte[] processedImage = File.ReadAllBytes(tmpFileName);
targetStream.Write(processedImage, 0, processedImage.Length);
return true;
}
LOG.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode);
LOG.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd());
LOG.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd());
}
}
}
catch (Exception e)
{
LOG.Error("Error while processing PNG image: ", e);
}
finally
{
if (File.Exists(tmpFileName))
{
LOG.DebugFormat("Cleaning up tmp file: {0}", tmpFileName);
File.Delete(tmpFileName);
}
}
return false;
}
/// <summary>
/// Create an image from a surface with the settings from the output settings applied
/// </summary>
@ -294,6 +376,44 @@ public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSetting
}
}
// check for color reduction, forced or automatically, only when the DisableReduceColors is false
if (outputSettings.DisableReduceColors || (!conf.OutputFileAutoReduceColors && !outputSettings.ReduceColors))
{
return disposeImage;
}
bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat);
if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors))
{
using (var quantizer = new WuQuantizer((Bitmap)imageToSave))
{
int colorCount = quantizer.GetColorCount();
LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount);
if (!outputSettings.ReduceColors && colorCount >= 256)
{
return disposeImage;
}
try
{
LOG.Info("Reducing colors on bitmap to 256.");
tmpImage = quantizer.GetQuantizedImage(conf.OutputFileReduceColorsTo);
if (disposeImage)
{
imageToSave.Dispose();
}
imageToSave = tmpImage;
// Make sure the "new" image is disposed
disposeImage = true;
}
catch (Exception e)
{
LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e);
}
}
}
else if (isAlpha && !outputSettings.ReduceColors)
{
LOG.Info("Skipping 'optional' color reduction as the image has alpha");
}
return disposeImage;
}
@ -460,7 +580,7 @@ public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDet
QualityDialog qualityDialog = new QualityDialog(outputSettings);
qualityDialog.ShowDialog();
}
// For now we always overwrite, should be changed
// TODO: For now we always overwrite, should be changed
Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard);
returnValue = fileNameWithExtension;
IniConfig.Save();

View file

@ -0,0 +1,911 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.IniFile;
using Greenshot.Plugin;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace GreenshotPlugin.Core
{
/// <summary>
/// HTTP Method to make sure we have the correct method
/// </summary>
public enum HTTPMethod
{
GET,
POST,
PUT,
DELETE,
HEAD
};
/// <summary>
/// Description of NetworkHelper.
/// </summary>
public static class NetworkHelper
{
private static readonly CoreConfiguration Config = IniConfig.GetIniSection<CoreConfiguration>();
static NetworkHelper()
{
// Disable certificate checking
ServicePointManager.ServerCertificateValidationCallback +=
delegate
{
return true;
};
}
/// <summary>
/// Download a uri response as string
/// </summary>
/// <param name="uri">An Uri to specify the download location</param>
/// <returns>string with the file content</returns>
public static string GetAsString(Uri uri)
{
return GetResponseAsString(CreateWebRequest(uri));
}
/// <summary>
/// Download the FavIcon as a Bitmap
/// </summary>
/// <param name="baseUri"></param>
/// <returns>Bitmap with the FavIcon</returns>
public static Bitmap DownloadFavIcon(Uri baseUri)
{
Uri url = new Uri(baseUri, new Uri("favicon.ico"));
try
{
HttpWebRequest request = CreateWebRequest(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (request.HaveResponse)
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (Image image = Image.FromStream(responseStream))
{
return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image);
}
}
}
}
}
}
catch (Exception e)
{
LOG.Error("Problem downloading the FavIcon from: " + baseUri, e);
}
return null;
}
/// <summary>
/// Download the uri into a memorystream, without catching exceptions
/// </summary>
/// <param name="url">Of an image</param>
/// <returns>MemoryStream which is already seeked to 0</returns>
public static MemoryStream GetAsMemoryStream(string url)
{
HttpWebRequest request = CreateWebRequest(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
MemoryStream memoryStream = new MemoryStream();
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
responseStream.CopyTo(memoryStream);
}
// Make sure it can be used directly
memoryStream.Seek(0, SeekOrigin.Begin);
}
return memoryStream;
}
}
/// <summary>
/// Download the uri to Bitmap
/// </summary>
/// <param name="url">Of an image</param>
/// <returns>Bitmap</returns>
public static Image DownloadImage(string url)
{
try
{
string content;
using (MemoryStream memoryStream = GetAsMemoryStream(url))
{
try
{
using (Image image = Image.FromStream(memoryStream))
{
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
}
}
catch (Exception)
{
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
{
content = streamReader.ReadLine();
}
Regex imageUrlRegex = new Regex(@"(http|https)://.*(\.png|\.gif|\.jpg|\.tiff|\.jpeg|\.bmp)");
Match match = imageUrlRegex.Match(content);
if (match.Success)
{
using (MemoryStream memoryStream2 = GetAsMemoryStream(match.Value))
{
using (Image image = Image.FromStream(memoryStream2))
{
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
}
}
}
throw;
}
}
}
catch (Exception e)
{
LOG.Error("Problem downloading the image from: " + url, e);
}
return null;
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">string with uri to connect to</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(string uri)
{
return CreateWebRequest(new Uri(uri));
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">string with uri to connect to</param>
/// /// <param name="method">Method to use</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method)
{
return CreateWebRequest(new Uri(uri), method);
}
/// <summary>
/// Helper method to create a web request with a lot of default settings
/// </summary>
/// <param name="uri">Uri with uri to connect to</param>
/// <param name="method">Method to use</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method)
{
HttpWebRequest webRequest = CreateWebRequest(uri);
webRequest.Method = method.ToString();
return webRequest;
}
/// <summary>
/// Helper method to create a web request, eventually with proxy
/// </summary>
/// <param name="uri">Uri with uri to connect to</param>
/// <returns>WebRequest</returns>
public static HttpWebRequest CreateWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
if (Config.UseProxy)
{
webRequest.Proxy = CreateProxy(uri);
}
else
{
// BUG-1655: Fix that Greenshot always uses the default proxy even if the "use default proxy" checkbox is unset
webRequest.Proxy = null;
}
// Make sure the default credentials are available
webRequest.Credentials = CredentialCache.DefaultCredentials;
// Allow redirect, this is usually needed so that we don't get a problem when a service moves
webRequest.AllowAutoRedirect = true;
// Set default timeouts
webRequest.Timeout = Config.WebRequestTimeout * 1000;
webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000;
return webRequest;
}
/// <summary>
/// Create a IWebProxy Object which can be used to access the Internet
/// This method will check the configuration if the proxy is allowed to be used.
/// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins
/// </summary>
/// <param name="uri"></param>
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
public static IWebProxy CreateProxy(Uri uri)
{
IWebProxy proxyToUse = null;
if (Config.UseProxy)
{
proxyToUse = WebRequest.DefaultWebProxy;
if (proxyToUse != null)
{
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
if (LOG.IsDebugEnabled)
{
// check the proxy for the Uri
if (!proxyToUse.IsBypassed(uri))
{
Uri proxyUri = proxyToUse.GetProxy(uri);
if (proxyUri != null)
{
LOG.Debug("Using proxy: " + proxyUri + " for " + uri);
}
else
{
LOG.Debug("No proxy found!");
}
}
else
{
LOG.Debug("Proxy bypass for: " + uri);
}
}
}
else
{
LOG.Debug("No proxy found!");
}
}
return proxyToUse;
}
/// <summary>
/// UrlEncodes a string without the requirement for System.Web
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
// [Obsolete("Use System.Uri.EscapeDataString instead")]
public static string UrlEncode(string text)
{
if (!string.IsNullOrEmpty(text))
{
// Sytem.Uri provides reliable parsing, but doesn't encode spaces.
return Uri.EscapeDataString(text).Replace("%20", "+");
}
return null;
}
/// <summary>
/// A wrapper around the EscapeDataString, as the limit is 32766 characters
/// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
/// </summary>
/// <param name="text"></param>
/// <returns>escaped data string</returns>
public static string EscapeDataString(string text)
{
if (!string.IsNullOrEmpty(text))
{
StringBuilder result = new StringBuilder();
int currentLocation = 0;
while (currentLocation < text.Length)
{
string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
result.Append(Uri.EscapeDataString(process));
currentLocation = currentLocation + 16384;
}
return result.ToString();
}
return null;
}
/// <summary>
/// UrlDecodes a string without requiring System.Web
/// </summary>
/// <param name="text">String to decode.</param>
/// <returns>decoded string</returns>
public static string UrlDecode(string text)
{
// pre-process for + sign space formatting since System.Uri doesn't handle it
// plus literals are encoded as %2b normally so this should be safe
text = text.Replace("+", " ");
return Uri.UnescapeDataString(text);
}
/// <summary>
/// ParseQueryString without the requirement for System.Web
/// </summary>
/// <param name="queryString"></param>
/// <returns>IDictionary string, string</returns>
public static IDictionary<string, string> ParseQueryString(string queryString)
{
IDictionary<string, string> parameters = new SortedDictionary<string, string>();
// remove anything other than query string from uri
if (queryString.Contains("?"))
{
queryString = queryString.Substring(queryString.IndexOf('?') + 1);
}
foreach (string vp in Regex.Split(queryString, "&"))
{
if (string.IsNullOrEmpty(vp))
{
continue;
}
string[] singlePair = Regex.Split(vp, "=");
if (parameters.ContainsKey(singlePair[0]))
{
parameters.Remove(singlePair[0]);
}
parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty);
}
return parameters;
}
/// <summary>
/// Generate the query paramters
/// </summary>
/// <param name="queryParameters">the list of query parameters</param>
/// <returns>a string with the query parameters</returns>
public static string GenerateQueryParameters(IDictionary<string, object> queryParameters)
{
if (queryParameters == null || queryParameters.Count == 0)
{
return string.Empty;
}
queryParameters = new SortedDictionary<string, object>(queryParameters);
StringBuilder sb = new StringBuilder();
foreach (string key in queryParameters.Keys)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode(string.Format("{0}", queryParameters[key])));
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest
/// </summary>
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary<string, object> postParameters)
{
string boundary = String.Format("----------{0:N}", Guid.NewGuid());
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
using (Stream formDataStream = webRequest.GetRequestStream())
{
WriteMultipartFormData(formDataStream, boundary, postParameters);
}
}
/// <summary>
/// Write Multipart Form Data to the HttpListenerResponse
/// </summary>
/// <param name="response">HttpListenerResponse</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary<string, object> postParameters)
{
string boundary = String.Format("----------{0:N}", Guid.NewGuid());
response.ContentType = "multipart/form-data; boundary=" + boundary;
WriteMultipartFormData(response.OutputStream, boundary, postParameters);
}
/// <summary>
/// Write Multipart Form Data to a Stream, content-type should be set before this!
/// </summary>
/// <param name="formDataStream">Stream to write the multipart form data to</param>
/// <param name="boundary">String boundary for the multipart/form-data</param>
/// <param name="postParameters">Parameters to include in the multipart form data</param>
public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary<string, object> postParameters)
{
bool needsClrf = false;
foreach (var param in postParameters)
{
// Add a CRLF to allow multiple parameters to be added.
// Skip it on the first parameter, add it to subsequent parameters.
if (needsClrf)
{
formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n"));
}
needsClrf = true;
if (param.Value is IBinaryContainer)
{
IBinaryContainer binaryParameter = (IBinaryContainer)param.Value;
binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream);
}
else
{
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
string footer = "\r\n--" + boundary + "--\r\n";
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
}
/// <summary>
/// Post the parameters "x-www-form-urlencoded"
/// </summary>
/// <param name="webRequest"></param>
public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary<string, object> parameters)
{
webRequest.ContentType = "application/x-www-form-urlencoded";
string urlEncoded = NetworkHelper.GenerateQueryParameters(parameters);
byte[] data = Encoding.UTF8.GetBytes(urlEncoded);
using (var requestStream = webRequest.GetRequestStream())
{
requestStream.Write(data, 0, data.Length);
}
}
/// <summary>
/// Log the headers of the WebResponse, if IsDebugEnabled
/// </summary>
/// <param name="response">WebResponse</param>
private static void DebugHeaders(WebResponse response)
{
if (!LOG.IsDebugEnabled)
{
return;
}
LOG.DebugFormat("Debug information on the response from {0} :", response.ResponseUri);
foreach (string key in response.Headers.AllKeys)
{
LOG.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]);
}
}
/// <summary>
/// Process the web response.
/// </summary>
/// <param name="webRequest">The request object.</param>
/// <returns>The response data.</returns>
/// TODO: This method should handle the StatusCode better!
public static string GetResponseAsString(HttpWebRequest webRequest)
{
return GetResponseAsString(webRequest, false);
}
/// <summary>
/// Read the response as string
/// </summary>
/// <param name="response"></param>
/// <returns>string or null</returns>
private static string GetResponseAsString(HttpWebResponse response)
{
string responseData = null;
if (response == null)
{
return null;
}
using (response)
{
Stream responseStream = response.GetResponseStream();
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream, true))
{
responseData = reader.ReadToEnd();
}
}
}
return responseData;
}
/// <summary>
///
/// </summary>
/// <param name="webRequest"></param>
/// <returns></returns>
public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError)
{
string responseData = null;
HttpWebResponse response = null;
bool isHttpError = false;
try
{
response = (HttpWebResponse)webRequest.GetResponse();
LOG.InfoFormat("Response status: {0}", response.StatusCode);
isHttpError = (int)response.StatusCode >= 300;
if (isHttpError)
{
LOG.ErrorFormat("HTTP error {0}", response.StatusCode);
}
DebugHeaders(response);
responseData = GetResponseAsString(response);
if (isHttpError)
{
LOG.ErrorFormat("HTTP response {0}", responseData);
}
}
catch (WebException e)
{
response = (HttpWebResponse)e.Response;
HttpStatusCode statusCode = HttpStatusCode.Unused;
if (response != null)
{
statusCode = response.StatusCode;
LOG.ErrorFormat("HTTP error {0}", statusCode);
string errorContent = GetResponseAsString(response);
if (alsoReturnContentOnError)
{
return errorContent;
}
LOG.ErrorFormat("Content: {0}", errorContent);
}
LOG.Error("WebException: ", e);
if (statusCode == HttpStatusCode.Unauthorized)
{
throw new UnauthorizedAccessException(e.Message);
}
throw;
}
finally
{
if (response != null)
{
if (isHttpError)
{
LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData);
}
response.Close();
}
}
return responseData;
}
/// <summary>
/// Get LastModified for a URI
/// </summary>
/// <param name="uri">Uri</param>
/// <returns>DateTime</returns>
public static DateTime GetLastModified(Uri uri)
{
try
{
HttpWebRequest webRequest = CreateWebRequest(uri);
webRequest.Method = HTTPMethod.HEAD.ToString();
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
return webResponse.LastModified;
}
}
catch (Exception wE)
{
LOG.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri);
LOG.Warn(wE.Message);
// Pretend it is old
return DateTime.MinValue;
}
}
}
/// <summary>
/// This interface can be used to pass binary information around, like byte[] or Image
/// </summary>
public interface IBinaryContainer
{
void WriteFormDataToStream(string boundary, string name, Stream formDataStream);
void WriteToStream(Stream formDataStream);
string ToBase64String(Base64FormattingOptions formattingOptions);
byte[] ToByteArray();
void Upload(HttpWebRequest webRequest);
}
/// <summary>
/// A container to supply files to a Multi-part form data upload
/// </summary>
public class ByteContainer : IBinaryContainer
{
private byte[] file;
private string fileName;
private string contentType;
private int fileSize;
public ByteContainer(byte[] file) : this(file, null)
{
}
public ByteContainer(byte[] file, string filename) : this(file, filename, null)
{
}
public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0)
{
}
public ByteContainer(byte[] file, string filename, string contenttype, int filesize)
{
this.file = file;
fileName = filename;
contentType = contenttype;
if (filesize == 0)
{
fileSize = file.Length;
}
else
{
fileSize = filesize;
}
}
/// <summary>
/// Create a Base64String from the byte[]
/// </summary>
/// <returns>string</returns>
public string ToBase64String(Base64FormattingOptions formattingOptions)
{
return Convert.ToBase64String(file, 0, fileSize, formattingOptions);
}
/// <summary>
/// Returns the initial byte-array which was supplied when creating the FileParameter
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
return file;
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Separator</param>
/// <param name="name">name</param>
/// <param name="formDataStream">Stream to write to</param>
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
{
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
name,
fileName ?? name,
contentType ?? "application/octet-stream");
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
formDataStream.Write(file, 0, fileSize);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream">Stream to write to</param>
public void WriteToStream(Stream dataStream)
{
// Write the file data directly to the Stream, rather than serializing it to a string.
dataStream.Write(file, 0, fileSize);
}
/// <summary>
/// Upload the file to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = contentType;
webRequest.ContentLength = fileSize;
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
/// <summary>
/// A container to supply images to a Multi-part form data upload
/// </summary>
public class BitmapContainer : IBinaryContainer
{
private Bitmap bitmap;
private SurfaceOutputSettings outputSettings;
private string fileName;
public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename)
{
this.bitmap = bitmap;
this.outputSettings = outputSettings;
fileName = filename;
}
/// <summary>
/// Create a Base64String from the image by saving it to a memory stream and converting it.
/// Should be avoided if possible, as this uses a lot of memory.
/// </summary>
/// <returns>string</returns>
public string ToBase64String(Base64FormattingOptions formattingOptions)
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(bitmap, null, stream, outputSettings);
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
}
}
/// <summary>
/// Create a byte[] from the image by saving it to a memory stream.
/// Should be avoided if possible, as this uses a lot of memory.
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(bitmap, null, stream, outputSettings);
return stream.ToArray();
}
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Separator</param>
/// <param name="name">Name of the thing/file</param>
/// <param name="formDataStream">Stream to write to</param>
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
{
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
name,
fileName ?? name,
"image/" + outputSettings.Format.ToString());
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
ImageOutput.SaveToStream(bitmap, null, formDataStream, outputSettings);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream"></param>
public void WriteToStream(Stream dataStream)
{
// Write the file data directly to the Stream, rather than serializing it to a string.
ImageOutput.SaveToStream(bitmap, null, dataStream, outputSettings);
}
/// <summary>
/// Upload the image to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = "image/" + outputSettings.Format.ToString();
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
/// <summary>
/// A container to supply surfaces to a Multi-part form data upload
/// </summary>
public class SurfaceContainer : IBinaryContainer
{
private ISurface surface;
private SurfaceOutputSettings outputSettings;
private string fileName;
public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename)
{
this.surface = surface;
this.outputSettings = outputSettings;
fileName = filename;
}
/// <summary>
/// Create a Base64String from the Surface by saving it to a memory stream and converting it.
/// Should be avoided if possible, as this uses a lot of memory.
/// </summary>
/// <returns>string</returns>
public string ToBase64String(Base64FormattingOptions formattingOptions)
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(surface, stream, outputSettings);
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
}
}
/// <summary>
/// Create a byte[] from the image by saving it to a memory stream.
/// Should be avoided if possible, as this uses a lot of memory.
/// </summary>
/// <returns>byte[]</returns>
public byte[] ToByteArray()
{
using (MemoryStream stream = new MemoryStream())
{
ImageOutput.SaveToStream(surface, stream, outputSettings);
return stream.ToArray();
}
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </summary>
/// <param name="boundary">Multipart separator</param>
/// <param name="name">Name of the thing</param>
/// <param name="formDataStream">Stream to write to</param>
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
{
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
name,
fileName ?? name,
"image/" + outputSettings.Format);
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
ImageOutput.SaveToStream(surface, formDataStream, outputSettings);
}
/// <summary>
/// A plain "write data to stream"
/// </summary>
/// <param name="dataStream"></param>
public void WriteToStream(Stream dataStream)
{
// Write the file data directly to the Stream, rather than serializing it to a string.
ImageOutput.SaveToStream(surface, dataStream, outputSettings);
}
/// <summary>
/// Upload the Surface as image to the webrequest
/// </summary>
/// <param name="webRequest"></param>
public void Upload(HttpWebRequest webRequest)
{
webRequest.ContentType = "image/" + outputSettings.Format.ToString();
using (var requestStream = webRequest.GetRequestStream())
{
WriteToStream(requestStream);
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -0,0 +1,292 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using Greenshot.IniFile;
using Greenshot.Plugin;
using GreenshotPlugin.UnmanagedHelpers;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Description of PluginUtils.
/// </summary>
public static class PluginUtils
{
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private const string PATH_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
private static IDictionary<string, Image> exeIconCache = new Dictionary<string, Image>();
static PluginUtils()
{
conf.PropertyChanged += OnIconSizeChanged;
}
/// <summary>
/// Simple global property to get the Greenshot host
/// </summary>
public static IGreenshotHost Host
{
get;
set;
}
/// <summary>
/// Clear icon cache
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IconSize")
{
List<Image> cachedImages = new List<Image>();
lock (exeIconCache)
{
foreach (string key in exeIconCache.Keys)
{
cachedImages.Add(exeIconCache[key]);
}
exeIconCache.Clear();
}
foreach (Image cachedImage in cachedImages)
{
if (cachedImage != null)
{
cachedImage.Dispose();
}
}
}
}
/// <summary>
/// Get the path of an executable
/// </summary>
/// <param name="exeName">e.g. cmd.exe</param>
/// <returns>Path to file</returns>
public static string GetExePath(string exeName)
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PATH_KEY + exeName, false))
{
if (key != null)
{
// "" is the default key, which should point to the requested location
return (string)key.GetValue("");
}
}
foreach (string pathEntry in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(';'))
{
try
{
string path = pathEntry.Trim();
if (!String.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exeName)))
{
return Path.GetFullPath(path);
}
}
catch (Exception)
{
LOG.WarnFormat("Problem with path entry '{0}'.", pathEntry);
}
}
return null;
}
/// <summary>
/// Get icon for executable, from the cache
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
public static Image GetCachedExeIcon(string path, int index)
{
string cacheKey = string.Format("{0}:{1}", path, index);
Image returnValue;
if (!exeIconCache.TryGetValue(cacheKey, out returnValue))
{
lock (exeIconCache)
{
if (!exeIconCache.TryGetValue(cacheKey, out returnValue))
{
returnValue = GetExeIcon(path, index);
if (returnValue != null)
{
exeIconCache.Add(cacheKey, returnValue);
}
}
}
}
return returnValue;
}
/// <summary>
/// Get icon for executable
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
private static Bitmap GetExeIcon(string path, int index)
{
if (!File.Exists(path))
{
return null;
}
try
{
using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, conf.UseLargeIcons))
{
if (appIcon != null)
{
return appIcon.ToBitmap();
}
}
using (Icon appIcon = Shell32.GetFileIcon(path, conf.UseLargeIcons ? Shell32.IconSize.Large : Shell32.IconSize.Small, false))
{
if (appIcon != null)
{
return appIcon.ToBitmap();
}
}
}
catch (Exception exIcon)
{
LOG.Error("error retrieving icon: ", exIcon);
}
return null;
}
/// <summary>
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
/// </summary>
/// <param name="image">Image to display in the menu</param>
/// <param name="text">Text to display in the menu</param>
/// <param name="tag">The TAG value</param>
/// <param name="shortcutKeys">Keys which can be used as shortcut</param>
/// <param name="handler">The onclick handler</param>
public static void AddToFileMenu(IImageEditor imageEditor, Image image, string text, object tag, Keys? shortcutKeys, EventHandler handler)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Image = image;
item.Text = text;
item.Tag = tag;
if (shortcutKeys.HasValue)
{
item.ShortcutKeys = shortcutKeys.Value;
}
item.Click += handler;
AddToFileMenu(imageEditor, item);
}
/// <summary>
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item)
{
ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem();
bool added = false;
for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++)
{
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator))
{
toolStripMenuItem.DropDownItems.Insert(i, item);
added = true;
break;
}
}
if (!added)
{
toolStripMenuItem.DropDownItems.Add(item);
}
}
/// <summary>
/// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item)
{
ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem();
bool added = false;
for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++)
{
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator))
{
toolStripMenuItem.DropDownItems.Insert(i, item);
added = true;
break;
}
}
if (!added)
{
toolStripMenuItem.DropDownItems.Add(item);
}
}
/// <summary>
/// Helper method to add a plugin MenuItem to the Greenshot context menu
/// </summary>
/// <param name="imageEditor"></param>
/// <param name="item"></param>
public static void AddToContextMenu(IGreenshotHost host, ToolStripMenuItem item)
{
// Here we can hang ourselves to the main context menu!
ContextMenuStrip contextMenu = host.MainMenu;
bool addedItem = false;
// Try to find a separator, so we insert ourselves after it
for (int i = 0; i < contextMenu.Items.Count; i++)
{
if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator))
{
// Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore"
if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag))
{
ToolStripSeparator separator = new ToolStripSeparator();
separator.Tag = "PluginsAreAddedAfter";
separator.Size = new Size(305, 6);
contextMenu.Items.Insert(i, separator);
}
else if (!"PluginsAreAddedAfter".Equals(contextMenu.Items[i].Tag))
{
continue;
}
contextMenu.Items.Insert(i + 1, item);
addedItem = true;
break;
}
}
// If we didn't insert the item, we just add it...
if (!addedItem)
{
contextMenu.Items.Add(item);
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -652,7 +652,7 @@ private Single Maximize(WuColorCube cube, Int32 direction, Int32 first, Int32 la
// the cube cannot be cut at bottom (this would lead to empty cube)
if (halfWeight != 0)
{
Single halfDistance = halfRed * halfRed + halfGreen * halfGreen + halfBlue * halfBlue;
Single halfDistance = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)halfBlue * halfBlue;
Single temp = halfDistance / halfWeight;
halfRed = wholeRed - halfRed;
@ -662,7 +662,7 @@ private Single Maximize(WuColorCube cube, Int32 direction, Int32 first, Int32 la
if (halfWeight != 0)
{
halfDistance = halfRed * halfRed + halfGreen * halfGreen + halfBlue * halfBlue;
halfDistance = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)halfBlue * halfBlue;
temp += halfDistance / halfWeight;
if (temp > result)

View file

@ -0,0 +1,191 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace GreenshotPlugin.Core
{
public static class StringExtensions
{
private const string RGBIV = "dlgjowejgogkklwj";
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
/// <summary>
/// Format a string with the specified object
/// </summary>
/// <param name="format">String with formatting, like {name}</param>
/// <param name="source">Object used for the formatting</param>
/// <returns>Formatted string</returns>
public static string FormatWith(this string format, object source)
{
return FormatWith(format, null, source);
}
/// <summary>
/// Format the string "format" with the source
/// </summary>
/// <param name="format"></param>
/// <param name="provider"></param>
/// <param name="source">object with properties, if a property has the type IDictionary string,string it can used these parameters too</param>
/// <returns>Formatted string</returns>
public static string FormatWith(this string format, IFormatProvider provider, object source)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
IDictionary<string, object> properties = new Dictionary<string, object>();
foreach (var propertyInfo in source.GetType().GetProperties())
{
if (propertyInfo.CanRead && propertyInfo.CanWrite)
{
object value = propertyInfo.GetValue(source, null);
if (propertyInfo.PropertyType != typeof(IDictionary<string, string>))
{
properties.Add(propertyInfo.Name, value);
}
else
{
IDictionary<string, string> dictionary = (IDictionary<string, string>)value;
foreach (var propertyKey in dictionary.Keys)
{
properties.Add(propertyKey, dictionary[propertyKey]);
}
}
}
}
Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
List<object> values = new List<object>();
string rewrittenFormat = r.Replace(format, delegate (Match m)
{
Group startGroup = m.Groups["start"];
Group propertyGroup = m.Groups["property"];
Group formatGroup = m.Groups["format"];
Group endGroup = m.Groups["end"];
object value;
if (properties.TryGetValue(propertyGroup.Value, out value))
{
values.Add(value);
}
else
{
values.Add(source);
}
return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value + new string('}', endGroup.Captures.Count);
});
return string.Format(provider, rewrittenFormat, values.ToArray());
}
/// <summary>
/// A simply rijndael aes encryption, can be used to store passwords
/// </summary>
/// <param name="ClearText">the string to call upon</param>
/// <returns>an encryped string in base64 form</returns>
public static string Encrypt(this string ClearText)
{
string returnValue = ClearText;
try
{
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
using (MemoryStream ms = new MemoryStream())
{
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
byte[] key = Encoding.ASCII.GetBytes(KEY);
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write))
{
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
cs.FlushFinalBlock();
returnValue = Convert.ToBase64String(ms.ToArray());
}
}
}
catch (Exception ex)
{
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
}
return returnValue;
}
/// <summary>
/// A simply rijndael aes decryption, can be used to store passwords
/// </summary>
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
/// <returns>Decrypeted text</returns>
public static string Decrypt(this string EncryptedText)
{
string returnValue = EncryptedText;
try
{
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
using (MemoryStream ms = new MemoryStream())
{
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
byte[] key = Encoding.ASCII.GetBytes(KEY);
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write))
{
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
cs.FlushFinalBlock();
returnValue = Encoding.ASCII.GetString(ms.ToArray());
}
}
}
catch (Exception ex)
{
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
}
return returnValue;
}
/// <summary>
/// Read "streamextensions" :)
/// </summary>
/// <param name="input">Stream</param>
/// <param name="output">Stream</param>
public static void CopyTo(this Stream input, Stream output)
{
byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -38,52 +38,36 @@ namespace GreenshotPlugin.Core
/// </summary>
public class CaptureDetails : ICaptureDetails
{
private string title;
public string Title
{
get { return title; }
set { title = value; }
get;
set;
}
private string filename;
public string Filename
{
get { return filename; }
set { filename = value; }
get;
set;
}
private DateTime dateTime;
public DateTime DateTime
{
get { return dateTime; }
set { dateTime = value; }
get;
set;
}
private float dpiX;
public float DpiX
{
get
{
return dpiX;
}
set
{
dpiX = value;
}
get;
set;
}
private float dpiY;
public float DpiY
{
get
{
return dpiY;
}
set
{
dpiY = value;
}
get;
set;
}
private Dictionary<string, string> metaData = new Dictionary<string, string>();
public Dictionary<string, string> MetaData
{
@ -102,44 +86,43 @@ public void AddMetaData(string key, string value)
}
}
private CaptureMode captureMode;
public CaptureMode CaptureMode
{
get { return captureMode; }
set { captureMode = value; }
get;
set;
}
private List<IDestination> captureDestinations = new List<IDestination>();
private List<IDestination> _captureDestinations = new List<IDestination>();
public List<IDestination> CaptureDestinations
{
get { return captureDestinations; }
set { captureDestinations = value; }
get { return _captureDestinations; }
set { _captureDestinations = value; }
}
public void ClearDestinations()
{
captureDestinations.Clear();
_captureDestinations.Clear();
}
public void RemoveDestination(IDestination destination)
{
if (captureDestinations.Contains(destination))
if (_captureDestinations.Contains(destination))
{
captureDestinations.Remove(destination);
_captureDestinations.Remove(destination);
}
}
public void AddDestination(IDestination captureDestination)
{
if (!captureDestinations.Contains(captureDestination))
if (!_captureDestinations.Contains(captureDestination))
{
captureDestinations.Add(captureDestination);
_captureDestinations.Add(captureDestination);
}
}
public bool HasDestination(string designation)
{
foreach (IDestination destination in captureDestinations)
foreach (IDestination destination in _captureDestinations)
{
if (designation.Equals(destination.Designation))
{
@ -151,7 +134,7 @@ public bool HasDestination(string designation)
public CaptureDetails()
{
dateTime = DateTime.Now;
DateTime = DateTime.Now;
}
}
@ -159,11 +142,11 @@ public CaptureDetails()
/// This class is used to pass an instance of the "Capture" around
/// Having the Bitmap, eventually the Windows Title and cursor all together.
/// </summary>
public class Capture : IDisposable, ICapture
public class Capture : ICapture
{
private List<ICaptureElement> elements = new List<ICaptureElement>();
private List<ICaptureElement> _elements = new List<ICaptureElement>();
private Rectangle screenBounds;
private Rectangle _screenBounds = Rectangle.Empty;
/// <summary>
/// Get/Set the Screenbounds
/// </summary>
@ -171,19 +154,19 @@ public Rectangle ScreenBounds
{
get
{
if (screenBounds == null)
if (_screenBounds == Rectangle.Empty)
{
screenBounds = WindowCapture.GetScreenBounds();
_screenBounds = WindowCapture.GetScreenBounds();
}
return screenBounds;
return _screenBounds;
}
set
{
screenBounds = value;
_screenBounds = value;
}
}
private Image image;
private Image _image;
/// <summary>
/// Get/Set the Image
/// </summary>
@ -191,15 +174,15 @@ public Image Image
{
get
{
return image;
return _image;
}
set
{
if (image != null)
if (_image != null)
{
image.Dispose();
_image.Dispose();
}
image = value;
_image = value;
if (value != null)
{
if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format4bppIndexed))
@ -208,7 +191,7 @@ public Image Image
try
{
// Default Bitmap PixelFormat is Format32bppArgb
image = new Bitmap(value);
_image = new Bitmap(value);
}
finally
{
@ -216,7 +199,7 @@ public Image Image
value.Dispose();
}
}
LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", image.Size, image.PixelFormat);
LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", _image.Size, _image.PixelFormat);
}
else
{
@ -227,10 +210,10 @@ public Image Image
public void NullImage()
{
image = null;
_image = null;
}
private Icon cursor;
private Icon _cursor;
/// <summary>
/// Get/Set the image for the Cursor
/// </summary>
@ -238,56 +221,56 @@ public Icon Cursor
{
get
{
return cursor;
return _cursor;
}
set
{
if (cursor != null)
if (_cursor != null)
{
cursor.Dispose();
_cursor.Dispose();
}
cursor = (Icon)value.Clone();
_cursor = (Icon)value.Clone();
}
}
private bool cursorVisible = false;
private bool _cursorVisible;
/// <summary>
/// Set if the cursor is visible
/// </summary>
public bool CursorVisible
{
get { return cursorVisible; }
set { cursorVisible = value; }
get { return _cursorVisible; }
set { _cursorVisible = value; }
}
private Point cursorLocation = Point.Empty;
private Point _cursorLocation = Point.Empty;
/// <summary>
/// Get/Set the CursorLocation
/// </summary>
public Point CursorLocation
{
get { return cursorLocation; }
set { cursorLocation = value; }
get { return _cursorLocation; }
set { _cursorLocation = value; }
}
private Point location = Point.Empty;
private Point _location = Point.Empty;
/// <summary>
/// Get/set the Location
/// </summary>
public Point Location
{
get { return location; }
set { location = value; }
get { return _location; }
set { _location = value; }
}
private CaptureDetails captureDetails;
private CaptureDetails _captureDetails;
/// <summary>
/// Get/set the CaptureDetails
/// </summary>
public ICaptureDetails CaptureDetails
{
get { return captureDetails; }
set { captureDetails = (CaptureDetails)value; }
get { return _captureDetails; }
set { _captureDetails = (CaptureDetails)value; }
}
/// <summary>
@ -295,8 +278,8 @@ public ICaptureDetails CaptureDetails
/// </summary>
public Capture()
{
screenBounds = WindowCapture.GetScreenBounds();
captureDetails = new CaptureDetails();
_screenBounds = WindowCapture.GetScreenBounds();
_captureDetails = new CaptureDetails();
}
/// <summary>
@ -304,8 +287,7 @@ public Capture()
/// Note: the supplied bitmap can be disposed immediately or when constructor is called.
/// </summary>
/// <param name="newImage">Image</param>
public Capture(Image newImage)
: this()
public Capture(Image newImage) : this()
{
Image = newImage;
}
@ -337,17 +319,17 @@ protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (image != null)
if (_image != null)
{
image.Dispose();
_image.Dispose();
}
if (cursor != null)
if (_cursor != null)
{
cursor.Dispose();
_cursor.Dispose();
}
}
image = null;
cursor = null;
_image = null;
_cursor = null;
}
/// <summary>
@ -357,24 +339,25 @@ protected virtual void Dispose(bool disposing)
public bool Crop(Rectangle cropRectangle)
{
LOG.Debug("Cropping to: " + cropRectangle.ToString());
if (ImageHelper.Crop(ref image, ref cropRectangle))
if (ImageHelper.Crop(ref _image, ref cropRectangle))
{
location = cropRectangle.Location;
_location = cropRectangle.Location;
// Change mouse location according to the cropRegtangle (including screenbounds) offset
MoveMouseLocation(-cropRectangle.Location.X, -cropRectangle.Location.Y);
// Move all the elements
// TODO: Enable when the elements are usable again.
// MoveElements(-cropRectangle.Location.X, -cropRectangle.Location.Y);
// Remove invisible elements
List<ICaptureElement> newElements = new List<ICaptureElement>();
foreach (ICaptureElement captureElement in elements)
foreach (ICaptureElement captureElement in _elements)
{
if (captureElement.Bounds.IntersectsWith(cropRectangle))
{
newElements.Add(captureElement);
}
}
elements = newElements;
_elements = newElements;
return true;
}
@ -389,9 +372,10 @@ public bool Crop(Rectangle cropRectangle)
/// <param name="y">y coordinates to move the mouse</param>
public void MoveMouseLocation(int x, int y)
{
cursorLocation.Offset(x, y);
_cursorLocation.Offset(x, y);
}
// TODO: Enable when the elements are usable again.
///// <summary>
///// Apply a translate to the elements
///// e.g. needed for crop
@ -461,16 +445,16 @@ public CaptureElement(string name, Rectangle bounds)
Bounds = bounds;
}
private List<ICaptureElement> children = new List<ICaptureElement>();
private List<ICaptureElement> _children = new List<ICaptureElement>();
public List<ICaptureElement> Children
{
get
{
return children;
return _children;
}
set
{
children = value;
_children = value;
}
}
@ -489,10 +473,10 @@ public Rectangle Bounds
public override bool Equals(object obj)
{
bool ret = false;
if (obj != null && GetType().Equals(obj.GetType()))
if (obj != null && GetType() == obj.GetType())
{
CaptureElement other = obj as CaptureElement;
if (Bounds.Equals(other.Bounds))
if (other != null && Bounds.Equals(other.Bounds))
{
ret = true;
}
@ -511,7 +495,7 @@ public override int GetHashCode()
/// </summary>
public class WindowCapture
{
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection<CoreConfiguration>();
/// <summary>
/// Used to cleanup the unmanged resource in the iconInfo for the CaptureCursor method
@ -544,36 +528,16 @@ public static Rectangle GetScreenBounds()
return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top)));
}
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7.
/// <returns>Point with cursor location, relative to the origin of the monitor setup (i.e. negative coordinates are
/// possible in multiscreen setups)</returns>
public static Point GetCursorLocation()
{
if (Environment.OSVersion.Version.Major >= 6)
{
POINT cursorLocation;
if (User32.GetPhysicalCursorPos(out cursorLocation))
{
return new Point(cursorLocation.X, cursorLocation.Y);
}
else
{
Win32Error error = Win32.GetLastErrorCode();
LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error));
}
}
return new Point(Cursor.Position.X, Cursor.Position.Y);
}
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
/// <returns>Point with cursor location, relative to the top left corner of the monitor setup (which itself might
/// actually not be on any screen)</returns>
/// </summary>
/// <returns>
/// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen)
/// </returns>
public static Point GetCursorLocationRelativeToScreenBounds()
{
return GetLocationRelativeToScreenBounds(GetCursorLocation());
return GetLocationRelativeToScreenBounds(User32.GetCursorLocation());
}
/// <summary>
@ -614,7 +578,7 @@ public static ICapture CaptureCursor(ICapture capture)
{
if (User32.GetIconInfo(safeIcon, out iconInfo))
{
Point cursorLocation = GetCursorLocation();
Point cursorLocation = User32.GetCursorLocation();
// Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X;
y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y;
@ -658,7 +622,6 @@ public static ICapture CaptureScreen(ICapture capture)
/// Helper method to create an exception that might explain what is wrong while capturing
/// </summary>
/// <param name="method">string with current method</param>
/// <param name="capture">ICapture</param>
/// <param name="captureBounds">Rectangle of what we want to capture</param>
/// <returns></returns>
private static Exception CreateCaptureException(string method, Rectangle captureBounds)
@ -677,16 +640,16 @@ private static Exception CreateCaptureException(string method, Rectangle capture
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
public static bool isDWMAllowed(Process process)
public static bool IsDwmAllowed(Process process)
{
if (process != null)
{
if (conf.NoDWMCaptureForProduct != null && conf.NoDWMCaptureForProduct.Count > 0)
if (Configuration.NoDWMCaptureForProduct != null && Configuration.NoDWMCaptureForProduct.Count > 0)
{
try
{
string productName = process.MainModule.FileVersionInfo.ProductName;
if (productName != null && conf.NoDWMCaptureForProduct.Contains(productName.ToLower()))
if (productName != null && Configuration.NoDWMCaptureForProduct.Contains(productName.ToLower()))
{
return false;
}
@ -703,18 +666,18 @@ public static bool isDWMAllowed(Process process)
/// <summary>
/// Helper method to check if it is allowed to capture the process using GDI
/// </summary>
/// <param name="processName">Process owning the window</param>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
public static bool isGDIAllowed(Process process)
public static bool IsGdiAllowed(Process process)
{
if (process != null)
{
if (conf.NoGDICaptureForProduct != null && conf.NoGDICaptureForProduct.Count > 0)
if (Configuration.NoGDICaptureForProduct != null && Configuration.NoGDICaptureForProduct.Count > 0)
{
try
{
string productName = process.MainModule.FileVersionInfo.ProductName;
if (productName != null && conf.NoGDICaptureForProduct.Contains(productName.ToLower()))
if (productName != null && Configuration.NoGDICaptureForProduct.Contains(productName.ToLower()))
{
return false;
}
@ -735,6 +698,40 @@ public static bool isGDIAllowed(Process process)
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds)
{
if (capture == null)
{
capture = new Capture();
}
Image capturedImage = null;
// If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here
if (CaptureHandler.CaptureScreenRectangle != null)
{
try
{
capturedImage = CaptureHandler.CaptureScreenRectangle(captureBounds);
}
catch
{
}
}
// If no capture, use the normal screen capture
if (capturedImage == null)
{
capturedImage = CaptureRectangle(captureBounds);
}
capture.Image = capturedImage;
capture.Location = captureBounds.Location;
return capture.Image == null ? null : capture;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds)
{
if (capture == null)
{
@ -742,15 +739,7 @@ public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBound
}
capture.Image = CaptureRectangle(captureBounds);
capture.Location = captureBounds.Location;
if (capture.CaptureDetails != null)
{
((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY);
}
if (capture.Image == null)
{
return null;
}
return capture;
return capture.Image == null ? null : capture;
}
/// <summary>
@ -766,10 +755,8 @@ public static Bitmap CaptureRectangle(Rectangle captureBounds)
LOG.Warn("Nothing to capture, ignoring!");
return null;
}
else
{
LOG.Debug("CaptureRectangle Called!");
}
LOG.Debug("CaptureRectangle Called!");
// .NET GDI+ Solution, according to some post this has a GDI+ leak...
// See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen
// Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height);
@ -800,15 +787,15 @@ public static Bitmap CaptureRectangle(Rectangle captureBounds)
// throw exception
throw exceptionToThrow;
}
// Create BitmapInfoHeader for CreateDIBSection
BitmapInfoHeader bmi = new BitmapInfoHeader(captureBounds.Width, captureBounds.Height, 24);
// Create BITMAPINFOHEADER for CreateDIBSection
BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24);
// Make sure the last error is set to 0
Win32.SetLastError(0);
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
using (SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDCHandle, ref bmi, BitmapInfoHeader.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0))
using (SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDCHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0))
{
if (safeDibSectionHandle.IsInvalid)
{
@ -820,87 +807,87 @@ public static Bitmap CaptureRectangle(Rectangle captureBounds)
// Throw so people can report the problem
throw exceptionToThrow;
}
else
// select the bitmap object and store the old handle
using (safeCompatibleDCHandle.SelectObject(safeDibSectionHandle))
{
// select the bitmap object and store the old handle
using (SafeSelectObjectHandle selectObject = safeCompatibleDCHandle.SelectObject(safeDibSectionHandle))
{
// bitblt over (make copy)
GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
}
// bitblt over (make copy)
GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
}
// get a .NET image object for it
// A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
bool success = false;
ExternalException exception = null;
for (int i = 0; i < 3; i++)
// get a .NET image object for it
// A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
bool success = false;
ExternalException exception = null;
for (int i = 0; i < 3; i++)
{
try
{
try
// Collect all screens inside this capture
List<Screen> screensInsideCapture = new List<Screen>();
foreach (Screen screen in Screen.AllScreens)
{
// Collect all screens inside this capture
List<Screen> screensInsideCapture = new List<Screen>();
foreach (Screen screen in Screen.AllScreens)
if (screen.Bounds.IntersectsWith(captureBounds))
{
if (screen.Bounds.IntersectsWith(captureBounds))
{
screensInsideCapture.Add(screen);
}
screensInsideCapture.Add(screen);
}
// Check all all screens are of an equal size
bool offscreenContent = false;
using (Region captureRegion = new Region(captureBounds))
}
// Check all all screens are of an equal size
bool offscreenContent;
using (Region captureRegion = new Region(captureBounds))
{
// Exclude every visible part
foreach (Screen screen in screensInsideCapture)
{
// Exclude every visible part
foreach (Screen screen in screensInsideCapture)
{
captureRegion.Exclude(screen.Bounds);
}
// If the region is not empty, we have "offscreenContent"
using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow()))
{
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
}
captureRegion.Exclude(screen.Bounds);
}
// Check if we need to have a transparent background, needed for offscreen content
if (offscreenContent)
// If the region is not empty, we have "offscreenContent"
using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow()))
{
using (Bitmap tmpBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()))
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
}
}
// Check if we need to have a transparent background, needed for offscreen content
if (offscreenContent)
{
using (Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()))
{
// Create a new bitmap which has a transparent background
returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
// Content will be copied here
using (Graphics graphics = Graphics.FromImage(returnBitmap))
{
// Create a new bitmap which has a transparent background
returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
// Content will be copied here
using (Graphics graphics = Graphics.FromImage(returnBitmap))
// For all screens copy the content to the new bitmap
foreach (Screen screen in Screen.AllScreens)
{
// For all screens copy the content to the new bitmap
foreach (Screen screen in Screen.AllScreens)
{
Rectangle screenBounds = screen.Bounds;
// Make sure the bounds are offsetted to the capture bounds
screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
}
Rectangle screenBounds = screen.Bounds;
// Make sure the bounds are offsetted to the capture bounds
screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
}
}
}
else
{
// All screens, which are inside the capture, are of equal size
// assign image to Capture, the image will be disposed there..
returnBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
}
// We got through the capture without exception
success = true;
break;
}
catch (ExternalException ee)
else
{
LOG.Warn("Problem getting bitmap at try " + i + " : ", ee);
exception = ee;
// All screens, which are inside the capture, are of equal size
// assign image to Capture, the image will be disposed there..
returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
}
// We got through the capture without exception
success = true;
break;
}
if (!success)
catch (ExternalException ee)
{
LOG.Warn("Problem getting bitmap at try " + i + " : ", ee);
exception = ee;
}
}
if (!success)
{
LOG.Error("Still couldn't create Bitmap!");
if (exception != null)
{
LOG.Error("Still couldn't create Bitmap!");
throw exception;
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -26,7 +26,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
@ -79,7 +78,7 @@ public WindowsEnumerator GetWindows()
/// <summary>
/// Gets all child windows of the specified window
/// </summary>
/// <param name="hWndParent">Window Handle to get children for</param>
/// <param name="parent">Window Handle to get children for</param>
public WindowsEnumerator GetWindows(WindowDetails parent)
{
if (parent != null)
@ -102,7 +101,7 @@ public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname)
{
items = new List<WindowDetails>();
List<WindowDetails> windows = new List<WindowDetails>();
User32.EnumChildWindows(hWndParent, WindowEnum, 0);
User32.EnumChildWindows(hWndParent, new EnumWindowsProc(WindowEnum), IntPtr.Zero);
bool hasParent = !IntPtr.Zero.Equals(hWndParent);
string parentText = null;
@ -190,17 +189,14 @@ public WindowsEnumerator()
/// Provides details about a Window returned by the
/// enumeration
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
public class WindowDetails : IEquatable<WindowDetails>
{
private const string METRO_WINDOWS_CLASS = "Windows.UI.Core.CoreWindow";
private const string METRO_APPLAUNCHER_CLASS = "ImmersiveLauncher";
private const string METRO_GUTTER_CLASS = "ImmersiveGutter";
private static Dictionary<string, List<string>> classnameTree = new Dictionary<string, List<string>>();
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private static List<IntPtr> ignoreHandles = new List<IntPtr>();
private static Dictionary<string, Image> iconCache = new Dictionary<string, Image>();
private static List<string> excludeProcessesFromFreeze = new List<string>();
private static IAppVisibility appVisibility = null;
@ -208,7 +204,7 @@ static WindowDetails()
{
try
{
// Only try to instanciate when Windows 8 or later.
// Only try to instantiate when Windows 8 or later.
if (Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2)
{
appVisibility = COMWrapper.CreateInstance<IAppVisibility>();
@ -338,7 +334,7 @@ public string ProcessPath
return string.Empty;
}
// Get the process id
IntPtr processid;
int processid;
User32.GetWindowThreadProcessId(Handle, out processid);
return Kernel32.GetProcessPath(processid);
}
@ -373,20 +369,7 @@ public Image DisplayIcon
}
try
{
string filename = ProcessPath;
if (!iconCache.ContainsKey(filename))
{
Image icon = null;
using (Icon appIcon = Shell32.ExtractAssociatedIcon(filename))
{
if (appIcon != null)
{
icon = appIcon.ToBitmap();
}
}
iconCache.Add(filename, icon);
}
return iconCache[filename];
return PluginUtils.GetCachedExeIcon(ProcessPath, 0);
}
catch (Exception ex)
{
@ -404,14 +387,26 @@ public Image DisplayIcon
/// <returns></returns>
private static Icon GetAppIcon(IntPtr hwnd)
{
const int ICON_SMALL = 0;
const int ICON_BIG = 1;
const int ICON_SMALL2 = 2;
IntPtr ICON_SMALL = IntPtr.Zero;
IntPtr ICON_BIG = new IntPtr(1);
IntPtr ICON_SMALL2 = new IntPtr(2);
IntPtr iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL2, 0);
IntPtr iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero);
if (conf.UseLargeIcons)
{
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero);
if (iconHandle == IntPtr.Zero)
{
iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICON);
}
}
else
{
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL2, IntPtr.Zero);
}
if (iconHandle == IntPtr.Zero)
{
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL, 0);
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_SMALL, IntPtr.Zero);
}
if (iconHandle == IntPtr.Zero)
{
@ -419,7 +414,7 @@ private static Icon GetAppIcon(IntPtr hwnd)
}
if (iconHandle == IntPtr.Zero)
{
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, 0);
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero);
}
if (iconHandle == IntPtr.Zero)
{
@ -502,7 +497,7 @@ private static List<WindowDetails> FindWindow(List<WindowDetails> windows, strin
}
/// <summary>
/// Retrieve the child with mathing classname
/// Retrieve the child with matching classname
/// </summary>
public WindowDetails GetChild(string childClassname)
{
@ -517,7 +512,7 @@ public WindowDetails GetChild(string childClassname)
}
/// <summary>
/// Retrieve the children with mathing classname
/// Retrieve the children with matching classname
/// </summary>
public IEnumerable<WindowDetails> GetChilden(string childClassname)
{
@ -610,7 +605,7 @@ public List<WindowDetails> GetChildren(int levelsToGo)
/// </summary>
/// <param name="titlePattern">The regexp to look for in the title</param>
/// <param name="classnamePattern">The regexp to look for in the classname</param>
/// <returns>List<WindowDetails> with all the found windows, or an emptry list</returns>
/// <returns>List<WindowDetails> with all the found windows, or an empty list</returns>
public List<WindowDetails> FindChildren(string titlePattern, string classnamePattern)
{
return FindWindow(Children, titlePattern, classnamePattern);
@ -766,7 +761,7 @@ public string ClassName
}
/// <summary>
/// Gets/Sets whether the window is iconic (mimimised) or not.
/// Gets/Sets whether the window is iconic (mimimized) or not.
/// </summary>
public bool Iconic
{
@ -874,7 +869,7 @@ public bool Visible
}
else
{
// Is only partly on the screen, when this happens the app is allways visible!
// Is only partly on the screen, when this happens the app is always visible!
return true;
}
}
@ -903,11 +898,11 @@ public bool HasParent
}
}
public IntPtr ProcessId
public int ProcessId
{
get
{
IntPtr processId;
int processId;
User32.GetWindowThreadProcessId(Handle, out processId);
return processId;
}
@ -919,9 +914,9 @@ public Process Process
{
try
{
IntPtr processId;
int processId;
User32.GetWindowThreadProcessId(Handle, out processId);
Process process = Process.GetProcessById(processId.ToInt32());
Process process = Process.GetProcessById(processId);
if (process != null)
{
return process;
@ -960,7 +955,7 @@ public Rectangle WindowRectangle
if (previousWindowRectangle.IsEmpty || now - lastWindowRectangleRetrieveTime > CACHE_TIME)
{
Rectangle windowRect = Rectangle.Empty;
if (!HasParent && DWM.isDWMEnabled())
if (DWM.isDWMEnabled())
{
GetExtendedFrameBounds(out windowRect);
}
@ -1210,7 +1205,7 @@ public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptu
// Correct capture size for maximized window by offsetting the X,Y with the border size
captureRectangle.X += borderSize.Width;
captureRectangle.Y += borderSize.Height;
// and subtrackting the border from the size (2 times, as we move right/down for the capture without resizing)
// and subtracting the border from the size (2 times, as we move right/down for the capture without resizing)
captureRectangle.Width -= 2 * borderSize.Width;
captureRectangle.Height -= 2 * borderSize.Height;
}
@ -1220,10 +1215,13 @@ public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptu
if (!doesCaptureFit)
{
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
if (!isMetroApp && WindowCapture.isGDIAllowed(Process))
using (Process thisWindowProcess = Process)
{
// we return null which causes the capturing code to try another method.
return null;
if (!isMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess))
{
// we return null which causes the capturing code to try another method.
return null;
}
}
}
}
@ -1268,7 +1266,7 @@ public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptu
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
// Make sure all changes are processed and visisble
// Make sure all changes are processed and visible
Application.DoEvents();
using (Bitmap blackBitmap = WindowCapture.CaptureRectangle(captureRectangle))
{
@ -1279,7 +1277,7 @@ public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptu
catch (Exception e)
{
LOG.Debug("Exception: ", e);
// Some problem occured, cleanup and make a normal capture
// Some problem occurred, cleanup and make a normal capture
if (capturedBitmap != null)
{
capturedBitmap.Dispose();
@ -1309,7 +1307,7 @@ public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptu
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
// Make sure all changes are processed and visisble
// Make sure all changes are processed and visible
Application.DoEvents();
// Capture from the screen
capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle);
@ -1393,7 +1391,7 @@ private void RemoveCorners(Bitmap image)
/// <summary>
/// Apply transparency by comparing a transparent capture with a black and white background
/// A "Math.min" makes sure there is no overflow, but this could cause the picture to have shifted colors.
/// The pictures should have been taken without differency, exect for the colors.
/// The pictures should have been taken without differency, except for the colors.
/// </summary>
/// <param name="blackBitmap">Bitmap with the black image</param>
/// <param name="whiteBitmap">Bitmap with the black image</param>
@ -1588,32 +1586,34 @@ private bool CanFreezeOrUnfreeze(string titleOrProcessname)
/// </summary>
private bool FreezeWindow()
{
Process proc = Process.GetProcessById(ProcessId.ToInt32());
string processName = proc.ProcessName;
if (!CanFreezeOrUnfreeze(processName))
{
LOG.DebugFormat("Not freezing {0}", processName);
return false;
}
if (!CanFreezeOrUnfreeze(Text))
{
LOG.DebugFormat("Not freezing {0}", processName);
return false;
}
LOG.DebugFormat("Freezing process: {0}", processName);
bool frozen = false;
foreach (ProcessThread pT in proc.Threads)
using (Process proc = Process.GetProcessById(ProcessId))
{
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
string processName = proc.ProcessName;
if (!CanFreezeOrUnfreeze(processName))
{
break;
LOG.DebugFormat("Not freezing {0}", processName);
return false;
}
if (!CanFreezeOrUnfreeze(Text))
{
LOG.DebugFormat("Not freezing {0}", processName);
return false;
}
LOG.DebugFormat("Freezing process: {0}", processName);
foreach (ProcessThread pT in proc.Threads)
{
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
frozen = true;
Kernel32.SuspendThread(pOpenThread);
pT.Dispose();
}
frozen = true;
Kernel32.SuspendThread(pOpenThread);
}
return frozen;
}
@ -1623,36 +1623,37 @@ private bool FreezeWindow()
/// </summary>
public void UnfreezeWindow()
{
Process proc = Process.GetProcessById(ProcessId.ToInt32());
string processName = proc.ProcessName;
if (!CanFreezeOrUnfreeze(processName))
using (Process proc = Process.GetProcessById(ProcessId))
{
LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
if (!CanFreezeOrUnfreeze(Text))
{
LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
LOG.DebugFormat("Unfreezing process: {0}", processName);
foreach (ProcessThread pT in proc.Threads)
{
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
string processName = proc.ProcessName;
if (!CanFreezeOrUnfreeze(processName))
{
break;
LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
if (!CanFreezeOrUnfreeze(Text))
{
LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
LOG.DebugFormat("Unfreezing process: {0}", processName);
Kernel32.ResumeThread(pOpenThread);
foreach (ProcessThread pT in proc.Threads)
{
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
break;
}
Kernel32.ResumeThread(pOpenThread);
}
}
}
/// <summary>
/// Return an Image representating the Window!
/// Return an Image representing the Window!
/// As GDI+ draws it, it will be without Aero borders!
/// </summary>
public Image PrintWindow()
@ -1672,20 +1673,15 @@ public Image PrintWindow()
returnImage = new Bitmap(windowRect.Width, windowRect.Height, pixelFormat);
using (Graphics graphics = Graphics.FromImage(returnImage))
{
IntPtr hDCDest = graphics.GetHdc();
try
using (SafeDeviceContextHandle graphicsDC = graphics.GetSafeDeviceContext())
{
bool printSucceeded = User32.PrintWindow(Handle, hDCDest, 0x0);
bool printSucceeded = User32.PrintWindow(Handle, graphicsDC.DangerousGetHandle(), 0x0);
if (!printSucceeded)
{
// something went wrong, most likely a "0x80004005" (Acess Denied) when using UAC
exceptionOccured = User32.CreateWin32Exception("PrintWindow");
}
}
finally
{
graphics.ReleaseHdc(hDCDest);
}
// Apply the region "transparency"
if (region != null && !region.IsEmpty(graphics))
@ -1765,7 +1761,10 @@ public bool IsGreenshot
{
if (!isMetroApp)
{
return "Greenshot".Equals(Process.MainModule.FileVersionInfo.ProductName);
using (Process thisWindowProcess = Process)
{
return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName);
}
}
}
catch (Exception ex)
@ -1777,9 +1776,9 @@ public bool IsGreenshot
}
/// <summary>
/// Gets the Destop window
/// Gets the Desktop window
/// </summary>
/// <returns>WindowDetails for the destop window</returns>
/// <returns>WindowDetails for the desktop window</returns>
public static WindowDetails GetDesktopWindow()
{
return new WindowDetails(User32.GetDesktopWindow());
@ -1830,7 +1829,7 @@ public WindowDetails FindChildUnderPoint(Point point)
/// </summary>
/// <param name="hWnd">IntPtr with the windows handle</param>
/// <returns>String with ClassName</returns>
public static String GetClassName(IntPtr hWnd)
public static string GetClassName(IntPtr hWnd)
{
StringBuilder classNameBuilder = new StringBuilder(260, 260);
User32.GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity);
@ -1979,7 +1978,7 @@ public static List<WindowDetails> GetTopLevelWindows()
/// <returns></returns>
public static WindowDetails GetLinkedWindow(WindowDetails windowToLinkTo)
{
IntPtr processIdSelectedWindow = windowToLinkTo.ProcessId;
int processIdSelectedWindow = windowToLinkTo.ProcessId;
foreach (WindowDetails window in GetAllWindows())
{
// Ignore windows without title

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -37,8 +37,7 @@ public enum ArrowHeadCombination { NONE, START_POINT, END_POINT, BOTH };
private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6);
public ArrowContainer(Surface parent)
: base(parent)
public ArrowContainer(Surface parent) : base(parent)
{
}
@ -48,7 +47,8 @@ public ArrowContainer(Surface parent)
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.ARROWHEADS, 2);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
AddField(GetType(), FieldType.SHADOW, true);
AddField(GetType(), FieldType.ARROWHEADS, ArrowHeadCombination.END_POINT);

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -31,8 +31,7 @@ namespace Greenshot.Drawing
/// </summary>
public class CropContainer : DrawableContainer
{
public CropContainer(Surface parent)
: base(parent)
public CropContainer(Surface parent) : base(parent)
{
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -37,13 +37,11 @@ public class CursorContainer : DrawableContainer, ICursorContainer
{
protected Cursor cursor;
public CursorContainer(Surface parent)
: base(parent)
public CursorContainer(Surface parent) : base(parent)
{
}
public CursorContainer(Surface parent, string filename)
: base(parent)
public CursorContainer(Surface parent, string filename) : base(parent)
{
Load(filename);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -47,9 +47,6 @@ namespace Greenshot.Drawing
public abstract class DrawableContainer : AbstractFieldHolderWithChildren, IDrawableContainer
{
protected static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection<EditorConfiguration>();
protected static readonly Color DefaultLineColor = Color.FromArgb(0, 150, 255);
private bool isMadeUndoable;
private const int M11 = 0;
private const int M12 = 1;
@ -282,7 +279,7 @@ public Size Size
protected Rectangle _boundsBeforeResize = Rectangle.Empty;
[NonSerialized]
// "workbench" rectangle - used for calculatoing bounds during resizing (to be applied to this DrawableContainer afterwards)
// "workbench" rectangle - used for calculating bounds during resizing (to be applied to this DrawableContainer afterwards)
protected RectangleF _boundsAfterResize = RectangleF.Empty;
public Rectangle Bounds

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -34,15 +34,14 @@ namespace Greenshot.Drawing
[Serializable()]
public class EllipseContainer : DrawableContainer
{
public EllipseContainer(Surface parent)
: base(parent)
public EllipseContainer(Surface parent) : base(parent)
{
}
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
AddField(GetType(), FieldType.SHADOW, true);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -48,7 +48,7 @@ public abstract class AbstractFieldHolder : IFieldHolder
remove { fieldChanged -= value; }
}
// we keep to Coolections of our fields, dictionary for quick access, list for serialization
// we keep two Collections of our fields, dictionary for quick access, list for serialization
// this allows us to use default serialization
[NonSerialized]
private Dictionary<FieldType, Field> fieldsByType = new Dictionary<FieldType, Field>();

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -38,18 +38,15 @@ public object convert(object o)
{
return null;
}
else if (o is T1)
if (o is T1)
{
return convert((T1)o);
}
else if (o is T2)
if (o is T2)
{
return convert((T2)o);
}
else
{
throw new ArgumentException("Cannot handle argument of type " + o.GetType());
}
throw new ArgumentException("Cannot handle argument of type " + o.GetType());
}
protected abstract T2 convert(T1 o);

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -71,9 +71,8 @@ public BidirectionalBinding(INotifyPropertyChanged controlObject, string control
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="converter">taking care of converting the synchronzied value to the correct target format and back</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter)
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
/// <param name="converter">taking care of converting the synchronized value to the correct target format and back</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
{
this.converter = converter;
}
@ -86,9 +85,8 @@ public BidirectionalBinding(INotifyPropertyChanged controlObject, string control
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="validator">validator to intercept synchronisation if the value does not match certain criteria</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator)
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
/// <param name="validator">validator to intercept synchronization if the value does not match certain criteria</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
{
this.validator = validator;
}
@ -101,10 +99,9 @@ public BidirectionalBinding(INotifyPropertyChanged controlObject, string control
/// <param name="controlPropertyName">Property of 1st object to bind</param>
/// <param name="fieldObject">Object containing 2nd property to bind</param>
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
/// <param name="converter">taking care of converting the synchronzied value to the correct target format and back</param>
/// <param name="validator">validator to intercept synchronisation if the value does not match certain criteria</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator)
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter)
/// <param name="converter">taking care of converting the synchronized value to the correct target format and back</param>
/// <param name="validator">validator to intercept synchronization if the value does not match certain criteria</param>
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter)
{
this.validator = validator;
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -43,7 +43,8 @@ public class FieldAggregator : AbstractFieldHolder
private List<IDrawableContainer> boundContainers;
private bool internalUpdateRunning = false;
private enum Status { IDLE, BINDING, UPDATING };
private enum Status
{ IDLE, BINDING, UPDATING };
private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -42,15 +42,14 @@ public PreparedFilter Filter
get { return (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); }
}
public FilterContainer(Surface parent)
: base(parent)
public FilterContainer(Surface parent) : base(parent)
{
}
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 0);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.SHADOW, false);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -39,8 +39,7 @@ public double PreviewQuality
set { previewQuality = value; OnPropertyChanged("PreviewQuality"); }
}
public BlurFilter(DrawableContainer parent)
: base(parent)
public BlurFilter(DrawableContainer parent) : base(parent)
{
AddField(GetType(), FieldType.BLUR_RADIUS, 3);
AddField(GetType(), FieldType.PREVIEW_QUALITY, 1.0d);
@ -60,7 +59,7 @@ public unsafe override void Apply(Graphics graphics, Bitmap applyBitmap, Rectang
graphics.SetClip(applyRect);
graphics.ExcludeClip(rect);
}
if (GDIplus.IsBlurPossible(blurRadius))
if (GDIplus.isBlurPossible(blurRadius))
{
GDIplus.DrawWithBlur(graphics, applyBitmap, applyRect, null, null, blurRadius, false);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -32,8 +32,7 @@ namespace Greenshot.Drawing.Filters
[Serializable()]
public class BrightnessFilter : AbstractFilter
{
public BrightnessFilter(DrawableContainer parent)
: base(parent)
public BrightnessFilter(DrawableContainer parent) : base(parent)
{
AddField(GetType(), FieldType.BRIGHTNESS, 0.9d);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -34,8 +34,7 @@ namespace Greenshot.Drawing.Filters
[Serializable()]
public class GrayscaleFilter : AbstractFilter
{
public GrayscaleFilter(DrawableContainer parent)
: base(parent)
public GrayscaleFilter(DrawableContainer parent) : base(parent)
{
}
@ -54,10 +53,10 @@ public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect
graphics.SetClip(applyRect);
graphics.ExcludeClip(rect);
}
ColorMatrix grayscaleMatrix = new ColorMatrix(new float[][] {
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
ColorMatrix grayscaleMatrix = new ColorMatrix(new[] {
new[] {.3f, .3f, .3f, 0, 0},
new[] {.59f, .59f, .59f, 0, 0},
new[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -31,8 +31,7 @@ namespace Greenshot.Drawing.Filters
[Serializable()]
public class HighlightFilter : AbstractFilter
{
public HighlightFilter(DrawableContainer parent)
: base(parent)
public HighlightFilter(DrawableContainer parent) : base(parent)
{
AddField(GetType(), FieldType.FILL_COLOR, Color.Yellow);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -31,8 +31,7 @@ namespace Greenshot.Drawing.Filters
[Serializable]
public class MagnifierFilter : AbstractFilter
{
public MagnifierFilter(DrawableContainer parent)
: base(parent)
public MagnifierFilter(DrawableContainer parent) : base(parent)
{
AddField(GetType(), FieldType.MAGNIFICATION_FACTOR, 2);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -32,8 +32,7 @@ namespace Greenshot.Drawing.Filters
[Serializable()]
public class PixelizationFilter : AbstractFilter
{
public PixelizationFilter(DrawableContainer parent)
: base(parent)
public PixelizationFilter(DrawableContainer parent) : base(parent)
{
AddField(GetType(), FieldType.PIXEL_SIZE, 5);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -48,8 +48,7 @@ public class FreehandContainer : DrawableContainer
/// <summary>
/// Constructor
/// </summary>
public FreehandContainer(Surface parent)
: base(parent)
public FreehandContainer(Surface parent) : base(parent)
{
Init();
Width = parent.Width;
@ -61,7 +60,7 @@ public FreehandContainer(Surface parent)
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 3);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
}
protected void Init()

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2013 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -43,16 +43,18 @@ public class Gripper : Label
public const int POSITION_BOTTOM_CENTER = 5;
public const int POSITION_BOTTOM_LEFT = 6;
public const int POSITION_MIDDLE_LEFT = 7;
public const int GripperSize = 7;
public int Position { get; set; }
public int Position
{
get;
set;
}
public Gripper()
{
Width = GripperSize;
Height = GripperSize;
BackColor = Color.White;
BorderStyle = BorderStyle.FixedSingle;
Width = 5;
Height = 5;
BackColor = Color.Black;
}
}
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -32,8 +32,7 @@ namespace Greenshot.Drawing
[Serializable]
public class HighlightContainer : FilterContainer
{
public HighlightContainer(Surface parent)
: base(parent)
public HighlightContainer(Surface parent) : base(parent)
{
Init();
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -36,13 +36,11 @@ public class IconContainer : DrawableContainer, IIconContainer
{
protected Icon icon;
public IconContainer(Surface parent)
: base(parent)
public IconContainer(Surface parent) : base(parent)
{
}
public IconContainer(Surface parent, string filename)
: base(parent)
public IconContainer(Surface parent, string filename) : base(parent)
{
Load(filename);
}
@ -66,9 +64,9 @@ public Icon Icon
}
/**
* This Dispose is called from the Dispose and the Destructor.
* When disposing==true all non-managed resources should be freed too!
*/
* This Dispose is called from the Dispose and the Destructor.
* When disposing==true all non-managed resources should be freed too!
*/
protected override void Dispose(bool disposing)
{

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -53,14 +53,12 @@ public class ImageContainer : DrawableContainer, IImageContainer
[NonSerialized]
private Point _shadowOffset = new Point(-1, -1);
public ImageContainer(Surface parent, string filename)
: this(parent)
public ImageContainer(Surface parent, string filename) : this(parent)
{
Load(filename);
}
public ImageContainer(Surface parent)
: base(parent)
public ImageContainer(Surface parent) : base(parent)
{
FieldChanged += BitmapContainer_OnFieldChanged;
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -37,8 +37,7 @@ public class LineContainer : DrawableContainer
{
public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10;
public LineContainer(Surface parent)
: base(parent)
public LineContainer(Surface parent) : base(parent)
{
Init();
}
@ -46,7 +45,7 @@ public LineContainer(Surface parent)
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.SHADOW, true);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -32,8 +32,7 @@ namespace Greenshot.Drawing
[Serializable]
public class ObfuscateContainer : FilterContainer
{
public ObfuscateContainer(Surface parent)
: base(parent)
public ObfuscateContainer(Surface parent) : base(parent)
{
Init();
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -34,15 +34,14 @@ namespace Greenshot.Drawing
[Serializable]
public class RectangleContainer : DrawableContainer
{
public RectangleContainer(Surface parent)
: base(parent)
public RectangleContainer(Surface parent) : base(parent)
{
}
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
AddField(GetType(), FieldType.SHADOW, true);
}

View file

@ -21,12 +21,14 @@
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
using Greenshot.Plugin;
using Greenshot.Plugin.Drawing;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace Greenshot.Drawing
{
@ -63,7 +65,7 @@ private void SetValuesOnSerializing(StreamingContext context)
[OnDeserialized]
private void SetValuesOnDeserialized(StreamingContext context)
{
InitTargetGripper(Color.Yellow, _storedTargetGripperLocation);
InitTargetGripper(Color.Green, _storedTargetGripperLocation);
}
#endregion TargetGripper serializing code
@ -79,10 +81,10 @@ public SpeechbubbleContainer(Surface parent)
protected override void InitializeFields()
{
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.LINE_COLOR, Color.Blue);
AddField(GetType(), FieldType.SHADOW, false);
AddField(GetType(), FieldType.FONT_ITALIC, false);
AddField(GetType(), FieldType.FONT_BOLD, false);
AddField(GetType(), FieldType.FONT_BOLD, true);
AddField(GetType(), FieldType.FILL_COLOR, Color.White);
AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
AddField(GetType(), FieldType.FONT_SIZE, 20f);
@ -99,7 +101,7 @@ public override bool HandleMouseDown(int mouseX, int mouseY)
if (TargetGripper == null)
{
_initialGripperPoint = new Point(mouseX, mouseY);
InitTargetGripper(Color.Yellow, new Point(mouseX, mouseY));
InitTargetGripper(Color.Green, new Point(mouseX, mouseY));
}
return base.HandleMouseDown(mouseX, mouseY);
}

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -44,8 +44,7 @@ public class StepLabelContainer : DrawableContainer
private float fontSize = 16;
public StepLabelContainer(Surface parent)
: base(parent)
public StepLabelContainer(Surface parent) : base(parent)
{
parent.AddStepLabel(this);
InitContent();
@ -145,7 +144,7 @@ public override bool HandleMouseDown(int mouseX, int mouseY)
/// </summary>
protected override void InitializeFields()
{
AddField(GetType(), FieldType.FILL_COLOR, DefaultLineColor);
AddField(GetType(), FieldType.FILL_COLOR, Color.DarkRed);
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
}
@ -208,8 +207,7 @@ public override void Draw(Graphics graphics, RenderMode rm)
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.None;
graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
string text = ((Surface)Parent).CountStepLabels(this).ToString();
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);

View file

@ -1,6 +1,6 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Greenshot.Configuration;
using Greenshot.Core;
using Greenshot.Drawing.Fields;
using Greenshot.Helpers;
@ -214,7 +215,7 @@ public Guid ID
/// This saves a lot of "create new bitmap" commands
/// Should not be serialized, as it's generated.
/// The actual bitmap is in the paintbox...
/// Check if this buffer is still needed!
/// TODO: Check if this buffer is still needed!
/// </summary>
[NonSerialized]
private Bitmap _buffer;
@ -458,8 +459,7 @@ public ICaptureDetails CaptureDetails
/// <summary>
/// Base Surface constructor
/// </summary>
public Surface()
: base()
public Surface() : base()
{
Count++;
_elements = new DrawableContainerList(_uniqueId);
@ -508,8 +508,7 @@ private void SetImage(Image newImage, bool dispose)
/// Surface constructor with an image
/// </summary>
/// <param name="newImage"></param>
public Surface(Image newImage)
: this()
public Surface(Image newImage) : this()
{
LOG.DebugFormat("Got image with dimensions {0} and format {1}", newImage.Size, newImage.PixelFormat);
SetImage(newImage, true);
@ -519,8 +518,7 @@ public Surface(Image newImage)
/// Surface contructor with a capture
/// </summary>
/// <param name="capture"></param>
public Surface(ICapture capture)
: this(capture.Image)
public Surface(ICapture capture) : this(capture.Image)
{
// check if cursor is captured, and visible
if (capture.Cursor != null && capture.CursorVisible)
@ -898,6 +896,22 @@ private void OnDragEnter(object sender, DragEventArgs e)
private void OnDragDrop(object sender, DragEventArgs e)
{
Point mouse = PointToClient(new Point(e.X, e.Y));
if (e.Data.GetDataPresent("Text"))
{
string possibleUrl = ClipboardHelper.GetText(e.Data);
// Test if it's an url and try to download the image so we have it in the original form
if (possibleUrl != null && possibleUrl.StartsWith("http"))
{
using (Image image = NetworkHelper.DownloadImage(possibleUrl))
{
if (image != null)
{
AddImageContainer(image, mouse.X, mouse.Y);
return;
}
}
}
}
foreach (Image image in ClipboardHelper.GetImages(e.Data))
{
@ -1622,6 +1636,7 @@ public void PasteElementFromClipboard()
{
return;
}
if (LOG.IsDebugEnabled)
{
LOG.Debug("List of clipboard formats available for pasting:");
@ -1906,8 +1921,8 @@ public bool ProcessCmdKey(Keys k)
ConfirmSelectedConfirmableElements(false);
break;
/*case Keys.Delete:
RemoveSelectedElements();
break;*/
RemoveSelectedElements();
break;*/
default:
return false;
}

Some files were not shown because too many files have changed in this diff Show more