From bd03e18ddccd1daaf145a95156fe8b6dc47e7f2a Mon Sep 17 00:00:00 2001 From: Christian Schulz <32000301+Christian-Schulz@users.noreply.github.com> Date: Sat, 21 May 2022 22:57:20 +0200 Subject: [PATCH 01/17] Bugfix crop selection scaling #404 (#407) Disable scaling for horizontal and vertical crop modes. --- src/Greenshot.Editor/Drawing/CropContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Greenshot.Editor/Drawing/CropContainer.cs b/src/Greenshot.Editor/Drawing/CropContainer.cs index d450e9dd2..c513b171f 100644 --- a/src/Greenshot.Editor/Drawing/CropContainer.cs +++ b/src/Greenshot.Editor/Drawing/CropContainer.cs @@ -247,10 +247,11 @@ namespace Greenshot.Editor.Drawing _boundsAfterResize = new NativeRectFloat( _boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); + + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); break; } } - _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); From 3f6f9863f885dac7127bcffc6853c719705bb319 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Fri, 3 Jun 2022 11:23:27 +0200 Subject: [PATCH 02/17] Removed copying all the dependencies for every plugin, this should fix #413. --- installer/innosetup/setup.iss | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 23788205e..bf49ea5ed 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -82,33 +82,34 @@ Source: {#LanguagesDir}\*zh-CN*; Excludes: "*installer*,*website*"; DestDir: {ap Source: {#LanguagesDir}\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhTW; Flags: overwritereadonly ignoreversion replacesameversion; ;Office Plugin -Source: {#PluginDir}\Greenshot.Plugin.Office\*.dll; DestDir: {app}\Plugins\Office; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Office\Greenshot.Plugin.Office.dll; DestDir: {app}\Plugins\Office; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; ;JIRA Plugin -Source: {#PluginDir}\Greenshot.Plugin.Jira\*.dll; DestDir: {app}\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Jira\*Jira*.dll; DestDir: {app}\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Jira\Languages\language_jira*.xml; DestDir: {app}\Languages\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion; ;Imgur Plugin -Source: {#PluginDir}\Greenshot.Plugin.Imgur\*.dll; DestDir: {app}\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Imgur\Greenshot.Plugin.Imgur.dll; DestDir: {app}\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Imgur\Languages\language_imgur*.xml; DestDir: {app}\Languages\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion; ;Box Plugin -Source: {#PluginDir}\Greenshot.Plugin.Box\*.dll; DestDir: {app}\Plugins\Box; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Box\Greenshot.Plugin.Box.dll; DestDir: {app}\Plugins\Box; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Box\Languages\language_box*.xml; DestDir: {app}\Languages\Plugins\Box; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion; ;DropBox Plugin -Source: {#PluginDir}\Greenshot.Plugin.DropBox\*.dll; DestDir: {app}\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.DropBox\Greenshot.Plugin.DropBox.dll; DestDir: {app}\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.DropBox\Languages\language_dropbox*.xml; DestDir: {app}\Languages\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion; ;Flickr Plugin -Source: {#PluginDir}\Greenshot.Plugin.Flickr\*.dll; DestDir: {app}\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Flickr\Greenshot.Plugin.Flickr.dll; DestDir: {app}\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Flickr\Languages\language_flickr*.xml; DestDir: {app}\Languages\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion; ;Photobucket Plugin -Source: {#PluginDir}\Greenshot.Plugin.Photobucket\*.dll; DestDir: {app}\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Photobucket\Greenshot.Plugin.Photobucket.dll; DestDir: {app}\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Photobucket\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion; ;Confluence Plugin -Source: {#PluginDir}\Greenshot.Plugin.Confluence\*.dll; DestDir: {app}\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Confluence\Greenshot.Plugin.Confluence.dll; DestDir: {app}\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Confluence\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion; ;ExternalCommand Plugin -Source: {#PluginDir}\Greenshot.Plugin.ExternalCommand\*.dll; DestDir: {app}\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.ExternalCommand\Greenshot.Plugin.ExternalCommand.dll; DestDir: {app}\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.ExternalCommand\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion; ;Win 10 Plugin -Source: {#PluginDir}\Greenshot.Plugin.Win10\*.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Win10\Greenshot.Plugin.Win10.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#PluginDir}\Greenshot.Plugin.Win10\Microsoft.Toolkit.Uwp.Notifications.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; [Setup] ; changes associations is used when the installer installs new extensions, it clears the explorer icon cache From 4c7494dd7486030e03d18aa561bc9a01b65c754a Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Sun, 26 Jun 2022 01:40:53 +0200 Subject: [PATCH 03/17] Some left over fixes for the move to Dapplo.Windows, also updated dependencies. --- src/Directory.Build.props | 2 +- src/Greenshot.Base/Greenshot.Base.csproj | 14 ++--- .../Drawing/Adorners/ResizeAdorner.cs | 4 +- src/Greenshot.Editor/Drawing/CropContainer.cs | 2 +- .../Drawing/DrawableContainer.cs | 7 ++- src/Greenshot.Editor/Drawing/LineContainer.cs | 4 +- .../Helpers/IDoubleProcessor.cs | 28 +++++++++ .../Helpers/IHaveScaleOptions.cs | 28 +++++++++ .../Helpers/LineAngleRoundBehavior.cs | 39 ++++++++++++ src/Greenshot.Editor/Helpers/ScaleHelper.cs | 62 ++----------------- src/Greenshot.Editor/Helpers/ScaleOptions.cs | 44 +++++++++++++ .../Helpers/ShapeAngleRoundBehavior.cs | 39 ++++++++++++ .../Greenshot.Plugin.Office.csproj | 10 +-- src/Greenshot/App.config | 3 +- src/Greenshot/Greenshot.csproj | 2 +- 15 files changed, 208 insertions(+), 80 deletions(-) create mode 100644 src/Greenshot.Editor/Helpers/IDoubleProcessor.cs create mode 100644 src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs create mode 100644 src/Greenshot.Editor/Helpers/LineAngleRoundBehavior.cs create mode 100644 src/Greenshot.Editor/Helpers/ScaleOptions.cs create mode 100644 src/Greenshot.Editor/Helpers/ShapeAngleRoundBehavior.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b6533ddd7..f5b9f2e1c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -46,7 +46,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj index 805098491..a698b8e0b 100644 --- a/src/Greenshot.Base/Greenshot.Base.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -6,13 +6,13 @@ - - - - - - - + + + + + + + diff --git a/src/Greenshot.Editor/Drawing/Adorners/ResizeAdorner.cs b/src/Greenshot.Editor/Drawing/Adorners/ResizeAdorner.cs index 523684232..263d5a31e 100644 --- a/src/Greenshot.Editor/Drawing/Adorners/ResizeAdorner.cs +++ b/src/Greenshot.Editor/Drawing/Adorners/ResizeAdorner.cs @@ -100,8 +100,10 @@ namespace Greenshot.Editor.Drawing.Adorners // reset "workbench" rectangle to current bounds _boundsAfterResize = _boundsBeforeResize; + var scaleOptions = (Owner as IHaveScaleOptions)?.GetScaleOptions(); + // calculate scaled rectangle - _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), ScaleHelper.GetScaleOptions()); + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Position, new NativePointFloat(mouseEventArgs.X, mouseEventArgs.Y), scaleOptions); // apply scaled bounds to this DrawableContainer Owner.ApplyBounds(_boundsAfterResize); diff --git a/src/Greenshot.Editor/Drawing/CropContainer.cs b/src/Greenshot.Editor/Drawing/CropContainer.cs index c513b171f..eb2f7179e 100644 --- a/src/Greenshot.Editor/Drawing/CropContainer.cs +++ b/src/Greenshot.Editor/Drawing/CropContainer.cs @@ -248,7 +248,7 @@ namespace Greenshot.Editor.Drawing _boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); - _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor()); break; } } diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs index c9737f9e3..cac23dc3a 100644 --- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs +++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs @@ -533,7 +533,8 @@ namespace Greenshot.Editor.Drawing // reset "workbench" rectangle to current bounds _boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); - _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); + var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions(); + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor(), scaleOptions); // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); @@ -666,9 +667,9 @@ namespace Greenshot.Editor.Drawing Height = points[1].Y - points[0].Y; } - protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() + protected virtual IDoubleProcessor GetAngleRoundProcessor() { - return ScaleHelper.ShapeAngleRoundBehavior.INSTANCE; + return ShapeAngleRoundBehavior.INSTANCE; } public virtual bool HasContextMenu => true; diff --git a/src/Greenshot.Editor/Drawing/LineContainer.cs b/src/Greenshot.Editor/Drawing/LineContainer.cs index ef4a68707..f48dddec7 100644 --- a/src/Greenshot.Editor/Drawing/LineContainer.cs +++ b/src/Greenshot.Editor/Drawing/LineContainer.cs @@ -115,9 +115,9 @@ namespace Greenshot.Editor.Drawing return false; } - protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() + protected override IDoubleProcessor GetAngleRoundProcessor() { - return ScaleHelper.LineAngleRoundBehavior.INSTANCE; + return LineAngleRoundBehavior.INSTANCE; } } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Helpers/IDoubleProcessor.cs b/src/Greenshot.Editor/Helpers/IDoubleProcessor.cs new file mode 100644 index 000000000..beb426c68 --- /dev/null +++ b/src/Greenshot.Editor/Helpers/IDoubleProcessor.cs @@ -0,0 +1,28 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: https://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 . + */ + +namespace Greenshot.Editor.Helpers +{ + public interface IDoubleProcessor + { + double Process(double d); + } +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs b/src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs new file mode 100644 index 000000000..3f1ed03ff --- /dev/null +++ b/src/Greenshot.Editor/Helpers/IHaveScaleOptions.cs @@ -0,0 +1,28 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel + * + * For more information see: https://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 . + */ + +namespace Greenshot.Editor.Helpers +{ + public interface IHaveScaleOptions + { + ScaleOptions GetScaleOptions(); + } +} diff --git a/src/Greenshot.Editor/Helpers/LineAngleRoundBehavior.cs b/src/Greenshot.Editor/Helpers/LineAngleRoundBehavior.cs new file mode 100644 index 000000000..6811f66cf --- /dev/null +++ b/src/Greenshot.Editor/Helpers/LineAngleRoundBehavior.cs @@ -0,0 +1,39 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: https://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 . + */ + +using System; + +namespace Greenshot.Editor.Helpers +{ + public class LineAngleRoundBehavior : IDoubleProcessor + { + public static readonly LineAngleRoundBehavior INSTANCE = new(); + + private LineAngleRoundBehavior() + { + } + + public double Process(double angle) + { + return Math.Round(angle / 15) * 15; + } + } +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Helpers/ScaleHelper.cs b/src/Greenshot.Editor/Helpers/ScaleHelper.cs index 63f25d0a0..8403bd939 100644 --- a/src/Greenshot.Editor/Helpers/ScaleHelper.cs +++ b/src/Greenshot.Editor/Helpers/ScaleHelper.cs @@ -33,25 +33,6 @@ namespace Greenshot.Editor.Helpers /// public static class ScaleHelper { - [Flags] - public enum ScaleOptions - { - /// - /// Default scale behavior. - /// - Default = 0x00, - - /// - /// Scale a rectangle in two our four directions, mirrored at it's center coordinates - /// - Centered = 0x01, - - /// - /// Scale a rectangle maintaining it's aspect ratio - /// - Rational = 0x02 - } - /// /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio /// @@ -231,18 +212,18 @@ namespace Greenshot.Editor.Helpers /// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior /// /// NativeRect - /// Positions /// int /// int /// IDoubleProcessor + /// ScaleOptions /// NativeRectFloat - public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior) + public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? scaleOptions = null) { - ScaleOptions opts = GetScaleOptions(); + scaleOptions ??= GetScaleOptions(); NativeRectFloat result = boundsBeforeResize; - bool rationalScale = (opts & ScaleOptions.Rational) == ScaleOptions.Rational; - bool centeredScale = (opts & ScaleOptions.Centered) == ScaleOptions.Centered; + bool rationalScale = (scaleOptions & ScaleOptions.Rational) == ScaleOptions.Rational; + bool centeredScale = (scaleOptions & ScaleOptions.Centered) == ScaleOptions.Centered; if (rationalScale) { @@ -280,38 +261,5 @@ namespace Greenshot.Editor.Helpers if (maintainAspectRatio) opts |= ScaleOptions.Rational; return opts; } - - public interface IDoubleProcessor - { - double Process(double d); - } - - public class ShapeAngleRoundBehavior : IDoubleProcessor - { - public static readonly ShapeAngleRoundBehavior INSTANCE = new(); - - private ShapeAngleRoundBehavior() - { - } - - public double Process(double angle) - { - return Math.Round((angle + 45) / 90) * 90 - 45; - } - } - - public class LineAngleRoundBehavior : IDoubleProcessor - { - public static readonly LineAngleRoundBehavior INSTANCE = new(); - - private LineAngleRoundBehavior() - { - } - - public double Process(double angle) - { - return Math.Round(angle / 15) * 15; - } - } } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Helpers/ScaleOptions.cs b/src/Greenshot.Editor/Helpers/ScaleOptions.cs new file mode 100644 index 000000000..1f47f5c02 --- /dev/null +++ b/src/Greenshot.Editor/Helpers/ScaleOptions.cs @@ -0,0 +1,44 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: https://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 . + */ + +using System; + +namespace Greenshot.Editor.Helpers +{ + [Flags] + public enum ScaleOptions + { + /// + /// Default scale behavior. + /// + Default = 0x00, + + /// + /// Scale a rectangle in two our four directions, mirrored at it's center coordinates + /// + Centered = 0x01, + + /// + /// Scale a rectangle maintaining it's aspect ratio + /// + Rational = 0x02 + } +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Helpers/ShapeAngleRoundBehavior.cs b/src/Greenshot.Editor/Helpers/ShapeAngleRoundBehavior.cs new file mode 100644 index 000000000..ba173df9f --- /dev/null +++ b/src/Greenshot.Editor/Helpers/ShapeAngleRoundBehavior.cs @@ -0,0 +1,39 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: https://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 . + */ + +using System; + +namespace Greenshot.Editor.Helpers +{ + public class ShapeAngleRoundBehavior : IDoubleProcessor + { + public static readonly ShapeAngleRoundBehavior INSTANCE = new(); + + private ShapeAngleRoundBehavior() + { + } + + public double Process(double angle) + { + return Math.Round((angle + 45) / 90) * 90 - 45; + } + } +} \ No newline at end of file diff --git a/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj b/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj index fdb555adc..347a58339 100644 --- a/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj +++ b/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj @@ -78,23 +78,23 @@ - + true runtime - + true runtime - + true runtime - + true runtime - + true runtime diff --git a/src/Greenshot/App.config b/src/Greenshot/App.config index 80b985a5c..ab8a7c40c 100644 --- a/src/Greenshot/App.config +++ b/src/Greenshot/App.config @@ -11,8 +11,7 @@ - - + \ No newline at end of file diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index 78fa3f6c6..fc4dd90d1 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -17,7 +17,7 @@ - + From f50f205b706aec10a9f9314eaa246b48668c4d39 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Tue, 28 Jun 2022 16:28:26 +0200 Subject: [PATCH 04/17] Removed old Windows 8 logic, which caused #403 (which is a very unlucky issue number LOL) This should actually make Greenshot a tiny bit faster and use less resources, but I am not 100% sure about the effects as some windows still seem to have the window class for Windows 8. --- src/Greenshot.Base/Core/WindowDetails.cs | 210 ++++------------------- src/Greenshot/Helpers/CaptureHelper.cs | 16 +- 2 files changed, 34 insertions(+), 192 deletions(-) diff --git a/src/Greenshot.Base/Core/WindowDetails.cs b/src/Greenshot.Base/Core/WindowDetails.cs index 281dde6f4..98416c105 100644 --- a/src/Greenshot.Base/Core/WindowDetails.cs +++ b/src/Greenshot.Base/Core/WindowDetails.cs @@ -42,8 +42,6 @@ namespace Greenshot.Base.Core { private const string AppWindowClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1) private const string AppFrameWindowClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow - private const string ApplauncherClass = "ImmersiveLauncher"; - private const string GutterClass = "ImmersiveGutter"; private static readonly IList IgnoreClasses = new List(new[] { @@ -89,13 +87,7 @@ namespace Greenshot.Base.Core private IntPtr _parentHandle = IntPtr.Zero; private WindowDetails _parent; private bool _frozen; - - /// - /// This checks if the window is a Windows 8 App - /// For Windows 10 most normal code works, as it's hosted inside "ApplicationFrameWindow" - /// - public bool IsApp => AppWindowClass.Equals(ClassName); - + /// /// This checks if the window is a Windows 10 App /// For Windows 10 apps are hosted inside "ApplicationFrameWindow" @@ -108,20 +100,6 @@ namespace Greenshot.Base.Core public bool IsBackgroundWin10App => WindowsVersion.IsWindows10OrLater && AppFrameWindowClass.Equals(ClassName) && !Children.Any(window => string.Equals(window.ClassName, AppWindowClass)); - /// - /// Check if the window is the metro gutter (sizeable separator) - /// - public bool IsGutter => GutterClass.Equals(ClassName); - - /// - /// Test if this window is for the App-Launcher - /// - public bool IsAppLauncher => ApplauncherClass.Equals(ClassName); - - /// - /// Check if this window is the window of a metro app - /// - public bool IsMetroApp => IsAppLauncher || IsApp; /// /// To allow items to be compared, the hash code @@ -226,12 +204,6 @@ namespace Greenshot.Base.Core Log.Warn(ex); } - if (IsMetroApp) - { - // No method yet to get the metro icon - return null; - } - try { return PluginUtils.GetCachedExeIcon(ProcessPath, 0); @@ -467,11 +439,6 @@ namespace Greenshot.Base.Core { get { - if (IsMetroApp) - { - return !Visible; - } - return User32Api.IsIconic(Handle) || Location.X <= -32000; } set @@ -494,22 +461,6 @@ namespace Greenshot.Base.Core { get { - if (IsApp) - { - if (Visible) - { - foreach (var displayInfo in DisplayInfo.AllDisplayInfos) - { - if (WindowRectangle.Equals(displayInfo.Bounds)) - { - return true; - } - } - } - - return false; - } - return User32Api.IsZoomed(Handle); } set @@ -546,50 +497,6 @@ namespace Greenshot.Base.Core return false; } - if (IsApp) - { - var windowRectangle = WindowRectangle; - - foreach (var displayInfo in DisplayInfo.AllDisplayInfos) - { - if (!displayInfo.Bounds.Contains(windowRectangle)) continue; - if (windowRectangle.Equals(displayInfo.Bounds)) - { - // Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes - // Although it might be the other App, this is not "very" important - NativeRect rect = displayInfo.Bounds; - IntPtr monitor = User32Api.MonitorFromRect(ref rect, MonitorFrom.DefaultToNull); - if (monitor != IntPtr.Zero) - { - MONITOR_APP_VISIBILITY? monitorAppVisibility = AppVisibility?.GetAppVisibilityOnMonitor(monitor); - //LOG.DebugFormat("App {0} visible: {1} on {2}", Text, monitorAppVisibility, screen.Bounds); - if (monitorAppVisibility == MONITOR_APP_VISIBILITY.MAV_APP_VISIBLE) - { - return true; - } - } - } - else - { - // Is only partly on the screen, when this happens the app is always visible! - return true; - } - } - - return false; - } - - if (IsGutter) - { - // gutter is only made available when it's visible - return true; - } - - if (IsAppLauncher) - { - return IsAppLauncherVisible; - } - return User32Api.IsWindowVisible(Handle); } } @@ -653,7 +560,7 @@ namespace Greenshot.Base.Core if (DwmApi.IsDwmEnabled) { bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); - if (IsApp) + if (IsWin10App) { // Pre-Cache for maximized call, this is only on Windows 8 apps (full screen) if (gotFrameBounds) @@ -683,8 +590,8 @@ namespace Greenshot.Base.Core } } - // Correction for maximized windows, only if it's not an app - if (!HasParent && !IsApp && Maximised) + // Correction for maximized windows + if (!HasParent && Maximised) { // Only if the border size can be retrieved if (GetBorderSize(out var size)) @@ -928,7 +835,7 @@ namespace Greenshot.Base.Core { // if GDI is allowed.. (a screenshot won't be better than we comes if we continue) using Process thisWindowProcess = Process; - if (!IsMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) + if (WindowCapture.IsGdiAllowed(thisWindowProcess)) { // we return null which causes the capturing code to try another method. return null; @@ -973,11 +880,8 @@ namespace Greenshot.Base.Core tempForm.BackColor = Color.Black; // Make sure everything is visible tempForm.Refresh(); - if (!IsMetroApp) - { - // Make sure the application window is active, so the colors & buttons are right - ToForeground(); - } + // Make sure the application window is active, so the colors & buttons are right + ToForeground(); // Make sure all changes are processed and visible Application.DoEvents(); @@ -1013,11 +917,8 @@ namespace Greenshot.Base.Core // Make sure everything is visible tempForm.Refresh(); - if (!IsMetroApp) - { - // Make sure the application window is active, so the colors & buttons are right - ToForeground(); - } + // Make sure the application window is active, so the colors & buttons are right + ToForeground(); // Make sure all changes are processed and visible Application.DoEvents(); @@ -1154,6 +1055,13 @@ namespace Greenshot.Base.Core return targetBuffer.UnlockAndReturnBitmap(); } + /// + /// If a window is hidden (Iconic), it also has the specified dimensions. + /// + /// NativeRect + /// bool true if hidden + private bool IsHidden(NativeRect rect) => rect.Width == 65535 && rect.Height == 65535 && rect.Left == 32767 && rect.Top == 32767; + /// /// Helper method to get the window size for DWM Windows /// @@ -1164,6 +1072,10 @@ namespace Greenshot.Base.Core var result = DwmApi.DwmGetWindowAttribute(Handle, DwmWindowAttributes.ExtendedFrameBounds, out NativeRect rect, Marshal.SizeOf(typeof(NativeRect))); if (result.Succeeded()) { + if (IsHidden(rect)) + { + rect = NativeRect.Empty; + } rectangle = rect; return true; } @@ -1196,7 +1108,14 @@ namespace Greenshot.Base.Core var windowInfo = new WindowInfo(); // Get the Window Info for this window bool result = User32Api.GetWindowInfo(Handle, ref windowInfo); - rectangle = result ? windowInfo.Bounds : NativeRect.Empty; + if (IsHidden(windowInfo.Bounds)) + { + rectangle = NativeRect.Empty; + } + else + { + rectangle = result ? windowInfo.Bounds : NativeRect.Empty; + } return result; } @@ -1577,7 +1496,7 @@ namespace Greenshot.Base.Core // Skip everything which is not rendered "normally", trying to fix BUG-2017 var exWindowStyle = window.ExtendedWindowStyle; - if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) + if (!window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) { return false; } @@ -1592,13 +1511,6 @@ namespace Greenshot.Base.Core public static IEnumerable GetVisibleWindows() { var screenBounds = DisplayInfo.ScreenBounds; - foreach (var window in GetAppWindows()) - { - if (IsVisible(window, screenBounds)) - { - yield return window; - } - } foreach (var window in GetAllWindows()) { @@ -1609,38 +1521,6 @@ namespace Greenshot.Base.Core } } - /// - /// Get the WindowDetails for all Metro Apps - /// These are all Windows with Classname "Windows.UI.Core.CoreWindow" - /// - /// List WindowDetails with visible metro apps - public static IEnumerable GetAppWindows() - { - // if the appVisibility != null we have Windows 8. - if (AppVisibility == null) - { - yield break; - } - - var nextHandle = User32Api.FindWindow(AppWindowClass, null); - while (nextHandle != IntPtr.Zero) - { - var metroApp = new WindowDetails(nextHandle); - yield return metroApp; - // Check if we have a gutter! - if (metroApp.Visible && !metroApp.Maximised) - { - var gutterHandle = User32Api.FindWindow(GutterClass, null); - if (gutterHandle != IntPtr.Zero) - { - yield return new WindowDetails(gutterHandle); - } - } - - nextHandle = User32Api.FindWindowEx(IntPtr.Zero, nextHandle, AppWindowClass, null); - } - } - /// /// Check if the window is a top level /// @@ -1671,7 +1551,7 @@ namespace Greenshot.Base.Core } // Skip everything which is not rendered "normally", trying to fix BUG-2017 - if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) + if (!window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) { return false; } @@ -1707,14 +1587,6 @@ namespace Greenshot.Base.Core /// List WindowDetails with all the top level windows public static IEnumerable GetTopLevelWindows() { - foreach (var possibleTopLevel in GetAppWindows()) - { - if (IsTopLevel(possibleTopLevel)) - { - yield return possibleTopLevel; - } - } - foreach (var possibleTopLevel in GetAllWindows()) { if (IsTopLevel(possibleTopLevel)) @@ -1790,27 +1662,6 @@ namespace Greenshot.Base.Core } } - /// - /// Get the AppLauncher - /// - /// - public static WindowDetails GetAppLauncher() - { - // Only if Windows 8 (or higher) - if (AppVisibility == null) - { - return null; - } - - IntPtr appLauncher = User32Api.FindWindow(ApplauncherClass, null); - if (appLauncher != IntPtr.Zero) - { - return new WindowDetails(appLauncher); - } - - return null; - } - /// /// Return true if the metro-app-launcher is visible /// @@ -1842,7 +1693,6 @@ namespace Greenshot.Base.Core result.AppendLine($"Size: {WindowRectangle.Size}"); result.AppendLine($"HasParent: {HasParent}"); result.AppendLine($"IsWin10App: {IsWin10App}"); - result.AppendLine($"IsApp: {IsApp}"); result.AppendLine($"Visible: {Visible}"); result.AppendLine($"IsWindowVisible: {User32Api.IsWindowVisible(Handle)}"); result.AppendLine($"IsCloaked: {IsCloaked}"); diff --git a/src/Greenshot/Helpers/CaptureHelper.cs b/src/Greenshot/Helpers/CaptureHelper.cs index c002c62ef..e51b51ebe 100644 --- a/src/Greenshot/Helpers/CaptureHelper.cs +++ b/src/Greenshot/Helpers/CaptureHelper.cs @@ -564,14 +564,6 @@ namespace Greenshot.Helpers { _windows = new List(); - // If the App Launcher is visible, no other windows are active - WindowDetails appLauncherWindow = WindowDetails.GetAppLauncher(); - if (appLauncherWindow != null && appLauncherWindow.Visible) - { - _windows.Add(appLauncherWindow); - return null; - } - Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails) { Name = "Retrieve window details", @@ -984,7 +976,7 @@ namespace Greenshot.Helpers else { // Change to GDI, if allowed - if (!windowToCapture.IsMetroApp && WindowCapture.IsGdiAllowed(process)) + if (WindowCapture.IsGdiAllowed(process)) { if (!dwmEnabled && IsWpf(process)) { @@ -1000,7 +992,7 @@ namespace Greenshot.Helpers // Change to DWM, if enabled and allowed if (dwmEnabled) { - if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) + if (WindowCapture.IsDwmAllowed(process)) { windowCaptureMode = WindowCaptureMode.Aero; } @@ -1009,7 +1001,7 @@ namespace Greenshot.Helpers } else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) { - if (!dwmEnabled || (!windowToCapture.IsMetroApp && !WindowCapture.IsDwmAllowed(process))) + if (!dwmEnabled || !WindowCapture.IsDwmAllowed(process)) { // Take default screen windowCaptureMode = WindowCaptureMode.Screen; @@ -1115,7 +1107,7 @@ namespace Greenshot.Helpers break; case WindowCaptureMode.Aero: case WindowCaptureMode.AeroTransparent: - if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) + if (WindowCapture.IsDwmAllowed(process)) { tmpCapture = windowToCapture.CaptureDwmWindow(captureForWindow, windowCaptureMode, isAutoMode); } From 36a285ebd4b9a8da071996d0b70c8be6e80e031d Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Tue, 28 Jun 2022 22:17:56 +0200 Subject: [PATCH 05/17] Fix capturing Maximised windows. --- src/Greenshot.Base/Core/WindowDetails.cs | 91 ++++++++++-------------- 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/src/Greenshot.Base/Core/WindowDetails.cs b/src/Greenshot.Base/Core/WindowDetails.cs index 98416c105..9cdf5f370 100644 --- a/src/Greenshot.Base/Core/WindowDetails.cs +++ b/src/Greenshot.Base/Core/WindowDetails.cs @@ -550,69 +550,56 @@ namespace Greenshot.Base.Core { // Try to return a cached value long now = DateTime.Now.Ticks; - if (_previousWindowRectangle.IsEmpty || !_frozen) - { - if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime) - { - return _previousWindowRectangle; - } - NativeRect windowRect = new(); - if (DwmApi.IsDwmEnabled) - { - bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); - if (IsWin10App) - { - // Pre-Cache for maximized call, this is only on Windows 8 apps (full screen) - if (gotFrameBounds) - { - _previousWindowRectangle = windowRect; - _lastWindowRectangleRetrieveTime = now; - } - } + if (!_previousWindowRectangle.IsEmpty && _frozen) return _previousWindowRectangle; - if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised) + if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime) + { + return _previousWindowRectangle; + } + NativeRect windowRect = new(); + if (DwmApi.IsDwmEnabled) + { + bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); + if (IsWin10App) + { + // Pre-Cache for maximized call, this is only on Windows 8 apps (full screen) + if (gotFrameBounds) { - // Somehow DWM doesn't calculate it correctly, there is a 1 pixel border around the capture - // Remove this border, currently it's fixed but TODO: Make it depend on the OS? - windowRect = windowRect.Inflate(Conf.Win10BorderCrop); _previousWindowRectangle = windowRect; _lastWindowRectangleRetrieveTime = now; - return windowRect; } } - if (windowRect.IsEmpty) + if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised) { - if (!GetWindowRect(out windowRect)) - { - Win32Error error = Win32.GetLastErrorCode(); - Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); - } + // Somehow DWM doesn't calculate it correctly, there is a 1 pixel border around the capture + // Remove this border, currently it's fixed but TODO: Make it depend on the OS? + windowRect = windowRect.Inflate(Conf.Win10BorderCrop); + _previousWindowRectangle = windowRect; + _lastWindowRectangleRetrieveTime = now; + return windowRect; } - - // Correction for maximized windows - if (!HasParent && Maximised) - { - // Only if the border size can be retrieved - if (GetBorderSize(out var size)) - { - windowRect = new NativeRect(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), - windowRect.Height - (2 * size.Height)); - } - } - - _lastWindowRectangleRetrieveTime = now; - // Try to return something valid, by getting returning the previous size if the window doesn't have a NativeRect anymore - if (windowRect.IsEmpty) - { - return _previousWindowRectangle; - } - - _previousWindowRectangle = windowRect; - return windowRect; } - return _previousWindowRectangle; + if (windowRect.IsEmpty) + { + if (!GetWindowRect(out windowRect)) + { + Win32Error error = Win32.GetLastErrorCode(); + Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); + } + } + + _lastWindowRectangleRetrieveTime = now; + // Try to return something valid, by getting returning the previous size if the window doesn't have a NativeRect anymore + if (windowRect.IsEmpty) + { + return _previousWindowRectangle; + } + + _previousWindowRectangle = windowRect; + return windowRect; + } } From 48675b01f0621172678ee359caeecb71a035a743 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Thu, 30 Jun 2022 22:57:55 +0200 Subject: [PATCH 06/17] Modified the configuration handling, added code to remove tokens when upgrading from 1.2 as these no longer work. See #421 --- src/Greenshot.Base/Core/CoreConfiguration.cs | 132 +++++++----------- src/Greenshot.Plugin.Box/BoxConfiguration.cs | 16 +++ .../DropboxConfiguration.cs | 16 +++ .../FlickrConfiguration.cs | 17 +++ .../ImgurConfiguration.cs | 19 ++- 5 files changed, 121 insertions(+), 79 deletions(-) diff --git a/src/Greenshot.Base/Core/CoreConfiguration.cs b/src/Greenshot.Base/Core/CoreConfiguration.cs index 580af8918..80ad3b719 100644 --- a/src/Greenshot.Base/Core/CoreConfiguration.cs +++ b/src/Greenshot.Base/Core/CoreConfiguration.cs @@ -388,89 +388,64 @@ namespace Greenshot.Base.Core return ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature); } + private string CreateOutputFilePath() + { + if (IniConfig.IsPortable) + { + string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots"); + if (!Directory.Exists(pafOutputFilePath)) + { + try + { + Directory.CreateDirectory(pafOutputFilePath); + return pafOutputFilePath; + } + catch (Exception ex) + { + // Problem creating directory, fallback to Desktop + LOG.Warn(ex); + } + } + else + { + return pafOutputFilePath; + } + } + + return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); + } + /// /// Supply values we can't put as defaults /// /// The property to return a default for /// object with the default value for the supplied property - public override object GetDefault(string property) - { - switch (property) + public override object GetDefault(string property) => + property switch { - case nameof(ExcludePlugins): - case nameof(IncludePlugins): - return new List(); - case nameof(OutputFileAsFullpath): - if (IniConfig.IsPortable) - { - return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png"); - } - - return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png"); - case nameof(OutputFilePath): - if (IniConfig.IsPortable) - { - string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots"); - if (!Directory.Exists(pafOutputFilePath)) - { - try - { - Directory.CreateDirectory(pafOutputFilePath); - return pafOutputFilePath; - } - catch (Exception ex) - { - LOG.Warn(ex); - // Problem creating directory, fallback to Desktop - } - } - else - { - return pafOutputFilePath; - } - } - - return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - case nameof(DWMBackgroundColor): - return Color.Transparent; - case nameof(ActiveTitleFixes): - return new List - { - "Firefox", - "IE", - "Chrome" - }; - case nameof(TitleFixMatcher): - return new Dictionary - { - { - "Firefox", " - Mozilla Firefox.*" - }, - { - "IE", " - (Microsoft|Windows) Internet Explorer.*" - }, - { - "Chrome", " - Google Chrome.*" - } - }; - case nameof(TitleFixReplacer): - return new Dictionary - { - { - "Firefox", string.Empty - }, - { - "IE", string.Empty - }, - { - "Chrome", string.Empty - } - }; - } - - return null; - } - + nameof(ExcludePlugins) => new List(), + nameof(IncludePlugins) => new List(), + nameof(OutputFileAsFullpath) => IniConfig.IsPortable ? Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png") : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png"), + nameof(OutputFilePath) => CreateOutputFilePath(), + nameof(DWMBackgroundColor) => Color.Transparent, + nameof(ActiveTitleFixes) => new List { + "Firefox", + "IE", + "Chrome" + }, + nameof(TitleFixMatcher) => new Dictionary { + { "Firefox", " - Mozilla Firefox.*" }, + { "IE", " - (Microsoft|Windows) Internet Explorer.*" }, + { "Chrome", " - Google Chrome.*" } + }, + nameof(TitleFixReplacer) => new Dictionary { + { "Firefox", string.Empty }, + { "IE", string.Empty }, + { "Chrome", string.Empty } + }, + _ => null + }; + /// /// This method will be called before converting the property, making to possible to correct a certain value /// Can be used when migration is needed @@ -540,8 +515,9 @@ namespace Greenshot.Base.Core OutputFileAutoReduceColors = false; } + bool isUpgradeFrom12 = LastSaveWithVersion?.StartsWith("1.2") ?? false; // Fix for excessive feed checking - if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && LastSaveWithVersion.StartsWith("1.2")) + if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && isUpgradeFrom12) { UpdateCheckInterval = 14; } diff --git a/src/Greenshot.Plugin.Box/BoxConfiguration.cs b/src/Greenshot.Plugin.Box/BoxConfiguration.cs index fdef95ae5..c745fe985 100644 --- a/src/Greenshot.Plugin.Box/BoxConfiguration.cs +++ b/src/Greenshot.Plugin.Box/BoxConfiguration.cs @@ -21,6 +21,7 @@ using System; using System.Windows.Forms; +using Greenshot.Base.Core; using Greenshot.Base.Core.Enums; using Greenshot.Base.IniFile; using Greenshot.Plugin.Box.Forms; @@ -75,5 +76,20 @@ namespace Greenshot.Plugin.Box return false; } + + /// + /// Upgrade certain values + /// + public override void AfterLoad() + { + var coreConfiguration = IniConfig.GetIniSection(); + bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false; + // Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421 + if (!isUpgradeFrom12) return; + + // We have an upgrade, remove all previous credentials. + RefreshToken = null; + AccessToken = null; + } } } \ No newline at end of file diff --git a/src/Greenshot.Plugin.Dropbox/DropboxConfiguration.cs b/src/Greenshot.Plugin.Dropbox/DropboxConfiguration.cs index b9dd8bf0c..d79db8686 100644 --- a/src/Greenshot.Plugin.Dropbox/DropboxConfiguration.cs +++ b/src/Greenshot.Plugin.Dropbox/DropboxConfiguration.cs @@ -21,6 +21,7 @@ using System; using System.Windows.Forms; +using Greenshot.Base.Core; using Greenshot.Base.Core.Enums; using Greenshot.Base.IniFile; using Greenshot.Plugin.Dropbox.Forms; @@ -69,5 +70,20 @@ namespace Greenshot.Plugin.Dropbox return false; } + + /// + /// Upgrade certain values + /// + public override void AfterLoad() + { + var coreConfiguration = IniConfig.GetIniSection(); + bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false; + // Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421 + if (!isUpgradeFrom12) return; + + // We have an upgrade, remove all previous credentials. + RefreshToken = null; + AccessToken = null; + } } } \ No newline at end of file diff --git a/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs b/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs index e4f602796..df5a428fa 100644 --- a/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs +++ b/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs @@ -20,6 +20,7 @@ */ using System.Windows.Forms; +using Greenshot.Base.Core; using Greenshot.Base.Core.Enums; using Greenshot.Base.IniFile; using Greenshot.Plugin.Flickr.Forms; @@ -86,5 +87,21 @@ namespace Greenshot.Plugin.Flickr return false; } + + /// + /// Upgrade certain values + /// + public override void AfterLoad() + { + var coreConfiguration = IniConfig.GetIniSection(); + bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false; + // Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421 + if (!isUpgradeFrom12) return; + + // We have an upgrade, remove all previous credentials. + FlickrToken = null; + FlickrTokenSecret = null; + } + } } \ No newline at end of file diff --git a/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs b/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs index 3bb695672..3dc145d0b 100644 --- a/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs +++ b/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; using System.Windows.Forms; +using Greenshot.Base.Core; using Greenshot.Base.Core.Enums; using Greenshot.Base.IniFile; using Greenshot.Plugin.Imgur.Forms; @@ -84,6 +85,22 @@ namespace Greenshot.Plugin.Imgur public Dictionary runtimeImgurHistory = new Dictionary(); public int Credits { get; set; } + /// + /// Upgrade certain values + /// + public override void AfterLoad() + { + var coreConfiguration = IniConfig.GetIniSection(); + bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false; + // Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421 + if (!isUpgradeFrom12) return; + + // We have an upgrade, remove all previous credentials. + AccessToken = null; + RefreshToken = null; + AccessTokenExpires = default; + } + /// /// Supply values we can't put as defaults /// @@ -92,7 +109,7 @@ namespace Greenshot.Plugin.Imgur public override object GetDefault(string property) => property switch { - "ImgurUploadHistory" => new Dictionary(), + nameof(ImgurUploadHistory) => new Dictionary(), _ => null }; From bfa8e2444e7d704f51e255765a812aa827416642 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Thu, 30 Jun 2022 23:34:51 +0200 Subject: [PATCH 07/17] This should hopefully fix an overflow exception while decoding the dib format. --- .../FileFormatHandlers/DibFileFormatHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Greenshot.Editor/FileFormatHandlers/DibFileFormatHandler.cs b/src/Greenshot.Editor/FileFormatHandlers/DibFileFormatHandler.cs index ad129c4ba..b14a33bd0 100644 --- a/src/Greenshot.Editor/FileFormatHandlers/DibFileFormatHandler.cs +++ b/src/Greenshot.Editor/FileFormatHandlers/DibFileFormatHandler.cs @@ -100,8 +100,7 @@ namespace Greenshot.Editor.FileFormatHandlers bitmap = new Bitmap(infoHeader.Width, infoHeader.Height, -(int)(infoHeader.SizeImage / infoHeader.Height), infoHeader.BitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb, - new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels + - (infoHeader.Height - 1) * (int)(infoHeader.SizeImage / infoHeader.Height)) + IntPtr.Add(handle.AddrOfPinnedObject(), (int)infoHeader.OffsetToPixels + (infoHeader.Height - 1) * (int)(infoHeader.SizeImage / infoHeader.Height)) ); } catch (Exception ex) From 2b5e45e33e87ee156edd2b28eaa392d5461775ef Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Thu, 30 Jun 2022 23:47:38 +0200 Subject: [PATCH 08/17] Fixed a log error, and made the ClipboardHotkey optional. --- src/Greenshot.Base/Core/ClipboardHelper.cs | 2 +- src/Greenshot.Base/Core/CoreConfiguration.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.Base/Core/ClipboardHelper.cs b/src/Greenshot.Base/Core/ClipboardHelper.cs index 7a30a1143..ed9f2c3e9 100644 --- a/src/Greenshot.Base/Core/ClipboardHelper.cs +++ b/src/Greenshot.Base/Core/ClipboardHelper.cs @@ -520,7 +520,7 @@ EndSelection:<<<<<<<4 Bitmap singleImage = GetImage(dataObject); if (singleImage != null) { - Log.InfoFormat($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}"); + Log.Info($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}"); yield return singleImage; yield break; } diff --git a/src/Greenshot.Base/Core/CoreConfiguration.cs b/src/Greenshot.Base/Core/CoreConfiguration.cs index 80ad3b719..3e085bc9b 100644 --- a/src/Greenshot.Base/Core/CoreConfiguration.cs +++ b/src/Greenshot.Base/Core/CoreConfiguration.cs @@ -59,7 +59,7 @@ namespace Greenshot.Base.Core [IniProperty("IEHotkey", Description = "Hotkey for starting the IE capture", DefaultValue = "Shift + Ctrl + PrintScreen")] public string IEHotkey { get; set; } - [IniProperty("ClipboardHotkey", Description = "Hotkey for opening the clipboard contents into the editor")] + [IniProperty("ClipboardHotkey", Description = "Hotkey for opening the clipboard contents into the editor", ExcludeIfNull = true)] public string ClipboardHotkey { get; set; } [IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")] From ba8ed074c8b3078a25c5abe9c2448c37bb492a6c Mon Sep 17 00:00:00 2001 From: jdavila71 <49653176+jdavila71@users.noreply.github.com> Date: Wed, 17 Aug 2022 16:01:01 -0400 Subject: [PATCH 09/17] Fix of BUG-2951, issues with finding Office installations (#431) --- src/Greenshot.Base/Core/PluginUtils.cs | 74 ++++++++++++++++++- .../Destinations/ExcelDestination.cs | 5 +- .../Destinations/OneNoteDestination.cs | 4 +- .../Destinations/OutlookDestination.cs | 5 +- .../Destinations/PowerpointDestination.cs | 4 +- .../Destinations/WordDestination.cs | 4 +- 6 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/Greenshot.Base/Core/PluginUtils.cs b/src/Greenshot.Base/Core/PluginUtils.cs index d41e545a5..6a2755d50 100644 --- a/src/Greenshot.Base/Core/PluginUtils.cs +++ b/src/Greenshot.Base/Core/PluginUtils.cs @@ -40,13 +40,85 @@ namespace Greenshot.Base.Core private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils)); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\"; + private static string[] strRootKeys = { @"SOFTWARE\Microsoft\Office", @"SOFTWARE\WOW6432Node\Microsoft\Office" }; private static readonly IDictionary ExeIconCache = new Dictionary(); static PluginUtils() { CoreConfig.PropertyChanged += OnIconSizeChanged; } + /// + /// Clear icon cache + /// + /// + /// + public static string GetOfficeExePath(string keyname) + { + string strKeyName = keyname switch + { + "WINWORD.EXE" => "Word", + "EXCEL.EXE" => "Excel", + "POWERPNT.EXE" => "PowerPoint", + "OUTLOOK.EXE" => "Outlook", + "ONENOTE.EXE" => "OneNote", + _ => "" + }; + RegistryKey rootKey = null; + RegistryKey officeKey = null; + RegistryKey programKey = null; + RegistryKey installRootKey = null; + string retValue = string.Empty; + + foreach (string strRootKey in strRootKeys) + { + rootKey = Registry.LocalMachine.OpenSubKey(strRootKey); + + if (rootKey != null) + { + string[] officeVersions = rootKey.GetSubKeyNames(); + if (officeVersions is null) + continue; + officeVersions = Array.FindAll(officeVersions, r => r.Contains(".")); + Array.Reverse(officeVersions); + // string latestOfficeVersion = officeVersions.Where(r => r.Contains(".")).Max(); + + foreach (string officeVersion in officeVersions) + { + officeKey = Registry.LocalMachine.OpenSubKey(strRootKey + "\\" + officeVersion); + + if (officeKey is null) + continue; + + programKey = officeKey.OpenSubKey(strKeyName); + + if (programKey is null) + continue; + + installRootKey = programKey.OpenSubKey("InstallRoot"); + + if (installRootKey != null) + { + retValue = installRootKey.GetValue("Path").ToString() + "\\" + keyname; + break; + + } + + } + + + } + } + if (rootKey != null) + rootKey.Dispose(); + if (officeKey != null) + officeKey.Dispose(); + if (programKey != null) + programKey.Dispose(); + if (installRootKey != null) + installRootKey.Dispose(); + return retValue; + } /// /// Clear icon cache /// @@ -84,7 +156,7 @@ namespace Greenshot.Base.Core if (key != null) { // "" is the default key, which should point to the requested location - return (string) key.GetValue(string.Empty); + return (string)key.GetValue(string.Empty); } } diff --git a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs index fb1930c8c..8c13e4754 100644 --- a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs @@ -42,7 +42,10 @@ namespace Greenshot.Plugin.Office.Destinations static ExcelDestination() { - ExePath = PluginUtils.GetExePath("EXCEL.EXE"); + ExePath = PluginUtils.GetOfficeExePath("EXCEL.EXE"); + if (ExePath == null) + ExePath = PluginUtils.GetExePath("EXCEL.EXE"); + if (ExePath != null && File.Exists(ExePath)) { WindowDetails.AddProcessToExcludeFromFreeze("excel"); diff --git a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs index 387810494..a2ab24937 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs @@ -41,7 +41,9 @@ namespace Greenshot.Plugin.Office.Destinations static OneNoteDestination() { - exePath = PluginUtils.GetExePath("ONENOTE.EXE"); + exePath = PluginUtils.GetOfficeExePath("ONENOTE.EXE"); + if (exePath == null) + exePath = PluginUtils.GetExePath("ONENOTE.EXE"); if (exePath != null && File.Exists(exePath)) { WindowDetails.AddProcessToExcludeFromFreeze("onenote"); diff --git a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs index 6d93c4096..68cdd706b 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs @@ -58,8 +58,9 @@ namespace Greenshot.Plugin.Office.Destinations { IsActiveFlag = true; } - - ExePath = PluginUtils.GetExePath("OUTLOOK.EXE"); + ExePath = PluginUtils.GetOfficeExePath("OUTLOOK.EXE"); + if (ExePath == null) + ExePath = PluginUtils.GetExePath("OUTLOOK.EXE"); if (ExePath != null && File.Exists(ExePath)) { WindowDetails.AddProcessToExcludeFromFreeze("outlook"); diff --git a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs index 3b9ce4bc8..34f734cc4 100644 --- a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs @@ -45,7 +45,9 @@ namespace Greenshot.Plugin.Office.Destinations static PowerpointDestination() { - ExePath = PluginUtils.GetExePath("POWERPNT.EXE"); + ExePath = PluginUtils.GetOfficeExePath("POWERPNT.EXE"); + if (ExePath == null) + ExePath = PluginUtils.GetExePath("POWERPNT.EXE"); if (ExePath != null && File.Exists(ExePath)) { WindowDetails.AddProcessToExcludeFromFreeze("powerpnt"); diff --git a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs index 99cf4693c..34dfebad7 100644 --- a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs @@ -46,7 +46,9 @@ namespace Greenshot.Plugin.Office.Destinations static WordDestination() { - ExePath = PluginUtils.GetExePath("WINWORD.EXE"); + ExePath = PluginUtils.GetOfficeExePath("WINWORD.EXE"); + if (ExePath == null) + ExePath = PluginUtils.GetExePath("WINWORD.EXE"); if (ExePath != null && !File.Exists(ExePath)) { ExePath = null; From 3e8809384692a713eb42f6b992cd1c4f43808a28 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 17 Aug 2022 23:01:24 +0200 Subject: [PATCH 10/17] Some aftercare for #431, moved the code to find the path for the office executables to the office plugin, as this is where it's needed. Also optimized the code a bit, using modern features. --- src/Directory.Build.props | 4 +- src/Greenshot.Base/Core/PluginUtils.cs | 77 +------------------ src/Greenshot.Base/Greenshot.Base.csproj | 4 +- .../Destinations/ExcelDestination.cs | 4 +- .../Destinations/OneNoteDestination.cs | 4 +- .../Destinations/OutlookDestination.cs | 4 +- .../Destinations/PowerpointDestination.cs | 4 +- .../Destinations/WordDestination.cs | 6 +- src/Greenshot.Plugin.Office/OfficeUtils.cs | 52 +++++++++++++ 9 files changed, 65 insertions(+), 94 deletions(-) create mode 100644 src/Greenshot.Plugin.Office/OfficeUtils.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f5b9f2e1c..2fbce49ed 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -7,7 +7,7 @@ git https://github.com/greenshot/greenshot GPL-3.0-only - 9 + 10 true true win10-x64;win10-x86;win-x64;win-x86 @@ -46,7 +46,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Greenshot.Base/Core/PluginUtils.cs b/src/Greenshot.Base/Core/PluginUtils.cs index 6a2755d50..76f08422b 100644 --- a/src/Greenshot.Base/Core/PluginUtils.cs +++ b/src/Greenshot.Base/Core/PluginUtils.cs @@ -24,6 +24,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; +using System.Linq; using System.Windows.Forms; using Dapplo.Windows.Icons; using Greenshot.Base.IniFile; @@ -39,86 +40,14 @@ namespace Greenshot.Base.Core { private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils)); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\"; - private static string[] strRootKeys = { @"SOFTWARE\Microsoft\Office", @"SOFTWARE\WOW6432Node\Microsoft\Office" }; private static readonly IDictionary ExeIconCache = new Dictionary(); - + private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\"; + static PluginUtils() { CoreConfig.PropertyChanged += OnIconSizeChanged; } - /// - /// Clear icon cache - /// - /// - /// - public static string GetOfficeExePath(string keyname) - { - string strKeyName = keyname switch - { - "WINWORD.EXE" => "Word", - "EXCEL.EXE" => "Excel", - "POWERPNT.EXE" => "PowerPoint", - "OUTLOOK.EXE" => "Outlook", - "ONENOTE.EXE" => "OneNote", - _ => "" - }; - RegistryKey rootKey = null; - RegistryKey officeKey = null; - RegistryKey programKey = null; - RegistryKey installRootKey = null; - string retValue = string.Empty; - - foreach (string strRootKey in strRootKeys) - { - rootKey = Registry.LocalMachine.OpenSubKey(strRootKey); - - if (rootKey != null) - { - string[] officeVersions = rootKey.GetSubKeyNames(); - if (officeVersions is null) - continue; - officeVersions = Array.FindAll(officeVersions, r => r.Contains(".")); - Array.Reverse(officeVersions); - // string latestOfficeVersion = officeVersions.Where(r => r.Contains(".")).Max(); - - foreach (string officeVersion in officeVersions) - { - officeKey = Registry.LocalMachine.OpenSubKey(strRootKey + "\\" + officeVersion); - - if (officeKey is null) - continue; - - programKey = officeKey.OpenSubKey(strKeyName); - - if (programKey is null) - continue; - - installRootKey = programKey.OpenSubKey("InstallRoot"); - - if (installRootKey != null) - { - retValue = installRootKey.GetValue("Path").ToString() + "\\" + keyname; - break; - - } - - } - - - } - } - if (rootKey != null) - rootKey.Dispose(); - if (officeKey != null) - officeKey.Dispose(); - if (programKey != null) - programKey.Dispose(); - if (installRootKey != null) - installRootKey.Dispose(); - return retValue; - } /// /// Clear icon cache /// diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj index a698b8e0b..021ea53ec 100644 --- a/src/Greenshot.Base/Greenshot.Base.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs index 8c13e4754..1a671cf7a 100644 --- a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs @@ -42,9 +42,7 @@ namespace Greenshot.Plugin.Office.Destinations static ExcelDestination() { - ExePath = PluginUtils.GetOfficeExePath("EXCEL.EXE"); - if (ExePath == null) - ExePath = PluginUtils.GetExePath("EXCEL.EXE"); + ExePath = OfficeUtils.GetOfficeExePath("EXCEL.EXE") ?? PluginUtils.GetExePath("EXCEL.EXE"); if (ExePath != null && File.Exists(ExePath)) { diff --git a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs index a2ab24937..5f8da7a67 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs @@ -41,9 +41,7 @@ namespace Greenshot.Plugin.Office.Destinations static OneNoteDestination() { - exePath = PluginUtils.GetOfficeExePath("ONENOTE.EXE"); - if (exePath == null) - exePath = PluginUtils.GetExePath("ONENOTE.EXE"); + exePath = OfficeUtils.GetOfficeExePath("ONENOTE.EXE") ?? PluginUtils.GetExePath("ONENOTE.EXE"); if (exePath != null && File.Exists(exePath)) { WindowDetails.AddProcessToExcludeFromFreeze("onenote"); diff --git a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs index 68cdd706b..3c77ea4f1 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs @@ -58,9 +58,7 @@ namespace Greenshot.Plugin.Office.Destinations { IsActiveFlag = true; } - ExePath = PluginUtils.GetOfficeExePath("OUTLOOK.EXE"); - if (ExePath == null) - ExePath = PluginUtils.GetExePath("OUTLOOK.EXE"); + ExePath = OfficeUtils.GetOfficeExePath("OUTLOOK.EXE") ?? PluginUtils.GetExePath("OUTLOOK.EXE"); if (ExePath != null && File.Exists(ExePath)) { WindowDetails.AddProcessToExcludeFromFreeze("outlook"); diff --git a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs index 34f734cc4..010093027 100644 --- a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs @@ -45,9 +45,7 @@ namespace Greenshot.Plugin.Office.Destinations static PowerpointDestination() { - ExePath = PluginUtils.GetOfficeExePath("POWERPNT.EXE"); - if (ExePath == null) - ExePath = PluginUtils.GetExePath("POWERPNT.EXE"); + ExePath = OfficeUtils.GetOfficeExePath("POWERPNT.EXE") ?? PluginUtils.GetExePath("POWERPNT.EXE"); if (ExePath != null && File.Exists(ExePath)) { WindowDetails.AddProcessToExcludeFromFreeze("powerpnt"); diff --git a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs index 34dfebad7..d6220a302 100644 --- a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs @@ -46,9 +46,7 @@ namespace Greenshot.Plugin.Office.Destinations static WordDestination() { - ExePath = PluginUtils.GetOfficeExePath("WINWORD.EXE"); - if (ExePath == null) - ExePath = PluginUtils.GetExePath("WINWORD.EXE"); + ExePath = OfficeUtils.GetOfficeExePath("WINWORD.EXE") ?? PluginUtils.GetExePath("WINWORD.EXE"); if (ExePath != null && !File.Exists(ExePath)) { ExePath = null; @@ -120,7 +118,7 @@ namespace Greenshot.Plugin.Office.Destinations if (!manuallyInitiated) { var documents = _wordExporter.GetWordDocuments().ToList(); - if (documents != null && documents.Count > 0) + if (documents is { Count: > 0 }) { var destinations = new List { diff --git a/src/Greenshot.Plugin.Office/OfficeUtils.cs b/src/Greenshot.Plugin.Office/OfficeUtils.cs new file mode 100644 index 000000000..770f8b1e8 --- /dev/null +++ b/src/Greenshot.Plugin.Office/OfficeUtils.cs @@ -0,0 +1,52 @@ +using System.Linq; +using Microsoft.Win32; + +namespace Greenshot.Plugin.Office; + +/// +/// A small utility class for helping with office +/// +internal static class OfficeUtils +{ + private static readonly string[] OfficeRootKeys = { @"SOFTWARE\Microsoft\Office", @"SOFTWARE\WOW6432Node\Microsoft\Office" }; + + /// + /// Get the path to the office exe + /// + /// Name of the office executable + public static string GetOfficeExePath(string exeName) + { + string strKeyName = exeName switch + { + "WINWORD.EXE" => "Word", + "EXCEL.EXE" => "Excel", + "POWERPNT.EXE" => "PowerPoint", + "OUTLOOK.EXE" => "Outlook", + "ONENOTE.EXE" => "OneNote", + _ => "" + }; + + foreach (string strRootKey in OfficeRootKeys) + { + using RegistryKey rootKey = Registry.LocalMachine.OpenSubKey(strRootKey); + + if (rootKey is null) continue; + + + foreach (string officeVersion in rootKey.GetSubKeyNames().Where(r => r.Contains(".")).Reverse()) + { + using RegistryKey officeKey = Registry.LocalMachine.OpenSubKey(strRootKey + "\\" + officeVersion); + if (officeKey is null) continue; + + using RegistryKey programKey = officeKey.OpenSubKey(strKeyName); + if (programKey is null) continue; + + using RegistryKey installRootKey = programKey.OpenSubKey("InstallRoot"); + if (installRootKey == null) continue; + + return installRootKey.GetValue("Path") + "\\" + exeName; + } + } + return string.Empty; + } +} From af3c22c38c33ffdd88c77f7d97d20531a1dff5f8 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 17 Aug 2022 23:08:59 +0200 Subject: [PATCH 11/17] Optimized the code to find the office executable even more. --- src/Greenshot.Plugin.Office/OfficeUtils.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Greenshot.Plugin.Office/OfficeUtils.cs b/src/Greenshot.Plugin.Office/OfficeUtils.cs index 770f8b1e8..4b828c558 100644 --- a/src/Greenshot.Plugin.Office/OfficeUtils.cs +++ b/src/Greenshot.Plugin.Office/OfficeUtils.cs @@ -35,16 +35,9 @@ internal static class OfficeUtils foreach (string officeVersion in rootKey.GetSubKeyNames().Where(r => r.Contains(".")).Reverse()) { - using RegistryKey officeKey = Registry.LocalMachine.OpenSubKey(strRootKey + "\\" + officeVersion); - if (officeKey is null) continue; - - using RegistryKey programKey = officeKey.OpenSubKey(strKeyName); - if (programKey is null) continue; - - using RegistryKey installRootKey = programKey.OpenSubKey("InstallRoot"); + using RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey($@"{strRootKey}\{officeVersion}\{strKeyName}\InstallRoot"); if (installRootKey == null) continue; - - return installRootKey.GetValue("Path") + "\\" + exeName; + return $@"{installRootKey.GetValue("Path")}\{exeName}"; } } return string.Empty; From 296dc9f34083dea09b819d91fe45f5b9031cad0c Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 17 Aug 2022 23:09:44 +0200 Subject: [PATCH 12/17] Formatting --- src/Greenshot.Plugin.Office/OfficeUtils.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Greenshot.Plugin.Office/OfficeUtils.cs b/src/Greenshot.Plugin.Office/OfficeUtils.cs index 4b828c558..78be20557 100644 --- a/src/Greenshot.Plugin.Office/OfficeUtils.cs +++ b/src/Greenshot.Plugin.Office/OfficeUtils.cs @@ -29,10 +29,8 @@ internal static class OfficeUtils foreach (string strRootKey in OfficeRootKeys) { using RegistryKey rootKey = Registry.LocalMachine.OpenSubKey(strRootKey); - if (rootKey is null) continue; - foreach (string officeVersion in rootKey.GetSubKeyNames().Where(r => r.Contains(".")).Reverse()) { using RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey($@"{strRootKey}\{officeVersion}\{strKeyName}\InstallRoot"); From 511034a34be0b87c28bb6a093026e75a40aa5b90 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 17 Aug 2022 23:12:55 +0200 Subject: [PATCH 13/17] Fixed the return value of the GetOfficeExePath, this should be null so it's clear the file hasn't been found. --- src/Greenshot.Plugin.Office/OfficeUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Greenshot.Plugin.Office/OfficeUtils.cs b/src/Greenshot.Plugin.Office/OfficeUtils.cs index 78be20557..52ca8d7cb 100644 --- a/src/Greenshot.Plugin.Office/OfficeUtils.cs +++ b/src/Greenshot.Plugin.Office/OfficeUtils.cs @@ -38,6 +38,6 @@ internal static class OfficeUtils return $@"{installRootKey.GetValue("Path")}\{exeName}"; } } - return string.Empty; + return null; } } From 029d47f479abadf5382daddc456790ad43a2e798 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Sat, 3 Sep 2022 15:11:16 +0200 Subject: [PATCH 14/17] Added some NPE protections for BUG-2991 --- src/Greenshot.Base/Core/ClipboardHelper.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Greenshot.Base/Core/ClipboardHelper.cs b/src/Greenshot.Base/Core/ClipboardHelper.cs index ed9f2c3e9..bfe13c121 100644 --- a/src/Greenshot.Base/Core/ClipboardHelper.cs +++ b/src/Greenshot.Base/Core/ClipboardHelper.cs @@ -386,6 +386,7 @@ EndSelection:<<<<<<<4 /// IEnumerable{(MemoryStream,string)} private static IEnumerable<(MemoryStream stream,string filename)> IterateClipboardContent(IDataObject dataObject) { + if (dataObject == null) yield break; var fileDescriptors = AvailableFileDescriptors(dataObject); if (fileDescriptors == null) yield break; @@ -499,6 +500,10 @@ EndSelection:<<<<<<<4 public static Image GetImage() { IDataObject clipboardData = GetDataObject(); + if (clipboardData == null) + { + return null; + } // Return the first image foreach (var clipboardImage in GetImages(clipboardData)) { From 9634f8abbc119959d84b940c14f8abcad0b709ff Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Sun, 4 Sep 2022 15:35:38 +0200 Subject: [PATCH 15/17] Updated dependencies. --- src/Directory.Build.props | 4 ++-- src/Greenshot.Base/Greenshot.Base.csproj | 16 ++++++++-------- .../Greenshot.Plugin.Jira.csproj | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 2fbce49ed..869f3b94d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,13 +1,13 @@  - Copyright © Greenshot 2004-2021 + Copyright © Greenshot 2004-2022 Greenshot https://getgreenshot.org/favicon.ico https://github.com/greenshot/greenshot git https://github.com/greenshot/greenshot GPL-3.0-only - 10 + latest true true win10-x64;win10-x86;win-x64;win-x86 diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj index 021ea53ec..15910a7d2 100644 --- a/src/Greenshot.Base/Greenshot.Base.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -5,14 +5,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj b/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj index 40f2caf2d..a06e33882 100644 --- a/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj +++ b/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj @@ -6,7 +6,7 @@ - - + + \ No newline at end of file From 4c6707b468561207d553e56314817020661c7ba8 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 28 Sep 2022 20:53:57 +0200 Subject: [PATCH 16/17] Fixed #432, inflate is not the best way of increasing a rectangle size. --- src/Greenshot/Forms/CaptureForm.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Greenshot/Forms/CaptureForm.cs b/src/Greenshot/Forms/CaptureForm.cs index 68e57f040..47dc6e0f6 100644 --- a/src/Greenshot/Forms/CaptureForm.cs +++ b/src/Greenshot/Forms/CaptureForm.cs @@ -197,7 +197,7 @@ namespace Greenshot.Forms private void CaptureForm_Resize(object sender, EventArgs e) { Log.DebugFormat("Resize was called, new size: {0}", this.Bounds); - if (Bounds.Equals(_capture.ScreenBounds)) + if (_capture.ScreenBounds.Equals(Bounds)) { // We have the correct size return; @@ -425,9 +425,11 @@ namespace Greenshot.Forms else if (_captureRect.Height > 0 && _captureRect.Width > 0) { // correct the GUI width to real width if Region mode - if (_captureMode == CaptureMode.Region || _captureMode == CaptureMode.Text) + if (_captureMode is CaptureMode.Region or CaptureMode.Text) { - _captureRect = _captureRect.Inflate(1, 1); + // Correct the rectangle size, by making it 1 pixel bigger + // We cannot use inflate, this would make the rect bigger to all sizes. + _captureRect = new NativeRect(_captureRect.Top, _captureRect.Left, _captureRect.Width+1, _captureRect.Height+1); } // Go and process the capture From 7e005f741a3f009a1f974ac80d6f6018fdc7528d Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 5 Oct 2022 22:29:01 +0200 Subject: [PATCH 17/17] Fixed #441, swapped left & top. --- src/Directory.Build.props | 2 +- src/Greenshot.Base/Greenshot.Base.csproj | 2 +- src/Greenshot/Forms/CaptureForm.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 869f3b94d..131878749 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -46,7 +46,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj index 15910a7d2..7e55c1dbc 100644 --- a/src/Greenshot.Base/Greenshot.Base.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Greenshot/Forms/CaptureForm.cs b/src/Greenshot/Forms/CaptureForm.cs index 47dc6e0f6..107aa9096 100644 --- a/src/Greenshot/Forms/CaptureForm.cs +++ b/src/Greenshot/Forms/CaptureForm.cs @@ -429,7 +429,7 @@ namespace Greenshot.Forms { // Correct the rectangle size, by making it 1 pixel bigger // We cannot use inflate, this would make the rect bigger to all sizes. - _captureRect = new NativeRect(_captureRect.Top, _captureRect.Left, _captureRect.Width+1, _captureRect.Height+1); + _captureRect = new NativeRect(_captureRect.Left, _captureRect.Top, _captureRect.Width+1, _captureRect.Height+1); } // Go and process the capture