Fixed the build order, so we can build the installer.

Moved UnobservedTaskException handling from the Jira plugin to the MainForm.
Introduced an interface for doing the OCR, to enable building some functionality into the editor.
This commit is contained in:
Robin Krom 2020-02-08 23:23:19 +01:00
parent 6d692dd3a5
commit 2293c70610
8 changed files with 184 additions and 117 deletions

View file

@ -4,6 +4,21 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 16.0.29728.190 VisualStudioVersion = 16.0.29728.190
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
ProjectSection(ProjectDependencies) = postProject
{92599C09-FF29-4ABD-B6E6-C48ECD781BAB} = {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}
{19FEEF09-313F-43C7-819D-F1BCA782B08B} = {19FEEF09-313F-43C7-819D-F1BCA782B08B}
{9801F62C-540F-4BFE-9211-6405DEDE563B} = {9801F62C-540F-4BFE-9211-6405DEDE563B}
{9C0ECC4C-7807-4111-916A-4F57BB29788A} = {9C0ECC4C-7807-4111-916A-4F57BB29788A}
{C3052651-598A-44E2-AAB3-2E41311D50F9} = {C3052651-598A-44E2-AAB3-2E41311D50F9}
{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E} = {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}
{697CF066-9077-4F22-99D9-D989CCE7282B} = {697CF066-9077-4F22-99D9-D989CCE7282B}
{47F23C86-604E-4CC3-8767-B3D4088F30BB} = {47F23C86-604E-4CC3-8767-B3D4088F30BB}
{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} = {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}
{D61E6ECE-E0B6-4467-B492-F08A06BA8F02} = {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}
{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} = {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}
{1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0}
{C6988EE8-2FEE-4349-9F09-F9628A0D8965} = {C6988EE8-2FEE-4349-9F09-F9628A0D8965}
EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}"
EndProject EndProject

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -102,7 +102,7 @@ namespace Greenshot.Drawing
add { _propertyChanged += value; } add { _propertyChanged += value; }
remove{ _propertyChanged -= value; } remove{ _propertyChanged -= value; }
} }
public IList<IFilter> Filters { public IList<IFilter> Filters {
get { get {
List<IFilter> ret = new List<IFilter>(); List<IFilter> ret = new List<IFilter>();
@ -114,7 +114,7 @@ namespace Greenshot.Drawing
return ret; return ret;
} }
} }
[NonSerialized] [NonSerialized]
internal Surface _parent; internal Surface _parent;
public ISurface Parent { public ISurface Parent {
@ -139,7 +139,7 @@ namespace Greenshot.Drawing
OnPropertyChanged("Selected"); OnPropertyChanged("Selected");
} }
} }
[NonSerialized] [NonSerialized]
private EditStatus _status = EditStatus.UNDRAWN; private EditStatus _status = EditStatus.UNDRAWN;
public EditStatus Status { public EditStatus Status {
@ -151,7 +151,7 @@ namespace Greenshot.Drawing
} }
} }
private int left; private int left;
public int Left { public int Left {
get { return left; } get { return left; }
@ -162,7 +162,7 @@ namespace Greenshot.Drawing
left = value; left = value;
} }
} }
private int top; private int top;
public int Top { public int Top {
get { return top; } get { return top; }
@ -173,7 +173,7 @@ namespace Greenshot.Drawing
top = value; top = value;
} }
} }
private int width; private int width;
public int Width { public int Width {
get { return width; } get { return width; }
@ -184,7 +184,7 @@ namespace Greenshot.Drawing
width = value; width = value;
} }
} }
private int height; private int height;
public int Height { public int Height {
get { return height; } get { return height; }
@ -195,7 +195,7 @@ namespace Greenshot.Drawing
height = value; height = value;
} }
} }
public Point Location { public Point Location {
get { get {
return new Point(left, top); return new Point(left, top);
@ -232,11 +232,11 @@ namespace Greenshot.Drawing
[NonSerialized] [NonSerialized]
// will store current bounds of this DrawableContainer before starting a resize // will store current bounds of this DrawableContainer before starting a resize
protected Rectangle _boundsBeforeResize = Rectangle.Empty; protected Rectangle _boundsBeforeResize = Rectangle.Empty;
[NonSerialized] [NonSerialized]
// "workbench" rectangle - used for calculating 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; protected RectangleF _boundsAfterResize = RectangleF.Empty;
public Rectangle Bounds { public Rectangle Bounds {
get { return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); } get { return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); }
set { set {
@ -246,14 +246,14 @@ namespace Greenshot.Drawing
Height = Round(value.Height); Height = Round(value.Height);
} }
} }
public virtual void ApplyBounds(RectangleF newBounds) { public virtual void ApplyBounds(RectangleF newBounds) {
Left = Round(newBounds.Left); Left = Round(newBounds.Left);
Top = Round(newBounds.Top); Top = Round(newBounds.Top);
Width = Round(newBounds.Width); Width = Round(newBounds.Width);
Height = Round(newBounds.Height); Height = Round(newBounds.Height);
} }
public DrawableContainer(Surface parent) { public DrawableContainer(Surface parent) {
InitializeFields(); InitializeFields();
_parent = parent; _parent = parent;
@ -262,17 +262,17 @@ namespace Greenshot.Drawing
public void Add(IFilter filter) { public void Add(IFilter filter) {
AddChild(filter); AddChild(filter);
} }
public void Remove(IFilter filter) { public void Remove(IFilter filter) {
RemoveChild(filter); RemoveChild(filter);
} }
private static int Round(float f) { private static int Round(float f) {
if(float.IsPositiveInfinity(f) || f>int.MaxValue/2) return int.MaxValue/2; if(float.IsPositiveInfinity(f) || f>int.MaxValue/2) return int.MaxValue/2;
if (float.IsNegativeInfinity(f) || f<int.MinValue/2) return int.MinValue/2; if (float.IsNegativeInfinity(f) || f<int.MinValue/2) return int.MinValue/2;
return (int)Math.Round(f); return (int)Math.Round(f);
} }
private bool accountForShadowChange; private bool accountForShadowChange;
public virtual Rectangle DrawingBounds { public virtual Rectangle DrawingBounds {
get { get {
@ -302,7 +302,7 @@ namespace Greenshot.Drawing
_parent?.Invalidate(DrawingBounds); _parent?.Invalidate(DrawingBounds);
} }
} }
public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) { public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) {
if (_parent == null) if (_parent == null)
{ {
@ -329,9 +329,9 @@ namespace Greenshot.Drawing
Top = (_parent.Height / 2) - (Height / 2) - lineThickness/2; Top = (_parent.Height / 2) - (Height / 2) - lineThickness/2;
} }
} }
public virtual bool InitContent() { return true; } public virtual bool InitContent() { return true; }
public virtual void OnDoubleClick() {} public virtual void OnDoubleClick() {}
/// <summary> /// <summary>
@ -369,7 +369,7 @@ namespace Greenshot.Drawing
} }
public abstract void Draw(Graphics graphics, RenderMode renderMode); public abstract void Draw(Graphics graphics, RenderMode renderMode);
public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode, Rectangle clipRectangle) { public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode, Rectangle clipRectangle) {
if (Children.Count > 0) { if (Children.Count > 0) {
if (Status != EditStatus.IDLE) { if (Status != EditStatus.IDLE) {
@ -392,22 +392,22 @@ namespace Greenshot.Drawing
} }
} }
} }
} }
} }
Draw(graphics, renderMode); Draw(graphics, renderMode);
} }
public virtual bool Contains(int x, int y) { public virtual bool Contains(int x, int y) {
return Bounds.Contains(x , y); return Bounds.Contains(x , y);
} }
public virtual bool ClickableAt(int x, int y) { public virtual bool ClickableAt(int x, int y) {
Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
r.Inflate(5, 5); r.Inflate(5, 5);
return r.Contains(x, y); return r.Contains(x, y);
} }
protected void DrawSelectionBorder(Graphics g, Rectangle rect) protected void DrawSelectionBorder(Graphics g, Rectangle rect)
{ {
using Pen pen = new Pen(Color.MediumSeaGreen) using Pen pen = new Pen(Color.MediumSeaGreen)
@ -417,7 +417,7 @@ namespace Greenshot.Drawing
}; };
g.DrawRectangle(pen, rect); g.DrawRectangle(pen, rect);
} }
public void ResizeTo(int width, int height, int anchorPosition) { public void ResizeTo(int width, int height, int anchorPosition) {
Width = width; Width = width;
@ -431,12 +431,12 @@ namespace Greenshot.Drawing
public void MakeBoundsChangeUndoable(bool allowMerge) { public void MakeBoundsChangeUndoable(bool allowMerge) {
_parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge); _parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge);
} }
public void MoveBy(int dx, int dy) { public void MoveBy(int dx, int dy) {
Left += dx; Left += dx;
Top += dy; Top += dy;
} }
/// <summary> /// <summary>
/// A handler for the MouseDown, used if you don't want the surface to handle this for you /// A handler for the MouseDown, used if you don't want the surface to handle this for you
/// </summary> /// </summary>
@ -457,22 +457,22 @@ namespace Greenshot.Drawing
/// <returns>true if the event is handled, false if the surface needs to handle it</returns> /// <returns>true if the event is handled, false if the surface needs to handle it</returns>
public virtual bool HandleMouseMove(int x, int y) { public virtual bool HandleMouseMove(int x, int y) {
Invalidate(); Invalidate();
// reset "workrbench" rectangle to current bounds // reset "workrbench" rectangle to current bounds
_boundsAfterResize.X = _boundsBeforeResize.Left; _boundsAfterResize.X = _boundsBeforeResize.Left;
_boundsAfterResize.Y = _boundsBeforeResize.Top; _boundsAfterResize.Y = _boundsBeforeResize.Top;
_boundsAfterResize.Width = x - _boundsAfterResize.Left; _boundsAfterResize.Width = x - _boundsAfterResize.Left;
_boundsAfterResize.Height = y - _boundsAfterResize.Top; _boundsAfterResize.Height = y - _boundsAfterResize.Top;
ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor()); ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor());
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize); ApplyBounds(_boundsAfterResize);
Invalidate(); Invalidate();
return true; return true;
} }
/// <summary> /// <summary>
/// A handler for the MouseUp /// A handler for the MouseUp
/// </summary> /// </summary>
@ -480,7 +480,7 @@ namespace Greenshot.Drawing
/// <param name="y">current mouse y</param> /// <param name="y">current mouse y</param>
public virtual void HandleMouseUp(int x, int y) { public virtual void HandleMouseUp(int x, int y) {
} }
protected virtual void SwitchParent(Surface newParent) { protected virtual void SwitchParent(Surface newParent) {
if (newParent == Parent) if (newParent == Parent)
{ {
@ -493,14 +493,14 @@ namespace Greenshot.Drawing
filter.Parent = this; filter.Parent = this;
} }
} }
protected void OnPropertyChanged(string propertyName) { protected void OnPropertyChanged(string propertyName) {
if (_propertyChanged != null) { if (_propertyChanged != null) {
_propertyChanged(this, new PropertyChangedEventArgs(propertyName)); _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
Invalidate(); Invalidate();
} }
} }
/// <summary> /// <summary>
/// This method will be called before a field is changes. /// This method will be called before a field is changes.
/// Using this makes it possible to invalidate the object as is before changing. /// Using this makes it possible to invalidate the object as is before changing.
@ -511,7 +511,7 @@ namespace Greenshot.Drawing
_parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true); _parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
Invalidate(); Invalidate();
} }
/// <summary> /// <summary>
/// Handle the field changed event, this should invalidate the correct bounds (e.g. when shadow comes or goes more pixels!) /// Handle the field changed event, this should invalidate the correct bounds (e.g. when shadow comes or goes more pixels!)
/// </summary> /// </summary>
@ -581,7 +581,7 @@ namespace Greenshot.Drawing
protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() { protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() {
return ScaleHelper.ShapeAngleRoundBehavior.Instance; return ScaleHelper.ShapeAngleRoundBehavior.Instance;
} }
public virtual bool HasContextMenu { public virtual bool HasContextMenu {
get { get {
return true; return true;

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -31,7 +31,7 @@ namespace Greenshot.Drawing {
/// <summary> /// <summary>
/// Represents a rectangular shape on the Surface /// Represents a rectangular shape on the Surface
/// </summary> /// </summary>
[Serializable] [Serializable]
public class RectangleContainer : DrawableContainer { public class RectangleContainer : DrawableContainer {
public RectangleContainer(Surface parent) : base(parent) { public RectangleContainer(Surface parent) : base(parent) {
@ -59,7 +59,7 @@ namespace Greenshot.Drawing {
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent); AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
AddField(GetType(), FieldType.SHADOW, true); AddField(GetType(), FieldType.SHADOW, true);
} }
public override void Draw(Graphics graphics, RenderMode rm) { public override void Draw(Graphics graphics, RenderMode rm) {
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR, Color.Red); Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR, Color.Red);

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -45,6 +45,7 @@ using Greenshot.Destinations;
using Greenshot.Drawing; using Greenshot.Drawing;
using log4net; using log4net;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
using System.Threading.Tasks;
namespace Greenshot { namespace Greenshot {
/// <summary> /// <summary>
@ -61,7 +62,7 @@ namespace Greenshot {
// Set the Thread name, is better than "1" // Set the Thread name, is better than "1"
Thread.CurrentThread.Name = Application.ProductName; Thread.CurrentThread.Name = Application.ProductName;
// Init Log4NET // Init Log4NET
LogFileLocation = LogHelper.InitializeLog4Net(); LogFileLocation = LogHelper.InitializeLog4Net();
// Get logger // Get logger
@ -70,6 +71,8 @@ namespace Greenshot {
Application.ThreadException += Application_ThreadException; Application.ThreadException += Application_ThreadException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += Task_UnhandledException;
// Initialize the IniConfig // Initialize the IniConfig
IniConfig.Init(); IniConfig.Init();
@ -140,7 +143,7 @@ namespace Greenshot {
FreeMutex(); FreeMutex();
return; return;
} }
if (argument.ToLower().Equals("/exit")) { if (argument.ToLower().Equals("/exit")) {
// unregister application on uninstall (allow uninstall) // unregister application on uninstall (allow uninstall)
try { try {
@ -153,7 +156,7 @@ namespace Greenshot {
FreeMutex(); FreeMutex();
return; return;
} }
// Reload the configuration // Reload the configuration
if (argument.ToLower().Equals("/reload")) { if (argument.ToLower().Equals("/reload")) {
// Modify configuration // Modify configuration
@ -163,14 +166,14 @@ namespace Greenshot {
FreeMutex(); FreeMutex();
return; return;
} }
// Stop running // Stop running
if (argument.ToLower().Equals("/norun")) { if (argument.ToLower().Equals("/norun")) {
// Make an exit possible // Make an exit possible
FreeMutex(); FreeMutex();
return; return;
} }
// Language // Language
if (argument.ToLower().Equals("/language")) { if (argument.ToLower().Equals("/language")) {
_conf.Language = arguments[++argumentNr]; _conf.Language = arguments[++argumentNr];
@ -302,7 +305,7 @@ namespace Greenshot {
public static MainForm Instance => _instance; public static MainForm Instance => _instance;
private readonly CopyData _copyData; private readonly CopyData _copyData;
// Thumbnail preview // Thumbnail preview
private ThumbnailForm _thumbnailForm; private ThumbnailForm _thumbnailForm;
// Make sure we have only one settings form // Make sure we have only one settings form
@ -338,16 +341,16 @@ namespace Greenshot {
// Make sure all hotkeys pass this window! // Make sure all hotkeys pass this window!
HotkeyControl.RegisterHotkeyHwnd(Handle); HotkeyControl.RegisterHotkeyHwnd(Handle);
RegisterHotkeys(); RegisterHotkeys();
new ToolTip(); new ToolTip();
UpdateUi(); UpdateUi();
// This forces the registration of all destinations inside Greenshot itself. // This forces the registration of all destinations inside Greenshot itself.
DestinationHelper.GetAllDestinations(); DestinationHelper.GetAllDestinations();
// This forces the registration of all processors inside Greenshot itself. // This forces the registration of all processors inside Greenshot itself.
ProcessorHelper.GetAllProcessors(); ProcessorHelper.GetAllProcessors();
// Load all the plugins // Load all the plugins
PluginHelper.Instance.LoadPlugins(); PluginHelper.Instance.LoadPlugins();
@ -386,7 +389,7 @@ namespace Greenshot {
// Assign the handle: // Assign the handle:
_copyData.AssignHandle(Handle); _copyData.AssignHandle(Handle);
// Create the channel to send on: // Create the channel to send on:
_copyData.Channels.Add("Greenshot"); _copyData.Channels.Add("Greenshot");
// Hook up received event: // Hook up received event:
_copyData.CopyDataReceived += CopyDataDataReceived; _copyData.CopyDataReceived += CopyDataDataReceived;
@ -474,7 +477,7 @@ namespace Greenshot {
} }
} }
} }
/// <summary> /// <summary>
/// Main context menu /// Main context menu
/// </summary> /// </summary>
@ -631,7 +634,7 @@ namespace Greenshot {
} }
/// <summary> /// <summary>
/// Displays a dialog for the user to choose how to handle hotkey registration failures: /// Displays a dialog for the user to choose how to handle hotkey registration failures:
/// retry (allowing to shut down the conflicting application before), /// retry (allowing to shut down the conflicting application before),
/// ignore (not registering the conflicting hotkey and resetting the respective config to "None", i.e. not trying to register it again on next startup) /// ignore (not registering the conflicting hotkey and resetting the respective config to "None", i.e. not trying to register it again on next startup)
/// abort (do nothing about it) /// abort (do nothing about it)
@ -759,7 +762,7 @@ namespace Greenshot {
contextmenu_capturewindowfromlist.DropDownItems.Clear(); contextmenu_capturewindowfromlist.DropDownItems.Clear();
CleanupThumbnail(); CleanupThumbnail();
} }
/// <summary> /// <summary>
/// Build a selectable list of IE tabs when we enter the menu item /// Build a selectable list of IE tabs when we enter the menu item
/// </summary> /// </summary>
@ -774,7 +777,7 @@ namespace Greenshot {
contextmenu_captureie.Enabled = true; contextmenu_captureie.Enabled = true;
contextmenu_captureiefromlist.Enabled = true; contextmenu_captureiefromlist.Enabled = true;
Dictionary<WindowDetails, int> counter = new Dictionary<WindowDetails, int>(); Dictionary<WindowDetails, int> counter = new Dictionary<WindowDetails, int>();
foreach(KeyValuePair<WindowDetails, string> tabData in tabs) { foreach(KeyValuePair<WindowDetails, string> tabData in tabs) {
string title = tabData.Value; string title = tabData.Value;
if (title == null) { if (title == null) {
@ -805,7 +808,7 @@ namespace Greenshot {
} }
/// <summary> /// <summary>
/// MultiScreenDropDownOpening is called when mouse hovers over the Capture-Screen context menu /// MultiScreenDropDownOpening is called when mouse hovers over the Capture-Screen context menu
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
@ -847,7 +850,7 @@ namespace Greenshot {
} }
/// <summary> /// <summary>
/// MultiScreenDropDownOpening is called when mouse leaves the context menu /// MultiScreenDropDownOpening is called when mouse leaves the context menu
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
@ -855,7 +858,7 @@ namespace Greenshot {
ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender; ToolStripMenuItem captureScreenMenuItem = (ToolStripMenuItem)sender;
captureScreenMenuItem.DropDownItems.Clear(); captureScreenMenuItem.DropDownItems.Clear();
} }
/// <summary> /// <summary>
/// Build a selectable list of windows when we enter the menu item /// Build a selectable list of windows when we enter the menu item
/// </summary> /// </summary>
@ -866,11 +869,11 @@ namespace Greenshot {
ToolStripMenuItem captureWindowFromListMenuItem = (ToolStripMenuItem)sender; ToolStripMenuItem captureWindowFromListMenuItem = (ToolStripMenuItem)sender;
AddCaptureWindowMenuItems(captureWindowFromListMenuItem, Contextmenu_capturewindowfromlist_Click); AddCaptureWindowMenuItems(captureWindowFromListMenuItem, Contextmenu_capturewindowfromlist_Click);
} }
private void CaptureWindowFromListMenuDropDownClosed(object sender, EventArgs e) { private void CaptureWindowFromListMenuDropDownClosed(object sender, EventArgs e) {
CleanupThumbnail(); CleanupThumbnail();
} }
private void ShowThumbnailOnEnter(object sender, EventArgs e) { private void ShowThumbnailOnEnter(object sender, EventArgs e) {
if (!(sender is ToolStripMenuItem captureWindowItem)) return; if (!(sender is ToolStripMenuItem captureWindowItem)) return;
WindowDetails window = captureWindowItem.Tag as WindowDetails; WindowDetails window = captureWindowItem.Tag as WindowDetails;
@ -884,7 +887,7 @@ namespace Greenshot {
{ {
_thumbnailForm?.Hide(); _thumbnailForm?.Hide();
} }
private void CleanupThumbnail() { private void CleanupThumbnail() {
if (_thumbnailForm == null) if (_thumbnailForm == null)
{ {
@ -1002,7 +1005,7 @@ namespace Greenshot {
Process.Start("http://getgreenshot.org/support/?version=" + Assembly.GetEntryAssembly().GetName().Version); Process.Start("http://getgreenshot.org/support/?version=" + Assembly.GetEntryAssembly().GetName().Version);
}); });
} }
/// <summary> /// <summary>
/// Context menu entry "Preferences" /// Context menu entry "Preferences"
/// </summary> /// </summary>
@ -1011,7 +1014,7 @@ namespace Greenshot {
private void Contextmenu_settingsClick(object sender, EventArgs e) { private void Contextmenu_settingsClick(object sender, EventArgs e) {
BeginInvoke((MethodInvoker)ShowSetting); BeginInvoke((MethodInvoker)ShowSetting);
} }
/// <summary> /// <summary>
/// This is called indirectly from the context menu "Preferences" /// This is called indirectly from the context menu "Preferences"
/// </summary> /// </summary>
@ -1030,7 +1033,7 @@ namespace Greenshot {
} }
} }
} }
/// <summary> /// <summary>
/// The "About Greenshot" entry is clicked /// The "About Greenshot" entry is clicked
/// </summary> /// </summary>
@ -1053,7 +1056,7 @@ namespace Greenshot {
} }
} }
} }
/// <summary> /// <summary>
/// The "Help" entry is clicked /// The "Help" entry is clicked
/// </summary> /// </summary>
@ -1062,7 +1065,7 @@ namespace Greenshot {
private void Contextmenu_helpClick(object sender, EventArgs e) { private void Contextmenu_helpClick(object sender, EventArgs e) {
HelpFileLoader.LoadHelp(); HelpFileLoader.LoadHelp();
} }
/// <summary> /// <summary>
/// The "Exit" entry is clicked /// The "Exit" entry is clicked
/// </summary> /// </summary>
@ -1077,7 +1080,7 @@ namespace Greenshot {
_conf.CaptureMousepointer = captureMouseItem.Checked; _conf.CaptureMousepointer = captureMouseItem.Checked;
} }
} }
/// <summary> /// <summary>
/// This needs to be called to initialize the quick settings menu entries /// This needs to be called to initialize the quick settings menu entries
/// </summary> /// </summary>
@ -1217,6 +1220,20 @@ namespace Greenshot {
InitializeQuickSettingsMenu(); InitializeQuickSettingsMenu();
} }
private static void Task_UnhandledException(object sender, UnobservedTaskExceptionEventArgs args)
{
try {
Exception exceptionToLog = args.Exception;
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
LOG.Error("Exception caught in the UnobservedTaskException handler.");
LOG.Error(exceptionText);
new BugReportForm(exceptionText).ShowDialog();
}
finally {
args.SetObserved();
}
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
Exception exceptionToLog = e.ExceptionObject as Exception; Exception exceptionToLog = e.ExceptionObject as Exception;
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog); string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
@ -1229,7 +1246,7 @@ namespace Greenshot {
} }
new BugReportForm(exceptionText).ShowDialog(); new BugReportForm(exceptionText).ShowDialog();
} }
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
Exception exceptionToLog = e.Exception; Exception exceptionToLog = e.Exception;
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog); string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
@ -1357,7 +1374,7 @@ namespace Greenshot {
MessageBox.Show(this, ex.Message, "Opening " + path, MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show(this, ex.Message, "Opening " + path, MessageBoxButtons.OK, MessageBoxIcon.Error);
} }
} }
/// <summary> /// <summary>
/// Shutdown / cleanup /// Shutdown / cleanup
/// </summary> /// </summary>
@ -1380,21 +1397,21 @@ namespace Greenshot {
LOG.Error("Error closing form!", e); LOG.Error("Error closing form!", e);
} }
} }
// Make sure hotkeys are disabled // Make sure hotkeys are disabled
try { try {
HotkeyControl.UnregisterHotkeys(); HotkeyControl.UnregisterHotkeys();
} catch (Exception e) { } catch (Exception e) {
LOG.Error("Error unregistering hotkeys!", e); LOG.Error("Error unregistering hotkeys!", e);
} }
// Now the sound isn't needed anymore // Now the sound isn't needed anymore
try { try {
SoundHelper.Deinitialize(); SoundHelper.Deinitialize();
} catch (Exception e) { } catch (Exception e) {
LOG.Error("Error deinitializing sound!", e); LOG.Error("Error deinitializing sound!", e);
} }
// Inform all registed plugins // Inform all registed plugins
try { try {
PluginHelper.Instance.Shutdown(); PluginHelper.Instance.Shutdown();

View file

@ -12,7 +12,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" /> <ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" />
<ProjectReference Include="..\Greenshot\Greenshot.csproj" />
<PackageReference Include="Dapplo.Jira" version="0.5.12" /> <PackageReference Include="Dapplo.Jira" version="0.5.12" />
<PackageReference Include="Svg" version="2.3.0" /> <PackageReference Include="Svg" version="2.3.0" />
</ItemGroup> </ItemGroup>

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -25,8 +25,6 @@ using Greenshot.Plugin;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dapplo.Log; using Dapplo.Log;
using Greenshot.Forms;
using Greenshot.Helpers;
using GreenshotJiraPlugin.Forms; using GreenshotJiraPlugin.Forms;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using log4net; using log4net;
@ -59,22 +57,6 @@ namespace GreenshotJiraPlugin {
public JiraPlugin() { public JiraPlugin() {
_instance = this; _instance = this;
// Added to prevent Greenshot from shutting down when there was an exception in a Task
TaskScheduler.UnobservedTaskException += (sender, args) =>
{
try
{
Exception exceptionToLog = args.Exception;
string exceptionText = EnvironmentInfo.BuildReport(exceptionToLog);
Log.Error("Exception caught in the UnobservedTaskException handler.");
Log.Error(exceptionText);
new BugReportForm(exceptionText).ShowDialog();
}
finally
{
args.SetObserved();
}
};
} }
public IEnumerable<IDestination> Destinations() { public IEnumerable<IDestination> Destinations() {

View file

@ -0,0 +1,40 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Greenshot.Plugin;
using System.Collections.Generic;
using System.Drawing;
using System.Threading.Tasks;
namespace GreenshotPlugin.Interfaces
{
public interface IOcrProvider
{
Task<OcrInformation> DoOcrAsync(ISurface surface);
}
public class OcrInformation
{
public string Text { get; set; }
public IList<(string word, Rectangle location)> Words { get; } = new List<(string, Rectangle)>();
}
}

View file

@ -28,13 +28,14 @@ using Windows.Media.Ocr;
using Greenshot.Plugin; using Greenshot.Plugin;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using System.Text; using System.Text;
using GreenshotPlugin.Interfaces;
namespace GreenshotWin10Plugin namespace GreenshotWin10Plugin
{ {
/// <summary> /// <summary>
/// This uses the OcrEngine from Windows 10 to perform OCR on the captured image. /// This uses the OcrEngine from Windows 10 to perform OCR on the captured image.
/// </summary> /// </summary>
public class Win10OcrDestination : AbstractDestination public class Win10OcrDestination : AbstractDestination, IOcrProvider
{ {
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(Win10OcrDestination)); private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(Win10OcrDestination));
@ -63,7 +64,7 @@ namespace GreenshotWin10Plugin
/// </summary> /// </summary>
/// <param name="surface">ISurface</param> /// <param name="surface">ISurface</param>
/// <returns>OcrResult</returns> /// <returns>OcrResult</returns>
public async Task<OcrResult> DoOcrAsync(ISurface surface) public async Task<OcrInformation> DoOcrAsync(ISurface surface)
{ {
var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages(); var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
using var imageStream = new MemoryStream(); using var imageStream = new MemoryStream();
@ -73,7 +74,27 @@ namespace GreenshotWin10Plugin
var decoder = await BitmapDecoder.CreateAsync(imageStream.AsRandomAccessStream()); var decoder = await BitmapDecoder.CreateAsync(imageStream.AsRandomAccessStream());
var softwareBitmap = await decoder.GetSoftwareBitmapAsync(); var softwareBitmap = await decoder.GetSoftwareBitmapAsync();
return await ocrEngine.RecognizeAsync(softwareBitmap); var ocrResult = await ocrEngine.RecognizeAsync(softwareBitmap);
var result = new OcrInformation();
// Build the text from the lines, otherwise it's just everything concated together
var text = new StringBuilder();
foreach (var line in ocrResult.Lines)
{
text.AppendLine(line.Text);
}
result.Text = result.ToString();
foreach (var line in ocrResult.Lines)
{
foreach (var word in line.Words)
{
var rectangle = new Rectangle((int)word.BoundingRect.X, (int)word.BoundingRect.Y, (int)word.BoundingRect.Width, (int)word.BoundingRect.Height);
result.Words.Add((word.Text, rectangle));
}
}
return result;
} }
/// <summary> /// <summary>
@ -89,19 +110,12 @@ namespace GreenshotWin10Plugin
try try
{ {
var ocrResult = Task.Run(async () => await DoOcrAsync(surface)).Result; var ocrResult = Task.Run(async () => await DoOcrAsync(surface)).Result;
// Build the text from the lines, otherwise it's just everything concated together
var result = new StringBuilder();
foreach(var line in ocrResult.Lines)
{
result.AppendLine(line.Text);
}
var text = result.ToString();
// Check if we found text // Check if we found text
if (!string.IsNullOrWhiteSpace(text)) if (!string.IsNullOrWhiteSpace(ocrResult.Text))
{ {
// Place the OCR text on the // Place the OCR text on the
ClipboardHelper.SetClipboardData(text); ClipboardHelper.SetClipboardData(ocrResult.Text);
} }
exportInformation.ExportMade = true; exportInformation.ExportMade = true;
} }