diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 977f4cf8b..f8bd75b1d 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -20,7 +20,7 @@ [Files] Source: {#ReleaseDir}\Greenshot.exe; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\GreenshotPlugin.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Greenshot.Base.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Greenshot.exe.config; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\log4net.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Dapplo.Http*.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion diff --git a/src/GreenshotPlugin/Controls/AnimatingForm.cs b/src/Greenshot.Base/Controls/AnimatingForm.cs similarity index 94% rename from src/GreenshotPlugin/Controls/AnimatingForm.cs rename to src/Greenshot.Base/Controls/AnimatingForm.cs index 2bfb06a52..c5a5e3e7e 100644 --- a/src/GreenshotPlugin/Controls/AnimatingForm.cs +++ b/src/Greenshot.Base/Controls/AnimatingForm.cs @@ -1,140 +1,140 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Windows.Forms; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using log4net; - -namespace GreenshotPlugin.Controls -{ - /// - /// Extend this Form to have the possibility for animations on your form - /// - public class AnimatingForm : GreenshotForm - { - private static readonly ILog Log = LogManager.GetLogger(typeof(AnimatingForm)); - private const int DEFAULT_VREFRESH = 60; - private int _vRefresh; - private Timer _timer; - - /// - /// This flag specifies if any animation is used - /// - protected bool EnableAnimation { get; set; } - - /// - /// Vertical Refresh Rate - /// - protected int VRefresh - { - get - { - if (_vRefresh == 0) - { - // get te hDC of the desktop to get the VREFRESH - using SafeWindowDcHandle desktopHandle = SafeWindowDcHandle.FromDesktop(); - _vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH); - } - - // A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate. - // As there is currently no know way to get the default, we guess it. - if (_vRefresh <= 1) - { - _vRefresh = DEFAULT_VREFRESH; - } - - return _vRefresh; - } - } - - /// - /// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections - /// - protected bool IsTerminalServerSession => !coreConfiguration.DisableRDPOptimizing && (coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession); - - /// - /// Calculate the amount of frames that an animation takes - /// - /// - /// Number of frames, 1 if in Terminal Server Session - protected int FramesForMillis(int milliseconds) - { - // If we are in a Terminal Server Session we return 1 - if (IsTerminalServerSession) - { - return 1; - } - - return milliseconds / VRefresh; - } - - /// - /// Initialize the animation - /// - protected AnimatingForm() - { - Load += delegate - { - if (!EnableAnimation) - { - return; - } - - _timer = new Timer - { - Interval = 1000 / VRefresh - }; - _timer.Tick += timer_Tick; - _timer.Start(); - }; - - // Unregister at close - FormClosing += delegate { _timer?.Stop(); }; - } - - /// - /// The tick handler initiates the animation. - /// - /// - /// - private void timer_Tick(object sender, EventArgs e) - { - try - { - Animate(); - } - catch (Exception ex) - { - Log.Warn("An exception occured while animating:", ex); - } - } - - /// - /// This method will be called every frame, so implement your animation/redraw logic here. - /// - protected virtual void Animate() - { - throw new NotImplementedException(); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Windows.Forms; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// Extend this Form to have the possibility for animations on your form + /// + public class AnimatingForm : GreenshotForm + { + private static readonly ILog Log = LogManager.GetLogger(typeof(AnimatingForm)); + private const int DEFAULT_VREFRESH = 60; + private int _vRefresh; + private Timer _timer; + + /// + /// This flag specifies if any animation is used + /// + protected bool EnableAnimation { get; set; } + + /// + /// Vertical Refresh Rate + /// + protected int VRefresh + { + get + { + if (_vRefresh == 0) + { + // get te hDC of the desktop to get the VREFRESH + using SafeWindowDcHandle desktopHandle = SafeWindowDcHandle.FromDesktop(); + _vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH); + } + + // A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate. + // As there is currently no know way to get the default, we guess it. + if (_vRefresh <= 1) + { + _vRefresh = DEFAULT_VREFRESH; + } + + return _vRefresh; + } + } + + /// + /// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections + /// + protected bool IsTerminalServerSession => !coreConfiguration.DisableRDPOptimizing && (coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession); + + /// + /// Calculate the amount of frames that an animation takes + /// + /// + /// Number of frames, 1 if in Terminal Server Session + protected int FramesForMillis(int milliseconds) + { + // If we are in a Terminal Server Session we return 1 + if (IsTerminalServerSession) + { + return 1; + } + + return milliseconds / VRefresh; + } + + /// + /// Initialize the animation + /// + protected AnimatingForm() + { + Load += delegate + { + if (!EnableAnimation) + { + return; + } + + _timer = new Timer + { + Interval = 1000 / VRefresh + }; + _timer.Tick += timer_Tick; + _timer.Start(); + }; + + // Unregister at close + FormClosing += delegate { _timer?.Stop(); }; + } + + /// + /// The tick handler initiates the animation. + /// + /// + /// + private void timer_Tick(object sender, EventArgs e) + { + try + { + Animate(); + } + catch (Exception ex) + { + Log.Warn("An exception occured while animating:", ex); + } + } + + /// + /// This method will be called every frame, so implement your animation/redraw logic here. + /// + protected virtual void Animate() + { + throw new NotImplementedException(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/BackgroundForm.Designer.cs b/src/Greenshot.Base/Controls/BackgroundForm.Designer.cs similarity index 96% rename from src/GreenshotPlugin/Controls/BackgroundForm.Designer.cs rename to src/Greenshot.Base/Controls/BackgroundForm.Designer.cs index cafbb6e18..1bbde20ad 100644 --- a/src/GreenshotPlugin/Controls/BackgroundForm.Designer.cs +++ b/src/Greenshot.Base/Controls/BackgroundForm.Designer.cs @@ -1,96 +1,96 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ -namespace GreenshotPlugin.Controls -{ - partial class BackgroundForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.label_pleasewait = new System.Windows.Forms.Label(); - this.timer_checkforclose = new System.Windows.Forms.Timer(this.components); - this.SuspendLayout(); - // - // label_pleasewait - // - this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; - this.label_pleasewait.Location = new System.Drawing.Point(0, 0); - this.label_pleasewait.Name = "label_pleasewait"; - this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); - this.label_pleasewait.Size = new System.Drawing.Size(90, 33); - this.label_pleasewait.TabIndex = 0; - this.label_pleasewait.Text = "Please wait..."; - this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label_pleasewait.UseWaitCursor = true; - // - // timer_checkforclose - // - this.timer_checkforclose.Interval = 200; - this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick); - // - // BackgroundForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(169, 52); - this.ControlBox = true; - this.Controls.Add(this.label_pleasewait); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "BackgroundForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Greenshot"; - this.TopMost = true; - this.UseWaitCursor = true; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing); - this.ResumeLayout(false); - this.PerformLayout(); - } - private System.Windows.Forms.Timer timer_checkforclose; - private System.Windows.Forms.Label label_pleasewait; - } -} +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ +namespace Greenshot.Base.Controls +{ + partial class BackgroundForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.label_pleasewait = new System.Windows.Forms.Label(); + this.timer_checkforclose = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // label_pleasewait + // + this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; + this.label_pleasewait.Location = new System.Drawing.Point(0, 0); + this.label_pleasewait.Name = "label_pleasewait"; + this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); + this.label_pleasewait.Size = new System.Drawing.Size(90, 33); + this.label_pleasewait.TabIndex = 0; + this.label_pleasewait.Text = "Please wait..."; + this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label_pleasewait.UseWaitCursor = true; + // + // timer_checkforclose + // + this.timer_checkforclose.Interval = 200; + this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick); + // + // BackgroundForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(169, 52); + this.ControlBox = true; + this.Controls.Add(this.label_pleasewait); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "BackgroundForm"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Greenshot"; + this.TopMost = true; + this.UseWaitCursor = true; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing); + this.ResumeLayout(false); + this.PerformLayout(); + } + private System.Windows.Forms.Timer timer_checkforclose; + private System.Windows.Forms.Label label_pleasewait; + } +} diff --git a/src/GreenshotPlugin/Controls/BackgroundForm.cs b/src/Greenshot.Base/Controls/BackgroundForm.cs similarity index 95% rename from src/GreenshotPlugin/Controls/BackgroundForm.cs rename to src/Greenshot.Base/Controls/BackgroundForm.cs index beda8b73b..45691c8e3 100644 --- a/src/GreenshotPlugin/Controls/BackgroundForm.cs +++ b/src/Greenshot.Base/Controls/BackgroundForm.cs @@ -1,99 +1,99 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Windows.Forms; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of PleaseWaitForm. - /// - public sealed partial class BackgroundForm : Form - { - private volatile bool _shouldClose; - - public BackgroundForm(string title, string text) - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - Icon = GreenshotResources.GetGreenshotIcon(); - _shouldClose = false; - Text = title; - label_pleasewait.Text = text; - FormClosing += PreventFormClose; - timer_checkforclose.Start(); - } - - // Can be used instead of ShowDialog - public new void Show() - { - base.Show(); - bool positioned = false; - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(Cursor.Position)) - { - positioned = true; - Location = new Point(screen.Bounds.X + (screen.Bounds.Width / 2) - (Width / 2), screen.Bounds.Y + (screen.Bounds.Height / 2) - (Height / 2)); - break; - } - } - - if (!positioned) - { - Location = new Point(Cursor.Position.X - Width / 2, Cursor.Position.Y - Height / 2); - } - } - - private void PreventFormClose(object sender, FormClosingEventArgs e) - { - if (!_shouldClose) - { - e.Cancel = true; - } - } - - private void Timer_checkforcloseTick(object sender, EventArgs e) - { - if (_shouldClose) - { - timer_checkforclose.Stop(); - BeginInvoke(new EventHandler(delegate { Close(); })); - } - } - - public void CloseDialog() - { - _shouldClose = true; - Application.DoEvents(); - } - - private void BackgroundFormFormClosing(object sender, FormClosingEventArgs e) - { - timer_checkforclose.Stop(); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Windows.Forms; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Controls +{ + /// + /// Description of PleaseWaitForm. + /// + public sealed partial class BackgroundForm : Form + { + private volatile bool _shouldClose; + + public BackgroundForm(string title, string text) + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + Icon = GreenshotResources.GetGreenshotIcon(); + _shouldClose = false; + Text = title; + label_pleasewait.Text = text; + FormClosing += PreventFormClose; + timer_checkforclose.Start(); + } + + // Can be used instead of ShowDialog + public new void Show() + { + base.Show(); + bool positioned = false; + foreach (Screen screen in Screen.AllScreens) + { + if (screen.Bounds.Contains(Cursor.Position)) + { + positioned = true; + Location = new Point(screen.Bounds.X + (screen.Bounds.Width / 2) - (Width / 2), screen.Bounds.Y + (screen.Bounds.Height / 2) - (Height / 2)); + break; + } + } + + if (!positioned) + { + Location = new Point(Cursor.Position.X - Width / 2, Cursor.Position.Y - Height / 2); + } + } + + private void PreventFormClose(object sender, FormClosingEventArgs e) + { + if (!_shouldClose) + { + e.Cancel = true; + } + } + + private void Timer_checkforcloseTick(object sender, EventArgs e) + { + if (_shouldClose) + { + timer_checkforclose.Stop(); + BeginInvoke(new EventHandler(delegate { Close(); })); + } + } + + public void CloseDialog() + { + _shouldClose = true; + Application.DoEvents(); + } + + private void BackgroundFormFormClosing(object sender, FormClosingEventArgs e) + { + timer_checkforclose.Stop(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/ExtendedWebBrowser.cs b/src/Greenshot.Base/Controls/ExtendedWebBrowser.cs similarity index 94% rename from src/GreenshotPlugin/Controls/ExtendedWebBrowser.cs rename to src/Greenshot.Base/Controls/ExtendedWebBrowser.cs index e5bc1c622..0e4d439ae 100644 --- a/src/GreenshotPlugin/Controls/ExtendedWebBrowser.cs +++ b/src/Greenshot.Base/Controls/ExtendedWebBrowser.cs @@ -1,68 +1,68 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Windows.Forms; -using GreenshotPlugin.Interop; - -namespace GreenshotPlugin.Controls -{ - public class ExtendedWebBrowser : WebBrowser - { - protected class ExtendedWebBrowserSite : WebBrowserSite, IOleCommandTarget - { - private const int OLECMDID_SHOWSCRIPTERROR = 40; - - private static readonly Guid CGID_DocHostCommandHandler = new Guid("F38BC242-B950-11D1-8918-00C04FC2C836"); - - private const int S_OK = 0; - private const int OLECMDERR_E_NOTSUPPORTED = (-2147221248); - - public ExtendedWebBrowserSite(WebBrowser wb) : base(wb) - { - } - - public int QueryStatus(Guid pguidCmdGroup, int cCmds, IntPtr prgCmds, IntPtr pCmdText) - { - return OLECMDERR_E_NOTSUPPORTED; - } - - public int Exec(Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) - { - if (pguidCmdGroup == CGID_DocHostCommandHandler) - { - if (nCmdID == OLECMDID_SHOWSCRIPTERROR) - { - // do not need to alter pvaOut as the docs says, enough to return S_OK here - return S_OK; - } - } - - return OLECMDERR_E_NOTSUPPORTED; - } - } - - protected override WebBrowserSiteBase CreateWebBrowserSiteBase() - { - return new ExtendedWebBrowserSite(this); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Windows.Forms; +using Greenshot.Base.Interop; + +namespace Greenshot.Base.Controls +{ + public class ExtendedWebBrowser : WebBrowser + { + protected class ExtendedWebBrowserSite : WebBrowserSite, IOleCommandTarget + { + private const int OLECMDID_SHOWSCRIPTERROR = 40; + + private static readonly Guid CGID_DocHostCommandHandler = new Guid("F38BC242-B950-11D1-8918-00C04FC2C836"); + + private const int S_OK = 0; + private const int OLECMDERR_E_NOTSUPPORTED = (-2147221248); + + public ExtendedWebBrowserSite(WebBrowser wb) : base(wb) + { + } + + public int QueryStatus(Guid pguidCmdGroup, int cCmds, IntPtr prgCmds, IntPtr pCmdText) + { + return OLECMDERR_E_NOTSUPPORTED; + } + + public int Exec(Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) + { + if (pguidCmdGroup == CGID_DocHostCommandHandler) + { + if (nCmdID == OLECMDID_SHOWSCRIPTERROR) + { + // do not need to alter pvaOut as the docs says, enough to return S_OK here + return S_OK; + } + } + + return OLECMDERR_E_NOTSUPPORTED; + } + } + + protected override WebBrowserSiteBase CreateWebBrowserSiteBase() + { + return new ExtendedWebBrowserSite(this); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/FormWithoutActivation.cs b/src/Greenshot.Base/Controls/FormWithoutActivation.cs similarity index 94% rename from src/GreenshotPlugin/Controls/FormWithoutActivation.cs rename to src/Greenshot.Base/Controls/FormWithoutActivation.cs index 06cde98a2..f9fee5ef5 100644 --- a/src/GreenshotPlugin/Controls/FormWithoutActivation.cs +++ b/src/Greenshot.Base/Controls/FormWithoutActivation.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus) - /// - public class FormWithoutActivation : Form - { - protected override bool ShowWithoutActivation - { - get { return true; } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + /// + /// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus) + /// + public class FormWithoutActivation : Form + { + protected override bool ShowWithoutActivation + { + get { return true; } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotButton.cs b/src/Greenshot.Base/Controls/GreenshotButton.cs similarity index 94% rename from src/GreenshotPlugin/Controls/GreenshotButton.cs rename to src/Greenshot.Base/Controls/GreenshotButton.cs index 9849f2c50..703be11e5 100644 --- a/src/GreenshotPlugin/Controls/GreenshotButton.cs +++ b/src/Greenshot.Base/Controls/GreenshotButton.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotButton : Button, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotButton : Button, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotCheckBox.cs b/src/Greenshot.Base/Controls/GreenshotCheckBox.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotCheckBox.cs rename to src/Greenshot.Base/Controls/GreenshotCheckBox.cs index f0e4563b9..c7552fb74 100644 --- a/src/GreenshotPlugin/Controls/GreenshotCheckBox.cs +++ b/src/Greenshot.Base/Controls/GreenshotCheckBox.cs @@ -1,41 +1,41 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of GreenshotCheckbox. - /// - public class GreenshotCheckBox : CheckBox, IGreenshotLanguageBindable, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + /// + /// Description of GreenshotCheckbox. + /// + public class GreenshotCheckBox : CheckBox, IGreenshotLanguageBindable, IGreenshotConfigBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + + [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] + public string SectionName { get; set; } = "Core"; + + [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] + public string PropertyName { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotColumnSorter.cs b/src/Greenshot.Base/Controls/GreenshotColumnSorter.cs similarity index 99% rename from src/GreenshotPlugin/Controls/GreenshotColumnSorter.cs rename to src/Greenshot.Base/Controls/GreenshotColumnSorter.cs index 02c8f16ef..f33379cda 100644 --- a/src/GreenshotPlugin/Controls/GreenshotColumnSorter.cs +++ b/src/Greenshot.Base/Controls/GreenshotColumnSorter.cs @@ -22,7 +22,7 @@ using System.Collections; using System.Windows.Forms; -namespace GreenshotPlugin.Controls +namespace Greenshot.Base.Controls { /// /// This class is an implementation of the 'IComparer' interface. diff --git a/src/GreenshotPlugin/Controls/GreenshotComboBox.cs b/src/Greenshot.Base/Controls/GreenshotComboBox.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotComboBox.cs rename to src/Greenshot.Base/Controls/GreenshotComboBox.cs index 5fc0437b6..4c464544c 100644 --- a/src/GreenshotPlugin/Controls/GreenshotComboBox.cs +++ b/src/Greenshot.Base/Controls/GreenshotComboBox.cs @@ -1,116 +1,116 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.ComponentModel; -using System.Windows.Forms; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotComboBox : ComboBox, IGreenshotConfigBindable - { - private Type _enumType; - private Enum _selectedEnum; - - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName { get; set; } - - public GreenshotComboBox() - { - SelectedIndexChanged += delegate { StoreSelectedEnum(); }; - } - - public void SetValue(Enum currentValue) - { - if (currentValue != null) - { - _selectedEnum = currentValue; - SelectedItem = Language.Translate(currentValue); - } - } - - /// - /// This is a method to popululate the ComboBox - /// with the items from the enumeration - /// - /// TEnum to populate with - public void Populate(Type enumType) - { - // Store the enum-type, so we can work with it - _enumType = enumType; - - var availableValues = Enum.GetValues(enumType); - Items.Clear(); - foreach (var enumValue in availableValues) - { - Items.Add(Language.Translate((Enum) enumValue)); - } - } - - /// - /// Store the selected value internally - /// - private void StoreSelectedEnum() - { - string enumTypeName = _enumType.Name; - string selectedValue = SelectedItem as string; - var availableValues = Enum.GetValues(_enumType); - object returnValue = null; - - try - { - returnValue = Enum.Parse(_enumType, selectedValue); - } - catch (Exception) - { - // Ignore - } - - foreach (Enum enumValue in availableValues) - { - string enumKey = enumTypeName + "." + enumValue; - if (Language.HasKey(enumKey)) - { - string translation = Language.GetString(enumTypeName + "." + enumValue); - if (translation.Equals(selectedValue)) - { - returnValue = enumValue; - } - } - } - - _selectedEnum = (Enum) returnValue; - } - - /// - /// Get the selected enum value from the combobox, uses generics - /// - /// The enum value of the combobox - public Enum GetSelectedEnum() - { - return _selectedEnum; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.ComponentModel; +using System.Windows.Forms; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Controls +{ + public class GreenshotComboBox : ComboBox, IGreenshotConfigBindable + { + private Type _enumType; + private Enum _selectedEnum; + + [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] + public string SectionName { get; set; } = "Core"; + + [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] + public string PropertyName { get; set; } + + public GreenshotComboBox() + { + SelectedIndexChanged += delegate { StoreSelectedEnum(); }; + } + + public void SetValue(Enum currentValue) + { + if (currentValue != null) + { + _selectedEnum = currentValue; + SelectedItem = Language.Translate(currentValue); + } + } + + /// + /// This is a method to popululate the ComboBox + /// with the items from the enumeration + /// + /// TEnum to populate with + public void Populate(Type enumType) + { + // Store the enum-type, so we can work with it + _enumType = enumType; + + var availableValues = Enum.GetValues(enumType); + Items.Clear(); + foreach (var enumValue in availableValues) + { + Items.Add(Language.Translate((Enum) enumValue)); + } + } + + /// + /// Store the selected value internally + /// + private void StoreSelectedEnum() + { + string enumTypeName = _enumType.Name; + string selectedValue = SelectedItem as string; + var availableValues = Enum.GetValues(_enumType); + object returnValue = null; + + try + { + returnValue = Enum.Parse(_enumType, selectedValue); + } + catch (Exception) + { + // Ignore + } + + foreach (Enum enumValue in availableValues) + { + string enumKey = enumTypeName + "." + enumValue; + if (Language.HasKey(enumKey)) + { + string translation = Language.GetString(enumTypeName + "." + enumValue); + if (translation.Equals(selectedValue)) + { + returnValue = enumValue; + } + } + } + + _selectedEnum = (Enum) returnValue; + } + + /// + /// Get the selected enum value from the combobox, uses generics + /// + /// The enum value of the combobox + public Enum GetSelectedEnum() + { + return _selectedEnum; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotForm.cs b/src/Greenshot.Base/Controls/GreenshotForm.cs similarity index 96% rename from src/GreenshotPlugin/Controls/GreenshotForm.cs rename to src/Greenshot.Base/Controls/GreenshotForm.cs index c91a48ddc..9850e71ed 100644 --- a/src/GreenshotPlugin/Controls/GreenshotForm.cs +++ b/src/Greenshot.Base/Controls/GreenshotForm.cs @@ -1,643 +1,643 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using System.Reflection; -using GreenshotPlugin.Core; -using System.ComponentModel; -using System.ComponentModel.Design; -using System.IO; -using GreenshotPlugin.IniFile; -using log4net; - -namespace GreenshotPlugin.Controls -{ - /// - /// This form is used for automatically binding the elements of the form to the language - /// - public class GreenshotForm : Form, IGreenshotLanguageBindable - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(GreenshotForm)); - protected static CoreConfiguration coreConfiguration; - private static readonly IDictionary reflectionCache = new Dictionary(); - private IComponentChangeService m_changeService; - private bool _isDesignModeLanguageSet; - private bool _applyLanguageManually; - private bool _storeFieldsManually; - private IDictionary _designTimeControls; - private IDictionary _designTimeToolStripItems; - - static GreenshotForm() - { - if (!IsInDesignMode) - { - coreConfiguration = IniConfig.GetIniSection(); - } - } - - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - - /// - /// Used to check the designmode during a constructor - /// - /// - protected static bool IsInDesignMode - { - get - { - return (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1) || - (Application.ExecutablePath.IndexOf("sharpdevelop.exe", StringComparison.OrdinalIgnoreCase) > -1 || - (Application.ExecutablePath.IndexOf("wdexpress.exe", StringComparison.OrdinalIgnoreCase) > -1)); - } - } - - protected bool ManualLanguageApply - { - get { return _applyLanguageManually; } - set { _applyLanguageManually = value; } - } - - protected bool ManualStoreFields - { - get { return _storeFieldsManually; } - set { _storeFieldsManually = value; } - } - - /// - /// When this is set, the form will be brought to the foreground as soon as it is shown. - /// - protected bool ToFront { get; set; } - - /// - /// Code to initialize the language etc during design time - /// - protected void InitializeForDesigner() - { - if (!DesignMode) return; - _designTimeControls = new Dictionary(); - _designTimeToolStripItems = new Dictionary(); - try - { - ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService; - - // Add a hard-path if you are using SharpDevelop - // Language.AddLanguageFilePath(@"C:\Greenshot\Greenshot\Languages"); - - // this "type" - Assembly currentAssembly = GetType().Assembly; - if (typeResService != null) - { - string assemblyPath = typeResService.GetPathOfAssembly(currentAssembly.GetName()); - string assemblyDirectory = Path.GetDirectoryName(assemblyPath); - if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Greenshot\Languages\"))) - { - Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Greenshot\Languages\")); - } - - if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Languages\"))) - { - Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Languages\")); - } - } - } - catch (Exception ex) - { - MessageBox.Show(ex.Message); - } - } - - /// - /// This override is only for the design-time of the form - /// - /// - protected override void OnPaint(PaintEventArgs e) - { - if (DesignMode) - { - if (!_isDesignModeLanguageSet) - { - _isDesignModeLanguageSet = true; - try - { - ApplyLanguage(); - } - catch (Exception) - { - // ignored - } - } - } - - base.OnPaint(e); - } - - protected override void OnLoad(EventArgs e) - { - // Every GreenshotForm should have it's default icon - // And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important - Icon = GreenshotResources.GetGreenshotIcon(); - if (!DesignMode) - { - if (!_applyLanguageManually) - { - ApplyLanguage(); - } - - FillFields(); - base.OnLoad(e); - } - else - { - LOG.Info("OnLoad called from designer."); - InitializeForDesigner(); - base.OnLoad(e); - ApplyLanguage(); - } - } - - /// - /// Make sure the form is visible, if this is wanted - /// - /// EventArgs - protected override void OnShown(EventArgs e) - { - base.OnShown(e); - if (ToFront) - { - WindowDetails.ToForeground(Handle); - } - } - - /// - /// check if the form was closed with an OK, if so store the values in the GreenshotControls - /// - /// - protected override void OnClosed(EventArgs e) - { - if (!DesignMode && !_storeFieldsManually) - { - if (DialogResult == DialogResult.OK) - { - LOG.Info("Form was closed with OK: storing field values."); - StoreFields(); - } - } - - base.OnClosed(e); - } - - /// - /// This override allows the control to register event handlers for IComponentChangeService events - /// at the time the control is sited, which happens only in design mode. - /// - public override ISite Site - { - get { return base.Site; } - set - { - // Clear any component change event handlers. - ClearChangeNotifications(); - - // Set the new Site value. - base.Site = value; - - m_changeService = (IComponentChangeService) GetService(typeof(IComponentChangeService)); - - // Register event handlers for component change events. - RegisterChangeNotifications(); - } - } - - private void ClearChangeNotifications() - { - // The m_changeService value is null when not in design mode, - // as the IComponentChangeService is only available at design time. - m_changeService = (IComponentChangeService) GetService(typeof(IComponentChangeService)); - - // Clear our the component change events to prepare for re-siting. - if (m_changeService != null) - { - m_changeService.ComponentChanged -= OnComponentChanged; - m_changeService.ComponentAdded -= OnComponentAdded; - } - } - - private void RegisterChangeNotifications() - { - // Register the event handlers for the IComponentChangeService events - if (m_changeService != null) - { - m_changeService.ComponentChanged += OnComponentChanged; - m_changeService.ComponentAdded += OnComponentAdded; - } - } - - /// - /// This method handles the OnComponentChanged event to display a notification. - /// - /// - /// - private void OnComponentChanged(object sender, ComponentChangedEventArgs ce) - { - if (((IComponent) ce.Component)?.Site == null || ce.Member == null) return; - if (!"LanguageKey".Equals(ce.Member.Name)) return; - if (ce.Component is Control control) - { - LOG.InfoFormat("Changing LanguageKey for {0} to {1}", control.Name, ce.NewValue); - ApplyLanguage(control, (string) ce.NewValue); - } - else - { - if (ce.Component is ToolStripItem item) - { - LOG.InfoFormat("Changing LanguageKey for {0} to {1}", item.Name, ce.NewValue); - ApplyLanguage(item, (string) ce.NewValue); - } - else - { - LOG.InfoFormat("Not possible to changing LanguageKey for {0} to {1}", ce.Component.GetType(), ce.NewValue); - } - } - } - - private void OnComponentAdded(object sender, ComponentEventArgs ce) - { - if (ce.Component?.Site == null) return; - if (ce.Component is Control control) - { - if (!_designTimeControls.ContainsKey(control.Name)) - { - _designTimeControls.Add(control.Name, control); - } - else - { - _designTimeControls[control.Name] = control; - } - } - else - { - if (ce.Component is ToolStripItem stripItem) - { - ToolStripItem item = stripItem; - if (!_designTimeControls.ContainsKey(item.Name)) - { - _designTimeToolStripItems.Add(item.Name, item); - } - else - { - _designTimeToolStripItems[item.Name] = item; - } - } - } - } - - // Clean up any resources being used. - protected override void Dispose(bool disposing) - { - if (disposing) - { - ClearChangeNotifications(); - } - - base.Dispose(disposing); - } - - protected void ApplyLanguage(ToolStripItem applyTo, string languageKey) - { - string langString; - if (!string.IsNullOrEmpty(languageKey)) - { - if (!Language.TryGetString(languageKey, out langString)) - { - LOG.WarnFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name); - return; - } - - applyTo.Text = langString; - } - else - { - // Fallback to control name! - if (Language.TryGetString(applyTo.Name, out langString)) - { - applyTo.Text = langString; - return; - } - - if (!DesignMode) - { - LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name); - } - } - } - - protected void ApplyLanguage(ToolStripItem applyTo) - { - if (applyTo is IGreenshotLanguageBindable languageBindable) - { - ApplyLanguage(applyTo, languageBindable.LanguageKey); - } - } - - protected void ApplyLanguage(Control applyTo) - { - if (!(applyTo is IGreenshotLanguageBindable languageBindable)) - { - // check if it's a menu! - if (!(applyTo is ToolStrip toolStrip)) - { - return; - } - - foreach (ToolStripItem item in toolStrip.Items) - { - ApplyLanguage(item); - } - - return; - } - - // Apply language text to the control - ApplyLanguage(applyTo, languageBindable.LanguageKey); - - // Repopulate the combox boxes - if (applyTo is IGreenshotConfigBindable configBindable && applyTo is GreenshotComboBox comboxBox) - { - if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) - { - IniSection section = IniConfig.GetIniSection(configBindable.SectionName); - if (section != null) - { - // Only update the language, so get the actual value and than repopulate - Enum currentValue = comboxBox.GetSelectedEnum(); - comboxBox.Populate(section.Values[configBindable.PropertyName].ValueType); - comboxBox.SetValue(currentValue); - } - } - } - } - - /// - /// Helper method to cache the fieldinfo values, so we don't need to reflect all the time! - /// - /// - /// - private static FieldInfo[] GetCachedFields(Type typeToGetFieldsFor) - { - if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out var fields)) - { - fields = typeToGetFieldsFor.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - reflectionCache.Add(typeToGetFieldsFor, fields); - } - - return fields; - } - - /// - /// Apply all the language settings to the "Greenshot" Controls on this form - /// - protected void ApplyLanguage() - { - SuspendLayout(); - try - { - // Set title of the form - if (!string.IsNullOrEmpty(LanguageKey) && Language.TryGetString(LanguageKey, out var langString)) - { - Text = langString; - } - - // Reset the text values for all GreenshotControls - foreach (FieldInfo field in GetCachedFields(GetType())) - { - object controlObject = field.GetValue(this); - if (controlObject == null) - { - LOG.DebugFormat("No value: {0}", field.Name); - continue; - } - - if (!(controlObject is Control applyToControl)) - { - ToolStripItem applyToItem = controlObject as ToolStripItem; - if (applyToItem == null) - { - LOG.DebugFormat("No Control or ToolStripItem: {0}", field.Name); - continue; - } - - ApplyLanguage(applyToItem); - } - else - { - ApplyLanguage(applyToControl); - } - } - - if (DesignMode) - { - foreach (Control designControl in _designTimeControls.Values) - { - ApplyLanguage(designControl); - } - - foreach (ToolStripItem designToolStripItem in _designTimeToolStripItems.Values) - { - ApplyLanguage(designToolStripItem); - } - } - } - finally - { - ResumeLayout(); - } - } - - /// - /// Apply the language text to supplied control - /// - protected void ApplyLanguage(Control applyTo, string languageKey) - { - string langString; - if (!string.IsNullOrEmpty(languageKey)) - { - if (!Language.TryGetString(languageKey, out langString)) - { - LOG.WarnFormat("Wrong language key '{0}' configured for control '{1}'", languageKey, applyTo.Name); - return; - } - - applyTo.Text = langString; - } - else - { - // Fallback to control name! - if (Language.TryGetString(applyTo.Name, out langString)) - { - applyTo.Text = langString; - return; - } - - if (!DesignMode) - { - LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name); - } - } - } - - /// - /// Fill all GreenshotControls with the values from the configuration - /// - protected void FillFields() - { - foreach (FieldInfo field in GetCachedFields(GetType())) - { - var controlObject = field.GetValue(this); - IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; - if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) - { - IniSection section = IniConfig.GetIniSection(configBindable.SectionName); - if (section != null) - { - if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) - { - LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name); - continue; - } - - if (controlObject is CheckBox checkBox) - { - checkBox.Checked = (bool) iniValue.Value; - checkBox.Enabled = !iniValue.IsFixed; - continue; - } - - if (controlObject is RadioButton radíoButton) - { - radíoButton.Checked = (bool) iniValue.Value; - radíoButton.Enabled = !iniValue.IsFixed; - continue; - } - - if (controlObject is TextBox textBox) - { - if (controlObject is HotkeyControl hotkeyControl) - { - string hotkeyValue = (string) iniValue.Value; - if (!string.IsNullOrEmpty(hotkeyValue)) - { - hotkeyControl.SetHotkey(hotkeyValue); - hotkeyControl.Enabled = !iniValue.IsFixed; - } - - continue; - } - - textBox.Text = iniValue.ToString(); - textBox.Enabled = !iniValue.IsFixed; - continue; - } - - if (controlObject is GreenshotComboBox comboxBox) - { - comboxBox.Populate(iniValue.ValueType); - comboxBox.SetValue((Enum) iniValue.Value); - comboxBox.Enabled = !iniValue.IsFixed; - } - } - } - } - - OnFieldsFilled(); - } - - protected virtual void OnFieldsFilled() - { - } - - /// - /// Store all GreenshotControl values to the configuration - /// - protected void StoreFields() - { - bool iniDirty = false; - foreach (FieldInfo field in GetCachedFields(GetType())) - { - var controlObject = field.GetValue(this); - IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; - - if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) - { - IniSection section = IniConfig.GetIniSection(configBindable.SectionName); - if (section != null) - { - if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) - { - continue; - } - - if (controlObject is CheckBox checkBox) - { - iniValue.Value = checkBox.Checked; - iniDirty = true; - continue; - } - - if (controlObject is RadioButton radioButton) - { - iniValue.Value = radioButton.Checked; - iniDirty = true; - continue; - } - - if (controlObject is TextBox textBox) - { - if (controlObject is HotkeyControl hotkeyControl) - { - iniValue.Value = hotkeyControl.ToString(); - iniDirty = true; - continue; - } - - iniValue.UseValueOrDefault(textBox.Text); - iniDirty = true; - continue; - } - - if (controlObject is GreenshotComboBox comboxBox) - { - iniValue.Value = comboxBox.GetSelectedEnum(); - iniDirty = true; - } - } - } - } - - if (iniDirty) - { - IniConfig.Save(); - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.IO; +using System.Reflection; +using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// This form is used for automatically binding the elements of the form to the language + /// + public class GreenshotForm : Form, IGreenshotLanguageBindable + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(GreenshotForm)); + protected static CoreConfiguration coreConfiguration; + private static readonly IDictionary reflectionCache = new Dictionary(); + private IComponentChangeService m_changeService; + private bool _isDesignModeLanguageSet; + private bool _applyLanguageManually; + private bool _storeFieldsManually; + private IDictionary _designTimeControls; + private IDictionary _designTimeToolStripItems; + + static GreenshotForm() + { + if (!IsInDesignMode) + { + coreConfiguration = IniConfig.GetIniSection(); + } + } + + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + + /// + /// Used to check the designmode during a constructor + /// + /// + protected static bool IsInDesignMode + { + get + { + return (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1) || + (Application.ExecutablePath.IndexOf("sharpdevelop.exe", StringComparison.OrdinalIgnoreCase) > -1 || + (Application.ExecutablePath.IndexOf("wdexpress.exe", StringComparison.OrdinalIgnoreCase) > -1)); + } + } + + protected bool ManualLanguageApply + { + get { return _applyLanguageManually; } + set { _applyLanguageManually = value; } + } + + protected bool ManualStoreFields + { + get { return _storeFieldsManually; } + set { _storeFieldsManually = value; } + } + + /// + /// When this is set, the form will be brought to the foreground as soon as it is shown. + /// + protected bool ToFront { get; set; } + + /// + /// Code to initialize the language etc during design time + /// + protected void InitializeForDesigner() + { + if (!DesignMode) return; + _designTimeControls = new Dictionary(); + _designTimeToolStripItems = new Dictionary(); + try + { + ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService; + + // Add a hard-path if you are using SharpDevelop + // Language.AddLanguageFilePath(@"C:\Greenshot\Greenshot\Languages"); + + // this "type" + Assembly currentAssembly = GetType().Assembly; + if (typeResService != null) + { + string assemblyPath = typeResService.GetPathOfAssembly(currentAssembly.GetName()); + string assemblyDirectory = Path.GetDirectoryName(assemblyPath); + if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Greenshot\Languages\"))) + { + Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Greenshot\Languages\")); + } + + if (assemblyDirectory != null && !Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Languages\"))) + { + Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Languages\")); + } + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + /// + /// This override is only for the design-time of the form + /// + /// + protected override void OnPaint(PaintEventArgs e) + { + if (DesignMode) + { + if (!_isDesignModeLanguageSet) + { + _isDesignModeLanguageSet = true; + try + { + ApplyLanguage(); + } + catch (Exception) + { + // ignored + } + } + } + + base.OnPaint(e); + } + + protected override void OnLoad(EventArgs e) + { + // Every GreenshotForm should have it's default icon + // And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important + Icon = GreenshotResources.GetGreenshotIcon(); + if (!DesignMode) + { + if (!_applyLanguageManually) + { + ApplyLanguage(); + } + + FillFields(); + base.OnLoad(e); + } + else + { + LOG.Info("OnLoad called from designer."); + InitializeForDesigner(); + base.OnLoad(e); + ApplyLanguage(); + } + } + + /// + /// Make sure the form is visible, if this is wanted + /// + /// EventArgs + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + if (ToFront) + { + WindowDetails.ToForeground(Handle); + } + } + + /// + /// check if the form was closed with an OK, if so store the values in the GreenshotControls + /// + /// + protected override void OnClosed(EventArgs e) + { + if (!DesignMode && !_storeFieldsManually) + { + if (DialogResult == DialogResult.OK) + { + LOG.Info("Form was closed with OK: storing field values."); + StoreFields(); + } + } + + base.OnClosed(e); + } + + /// + /// This override allows the control to register event handlers for IComponentChangeService events + /// at the time the control is sited, which happens only in design mode. + /// + public override ISite Site + { + get { return base.Site; } + set + { + // Clear any component change event handlers. + ClearChangeNotifications(); + + // Set the new Site value. + base.Site = value; + + m_changeService = (IComponentChangeService) GetService(typeof(IComponentChangeService)); + + // Register event handlers for component change events. + RegisterChangeNotifications(); + } + } + + private void ClearChangeNotifications() + { + // The m_changeService value is null when not in design mode, + // as the IComponentChangeService is only available at design time. + m_changeService = (IComponentChangeService) GetService(typeof(IComponentChangeService)); + + // Clear our the component change events to prepare for re-siting. + if (m_changeService != null) + { + m_changeService.ComponentChanged -= OnComponentChanged; + m_changeService.ComponentAdded -= OnComponentAdded; + } + } + + private void RegisterChangeNotifications() + { + // Register the event handlers for the IComponentChangeService events + if (m_changeService != null) + { + m_changeService.ComponentChanged += OnComponentChanged; + m_changeService.ComponentAdded += OnComponentAdded; + } + } + + /// + /// This method handles the OnComponentChanged event to display a notification. + /// + /// + /// + private void OnComponentChanged(object sender, ComponentChangedEventArgs ce) + { + if (((IComponent) ce.Component)?.Site == null || ce.Member == null) return; + if (!"LanguageKey".Equals(ce.Member.Name)) return; + if (ce.Component is Control control) + { + LOG.InfoFormat("Changing LanguageKey for {0} to {1}", control.Name, ce.NewValue); + ApplyLanguage(control, (string) ce.NewValue); + } + else + { + if (ce.Component is ToolStripItem item) + { + LOG.InfoFormat("Changing LanguageKey for {0} to {1}", item.Name, ce.NewValue); + ApplyLanguage(item, (string) ce.NewValue); + } + else + { + LOG.InfoFormat("Not possible to changing LanguageKey for {0} to {1}", ce.Component.GetType(), ce.NewValue); + } + } + } + + private void OnComponentAdded(object sender, ComponentEventArgs ce) + { + if (ce.Component?.Site == null) return; + if (ce.Component is Control control) + { + if (!_designTimeControls.ContainsKey(control.Name)) + { + _designTimeControls.Add(control.Name, control); + } + else + { + _designTimeControls[control.Name] = control; + } + } + else + { + if (ce.Component is ToolStripItem stripItem) + { + ToolStripItem item = stripItem; + if (!_designTimeControls.ContainsKey(item.Name)) + { + _designTimeToolStripItems.Add(item.Name, item); + } + else + { + _designTimeToolStripItems[item.Name] = item; + } + } + } + } + + // Clean up any resources being used. + protected override void Dispose(bool disposing) + { + if (disposing) + { + ClearChangeNotifications(); + } + + base.Dispose(disposing); + } + + protected void ApplyLanguage(ToolStripItem applyTo, string languageKey) + { + string langString; + if (!string.IsNullOrEmpty(languageKey)) + { + if (!Language.TryGetString(languageKey, out langString)) + { + LOG.WarnFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name); + return; + } + + applyTo.Text = langString; + } + else + { + // Fallback to control name! + if (Language.TryGetString(applyTo.Name, out langString)) + { + applyTo.Text = langString; + return; + } + + if (!DesignMode) + { + LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name); + } + } + } + + protected void ApplyLanguage(ToolStripItem applyTo) + { + if (applyTo is IGreenshotLanguageBindable languageBindable) + { + ApplyLanguage(applyTo, languageBindable.LanguageKey); + } + } + + protected void ApplyLanguage(Control applyTo) + { + if (!(applyTo is IGreenshotLanguageBindable languageBindable)) + { + // check if it's a menu! + if (!(applyTo is ToolStrip toolStrip)) + { + return; + } + + foreach (ToolStripItem item in toolStrip.Items) + { + ApplyLanguage(item); + } + + return; + } + + // Apply language text to the control + ApplyLanguage(applyTo, languageBindable.LanguageKey); + + // Repopulate the combox boxes + if (applyTo is IGreenshotConfigBindable configBindable && applyTo is GreenshotComboBox comboxBox) + { + if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) + { + IniSection section = IniConfig.GetIniSection(configBindable.SectionName); + if (section != null) + { + // Only update the language, so get the actual value and than repopulate + Enum currentValue = comboxBox.GetSelectedEnum(); + comboxBox.Populate(section.Values[configBindable.PropertyName].ValueType); + comboxBox.SetValue(currentValue); + } + } + } + } + + /// + /// Helper method to cache the fieldinfo values, so we don't need to reflect all the time! + /// + /// + /// + private static FieldInfo[] GetCachedFields(Type typeToGetFieldsFor) + { + if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out var fields)) + { + fields = typeToGetFieldsFor.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + reflectionCache.Add(typeToGetFieldsFor, fields); + } + + return fields; + } + + /// + /// Apply all the language settings to the "Greenshot" Controls on this form + /// + protected void ApplyLanguage() + { + SuspendLayout(); + try + { + // Set title of the form + if (!string.IsNullOrEmpty(LanguageKey) && Language.TryGetString(LanguageKey, out var langString)) + { + Text = langString; + } + + // Reset the text values for all GreenshotControls + foreach (FieldInfo field in GetCachedFields(GetType())) + { + object controlObject = field.GetValue(this); + if (controlObject == null) + { + LOG.DebugFormat("No value: {0}", field.Name); + continue; + } + + if (!(controlObject is Control applyToControl)) + { + ToolStripItem applyToItem = controlObject as ToolStripItem; + if (applyToItem == null) + { + LOG.DebugFormat("No Control or ToolStripItem: {0}", field.Name); + continue; + } + + ApplyLanguage(applyToItem); + } + else + { + ApplyLanguage(applyToControl); + } + } + + if (DesignMode) + { + foreach (Control designControl in _designTimeControls.Values) + { + ApplyLanguage(designControl); + } + + foreach (ToolStripItem designToolStripItem in _designTimeToolStripItems.Values) + { + ApplyLanguage(designToolStripItem); + } + } + } + finally + { + ResumeLayout(); + } + } + + /// + /// Apply the language text to supplied control + /// + protected void ApplyLanguage(Control applyTo, string languageKey) + { + string langString; + if (!string.IsNullOrEmpty(languageKey)) + { + if (!Language.TryGetString(languageKey, out langString)) + { + LOG.WarnFormat("Wrong language key '{0}' configured for control '{1}'", languageKey, applyTo.Name); + return; + } + + applyTo.Text = langString; + } + else + { + // Fallback to control name! + if (Language.TryGetString(applyTo.Name, out langString)) + { + applyTo.Text = langString; + return; + } + + if (!DesignMode) + { + LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name); + } + } + } + + /// + /// Fill all GreenshotControls with the values from the configuration + /// + protected void FillFields() + { + foreach (FieldInfo field in GetCachedFields(GetType())) + { + var controlObject = field.GetValue(this); + IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; + if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) + { + IniSection section = IniConfig.GetIniSection(configBindable.SectionName); + if (section != null) + { + if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) + { + LOG.DebugFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name); + continue; + } + + if (controlObject is CheckBox checkBox) + { + checkBox.Checked = (bool) iniValue.Value; + checkBox.Enabled = !iniValue.IsFixed; + continue; + } + + if (controlObject is RadioButton radíoButton) + { + radíoButton.Checked = (bool) iniValue.Value; + radíoButton.Enabled = !iniValue.IsFixed; + continue; + } + + if (controlObject is TextBox textBox) + { + if (controlObject is HotkeyControl hotkeyControl) + { + string hotkeyValue = (string) iniValue.Value; + if (!string.IsNullOrEmpty(hotkeyValue)) + { + hotkeyControl.SetHotkey(hotkeyValue); + hotkeyControl.Enabled = !iniValue.IsFixed; + } + + continue; + } + + textBox.Text = iniValue.ToString(); + textBox.Enabled = !iniValue.IsFixed; + continue; + } + + if (controlObject is GreenshotComboBox comboxBox) + { + comboxBox.Populate(iniValue.ValueType); + comboxBox.SetValue((Enum) iniValue.Value); + comboxBox.Enabled = !iniValue.IsFixed; + } + } + } + } + + OnFieldsFilled(); + } + + protected virtual void OnFieldsFilled() + { + } + + /// + /// Store all GreenshotControl values to the configuration + /// + protected void StoreFields() + { + bool iniDirty = false; + foreach (FieldInfo field in GetCachedFields(GetType())) + { + var controlObject = field.GetValue(this); + IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable; + + if (!string.IsNullOrEmpty(configBindable?.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName)) + { + IniSection section = IniConfig.GetIniSection(configBindable.SectionName); + if (section != null) + { + if (!section.Values.TryGetValue(configBindable.PropertyName, out var iniValue)) + { + continue; + } + + if (controlObject is CheckBox checkBox) + { + iniValue.Value = checkBox.Checked; + iniDirty = true; + continue; + } + + if (controlObject is RadioButton radioButton) + { + iniValue.Value = radioButton.Checked; + iniDirty = true; + continue; + } + + if (controlObject is TextBox textBox) + { + if (controlObject is HotkeyControl hotkeyControl) + { + iniValue.Value = hotkeyControl.ToString(); + iniDirty = true; + continue; + } + + iniValue.UseValueOrDefault(textBox.Text); + iniDirty = true; + continue; + } + + if (controlObject is GreenshotComboBox comboxBox) + { + iniValue.Value = comboxBox.GetSelectedEnum(); + iniDirty = true; + } + } + } + } + + if (iniDirty) + { + IniConfig.Save(); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotGroupBox.cs b/src/Greenshot.Base/Controls/GreenshotGroupBox.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotGroupBox.cs rename to src/Greenshot.Base/Controls/GreenshotGroupBox.cs index 7f4886122..a213f1139 100644 --- a/src/GreenshotPlugin/Controls/GreenshotGroupBox.cs +++ b/src/Greenshot.Base/Controls/GreenshotGroupBox.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; -using System.ComponentModel; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotGroupBox : GroupBox, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotGroupBox : GroupBox, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotLabel.cs b/src/Greenshot.Base/Controls/GreenshotLabel.cs similarity index 94% rename from src/GreenshotPlugin/Controls/GreenshotLabel.cs rename to src/Greenshot.Base/Controls/GreenshotLabel.cs index 904980f9f..152bf5fb1 100644 --- a/src/GreenshotPlugin/Controls/GreenshotLabel.cs +++ b/src/Greenshot.Base/Controls/GreenshotLabel.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; -using System.ComponentModel; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotLabel : Label, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotLabel : Label, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotRadioButton.cs b/src/Greenshot.Base/Controls/GreenshotRadioButton.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotRadioButton.cs rename to src/Greenshot.Base/Controls/GreenshotRadioButton.cs index 9fdc172d4..0e0e87d58 100644 --- a/src/GreenshotPlugin/Controls/GreenshotRadioButton.cs +++ b/src/Greenshot.Base/Controls/GreenshotRadioButton.cs @@ -1,41 +1,41 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of GreenshotCheckbox. - /// - public class GreenshotRadioButton : RadioButton, IGreenshotLanguageBindable, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + /// + /// Description of GreenshotCheckbox. + /// + public class GreenshotRadioButton : RadioButton, IGreenshotLanguageBindable, IGreenshotConfigBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + + [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] + public string SectionName { get; set; } = "Core"; + + [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] + public string PropertyName { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotTabPage.cs b/src/Greenshot.Base/Controls/GreenshotTabPage.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotTabPage.cs rename to src/Greenshot.Base/Controls/GreenshotTabPage.cs index 40b53b30f..8577368c9 100644 --- a/src/GreenshotPlugin/Controls/GreenshotTabPage.cs +++ b/src/Greenshot.Base/Controls/GreenshotTabPage.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; -using System.ComponentModel; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotTabPage : TabPage, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotTabPage : TabPage, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotTextBox.cs b/src/Greenshot.Base/Controls/GreenshotTextBox.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotTextBox.cs rename to src/Greenshot.Base/Controls/GreenshotTextBox.cs index 49c7a4d2e..744a479d1 100644 --- a/src/GreenshotPlugin/Controls/GreenshotTextBox.cs +++ b/src/Greenshot.Base/Controls/GreenshotTextBox.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotTextBox : TextBox, IGreenshotConfigBindable - { - [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] - public string SectionName { get; set; } = "Core"; - - [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] - public string PropertyName { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotTextBox : TextBox, IGreenshotConfigBindable + { + [Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")] + public string SectionName { get; set; } = "Core"; + + [Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")] + public string PropertyName { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs b/src/Greenshot.Base/Controls/GreenshotToolDropDownButton.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs rename to src/Greenshot.Base/Controls/GreenshotToolDropDownButton.cs index e719187c7..81f5b7c2f 100644 --- a/src/GreenshotPlugin/Controls/GreenshotToolDropDownButton.cs +++ b/src/Greenshot.Base/Controls/GreenshotToolDropDownButton.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotToolStripDropDownButton : ToolStripDropDownButton, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotToolStripDropDownButton : ToolStripDropDownButton, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotToolStripButton.cs b/src/Greenshot.Base/Controls/GreenshotToolStripButton.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotToolStripButton.cs rename to src/Greenshot.Base/Controls/GreenshotToolStripButton.cs index e95bd1803..68dee4ba6 100644 --- a/src/GreenshotPlugin/Controls/GreenshotToolStripButton.cs +++ b/src/Greenshot.Base/Controls/GreenshotToolStripButton.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotToolStripButton : ToolStripButton, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotToolStripButton : ToolStripButton, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs b/src/Greenshot.Base/Controls/GreenshotToolStripLabel.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs rename to src/Greenshot.Base/Controls/GreenshotToolStripLabel.cs index 07443d894..e47de2955 100644 --- a/src/GreenshotPlugin/Controls/GreenshotToolStripLabel.cs +++ b/src/Greenshot.Base/Controls/GreenshotToolStripLabel.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; -using System.ComponentModel; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotToolStripLabel : ToolStripLabel, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotToolStripLabel : ToolStripLabel, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs b/src/Greenshot.Base/Controls/GreenshotToolStripMenuItem.cs similarity index 95% rename from src/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs rename to src/Greenshot.Base/Controls/GreenshotToolStripMenuItem.cs index c7a64c743..4feec806b 100644 --- a/src/GreenshotPlugin/Controls/GreenshotToolStripMenuItem.cs +++ b/src/Greenshot.Base/Controls/GreenshotToolStripMenuItem.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Windows.Forms; - -namespace GreenshotPlugin.Controls -{ - public class GreenshotToolStripMenuItem : ToolStripMenuItem, IGreenshotLanguageBindable - { - [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] - public string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Windows.Forms; + +namespace Greenshot.Base.Controls +{ + public class GreenshotToolStripMenuItem : ToolStripMenuItem, IGreenshotLanguageBindable + { + [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] + public string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/HotkeyControl.cs b/src/Greenshot.Base/Controls/HotkeyControl.cs similarity index 96% rename from src/GreenshotPlugin/Controls/HotkeyControl.cs rename to src/Greenshot.Base/Controls/HotkeyControl.cs index af59a27dd..da1ae6696 100644 --- a/src/GreenshotPlugin/Controls/HotkeyControl.cs +++ b/src/Greenshot.Base/Controls/HotkeyControl.cs @@ -1,686 +1,686 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; -using System.Windows.Forms; -using log4net; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Plugin; - -namespace GreenshotPlugin.Controls -{ - /// - /// A simple control that allows the user to select pretty much any valid hotkey combination - /// See: http://www.codeproject.com/KB/buttons/hotkeycontrol.aspx - /// But is modified to fit in Greenshot, and have localized support - /// - public sealed class HotkeyControl : GreenshotTextBox - { - private static readonly ILog Log = LogManager.GetLogger(typeof(HotkeyControl)); - - private static readonly EventDelay EventDelay = new EventDelay(TimeSpan.FromMilliseconds(600).Ticks); - private static readonly bool IsWindows7OrOlder = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1; - - // Holds the list of hotkeys - private static readonly IDictionary KeyHandlers = new Dictionary(); - private static int _hotKeyCounter = 1; - private const uint WM_HOTKEY = 0x312; - private static IntPtr _hotkeyHwnd; - - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum Modifiers : uint - { - NONE = 0, - ALT = 1, - CTRL = 2, - SHIFT = 4, - WIN = 8, - NO_REPEAT = 0x4000 - } - - [SuppressMessage("ReSharper", "InconsistentNaming")] - private enum MapType : uint - { - MAPVK_VK_TO_VSC = - 0, //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0. - - MAPVK_VSC_TO_VK = - 1, //The uCode parameter is a scan code and is translated into a virtual-key code that does not distinguish between left- and right-hand keys. If there is no translation, the function returns 0. - - MAPVK_VK_TO_CHAR = - 2, //The uCode parameter is a virtual-key code and is translated into an unshifted character value in the low order word of the return value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, the function returns 0. - - MAPVK_VSC_TO_VK_EX = - 3, //The uCode parameter is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand keys. If there is no translation, the function returns 0. - - MAPVK_VK_TO_VSC_EX = - 4 //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If the scan code is an extended scan code, the high byte of the uCode value can contain either 0xe0 or 0xe1 to specify the extended scan code. If there is no translation, the function returns 0. - } - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode); - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool UnregisterHotKey(IntPtr hWnd, int id); - - [DllImport("user32.dll", SetLastError = true)] - private static extern uint MapVirtualKey(uint uCode, uint uMapType); - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize); - - // These variables store the current hotkey and modifier(s) - private Keys _hotkey = Keys.None; - private Keys _modifiers = Keys.None; - - // ArrayLists used to enforce the use of proper modifiers. - // Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing. - private readonly IList _needNonShiftModifier = new List(); - private readonly IList _needNonAltGrModifier = new List(); - - private readonly ContextMenuStrip _dummy = new ContextMenuStrip(); - - /// - /// Used to make sure that there is no right-click menu available - /// - public override ContextMenuStrip ContextMenuStrip - { - get { return _dummy; } - set { base.ContextMenuStrip = _dummy; } - } - - /// - /// Forces the control to be non-multiline - /// - public override bool Multiline - { - get { return base.Multiline; } - set - { - // Ignore what the user wants; force Multiline to false - base.Multiline = false; - } - } - - /// - /// Creates a new HotkeyControl - /// - public HotkeyControl() - { - ContextMenuStrip = _dummy; // Disable right-clicking - Text = "None"; - - // Handle events that occurs when keys are pressed - KeyPress += HotkeyControl_KeyPress; - KeyUp += HotkeyControl_KeyUp; - KeyDown += HotkeyControl_KeyDown; - - PopulateModifierLists(); - } - - /// - /// Populates the ArrayLists specifying disallowed hotkeys - /// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc - /// - private void PopulateModifierLists() - { - // Shift + 0 - 9, A - Z - for (Keys k = Keys.D0; k <= Keys.Z; k++) - { - _needNonShiftModifier.Add((int) k); - } - - // Shift + Numpad keys - for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++) - { - _needNonShiftModifier.Add((int) k); - } - - // Shift + Misc (,;<./ etc) - for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++) - { - _needNonShiftModifier.Add((int) k); - } - - // Shift + Space, PgUp, PgDn, End, Home - for (Keys k = Keys.Space; k <= Keys.Home; k++) - { - _needNonShiftModifier.Add((int) k); - } - - // Misc keys that we can't loop through - _needNonShiftModifier.Add((int) Keys.Insert); - _needNonShiftModifier.Add((int) Keys.Help); - _needNonShiftModifier.Add((int) Keys.Multiply); - _needNonShiftModifier.Add((int) Keys.Add); - _needNonShiftModifier.Add((int) Keys.Subtract); - _needNonShiftModifier.Add((int) Keys.Divide); - _needNonShiftModifier.Add((int) Keys.Decimal); - _needNonShiftModifier.Add((int) Keys.Return); - _needNonShiftModifier.Add((int) Keys.Escape); - _needNonShiftModifier.Add((int) Keys.NumLock); - - // Ctrl+Alt + 0 - 9 - for (Keys k = Keys.D0; k <= Keys.D9; k++) - { - _needNonAltGrModifier.Add((int) k); - } - } - - /// - /// Resets this hotkey control to None - /// - public new void Clear() - { - Hotkey = Keys.None; - HotkeyModifiers = Keys.None; - } - - /// - /// Fires when a key is pushed down. Here, we'll want to update the text in the box - /// to notify the user what combination is currently pressed. - /// - private void HotkeyControl_KeyDown(object sender, KeyEventArgs e) - { - // Clear the current hotkey - if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) - { - ResetHotkey(); - } - else - { - _modifiers = e.Modifiers; - _hotkey = e.KeyCode; - Redraw(); - } - } - - /// - /// Fires when all keys are released. If the current hotkey isn't valid, reset it. - /// Otherwise, do nothing and keep the text and hotkey as it was. - /// - private void HotkeyControl_KeyUp(object sender, KeyEventArgs e) - { - // Somehow the PrintScreen only comes as a keyup, therefore we handle it here. - if (e.KeyCode == Keys.PrintScreen) - { - _modifiers = e.Modifiers; - _hotkey = e.KeyCode; - Redraw(); - } - - if (_hotkey == Keys.None && ModifierKeys == Keys.None) - { - ResetHotkey(); - } - } - - /// - /// Prevents the letter/whatever entered to show up in the TextBox - /// Without this, a "A" key press would appear as "aControl, Alt + A" - /// - private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e) - { - e.Handled = true; - } - - /// - /// Handles some misc keys, such as Ctrl+Delete and Shift+Insert - /// - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) - { - if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete)) - { - ResetHotkey(); - return true; - } - - // Paste - if (keyData == (Keys.Shift | Keys.Insert)) - { - return true; // Don't allow - } - - // Allow the rest - return base.ProcessCmdKey(ref msg, keyData); - } - - /// - /// Clears the current hotkey and resets the TextBox - /// - public void ResetHotkey() - { - _hotkey = Keys.None; - _modifiers = Keys.None; - Redraw(); - } - - /// - /// Used to get/set the hotkey (e.g. Keys.A) - /// - public Keys Hotkey - { - get { return _hotkey; } - set - { - _hotkey = value; - Redraw(true); - } - } - - /// - /// Used to get/set the hotkey (e.g. Keys.A) - /// - public void SetHotkey(string hotkey) - { - _hotkey = HotkeyFromString(hotkey); - _modifiers = HotkeyModifiersFromString(hotkey); - Redraw(true); - } - - /// - /// Used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control) - /// - public Keys HotkeyModifiers - { - get { return _modifiers; } - set - { - _modifiers = value; - Redraw(true); - } - } - - /// - /// Redraws the TextBox when necessary. - /// - /// Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user. - private void Redraw(bool bCalledProgramatically = false) - { - // No hotkey set - if (_hotkey == Keys.None) - { - Text = string.Empty; - return; - } - - // LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0) - if (_hotkey == Keys.LWin || _hotkey == Keys.RWin) - { - Text = string.Empty; - return; - } - - // Only validate input if it comes from the user - if (bCalledProgramatically == false) - { - // No modifier or shift only, AND a hotkey that needs another modifier - if ((_modifiers == Keys.Shift || _modifiers == Keys.None) && _needNonShiftModifier.Contains((int) _hotkey)) - { - if (_modifiers == Keys.None) - { - // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work... - if (_needNonAltGrModifier.Contains((int) _hotkey) == false) - { - _modifiers = Keys.Alt | Keys.Control; - } - else - { - // ... in that case, use Shift+Alt instead. - _modifiers = Keys.Alt | Keys.Shift; - } - } - else - { - // User pressed Shift and an invalid key (e.g. a letter or a number), - // that needs another set of modifier keys - _hotkey = Keys.None; - Text = string.Empty; - return; - } - } - - // Check all Ctrl+Alt keys - if ((_modifiers == (Keys.Alt | Keys.Control)) && _needNonAltGrModifier.Contains((int) _hotkey)) - { - // Ctrl+Alt+4 etc won't work; reset hotkey and tell the user - _hotkey = Keys.None; - Text = string.Empty; - return; - } - } - - // I have no idea why this is needed, but it is. Without this code, pressing only Ctrl - // will show up as "Control + ControlKey", etc. - if (_hotkey == Keys.Menu /* Alt */ || _hotkey == Keys.ShiftKey || _hotkey == Keys.ControlKey) - { - _hotkey = Keys.None; - } - - Text = HotkeyToLocalizedString(_modifiers, _hotkey); - } - - public override string ToString() - { - return HotkeyToString(HotkeyModifiers, Hotkey); - } - - public static string GetLocalizedHotkeyStringFromString(string hotkeyString) - { - Keys virtualKeyCode = HotkeyFromString(hotkeyString); - Keys modifiers = HotkeyModifiersFromString(hotkeyString); - return HotkeyToLocalizedString(modifiers, virtualKeyCode); - } - - public static string HotkeyToString(Keys modifierKeyCode, Keys virtualKeyCode) - { - return HotkeyModifiersToString(modifierKeyCode) + virtualKeyCode; - } - - public static string HotkeyModifiersToString(Keys modifierKeyCode) - { - StringBuilder hotkeyString = new StringBuilder(); - if ((modifierKeyCode & Keys.Alt) > 0) - { - hotkeyString.Append("Alt").Append(" + "); - } - - if ((modifierKeyCode & Keys.Control) > 0) - { - hotkeyString.Append("Ctrl").Append(" + "); - } - - if ((modifierKeyCode & Keys.Shift) > 0) - { - hotkeyString.Append("Shift").Append(" + "); - } - - if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) - { - hotkeyString.Append("Win").Append(" + "); - } - - return hotkeyString.ToString(); - } - - - public static string HotkeyToLocalizedString(Keys modifierKeyCode, Keys virtualKeyCode) - { - return HotkeyModifiersToLocalizedString(modifierKeyCode) + GetKeyName(virtualKeyCode); - } - - public static string HotkeyModifiersToLocalizedString(Keys modifierKeyCode) - { - StringBuilder hotkeyString = new StringBuilder(); - if ((modifierKeyCode & Keys.Alt) > 0) - { - hotkeyString.Append(GetKeyName(Keys.Alt)).Append(" + "); - } - - if ((modifierKeyCode & Keys.Control) > 0) - { - hotkeyString.Append(GetKeyName(Keys.Control)).Append(" + "); - } - - if ((modifierKeyCode & Keys.Shift) > 0) - { - hotkeyString.Append(GetKeyName(Keys.Shift)).Append(" + "); - } - - if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) - { - hotkeyString.Append("Win").Append(" + "); - } - - return hotkeyString.ToString(); - } - - - public static Keys HotkeyModifiersFromString(string modifiersString) - { - Keys modifiers = Keys.None; - if (!string.IsNullOrEmpty(modifiersString)) - { - if (modifiersString.ToLower().Contains("alt")) - { - modifiers |= Keys.Alt; - } - - if (modifiersString.ToLower().Contains("ctrl")) - { - modifiers |= Keys.Control; - } - - if (modifiersString.ToLower().Contains("shift")) - { - modifiers |= Keys.Shift; - } - - if (modifiersString.ToLower().Contains("win")) - { - modifiers |= Keys.LWin; - } - } - - return modifiers; - } - - public static Keys HotkeyFromString(string hotkey) - { - Keys key = Keys.None; - if (!string.IsNullOrEmpty(hotkey)) - { - if (hotkey.LastIndexOf('+') > 0) - { - hotkey = hotkey.Remove(0, hotkey.LastIndexOf('+') + 1).Trim(); - } - - key = (Keys) Enum.Parse(typeof(Keys), hotkey); - } - - return key; - } - - public static void RegisterHotkeyHwnd(IntPtr hWnd) - { - _hotkeyHwnd = hWnd; - } - - /// - /// Register a hotkey - /// - /// The modifier, e.g.: Modifiers.CTRL, Modifiers.NONE or Modifiers.ALT - /// The virtual key code - /// A HotKeyHandler, this will be called to handle the hotkey press - /// the hotkey number, -1 if failed - public static int RegisterHotKey(Keys modifierKeyCode, Keys virtualKeyCode, HotKeyHandler handler) - { - if (virtualKeyCode == Keys.None) - { - Log.Warn("Trying to register a Keys.none hotkey, ignoring"); - return 0; - } - - // Convert Modifiers to fit HKM_SETHOTKEY - uint modifiers = 0; - if ((modifierKeyCode & Keys.Alt) > 0) - { - modifiers |= (uint) Modifiers.ALT; - } - - if ((modifierKeyCode & Keys.Control) > 0) - { - modifiers |= (uint) Modifiers.CTRL; - } - - if ((modifierKeyCode & Keys.Shift) > 0) - { - modifiers |= (uint) Modifiers.SHIFT; - } - - if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) - { - modifiers |= (uint) Modifiers.WIN; - } - - // Disable repeating hotkey for Windows 7 and beyond, as described in #1559 - if (IsWindows7OrOlder) - { - modifiers |= (uint) Modifiers.NO_REPEAT; - } - - if (RegisterHotKey(_hotkeyHwnd, _hotKeyCounter, modifiers, (uint) virtualKeyCode)) - { - KeyHandlers.Add(_hotKeyCounter, handler); - return _hotKeyCounter++; - } - - Log.Warn($"Couldn't register hotkey modifier {modifierKeyCode} virtualKeyCode {virtualKeyCode}"); - return -1; - } - - public static void UnregisterHotkeys() - { - foreach (int hotkey in KeyHandlers.Keys) - { - UnregisterHotKey(_hotkeyHwnd, hotkey); - } - - // Remove all key handlers - KeyHandlers.Clear(); - } - - /// - /// Handle WndProc messages for the hotkey - /// - /// - /// true if the message was handled - public static bool HandleMessages(ref Message m) - { - if (m.Msg != WM_HOTKEY) - { - return false; - } - - // Call handler - if (!IsWindows7OrOlder && !EventDelay.Check()) - { - return true; - } - - if (KeyHandlers.TryGetValue((int) m.WParam, out var handler)) - { - handler(); - } - - return true; - } - - public static string GetKeyName(Keys givenKey) - { - StringBuilder keyName = new StringBuilder(); - const uint numpad = 55; - - Keys virtualKey = givenKey; - string keyString; - // Make VC's to real keys - switch (virtualKey) - { - case Keys.Alt: - virtualKey = Keys.LMenu; - break; - case Keys.Control: - virtualKey = Keys.ControlKey; - break; - case Keys.Shift: - virtualKey = Keys.LShiftKey; - break; - case Keys.Multiply: - GetKeyNameText(numpad << 16, keyName, 100); - keyString = keyName.ToString().Replace("*", string.Empty).Trim().ToLower(); - if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) - { - return "* " + keyString; - } - - keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower(); - return keyString + " *"; - case Keys.Divide: - GetKeyNameText(numpad << 16, keyName, 100); - keyString = keyName.ToString().Replace("*", string.Empty).Trim().ToLower(); - if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) - { - return "/ " + keyString; - } - - keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower(); - return keyString + " /"; - } - - uint scanCode = MapVirtualKey((uint) virtualKey, (uint) MapType.MAPVK_VK_TO_VSC); - - // because MapVirtualKey strips the extended bit for some keys - switch (virtualKey) - { - case Keys.Left: - case Keys.Up: - case Keys.Right: - case Keys.Down: // arrow keys - case Keys.Prior: - case Keys.Next: // page up and page down - case Keys.End: - case Keys.Home: - case Keys.Insert: - case Keys.Delete: - case Keys.NumLock: - Log.Debug("Modifying Extended bit"); - scanCode |= 0x100; // set extended bit - break; - case Keys.PrintScreen: // PrintScreen - scanCode = 311; - break; - case Keys.Pause: // PrintScreen - scanCode = 69; - break; - } - - scanCode |= 0x200; - if (GetKeyNameText(scanCode << 16, keyName, 100) != 0) - { - string visibleName = keyName.ToString(); - if (visibleName.Length > 1) - { - visibleName = visibleName.Substring(0, 1) + visibleName.Substring(1).ToLower(); - } - - return visibleName; - } - - return givenKey.ToString(); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Plugin; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// A simple control that allows the user to select pretty much any valid hotkey combination + /// See: http://www.codeproject.com/KB/buttons/hotkeycontrol.aspx + /// But is modified to fit in Greenshot, and have localized support + /// + public sealed class HotkeyControl : GreenshotTextBox + { + private static readonly ILog Log = LogManager.GetLogger(typeof(HotkeyControl)); + + private static readonly EventDelay EventDelay = new EventDelay(TimeSpan.FromMilliseconds(600).Ticks); + private static readonly bool IsWindows7OrOlder = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1; + + // Holds the list of hotkeys + private static readonly IDictionary KeyHandlers = new Dictionary(); + private static int _hotKeyCounter = 1; + private const uint WM_HOTKEY = 0x312; + private static IntPtr _hotkeyHwnd; + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum Modifiers : uint + { + NONE = 0, + ALT = 1, + CTRL = 2, + SHIFT = 4, + WIN = 8, + NO_REPEAT = 0x4000 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + private enum MapType : uint + { + MAPVK_VK_TO_VSC = + 0, //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0. + + MAPVK_VSC_TO_VK = + 1, //The uCode parameter is a scan code and is translated into a virtual-key code that does not distinguish between left- and right-hand keys. If there is no translation, the function returns 0. + + MAPVK_VK_TO_CHAR = + 2, //The uCode parameter is a virtual-key code and is translated into an unshifted character value in the low order word of the return value. Dead keys (diacritics) are indicated by setting the top bit of the return value. If there is no translation, the function returns 0. + + MAPVK_VSC_TO_VK_EX = + 3, //The uCode parameter is a scan code and is translated into a virtual-key code that distinguishes between left- and right-hand keys. If there is no translation, the function returns 0. + + MAPVK_VK_TO_VSC_EX = + 4 //The uCode parameter is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If the scan code is an extended scan code, the high byte of the uCode value can contain either 0xe0 or 0xe1 to specify the extended scan code. If there is no translation, the function returns 0. + } + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll", SetLastError = true)] + private static extern uint MapVirtualKey(uint uCode, uint uMapType); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize); + + // These variables store the current hotkey and modifier(s) + private Keys _hotkey = Keys.None; + private Keys _modifiers = Keys.None; + + // ArrayLists used to enforce the use of proper modifiers. + // Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing. + private readonly IList _needNonShiftModifier = new List(); + private readonly IList _needNonAltGrModifier = new List(); + + private readonly ContextMenuStrip _dummy = new ContextMenuStrip(); + + /// + /// Used to make sure that there is no right-click menu available + /// + public override ContextMenuStrip ContextMenuStrip + { + get { return _dummy; } + set { base.ContextMenuStrip = _dummy; } + } + + /// + /// Forces the control to be non-multiline + /// + public override bool Multiline + { + get { return base.Multiline; } + set + { + // Ignore what the user wants; force Multiline to false + base.Multiline = false; + } + } + + /// + /// Creates a new HotkeyControl + /// + public HotkeyControl() + { + ContextMenuStrip = _dummy; // Disable right-clicking + Text = "None"; + + // Handle events that occurs when keys are pressed + KeyPress += HotkeyControl_KeyPress; + KeyUp += HotkeyControl_KeyUp; + KeyDown += HotkeyControl_KeyDown; + + PopulateModifierLists(); + } + + /// + /// Populates the ArrayLists specifying disallowed hotkeys + /// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc + /// + private void PopulateModifierLists() + { + // Shift + 0 - 9, A - Z + for (Keys k = Keys.D0; k <= Keys.Z; k++) + { + _needNonShiftModifier.Add((int) k); + } + + // Shift + Numpad keys + for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++) + { + _needNonShiftModifier.Add((int) k); + } + + // Shift + Misc (,;<./ etc) + for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++) + { + _needNonShiftModifier.Add((int) k); + } + + // Shift + Space, PgUp, PgDn, End, Home + for (Keys k = Keys.Space; k <= Keys.Home; k++) + { + _needNonShiftModifier.Add((int) k); + } + + // Misc keys that we can't loop through + _needNonShiftModifier.Add((int) Keys.Insert); + _needNonShiftModifier.Add((int) Keys.Help); + _needNonShiftModifier.Add((int) Keys.Multiply); + _needNonShiftModifier.Add((int) Keys.Add); + _needNonShiftModifier.Add((int) Keys.Subtract); + _needNonShiftModifier.Add((int) Keys.Divide); + _needNonShiftModifier.Add((int) Keys.Decimal); + _needNonShiftModifier.Add((int) Keys.Return); + _needNonShiftModifier.Add((int) Keys.Escape); + _needNonShiftModifier.Add((int) Keys.NumLock); + + // Ctrl+Alt + 0 - 9 + for (Keys k = Keys.D0; k <= Keys.D9; k++) + { + _needNonAltGrModifier.Add((int) k); + } + } + + /// + /// Resets this hotkey control to None + /// + public new void Clear() + { + Hotkey = Keys.None; + HotkeyModifiers = Keys.None; + } + + /// + /// Fires when a key is pushed down. Here, we'll want to update the text in the box + /// to notify the user what combination is currently pressed. + /// + private void HotkeyControl_KeyDown(object sender, KeyEventArgs e) + { + // Clear the current hotkey + if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) + { + ResetHotkey(); + } + else + { + _modifiers = e.Modifiers; + _hotkey = e.KeyCode; + Redraw(); + } + } + + /// + /// Fires when all keys are released. If the current hotkey isn't valid, reset it. + /// Otherwise, do nothing and keep the text and hotkey as it was. + /// + private void HotkeyControl_KeyUp(object sender, KeyEventArgs e) + { + // Somehow the PrintScreen only comes as a keyup, therefore we handle it here. + if (e.KeyCode == Keys.PrintScreen) + { + _modifiers = e.Modifiers; + _hotkey = e.KeyCode; + Redraw(); + } + + if (_hotkey == Keys.None && ModifierKeys == Keys.None) + { + ResetHotkey(); + } + } + + /// + /// Prevents the letter/whatever entered to show up in the TextBox + /// Without this, a "A" key press would appear as "aControl, Alt + A" + /// + private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = true; + } + + /// + /// Handles some misc keys, such as Ctrl+Delete and Shift+Insert + /// + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete)) + { + ResetHotkey(); + return true; + } + + // Paste + if (keyData == (Keys.Shift | Keys.Insert)) + { + return true; // Don't allow + } + + // Allow the rest + return base.ProcessCmdKey(ref msg, keyData); + } + + /// + /// Clears the current hotkey and resets the TextBox + /// + public void ResetHotkey() + { + _hotkey = Keys.None; + _modifiers = Keys.None; + Redraw(); + } + + /// + /// Used to get/set the hotkey (e.g. Keys.A) + /// + public Keys Hotkey + { + get { return _hotkey; } + set + { + _hotkey = value; + Redraw(true); + } + } + + /// + /// Used to get/set the hotkey (e.g. Keys.A) + /// + public void SetHotkey(string hotkey) + { + _hotkey = HotkeyFromString(hotkey); + _modifiers = HotkeyModifiersFromString(hotkey); + Redraw(true); + } + + /// + /// Used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control) + /// + public Keys HotkeyModifiers + { + get { return _modifiers; } + set + { + _modifiers = value; + Redraw(true); + } + } + + /// + /// Redraws the TextBox when necessary. + /// + /// Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user. + private void Redraw(bool bCalledProgramatically = false) + { + // No hotkey set + if (_hotkey == Keys.None) + { + Text = string.Empty; + return; + } + + // LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0) + if (_hotkey == Keys.LWin || _hotkey == Keys.RWin) + { + Text = string.Empty; + return; + } + + // Only validate input if it comes from the user + if (bCalledProgramatically == false) + { + // No modifier or shift only, AND a hotkey that needs another modifier + if ((_modifiers == Keys.Shift || _modifiers == Keys.None) && _needNonShiftModifier.Contains((int) _hotkey)) + { + if (_modifiers == Keys.None) + { + // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work... + if (_needNonAltGrModifier.Contains((int) _hotkey) == false) + { + _modifiers = Keys.Alt | Keys.Control; + } + else + { + // ... in that case, use Shift+Alt instead. + _modifiers = Keys.Alt | Keys.Shift; + } + } + else + { + // User pressed Shift and an invalid key (e.g. a letter or a number), + // that needs another set of modifier keys + _hotkey = Keys.None; + Text = string.Empty; + return; + } + } + + // Check all Ctrl+Alt keys + if ((_modifiers == (Keys.Alt | Keys.Control)) && _needNonAltGrModifier.Contains((int) _hotkey)) + { + // Ctrl+Alt+4 etc won't work; reset hotkey and tell the user + _hotkey = Keys.None; + Text = string.Empty; + return; + } + } + + // I have no idea why this is needed, but it is. Without this code, pressing only Ctrl + // will show up as "Control + ControlKey", etc. + if (_hotkey == Keys.Menu /* Alt */ || _hotkey == Keys.ShiftKey || _hotkey == Keys.ControlKey) + { + _hotkey = Keys.None; + } + + Text = HotkeyToLocalizedString(_modifiers, _hotkey); + } + + public override string ToString() + { + return HotkeyToString(HotkeyModifiers, Hotkey); + } + + public static string GetLocalizedHotkeyStringFromString(string hotkeyString) + { + Keys virtualKeyCode = HotkeyFromString(hotkeyString); + Keys modifiers = HotkeyModifiersFromString(hotkeyString); + return HotkeyToLocalizedString(modifiers, virtualKeyCode); + } + + public static string HotkeyToString(Keys modifierKeyCode, Keys virtualKeyCode) + { + return HotkeyModifiersToString(modifierKeyCode) + virtualKeyCode; + } + + public static string HotkeyModifiersToString(Keys modifierKeyCode) + { + StringBuilder hotkeyString = new StringBuilder(); + if ((modifierKeyCode & Keys.Alt) > 0) + { + hotkeyString.Append("Alt").Append(" + "); + } + + if ((modifierKeyCode & Keys.Control) > 0) + { + hotkeyString.Append("Ctrl").Append(" + "); + } + + if ((modifierKeyCode & Keys.Shift) > 0) + { + hotkeyString.Append("Shift").Append(" + "); + } + + if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) + { + hotkeyString.Append("Win").Append(" + "); + } + + return hotkeyString.ToString(); + } + + + public static string HotkeyToLocalizedString(Keys modifierKeyCode, Keys virtualKeyCode) + { + return HotkeyModifiersToLocalizedString(modifierKeyCode) + GetKeyName(virtualKeyCode); + } + + public static string HotkeyModifiersToLocalizedString(Keys modifierKeyCode) + { + StringBuilder hotkeyString = new StringBuilder(); + if ((modifierKeyCode & Keys.Alt) > 0) + { + hotkeyString.Append(GetKeyName(Keys.Alt)).Append(" + "); + } + + if ((modifierKeyCode & Keys.Control) > 0) + { + hotkeyString.Append(GetKeyName(Keys.Control)).Append(" + "); + } + + if ((modifierKeyCode & Keys.Shift) > 0) + { + hotkeyString.Append(GetKeyName(Keys.Shift)).Append(" + "); + } + + if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) + { + hotkeyString.Append("Win").Append(" + "); + } + + return hotkeyString.ToString(); + } + + + public static Keys HotkeyModifiersFromString(string modifiersString) + { + Keys modifiers = Keys.None; + if (!string.IsNullOrEmpty(modifiersString)) + { + if (modifiersString.ToLower().Contains("alt")) + { + modifiers |= Keys.Alt; + } + + if (modifiersString.ToLower().Contains("ctrl")) + { + modifiers |= Keys.Control; + } + + if (modifiersString.ToLower().Contains("shift")) + { + modifiers |= Keys.Shift; + } + + if (modifiersString.ToLower().Contains("win")) + { + modifiers |= Keys.LWin; + } + } + + return modifiers; + } + + public static Keys HotkeyFromString(string hotkey) + { + Keys key = Keys.None; + if (!string.IsNullOrEmpty(hotkey)) + { + if (hotkey.LastIndexOf('+') > 0) + { + hotkey = hotkey.Remove(0, hotkey.LastIndexOf('+') + 1).Trim(); + } + + key = (Keys) Enum.Parse(typeof(Keys), hotkey); + } + + return key; + } + + public static void RegisterHotkeyHwnd(IntPtr hWnd) + { + _hotkeyHwnd = hWnd; + } + + /// + /// Register a hotkey + /// + /// The modifier, e.g.: Modifiers.CTRL, Modifiers.NONE or Modifiers.ALT + /// The virtual key code + /// A HotKeyHandler, this will be called to handle the hotkey press + /// the hotkey number, -1 if failed + public static int RegisterHotKey(Keys modifierKeyCode, Keys virtualKeyCode, HotKeyHandler handler) + { + if (virtualKeyCode == Keys.None) + { + Log.Warn("Trying to register a Keys.none hotkey, ignoring"); + return 0; + } + + // Convert Modifiers to fit HKM_SETHOTKEY + uint modifiers = 0; + if ((modifierKeyCode & Keys.Alt) > 0) + { + modifiers |= (uint) Modifiers.ALT; + } + + if ((modifierKeyCode & Keys.Control) > 0) + { + modifiers |= (uint) Modifiers.CTRL; + } + + if ((modifierKeyCode & Keys.Shift) > 0) + { + modifiers |= (uint) Modifiers.SHIFT; + } + + if (modifierKeyCode == Keys.LWin || modifierKeyCode == Keys.RWin) + { + modifiers |= (uint) Modifiers.WIN; + } + + // Disable repeating hotkey for Windows 7 and beyond, as described in #1559 + if (IsWindows7OrOlder) + { + modifiers |= (uint) Modifiers.NO_REPEAT; + } + + if (RegisterHotKey(_hotkeyHwnd, _hotKeyCounter, modifiers, (uint) virtualKeyCode)) + { + KeyHandlers.Add(_hotKeyCounter, handler); + return _hotKeyCounter++; + } + + Log.Warn($"Couldn't register hotkey modifier {modifierKeyCode} virtualKeyCode {virtualKeyCode}"); + return -1; + } + + public static void UnregisterHotkeys() + { + foreach (int hotkey in KeyHandlers.Keys) + { + UnregisterHotKey(_hotkeyHwnd, hotkey); + } + + // Remove all key handlers + KeyHandlers.Clear(); + } + + /// + /// Handle WndProc messages for the hotkey + /// + /// + /// true if the message was handled + public static bool HandleMessages(ref Message m) + { + if (m.Msg != WM_HOTKEY) + { + return false; + } + + // Call handler + if (!IsWindows7OrOlder && !EventDelay.Check()) + { + return true; + } + + if (KeyHandlers.TryGetValue((int) m.WParam, out var handler)) + { + handler(); + } + + return true; + } + + public static string GetKeyName(Keys givenKey) + { + StringBuilder keyName = new StringBuilder(); + const uint numpad = 55; + + Keys virtualKey = givenKey; + string keyString; + // Make VC's to real keys + switch (virtualKey) + { + case Keys.Alt: + virtualKey = Keys.LMenu; + break; + case Keys.Control: + virtualKey = Keys.ControlKey; + break; + case Keys.Shift: + virtualKey = Keys.LShiftKey; + break; + case Keys.Multiply: + GetKeyNameText(numpad << 16, keyName, 100); + keyString = keyName.ToString().Replace("*", string.Empty).Trim().ToLower(); + if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) + { + return "* " + keyString; + } + + keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower(); + return keyString + " *"; + case Keys.Divide: + GetKeyNameText(numpad << 16, keyName, 100); + keyString = keyName.ToString().Replace("*", string.Empty).Trim().ToLower(); + if (keyString.IndexOf("(", StringComparison.Ordinal) >= 0) + { + return "/ " + keyString; + } + + keyString = keyString.Substring(0, 1).ToUpper() + keyString.Substring(1).ToLower(); + return keyString + " /"; + } + + uint scanCode = MapVirtualKey((uint) virtualKey, (uint) MapType.MAPVK_VK_TO_VSC); + + // because MapVirtualKey strips the extended bit for some keys + switch (virtualKey) + { + case Keys.Left: + case Keys.Up: + case Keys.Right: + case Keys.Down: // arrow keys + case Keys.Prior: + case Keys.Next: // page up and page down + case Keys.End: + case Keys.Home: + case Keys.Insert: + case Keys.Delete: + case Keys.NumLock: + Log.Debug("Modifying Extended bit"); + scanCode |= 0x100; // set extended bit + break; + case Keys.PrintScreen: // PrintScreen + scanCode = 311; + break; + case Keys.Pause: // PrintScreen + scanCode = 69; + break; + } + + scanCode |= 0x200; + if (GetKeyNameText(scanCode << 16, keyName, 100) != 0) + { + string visibleName = keyName.ToString(); + if (visibleName.Length > 1) + { + visibleName = visibleName.Substring(0, 1) + visibleName.Substring(1).ToLower(); + } + + return visibleName; + } + + return givenKey.ToString(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs b/src/Greenshot.Base/Controls/IGreenshotConfigBindable.cs similarity index 94% rename from src/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs rename to src/Greenshot.Base/Controls/IGreenshotConfigBindable.cs index e02358718..7a4865031 100644 --- a/src/GreenshotPlugin/Controls/IGreenshotConfigBindable.cs +++ b/src/Greenshot.Base/Controls/IGreenshotConfigBindable.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -namespace GreenshotPlugin.Controls -{ - public interface IGreenshotConfigBindable - { - /// - /// The class where the property-value is stored - /// - string SectionName { get; set; } - - /// - /// Path to the property value which will be mapped with this control - /// - string PropertyName { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +namespace Greenshot.Base.Controls +{ + public interface IGreenshotConfigBindable + { + /// + /// The class where the property-value is stored + /// + string SectionName { get; set; } + + /// + /// Path to the property value which will be mapped with this control + /// + string PropertyName { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs b/src/Greenshot.Base/Controls/IGreenshotLanguageBindable.cs similarity index 94% rename from src/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs rename to src/Greenshot.Base/Controls/IGreenshotLanguageBindable.cs index c83c50d57..2a06d4f7e 100644 --- a/src/GreenshotPlugin/Controls/IGreenshotLanguageBindable.cs +++ b/src/Greenshot.Base/Controls/IGreenshotLanguageBindable.cs @@ -1,34 +1,34 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -namespace GreenshotPlugin.Controls -{ - /// - /// This interface describes the designer fields that need to be implemented for Greenshot controls - /// - public interface IGreenshotLanguageBindable - { - /// - /// Language key to use to fill the Text value with - /// - string LanguageKey { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +namespace Greenshot.Base.Controls +{ + /// + /// This interface describes the designer fields that need to be implemented for Greenshot controls + /// + public interface IGreenshotLanguageBindable + { + /// + /// Language key to use to fill the Text value with + /// + string LanguageKey { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs b/src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs similarity index 96% rename from src/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs rename to src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs index abf92060c..f930762af 100644 --- a/src/GreenshotPlugin/Controls/OAuthLoginForm.Designer.cs +++ b/src/Greenshot.Base/Controls/OAuthLoginForm.Designer.cs @@ -1,92 +1,92 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ -namespace GreenshotPlugin.Controls { - partial class OAuthLoginForm { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - this._addressTextBox = new System.Windows.Forms.TextBox(); - this._browser = new ExtendedWebBrowser(); - this.SuspendLayout(); - // - // _addressTextBox - // - this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow; - this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top; - this._addressTextBox.Enabled = false; - this._addressTextBox.Location = new System.Drawing.Point(0, 0); - this._addressTextBox.Name = "addressTextBox"; - this._addressTextBox.Size = new System.Drawing.Size(595, 20); - this._addressTextBox.TabIndex = 3; - this._addressTextBox.TabStop = false; - // - // _browser - // - this._browser.Dock = System.Windows.Forms.DockStyle.Fill; - this._browser.Location = new System.Drawing.Point(0, 20); - this._browser.MinimumSize = new System.Drawing.Size(100, 100); - this._browser.Name = "browser"; - this._browser.Size = new System.Drawing.Size(595, 295); - this._browser.TabIndex = 4; - // - // OAuthLoginForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(595, 315); - this.Controls.Add(this._browser); - this.Controls.Add(this._addressTextBox); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "OAuthLoginForm"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.TextBox _addressTextBox; - private ExtendedWebBrowser _browser; - - } -} +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ +namespace Greenshot.Base.Controls { + partial class OAuthLoginForm { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + this._addressTextBox = new System.Windows.Forms.TextBox(); + this._browser = new ExtendedWebBrowser(); + this.SuspendLayout(); + // + // _addressTextBox + // + this._addressTextBox.Cursor = System.Windows.Forms.Cursors.Arrow; + this._addressTextBox.Dock = System.Windows.Forms.DockStyle.Top; + this._addressTextBox.Enabled = false; + this._addressTextBox.Location = new System.Drawing.Point(0, 0); + this._addressTextBox.Name = "addressTextBox"; + this._addressTextBox.Size = new System.Drawing.Size(595, 20); + this._addressTextBox.TabIndex = 3; + this._addressTextBox.TabStop = false; + // + // _browser + // + this._browser.Dock = System.Windows.Forms.DockStyle.Fill; + this._browser.Location = new System.Drawing.Point(0, 20); + this._browser.MinimumSize = new System.Drawing.Size(100, 100); + this._browser.Name = "browser"; + this._browser.Size = new System.Drawing.Size(595, 295); + this._browser.TabIndex = 4; + // + // OAuthLoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(595, 315); + this.Controls.Add(this._browser); + this.Controls.Add(this._addressTextBox); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OAuthLoginForm"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox _addressTextBox; + private ExtendedWebBrowser _browser; + + } +} diff --git a/src/GreenshotPlugin/Controls/OAuthLoginForm.cs b/src/Greenshot.Base/Controls/OAuthLoginForm.cs similarity index 95% rename from src/GreenshotPlugin/Controls/OAuthLoginForm.cs rename to src/Greenshot.Base/Controls/OAuthLoginForm.cs index 59a1ea9ca..4cbc1dc9c 100644 --- a/src/GreenshotPlugin/Controls/OAuthLoginForm.cs +++ b/src/Greenshot.Base/Controls/OAuthLoginForm.cs @@ -1,121 +1,121 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using GreenshotPlugin.Core; -using log4net; - -namespace GreenshotPlugin.Controls -{ - /// - /// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application - /// - public sealed partial class OAuthLoginForm : Form - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm)); - private readonly string _callbackUrl; - - public IDictionary CallbackParameters { get; private set; } - - public bool IsOk => DialogResult == DialogResult.OK; - - public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) - { - // Make sure Greenshot uses the correct browser version - IEHelper.FixBrowserVersion(false); - - _callbackUrl = callbackUrl; - // Fix for BUG-2071 - if (callbackUrl.EndsWith("/")) - { - _callbackUrl = callbackUrl.Substring(0, callbackUrl.Length - 1); - } - - InitializeComponent(); - ClientSize = size; - Icon = GreenshotResources.GetGreenshotIcon(); - Text = browserTitle; - _addressTextBox.Text = authorizationLink; - - // The script errors are suppressed by using the ExtendedWebBrowser - _browser.ScriptErrorsSuppressed = false; - _browser.DocumentCompleted += Browser_DocumentCompleted; - _browser.Navigated += Browser_Navigated; - _browser.Navigating += Browser_Navigating; - _browser.Navigate(new Uri(authorizationLink)); - } - - /// - /// Make sure the form is visible - /// - /// EventArgs - protected override void OnShown(EventArgs e) - { - base.OnShown(e); - WindowDetails.ToForeground(Handle); - } - - private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) - { - LOG.DebugFormat("document completed with url: {0}", _browser.Url); - CheckUrl(); - } - - private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e) - { - LOG.DebugFormat("Navigating to url: {0}", _browser.Url); - _addressTextBox.Text = e.Url.ToString(); - } - - private void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) - { - LOG.DebugFormat("Navigated to url: {0}", _browser.Url); - CheckUrl(); - } - - private void CheckUrl() - { - if (_browser.Url.ToString().StartsWith(_callbackUrl)) - { - var correctedUri = new Uri(_browser.Url.AbsoluteUri.Replace("#", "&")); - - string queryParams = correctedUri.Query; - if (queryParams.Length > 0) - { - queryParams = NetworkHelper.UrlDecode(queryParams); - //Store the Token and Token Secret - CallbackParameters = NetworkHelper.ParseQueryString(queryParams); - } - - DialogResult = DialogResult.OK; - } - } - - private void AddressTextBox_KeyPress(object sender, KeyPressEventArgs e) - { - //Cancel the key press so the user can't enter a new url - e.Handled = true; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using Greenshot.Base.Core; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application + /// + public sealed partial class OAuthLoginForm : Form + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm)); + private readonly string _callbackUrl; + + public IDictionary CallbackParameters { get; private set; } + + public bool IsOk => DialogResult == DialogResult.OK; + + public OAuthLoginForm(string browserTitle, Size size, string authorizationLink, string callbackUrl) + { + // Make sure Greenshot uses the correct browser version + IEHelper.FixBrowserVersion(false); + + _callbackUrl = callbackUrl; + // Fix for BUG-2071 + if (callbackUrl.EndsWith("/")) + { + _callbackUrl = callbackUrl.Substring(0, callbackUrl.Length - 1); + } + + InitializeComponent(); + ClientSize = size; + Icon = GreenshotResources.GetGreenshotIcon(); + Text = browserTitle; + _addressTextBox.Text = authorizationLink; + + // The script errors are suppressed by using the ExtendedWebBrowser + _browser.ScriptErrorsSuppressed = false; + _browser.DocumentCompleted += Browser_DocumentCompleted; + _browser.Navigated += Browser_Navigated; + _browser.Navigating += Browser_Navigating; + _browser.Navigate(new Uri(authorizationLink)); + } + + /// + /// Make sure the form is visible + /// + /// EventArgs + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + WindowDetails.ToForeground(Handle); + } + + private void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) + { + LOG.DebugFormat("document completed with url: {0}", _browser.Url); + CheckUrl(); + } + + private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e) + { + LOG.DebugFormat("Navigating to url: {0}", _browser.Url); + _addressTextBox.Text = e.Url.ToString(); + } + + private void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e) + { + LOG.DebugFormat("Navigated to url: {0}", _browser.Url); + CheckUrl(); + } + + private void CheckUrl() + { + if (_browser.Url.ToString().StartsWith(_callbackUrl)) + { + var correctedUri = new Uri(_browser.Url.AbsoluteUri.Replace("#", "&")); + + string queryParams = correctedUri.Query; + if (queryParams.Length > 0) + { + queryParams = NetworkHelper.UrlDecode(queryParams); + //Store the Token and Token Secret + CallbackParameters = NetworkHelper.ParseQueryString(queryParams); + } + + DialogResult = DialogResult.OK; + } + } + + private void AddressTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + //Cancel the key press so the user can't enter a new url + e.Handled = true; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs b/src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs similarity index 96% rename from src/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs rename to src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs index a3ab2832b..3083b7bf2 100644 --- a/src/GreenshotPlugin/Controls/PleaseWaitForm.Designer.cs +++ b/src/Greenshot.Base/Controls/PleaseWaitForm.Designer.cs @@ -1,99 +1,99 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ -namespace GreenshotPlugin.Controls { - partial class PleaseWaitForm { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() { - this.label_pleasewait = new System.Windows.Forms.Label(); - this.cancelButton = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // label_pleasewait - // - this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; - this.label_pleasewait.Location = new System.Drawing.Point(0, 0); - this.label_pleasewait.Name = "label_pleasewait"; - this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); - this.label_pleasewait.Size = new System.Drawing.Size(90, 33); - this.label_pleasewait.TabIndex = 0; - this.label_pleasewait.Text = "Please wait..."; - this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.label_pleasewait.UseWaitCursor = true; - // - // cancelButton - // - this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(38, 41); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(94, 23); - this.cancelButton.TabIndex = 1; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.UseWaitCursor = true; - this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick); - // - // PleaseWaitForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.CancelButton = this.cancelButton; - this.ClientSize = new System.Drawing.Size(169, 76); - this.Controls.Add(this.cancelButton); - this.Controls.Add(this.label_pleasewait); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "PleaseWaitForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Greenshot"; - this.UseWaitCursor = true; - this.ResumeLayout(false); - this.PerformLayout(); - } - private System.Windows.Forms.Button cancelButton; - private System.Windows.Forms.Label label_pleasewait; - } -} +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ +namespace Greenshot.Base.Controls { + partial class PleaseWaitForm { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() { + this.label_pleasewait = new System.Windows.Forms.Label(); + this.cancelButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label_pleasewait + // + this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill; + this.label_pleasewait.Location = new System.Drawing.Point(0, 0); + this.label_pleasewait.Name = "label_pleasewait"; + this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10); + this.label_pleasewait.Size = new System.Drawing.Size(90, 33); + this.label_pleasewait.TabIndex = 0; + this.label_pleasewait.Text = "Please wait..."; + this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label_pleasewait.UseWaitCursor = true; + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancelButton.Location = new System.Drawing.Point(38, 41); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(94, 23); + this.cancelButton.TabIndex = 1; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.UseWaitCursor = true; + this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick); + // + // PleaseWaitForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.cancelButton; + this.ClientSize = new System.Drawing.Size(169, 76); + this.Controls.Add(this.cancelButton); + this.Controls.Add(this.label_pleasewait); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PleaseWaitForm"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Greenshot"; + this.UseWaitCursor = true; + this.ResumeLayout(false); + this.PerformLayout(); + } + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Label label_pleasewait; + } +} diff --git a/src/GreenshotPlugin/Controls/PleaseWaitForm.cs b/src/Greenshot.Base/Controls/PleaseWaitForm.cs similarity index 95% rename from src/GreenshotPlugin/Controls/PleaseWaitForm.cs rename to src/Greenshot.Base/Controls/PleaseWaitForm.cs index 8d0ced972..e87ab38ef 100644 --- a/src/GreenshotPlugin/Controls/PleaseWaitForm.cs +++ b/src/Greenshot.Base/Controls/PleaseWaitForm.cs @@ -1,143 +1,143 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Windows.Forms; -using System.Threading; -using GreenshotPlugin.Core; -using log4net; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of PleaseWaitForm. - /// - public partial class PleaseWaitForm : Form - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(PleaseWaitForm)); - private Thread _waitFor; - private string _title; - - public PleaseWaitForm() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - Icon = GreenshotResources.GetGreenshotIcon(); - } - - /// - /// Prevent the close-window button showing - /// - private const int CP_NOCLOSE_BUTTON = 0x200; - - protected override CreateParams CreateParams - { - get - { - CreateParams createParams = base.CreateParams; - createParams.ClassStyle |= CP_NOCLOSE_BUTTON; - return createParams; - } - } - - /// - /// Show the "please wait" form, execute the code from the delegate and wait until execution finishes. - /// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown. - /// - /// The title of the form (and Thread) - /// The text in the form - /// delegate { with your code } - public void ShowAndWait(string title, string text, ThreadStart waitDelegate) - { - _title = title; - Text = title; - label_pleasewait.Text = text; - cancelButton.Text = Language.GetString("CANCEL"); - - // Make sure the form is shown. - Show(); - - // Variable to store the exception, if one is generated, from inside the thread. - Exception threadException = null; - try - { - // Wrap the passed delegate in a try/catch which makes it possible to save the exception - _waitFor = new Thread(new ThreadStart( - delegate - { - try - { - waitDelegate.Invoke(); - } - catch (Exception ex) - { - LOG.Error("invoke error:", ex); - threadException = ex; - } - }) - ) - { - Name = title, - IsBackground = true - }; - _waitFor.SetApartmentState(ApartmentState.STA); - _waitFor.Start(); - - // Wait until finished - while (!_waitFor.Join(TimeSpan.FromMilliseconds(100))) - { - Application.DoEvents(); - } - - LOG.DebugFormat("Finished {0}", title); - } - catch (Exception ex) - { - LOG.Error(ex); - throw; - } - finally - { - Close(); - } - - // Check if an exception occured, if so throw it - if (threadException != null) - { - throw threadException; - } - } - - /// - /// Called if the cancel button is clicked, will use Thread.Abort() - /// - /// - /// - private void CancelButtonClick(object sender, EventArgs e) - { - LOG.DebugFormat("Cancel clicked on {0}", _title); - cancelButton.Enabled = false; - _waitFor.Abort(); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Threading; +using System.Windows.Forms; +using Greenshot.Base.Core; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// Description of PleaseWaitForm. + /// + public partial class PleaseWaitForm : Form + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(PleaseWaitForm)); + private Thread _waitFor; + private string _title; + + public PleaseWaitForm() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + Icon = GreenshotResources.GetGreenshotIcon(); + } + + /// + /// Prevent the close-window button showing + /// + private const int CP_NOCLOSE_BUTTON = 0x200; + + protected override CreateParams CreateParams + { + get + { + CreateParams createParams = base.CreateParams; + createParams.ClassStyle |= CP_NOCLOSE_BUTTON; + return createParams; + } + } + + /// + /// Show the "please wait" form, execute the code from the delegate and wait until execution finishes. + /// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown. + /// + /// The title of the form (and Thread) + /// The text in the form + /// delegate { with your code } + public void ShowAndWait(string title, string text, ThreadStart waitDelegate) + { + _title = title; + Text = title; + label_pleasewait.Text = text; + cancelButton.Text = Language.GetString("CANCEL"); + + // Make sure the form is shown. + Show(); + + // Variable to store the exception, if one is generated, from inside the thread. + Exception threadException = null; + try + { + // Wrap the passed delegate in a try/catch which makes it possible to save the exception + _waitFor = new Thread(new ThreadStart( + delegate + { + try + { + waitDelegate.Invoke(); + } + catch (Exception ex) + { + LOG.Error("invoke error:", ex); + threadException = ex; + } + }) + ) + { + Name = title, + IsBackground = true + }; + _waitFor.SetApartmentState(ApartmentState.STA); + _waitFor.Start(); + + // Wait until finished + while (!_waitFor.Join(TimeSpan.FromMilliseconds(100))) + { + Application.DoEvents(); + } + + LOG.DebugFormat("Finished {0}", title); + } + catch (Exception ex) + { + LOG.Error(ex); + throw; + } + finally + { + Close(); + } + + // Check if an exception occured, if so throw it + if (threadException != null) + { + throw threadException; + } + } + + /// + /// Called if the cancel button is clicked, will use Thread.Abort() + /// + /// + /// + private void CancelButtonClick(object sender, EventArgs e) + { + LOG.DebugFormat("Cancel clicked on {0}", _title); + cancelButton.Enabled = false; + _waitFor.Abort(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/QualityDialog.Designer.cs b/src/Greenshot.Base/Controls/QualityDialog.Designer.cs similarity index 90% rename from src/GreenshotPlugin/Controls/QualityDialog.Designer.cs rename to src/Greenshot.Base/Controls/QualityDialog.Designer.cs index 5f1c03fce..dd67f3358 100644 --- a/src/GreenshotPlugin/Controls/QualityDialog.Designer.cs +++ b/src/Greenshot.Base/Controls/QualityDialog.Designer.cs @@ -1,147 +1,147 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ -namespace GreenshotPlugin.Controls { - partial class QualityDialog { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxJpegQuality = new System.Windows.Forms.TextBox(); - this.trackBarJpegQuality = new System.Windows.Forms.TrackBar(); - this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.button_ok = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkBox_reduceColors = new System.Windows.Forms.CheckBox(); - ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit(); - this.SuspendLayout(); - // - // label_choosejpegquality - // - this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47); - this.label_choosejpegquality.Name = "label_choosejpegquality"; - this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19); - this.label_choosejpegquality.TabIndex = 15; - this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality"; - // - // textBoxJpegQuality - // - this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69); - this.textBoxJpegQuality.Name = "textBoxJpegQuality"; - this.textBoxJpegQuality.ReadOnly = true; - this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20); - this.textBoxJpegQuality.TabIndex = 4; - this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - // - // trackBarJpegQuality - // - this.trackBarJpegQuality.LargeChange = 10; - this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69); - this.trackBarJpegQuality.Maximum = 100; - this.trackBarJpegQuality.Name = "trackBarJpegQuality"; - this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45); - this.trackBarJpegQuality.TabIndex = 3; - this.trackBarJpegQuality.TickFrequency = 10; - this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll); - // - // checkbox_dontaskagain - // - this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106); - this.checkbox_dontaskagain.Name = "checkbox_dontaskagain"; - this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain"; - this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37); - this.checkbox_dontaskagain.TabIndex = 5; - this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft; - this.checkbox_dontaskagain.UseVisualStyleBackColor = true; - // - // button_ok - // - this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.button_ok.Location = new System.Drawing.Point(205, 149); - this.button_ok.Name = "button_ok"; - this.button_ok.Size = new System.Drawing.Size(75, 23); - this.button_ok.TabIndex = 1; - this.button_ok.LanguageKey = "OK"; - this.button_ok.UseVisualStyleBackColor = true; - this.button_ok.Click += new System.EventHandler(this.Button_okClick); - // - // checkBox_reduceColors - // - this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11); - this.checkBox_reduceColors.Name = "checkBox_reduceColors"; - this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17); - this.checkBox_reduceColors.TabIndex = 2; - this.checkBox_reduceColors.Text = "settings_reducecolors"; - this.checkBox_reduceColors.UseVisualStyleBackColor = true; - // - // QualityDialog - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(299, 184); - this.ControlBox = false; - this.Controls.Add(this.checkBox_reduceColors); - this.Controls.Add(this.button_ok); - this.Controls.Add(this.checkbox_dontaskagain); - this.Controls.Add(this.label_choosejpegquality); - this.Controls.Add(this.textBoxJpegQuality); - this.Controls.Add(this.trackBarJpegQuality); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "QualityDialog"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.LanguageKey = "qualitydialog_title"; - ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - private GreenshotPlugin.Controls.GreenshotButton button_ok; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain; - private System.Windows.Forms.TrackBar trackBarJpegQuality; - private System.Windows.Forms.TextBox textBoxJpegQuality; - private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality; - private System.Windows.Forms.CheckBox checkBox_reduceColors; - } -} +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ +namespace Greenshot.Base.Controls { + partial class QualityDialog { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.label_choosejpegquality = new GreenshotLabel(); + this.textBoxJpegQuality = new System.Windows.Forms.TextBox(); + this.trackBarJpegQuality = new System.Windows.Forms.TrackBar(); + this.checkbox_dontaskagain = new GreenshotCheckBox(); + this.button_ok = new GreenshotButton(); + this.checkBox_reduceColors = new System.Windows.Forms.CheckBox(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit(); + this.SuspendLayout(); + // + // label_choosejpegquality + // + this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47); + this.label_choosejpegquality.Name = "label_choosejpegquality"; + this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19); + this.label_choosejpegquality.TabIndex = 15; + this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality"; + // + // textBoxJpegQuality + // + this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69); + this.textBoxJpegQuality.Name = "textBoxJpegQuality"; + this.textBoxJpegQuality.ReadOnly = true; + this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20); + this.textBoxJpegQuality.TabIndex = 4; + this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + // + // trackBarJpegQuality + // + this.trackBarJpegQuality.LargeChange = 10; + this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69); + this.trackBarJpegQuality.Maximum = 100; + this.trackBarJpegQuality.Name = "trackBarJpegQuality"; + this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45); + this.trackBarJpegQuality.TabIndex = 3; + this.trackBarJpegQuality.TickFrequency = 10; + this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll); + // + // checkbox_dontaskagain + // + this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft; + this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft; + this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106); + this.checkbox_dontaskagain.Name = "checkbox_dontaskagain"; + this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain"; + this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37); + this.checkbox_dontaskagain.TabIndex = 5; + this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft; + this.checkbox_dontaskagain.UseVisualStyleBackColor = true; + // + // button_ok + // + this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button_ok.Location = new System.Drawing.Point(205, 149); + this.button_ok.Name = "button_ok"; + this.button_ok.Size = new System.Drawing.Size(75, 23); + this.button_ok.TabIndex = 1; + this.button_ok.LanguageKey = "OK"; + this.button_ok.UseVisualStyleBackColor = true; + this.button_ok.Click += new System.EventHandler(this.Button_okClick); + // + // checkBox_reduceColors + // + this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11); + this.checkBox_reduceColors.Name = "checkBox_reduceColors"; + this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17); + this.checkBox_reduceColors.TabIndex = 2; + this.checkBox_reduceColors.Text = "settings_reducecolors"; + this.checkBox_reduceColors.UseVisualStyleBackColor = true; + // + // QualityDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(299, 184); + this.ControlBox = false; + this.Controls.Add(this.checkBox_reduceColors); + this.Controls.Add(this.button_ok); + this.Controls.Add(this.checkbox_dontaskagain); + this.Controls.Add(this.label_choosejpegquality); + this.Controls.Add(this.textBoxJpegQuality); + this.Controls.Add(this.trackBarJpegQuality); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "QualityDialog"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.LanguageKey = "qualitydialog_title"; + ((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + private GreenshotButton button_ok; + private GreenshotCheckBox checkbox_dontaskagain; + private System.Windows.Forms.TrackBar trackBarJpegQuality; + private System.Windows.Forms.TextBox textBoxJpegQuality; + private GreenshotLabel label_choosejpegquality; + private System.Windows.Forms.CheckBox checkBox_reduceColors; + } +} diff --git a/src/GreenshotPlugin/Controls/QualityDialog.cs b/src/Greenshot.Base/Controls/QualityDialog.cs similarity index 92% rename from src/GreenshotPlugin/Controls/QualityDialog.cs rename to src/Greenshot.Base/Controls/QualityDialog.cs index ae8ae07f2..1da67eb2b 100644 --- a/src/GreenshotPlugin/Controls/QualityDialog.cs +++ b/src/Greenshot.Base/Controls/QualityDialog.cs @@ -1,71 +1,71 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces.Plugin; - -namespace GreenshotPlugin.Controls -{ - /// - /// Description of JpegQualityDialog. - /// - public partial class QualityDialog : GreenshotForm - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - public SurfaceOutputSettings Settings { get; set; } - - public QualityDialog(SurfaceOutputSettings outputSettings) - { - Settings = outputSettings; - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - - checkBox_reduceColors.Checked = Settings.ReduceColors; - trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); - trackBarJpegQuality.Value = Settings.JPGQuality; - textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); - textBoxJpegQuality.Text = Settings.JPGQuality.ToString(); - ToFront = true; - } - - private void Button_okClick(object sender, EventArgs e) - { - Settings.JPGQuality = trackBarJpegQuality.Value; - Settings.ReduceColors = checkBox_reduceColors.Checked; - if (checkbox_dontaskagain.Checked) - { - conf.OutputFileJpegQuality = Settings.JPGQuality; - conf.OutputFilePromptQuality = false; - conf.OutputFileReduceColors = Settings.ReduceColors; - IniConfig.Save(); - } - } - - private void TrackBarJpegQualityScroll(object sender, EventArgs e) - { - textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString(); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces.Plugin; + +namespace Greenshot.Base.Controls +{ + /// + /// Description of JpegQualityDialog. + /// + public partial class QualityDialog : GreenshotForm + { + private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); + public SurfaceOutputSettings Settings { get; set; } + + public QualityDialog(SurfaceOutputSettings outputSettings) + { + Settings = outputSettings; + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + checkBox_reduceColors.Checked = Settings.ReduceColors; + trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); + trackBarJpegQuality.Value = Settings.JPGQuality; + textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format); + textBoxJpegQuality.Text = Settings.JPGQuality.ToString(); + ToFront = true; + } + + private void Button_okClick(object sender, EventArgs e) + { + Settings.JPGQuality = trackBarJpegQuality.Value; + Settings.ReduceColors = checkBox_reduceColors.Checked; + if (checkbox_dontaskagain.Checked) + { + conf.OutputFileJpegQuality = Settings.JPGQuality; + conf.OutputFilePromptQuality = false; + conf.OutputFileReduceColors = Settings.ReduceColors; + IniConfig.Save(); + } + } + + private void TrackBarJpegQualityScroll(object sender, EventArgs e) + { + textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/SaveImageFileDialog.cs b/src/Greenshot.Base/Controls/SaveImageFileDialog.cs similarity index 95% rename from src/GreenshotPlugin/Controls/SaveImageFileDialog.cs rename to src/Greenshot.Base/Controls/SaveImageFileDialog.cs index 49caedb07..d95702547 100644 --- a/src/GreenshotPlugin/Controls/SaveImageFileDialog.cs +++ b/src/Greenshot.Base/Controls/SaveImageFileDialog.cs @@ -1,235 +1,235 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.IO; -using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using log4net; - -namespace GreenshotPlugin.Controls -{ - /// - /// Custom dialog for saving images, wraps SaveFileDialog. - /// For some reason SFD is sealed :( - /// - public class SaveImageFileDialog : IDisposable - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(SaveImageFileDialog)); - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - protected SaveFileDialog SaveFileDialog; - private FilterOption[] _filterOptions; - private DirectoryInfo _eagerlyCreatedDirectory; - private readonly ICaptureDetails _captureDetails; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (SaveFileDialog != null) - { - SaveFileDialog.Dispose(); - SaveFileDialog = null; - } - } - } - - public SaveImageFileDialog(ICaptureDetails captureDetails) - { - _captureDetails = captureDetails; - Init(); - } - - private void Init() - { - SaveFileDialog = new SaveFileDialog(); - ApplyFilterOptions(); - string initialDirectory = null; - try - { - conf.ValidateAndCorrectOutputFileAsFullpath(); - initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath); - } - catch - { - LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath); - } - - if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory)) - { - SaveFileDialog.InitialDirectory = initialDirectory; - } - else if (Directory.Exists(conf.OutputFilePath)) - { - SaveFileDialog.InitialDirectory = conf.OutputFilePath; - } - - // The following property fixes a problem that the directory where we save is locked (bug #2899790) - SaveFileDialog.RestoreDirectory = true; - SaveFileDialog.OverwritePrompt = true; - SaveFileDialog.CheckPathExists = false; - SaveFileDialog.AddExtension = true; - ApplySuggestedValues(); - } - - private void ApplyFilterOptions() - { - PrepareFilterOptions(); - string fdf = string.Empty; - int preselect = 0; - var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat); - for (int i = 0; i < _filterOptions.Length; i++) - { - FilterOption fo = _filterOptions[i]; - fdf += fo.Label + "|*." + fo.Extension + "|"; - if (outputFileFormatAsString == fo.Extension) - preselect = i; - } - - fdf = fdf.Substring(0, fdf.Length - 1); - SaveFileDialog.Filter = fdf; - SaveFileDialog.FilterIndex = preselect + 1; - } - - private void PrepareFilterOptions() - { - OutputFormat[] supportedImageFormats = (OutputFormat[]) Enum.GetValues(typeof(OutputFormat)); - _filterOptions = new FilterOption[supportedImageFormats.Length]; - for (int i = 0; i < _filterOptions.Length; i++) - { - string ifo = supportedImageFormats[i].ToString(); - if (ifo.ToLower().Equals("jpeg")) ifo = "Jpg"; // we dont want no jpeg files, so let the dialog check for jpg - FilterOption fo = new FilterOption - { - Label = ifo.ToUpper(), - Extension = ifo.ToLower() - }; - _filterOptions.SetValue(fo, i); - } - } - - /// - /// filename exactly as typed in the filename field - /// - public string FileName - { - get { return SaveFileDialog.FileName; } - set { SaveFileDialog.FileName = value; } - } - - /// - /// initial directory of the dialog - /// - public string InitialDirectory - { - get { return SaveFileDialog.InitialDirectory; } - set { SaveFileDialog.InitialDirectory = value; } - } - - /// - /// returns filename as typed in the filename field with extension. - /// if filename field value ends with selected extension, the value is just returned. - /// otherwise, the selected extension is appended to the filename. - /// - public string FileNameWithExtension - { - get - { - string fn = SaveFileDialog.FileName; - // if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay - if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn; - // otherwise we just add the selected filter item's extension - else return fn + "." + Extension; - } - set - { - FileName = Path.GetFileNameWithoutExtension(value); - Extension = Path.GetExtension(value); - } - } - - /// - /// gets or sets selected extension - /// - public string Extension - { - get { return _filterOptions[SaveFileDialog.FilterIndex - 1].Extension; } - set - { - for (int i = 0; i < _filterOptions.Length; i++) - { - if (value.Equals(_filterOptions[i].Extension, StringComparison.CurrentCultureIgnoreCase)) - { - SaveFileDialog.FilterIndex = i + 1; - } - } - } - } - - public DialogResult ShowDialog() - { - DialogResult ret = SaveFileDialog.ShowDialog(); - CleanUp(); - return ret; - } - - /// - /// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path - /// - private void ApplySuggestedValues() - { - // build the full path and set dialog properties - FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, _captureDetails); - } - - private class FilterOption - { - public string Label; - public string Extension; - } - - private void CleanUp() - { - // fix for bug #3379053 - try - { - if (_eagerlyCreatedDirectory != null && _eagerlyCreatedDirectory.GetFiles().Length == 0 && _eagerlyCreatedDirectory.GetDirectories().Length == 0) - { - _eagerlyCreatedDirectory.Delete(); - _eagerlyCreatedDirectory = null; - } - } - catch (Exception e) - { - LOG.WarnFormat("Couldn't cleanup directory due to: {0}", e.Message); - _eagerlyCreatedDirectory = null; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.IO; +using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using log4net; + +namespace Greenshot.Base.Controls +{ + /// + /// Custom dialog for saving images, wraps SaveFileDialog. + /// For some reason SFD is sealed :( + /// + public class SaveImageFileDialog : IDisposable + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(SaveImageFileDialog)); + private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); + protected SaveFileDialog SaveFileDialog; + private FilterOption[] _filterOptions; + private DirectoryInfo _eagerlyCreatedDirectory; + private readonly ICaptureDetails _captureDetails; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (SaveFileDialog != null) + { + SaveFileDialog.Dispose(); + SaveFileDialog = null; + } + } + } + + public SaveImageFileDialog(ICaptureDetails captureDetails) + { + _captureDetails = captureDetails; + Init(); + } + + private void Init() + { + SaveFileDialog = new SaveFileDialog(); + ApplyFilterOptions(); + string initialDirectory = null; + try + { + conf.ValidateAndCorrectOutputFileAsFullpath(); + initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath); + } + catch + { + LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath); + } + + if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory)) + { + SaveFileDialog.InitialDirectory = initialDirectory; + } + else if (Directory.Exists(conf.OutputFilePath)) + { + SaveFileDialog.InitialDirectory = conf.OutputFilePath; + } + + // The following property fixes a problem that the directory where we save is locked (bug #2899790) + SaveFileDialog.RestoreDirectory = true; + SaveFileDialog.OverwritePrompt = true; + SaveFileDialog.CheckPathExists = false; + SaveFileDialog.AddExtension = true; + ApplySuggestedValues(); + } + + private void ApplyFilterOptions() + { + PrepareFilterOptions(); + string fdf = string.Empty; + int preselect = 0; + var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat); + for (int i = 0; i < _filterOptions.Length; i++) + { + FilterOption fo = _filterOptions[i]; + fdf += fo.Label + "|*." + fo.Extension + "|"; + if (outputFileFormatAsString == fo.Extension) + preselect = i; + } + + fdf = fdf.Substring(0, fdf.Length - 1); + SaveFileDialog.Filter = fdf; + SaveFileDialog.FilterIndex = preselect + 1; + } + + private void PrepareFilterOptions() + { + OutputFormat[] supportedImageFormats = (OutputFormat[]) Enum.GetValues(typeof(OutputFormat)); + _filterOptions = new FilterOption[supportedImageFormats.Length]; + for (int i = 0; i < _filterOptions.Length; i++) + { + string ifo = supportedImageFormats[i].ToString(); + if (ifo.ToLower().Equals("jpeg")) ifo = "Jpg"; // we dont want no jpeg files, so let the dialog check for jpg + FilterOption fo = new FilterOption + { + Label = ifo.ToUpper(), + Extension = ifo.ToLower() + }; + _filterOptions.SetValue(fo, i); + } + } + + /// + /// filename exactly as typed in the filename field + /// + public string FileName + { + get { return SaveFileDialog.FileName; } + set { SaveFileDialog.FileName = value; } + } + + /// + /// initial directory of the dialog + /// + public string InitialDirectory + { + get { return SaveFileDialog.InitialDirectory; } + set { SaveFileDialog.InitialDirectory = value; } + } + + /// + /// returns filename as typed in the filename field with extension. + /// if filename field value ends with selected extension, the value is just returned. + /// otherwise, the selected extension is appended to the filename. + /// + public string FileNameWithExtension + { + get + { + string fn = SaveFileDialog.FileName; + // if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay + if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn; + // otherwise we just add the selected filter item's extension + else return fn + "." + Extension; + } + set + { + FileName = Path.GetFileNameWithoutExtension(value); + Extension = Path.GetExtension(value); + } + } + + /// + /// gets or sets selected extension + /// + public string Extension + { + get { return _filterOptions[SaveFileDialog.FilterIndex - 1].Extension; } + set + { + for (int i = 0; i < _filterOptions.Length; i++) + { + if (value.Equals(_filterOptions[i].Extension, StringComparison.CurrentCultureIgnoreCase)) + { + SaveFileDialog.FilterIndex = i + 1; + } + } + } + } + + public DialogResult ShowDialog() + { + DialogResult ret = SaveFileDialog.ShowDialog(); + CleanUp(); + return ret; + } + + /// + /// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path + /// + private void ApplySuggestedValues() + { + // build the full path and set dialog properties + FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, _captureDetails); + } + + private class FilterOption + { + public string Label; + public string Extension; + } + + private void CleanUp() + { + // fix for bug #3379053 + try + { + if (_eagerlyCreatedDirectory != null && _eagerlyCreatedDirectory.GetFiles().Length == 0 && _eagerlyCreatedDirectory.GetDirectories().Length == 0) + { + _eagerlyCreatedDirectory.Delete(); + _eagerlyCreatedDirectory = null; + } + } + catch (Exception e) + { + LOG.WarnFormat("Couldn't cleanup directory due to: {0}", e.Message); + _eagerlyCreatedDirectory = null; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Controls/ThumbnailForm.cs b/src/Greenshot.Base/Controls/ThumbnailForm.cs similarity index 92% rename from src/GreenshotPlugin/Controls/ThumbnailForm.cs rename to src/Greenshot.Base/Controls/ThumbnailForm.cs index 2b6b349b4..16d597f3c 100644 --- a/src/GreenshotPlugin/Controls/ThumbnailForm.cs +++ b/src/Greenshot.Base/Controls/ThumbnailForm.cs @@ -1,157 +1,156 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Windows.Forms; -using GreenshotPlugin.Core; -using System.Drawing; -using GreenshotPlugin.Core.Enums; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; - -namespace GreenshotPlugin.Controls -{ - /// - /// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture. - /// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform. - /// - public sealed class ThumbnailForm : FormWithoutActivation - { - private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); - - private IntPtr _thumbnailHandle = IntPtr.Zero; - - public ThumbnailForm() - { - ShowInTaskbar = false; - FormBorderStyle = FormBorderStyle.None; - TopMost = false; - Enabled = false; - if (conf.WindowCaptureMode == WindowCaptureMode.Auto || conf.WindowCaptureMode == WindowCaptureMode.Aero) - { - BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B); - } - else - { - BackColor = Color.White; - } - - // cleanup at close - FormClosing += delegate { UnregisterThumbnail(); }; - } - - public new void Hide() - { - UnregisterThumbnail(); - base.Hide(); - } - - private void UnregisterThumbnail() - { - if (_thumbnailHandle == IntPtr.Zero) return; - - DWM.DwmUnregisterThumbnail(_thumbnailHandle); - _thumbnailHandle = IntPtr.Zero; - } - - /// - /// Show the thumbnail of the supplied window above (or under) the parent Control - /// - /// WindowDetails - /// Control - public void ShowThumbnail(WindowDetails window, Control parentControl) - { - UnregisterThumbnail(); - - DWM.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle); - if (_thumbnailHandle == IntPtr.Zero) return; - - var result = DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); - if (result.Failed()) - { - DWM.DwmUnregisterThumbnail(_thumbnailHandle); - return; - } - - if (sourceSize.IsEmpty) - { - DWM.DwmUnregisterThumbnail(_thumbnailHandle); - return; - } - - int thumbnailHeight = 200; - int thumbnailWidth = (int) (thumbnailHeight * (sourceSize.Width / (float) sourceSize.Height)); - if (parentControl != null && thumbnailWidth > parentControl.Width) - { - thumbnailWidth = parentControl.Width; - thumbnailHeight = (int) (thumbnailWidth * (sourceSize.Height / (float) sourceSize.Width)); - } - - Width = thumbnailWidth; - Height = thumbnailHeight; - // Prepare the displaying of the Thumbnail - var dwmThumbnailProperties = new DWM_THUMBNAIL_PROPERTIES - { - Opacity = 255, - Visible = true, - SourceClientAreaOnly = false, - Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight) - }; - result = DWM.DwmUpdateThumbnailProperties(_thumbnailHandle, ref dwmThumbnailProperties); - if (result.Failed()) - { - DWM.DwmUnregisterThumbnail(_thumbnailHandle); - return; - } - - if (parentControl != null) - { - AlignToControl(parentControl); - } - - if (!Visible) - { - Show(); - } - - // Make sure it's on "top"! - if (parentControl != null) - { - User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); - } - } - - public void AlignToControl(Control alignTo) - { - var screenBounds = WindowCapture.GetScreenBounds(); - if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) - { - Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height); - } - else - { - Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Bottom); - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; + +namespace Greenshot.Base.Controls +{ + /// + /// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture. + /// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform. + /// + public sealed class ThumbnailForm : FormWithoutActivation + { + private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); + + private IntPtr _thumbnailHandle = IntPtr.Zero; + + public ThumbnailForm() + { + ShowInTaskbar = false; + FormBorderStyle = FormBorderStyle.None; + TopMost = false; + Enabled = false; + if (conf.WindowCaptureMode == WindowCaptureMode.Auto || conf.WindowCaptureMode == WindowCaptureMode.Aero) + { + BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B); + } + else + { + BackColor = Color.White; + } + + // cleanup at close + FormClosing += delegate { UnregisterThumbnail(); }; + } + + public new void Hide() + { + UnregisterThumbnail(); + base.Hide(); + } + + private void UnregisterThumbnail() + { + if (_thumbnailHandle == IntPtr.Zero) return; + + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + _thumbnailHandle = IntPtr.Zero; + } + + /// + /// Show the thumbnail of the supplied window above (or under) the parent Control + /// + /// WindowDetails + /// Control + public void ShowThumbnail(WindowDetails window, Control parentControl) + { + UnregisterThumbnail(); + + DWM.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle); + if (_thumbnailHandle == IntPtr.Zero) return; + + var result = DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); + if (result.Failed()) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + if (sourceSize.IsEmpty) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + int thumbnailHeight = 200; + int thumbnailWidth = (int) (thumbnailHeight * (sourceSize.Width / (float) sourceSize.Height)); + if (parentControl != null && thumbnailWidth > parentControl.Width) + { + thumbnailWidth = parentControl.Width; + thumbnailHeight = (int) (thumbnailWidth * (sourceSize.Height / (float) sourceSize.Width)); + } + + Width = thumbnailWidth; + Height = thumbnailHeight; + // Prepare the displaying of the Thumbnail + var dwmThumbnailProperties = new DWM_THUMBNAIL_PROPERTIES + { + Opacity = 255, + Visible = true, + SourceClientAreaOnly = false, + Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight) + }; + result = DWM.DwmUpdateThumbnailProperties(_thumbnailHandle, ref dwmThumbnailProperties); + if (result.Failed()) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + if (parentControl != null) + { + AlignToControl(parentControl); + } + + if (!Visible) + { + Show(); + } + + // Make sure it's on "top"! + if (parentControl != null) + { + User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); + } + } + + public void AlignToControl(Control alignTo) + { + var screenBounds = WindowCapture.GetScreenBounds(); + if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) + { + Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height); + } + else + { + Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Bottom); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/AbstractDestination.cs b/src/Greenshot.Base/Core/AbstractDestination.cs similarity index 96% rename from src/GreenshotPlugin/Core/AbstractDestination.cs rename to src/Greenshot.Base/Core/AbstractDestination.cs index 27c6abbb4..c9864f99b 100644 --- a/src/GreenshotPlugin/Core/AbstractDestination.cs +++ b/src/Greenshot.Base/Core/AbstractDestination.cs @@ -1,416 +1,416 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.UnmanagedHelpers; -using log4net; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of AbstractDestination. - /// - public abstract class AbstractDestination : IDestination - { - private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination)); - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - - public virtual int CompareTo(object obj) - { - if (!(obj is IDestination other)) - { - return 1; - } - - if (Priority == other.Priority) - { - return string.Compare(Description, other.Description, StringComparison.Ordinal); - } - - return Priority - other.Priority; - } - - public abstract string Designation { get; } - - public abstract string Description { get; } - - public virtual int Priority => 10; - - public virtual Image DisplayIcon => null; - - public virtual Keys EditorShortcutKeys => Keys.None; - - public virtual IEnumerable DynamicDestinations() - { - yield break; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - //if (disposing) {} - } - - public virtual bool IsDynamic => false; - - public virtual bool UseDynamicsOnly => false; - - public virtual bool IsLinkable => false; - - public virtual bool IsActive - { - get - { - if (CoreConfig.ExcludeDestinations != null && CoreConfig.ExcludeDestinations.Contains(Designation)) - { - return false; - } - - return true; - } - } - - public abstract ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails); - - /// - /// A small helper method to perform some default destination actions, like inform the surface of the export - /// - /// - /// - public void ProcessExport(ExportInformation exportInformation, ISurface surface) - { - if (exportInformation != null && exportInformation.ExportMade) - { - if (!string.IsNullOrEmpty(exportInformation.Uri)) - { - surface.UploadUrl = exportInformation.Uri; - surface.SendMessageEvent(this, SurfaceMessageTyp.UploadedUri, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); - } - else if (!string.IsNullOrEmpty(exportInformation.Filepath)) - { - surface.LastSaveFullPath = exportInformation.Filepath; - surface.SendMessageEvent(this, SurfaceMessageTyp.FileSaved, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); - } - else - { - surface.SendMessageEvent(this, SurfaceMessageTyp.Info, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); - } - - surface.Modified = false; - } - else if (!string.IsNullOrEmpty(exportInformation?.ErrorMessage)) - { - surface.SendMessageEvent(this, SurfaceMessageTyp.Error, - Language.GetFormattedString("exported_to_error", exportInformation.DestinationDescription) + " " + exportInformation.ErrorMessage); - } - } - - public override string ToString() - { - return Description; - } - - /// - /// Helper method to add events which set the tag, this way we can see why there might be a close. - /// - /// Item to add the events to - /// Menu to set the tag - /// Value for the tag - private void AddTagEvents(ToolStripMenuItem menuItem, ContextMenuStrip menu, string tagValue) - { - if (menuItem != null && menu != null) - { - menuItem.MouseDown += delegate - { - Log.DebugFormat("Setting tag to '{0}'", tagValue); - menu.Tag = tagValue; - }; - menuItem.MouseUp += delegate - { - Log.Debug("Deleting tag"); - menu.Tag = null; - }; - } - } - - /// - /// This method will create and show the destination picker menu - /// - /// Boolean if the dynamic values also need to be added - /// The surface which can be exported - /// Details for the surface - /// The list of destinations to show - /// - public ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable destinations) - { - // Generate an empty ExportInformation object, for when nothing was selected. - ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker")); - var menu = new ContextMenuStrip - { - ImageScalingSize = CoreConfig.ScaledIconSize, - Tag = null, - TopLevel = true - }; - - menu.Opening += (sender, args) => - { - // find the DPI settings for the screen where this is going to land - var screenDpi = DpiHelper.GetDpi(menu.Location); - var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, screenDpi); - menu.SuspendLayout(); - var fontSize = DpiHelper.ScaleWithDpi(12f, screenDpi); - menu.Font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Regular, GraphicsUnit.Pixel); - menu.ImageScalingSize = scaledIconSize; - menu.ResumeLayout(); - }; - - menu.Closing += delegate(object source, ToolStripDropDownClosingEventArgs eventArgs) - { - Log.DebugFormat("Close reason: {0}", eventArgs.CloseReason); - switch (eventArgs.CloseReason) - { - case ToolStripDropDownCloseReason.AppFocusChange: - if (menu.Tag == null) - { - // Do not allow the close if the tag is not set, this means the user clicked somewhere else. - eventArgs.Cancel = true; - } - else - { - Log.DebugFormat("Letting the menu 'close' as the tag is set to '{0}'", menu.Tag); - } - - break; - case ToolStripDropDownCloseReason.ItemClicked: - case ToolStripDropDownCloseReason.CloseCalled: - // The ContextMenuStrip can be "closed" for these reasons. - break; - case ToolStripDropDownCloseReason.Keyboard: - // Dispose as the close is clicked - if (!captureDetails.HasDestination("Editor")) - { - surface.Dispose(); - surface = null; - } - - break; - default: - eventArgs.Cancel = true; - break; - } - }; - menu.MouseEnter += delegate - { - // in case the menu has been unfocused, focus again so that dropdown menus will still open on mouseenter - if (!menu.ContainsFocus) - { - menu.Focus(); - } - }; - foreach (IDestination destination in destinations) - { - // Fix foreach loop variable for the delegate - ToolStripMenuItem item = destination.GetMenuItem(addDynamics, menu, - delegate(object sender, EventArgs e) - { - ToolStripMenuItem toolStripMenuItem = sender as ToolStripMenuItem; - IDestination clickedDestination = (IDestination) toolStripMenuItem?.Tag; - if (clickedDestination == null) - { - return; - } - - menu.Tag = clickedDestination.Designation; - // Export - exportInformation = clickedDestination.ExportCapture(true, surface, captureDetails); - if (exportInformation != null && exportInformation.ExportMade) - { - Log.InfoFormat("Export to {0} success, closing menu", exportInformation.DestinationDescription); - // close menu if the destination wasn't the editor - menu.Close(); - - // Cleanup surface, only if there is no editor in the destinations and we didn't export to the editor - if (!captureDetails.HasDestination("Editor") && !"Editor".Equals(clickedDestination.Designation)) - { - surface.Dispose(); - surface = null; - } - } - else - { - Log.Info("Export cancelled or failed, showing menu again"); - - // Make sure a click besides the menu don't close it. - menu.Tag = null; - - // This prevents the problem that the context menu shows in the task-bar - ShowMenuAtCursor(menu); - } - } - ); - if (item != null) - { - menu.Items.Add(item); - } - } - - // Close - menu.Items.Add(new ToolStripSeparator()); - ToolStripMenuItem closeItem = new ToolStripMenuItem(Language.GetString("editor_close")) - { - Image = GreenshotResources.GetImage("Close.Image") - }; - closeItem.Click += delegate - { - // This menu entry is the close itself, we can dispose the surface - menu.Close(); - if (!captureDetails.HasDestination("Editor")) - { - surface.Dispose(); - surface = null; - } - }; - menu.Items.Add(closeItem); - - ShowMenuAtCursor(menu); - return exportInformation; - } - - /// - /// This method will show the supplied context menu at the mouse cursor, also makes sure it has focus and it's not visible in the taskbar. - /// - /// - private static void ShowMenuAtCursor(ContextMenuStrip menu) - { - // find a suitable location - Point location = Cursor.Position; - Rectangle menuRectangle = new Rectangle(location, menu.Size); - - menuRectangle.Intersect(WindowCapture.GetScreenBounds()); - if (menuRectangle.Height < menu.Height) - { - location.Offset(-40, -(menuRectangle.Height - menu.Height)); - } - else - { - location.Offset(-40, -10); - } - - // This prevents the problem that the context menu shows in the task-bar - User32.SetForegroundWindow(SimpleServiceProvider.Current.GetInstance().ContextMenuStrip.Handle); - menu.Show(location); - menu.Focus(); - - // Wait for the menu to close, so we can dispose it. - while (true) - { - if (menu.Visible) - { - Application.DoEvents(); - Thread.Sleep(100); - } - else - { - menu.Dispose(); - break; - } - } - } - - /// - /// Return a menu item - /// - /// - /// - /// - /// ToolStripMenuItem - public virtual ToolStripMenuItem GetMenuItem(bool addDynamics, ContextMenuStrip menu, EventHandler destinationClickHandler) - { - var basisMenuItem = new ToolStripMenuItem(Description) - { - Image = DisplayIcon, - Tag = this, - Text = Description - }; - AddTagEvents(basisMenuItem, menu, Description); - basisMenuItem.Click -= destinationClickHandler; - basisMenuItem.Click += destinationClickHandler; - - if (IsDynamic && addDynamics) - { - basisMenuItem.DropDownOpening += delegate - { - if (basisMenuItem.DropDownItems.Count == 0) - { - List subDestinations = new List(); - // Fixing Bug #3536968 by catching the COMException (every exception) and not displaying the "subDestinations" - try - { - subDestinations.AddRange(DynamicDestinations()); - } - catch (Exception ex) - { - Log.ErrorFormat("Skipping {0}, due to the following error: {1}", Description, ex.Message); - } - - if (subDestinations.Count > 0) - { - if (UseDynamicsOnly && subDestinations.Count == 1) - { - basisMenuItem.Tag = subDestinations[0]; - basisMenuItem.Text = subDestinations[0].Description; - basisMenuItem.Click -= destinationClickHandler; - basisMenuItem.Click += destinationClickHandler; - } - else - { - foreach (IDestination subDestination in subDestinations) - { - var destinationMenuItem = new ToolStripMenuItem(subDestination.Description) - { - Tag = subDestination, - Image = subDestination.DisplayIcon - }; - destinationMenuItem.Click += destinationClickHandler; - AddTagEvents(destinationMenuItem, menu, subDestination.Description); - basisMenuItem.DropDownItems.Add(destinationMenuItem); - } - } - } - } - }; - } - - return basisMenuItem; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.UnmanagedHelpers; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// Description of AbstractDestination. + /// + public abstract class AbstractDestination : IDestination + { + private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination)); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + + public virtual int CompareTo(object obj) + { + if (!(obj is IDestination other)) + { + return 1; + } + + if (Priority == other.Priority) + { + return string.Compare(Description, other.Description, StringComparison.Ordinal); + } + + return Priority - other.Priority; + } + + public abstract string Designation { get; } + + public abstract string Description { get; } + + public virtual int Priority => 10; + + public virtual Image DisplayIcon => null; + + public virtual Keys EditorShortcutKeys => Keys.None; + + public virtual IEnumerable DynamicDestinations() + { + yield break; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + //if (disposing) {} + } + + public virtual bool IsDynamic => false; + + public virtual bool UseDynamicsOnly => false; + + public virtual bool IsLinkable => false; + + public virtual bool IsActive + { + get + { + if (CoreConfig.ExcludeDestinations != null && CoreConfig.ExcludeDestinations.Contains(Designation)) + { + return false; + } + + return true; + } + } + + public abstract ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails); + + /// + /// A small helper method to perform some default destination actions, like inform the surface of the export + /// + /// + /// + public void ProcessExport(ExportInformation exportInformation, ISurface surface) + { + if (exportInformation != null && exportInformation.ExportMade) + { + if (!string.IsNullOrEmpty(exportInformation.Uri)) + { + surface.UploadUrl = exportInformation.Uri; + surface.SendMessageEvent(this, SurfaceMessageTyp.UploadedUri, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); + } + else if (!string.IsNullOrEmpty(exportInformation.Filepath)) + { + surface.LastSaveFullPath = exportInformation.Filepath; + surface.SendMessageEvent(this, SurfaceMessageTyp.FileSaved, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); + } + else + { + surface.SendMessageEvent(this, SurfaceMessageTyp.Info, Language.GetFormattedString("exported_to", exportInformation.DestinationDescription)); + } + + surface.Modified = false; + } + else if (!string.IsNullOrEmpty(exportInformation?.ErrorMessage)) + { + surface.SendMessageEvent(this, SurfaceMessageTyp.Error, + Language.GetFormattedString("exported_to_error", exportInformation.DestinationDescription) + " " + exportInformation.ErrorMessage); + } + } + + public override string ToString() + { + return Description; + } + + /// + /// Helper method to add events which set the tag, this way we can see why there might be a close. + /// + /// Item to add the events to + /// Menu to set the tag + /// Value for the tag + private void AddTagEvents(ToolStripMenuItem menuItem, ContextMenuStrip menu, string tagValue) + { + if (menuItem != null && menu != null) + { + menuItem.MouseDown += delegate + { + Log.DebugFormat("Setting tag to '{0}'", tagValue); + menu.Tag = tagValue; + }; + menuItem.MouseUp += delegate + { + Log.Debug("Deleting tag"); + menu.Tag = null; + }; + } + } + + /// + /// This method will create and show the destination picker menu + /// + /// Boolean if the dynamic values also need to be added + /// The surface which can be exported + /// Details for the surface + /// The list of destinations to show + /// + public ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable destinations) + { + // Generate an empty ExportInformation object, for when nothing was selected. + ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker")); + var menu = new ContextMenuStrip + { + ImageScalingSize = CoreConfig.ScaledIconSize, + Tag = null, + TopLevel = true + }; + + menu.Opening += (sender, args) => + { + // find the DPI settings for the screen where this is going to land + var screenDpi = DpiHelper.GetDpi(menu.Location); + var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, screenDpi); + menu.SuspendLayout(); + var fontSize = DpiHelper.ScaleWithDpi(12f, screenDpi); + menu.Font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Regular, GraphicsUnit.Pixel); + menu.ImageScalingSize = scaledIconSize; + menu.ResumeLayout(); + }; + + menu.Closing += delegate(object source, ToolStripDropDownClosingEventArgs eventArgs) + { + Log.DebugFormat("Close reason: {0}", eventArgs.CloseReason); + switch (eventArgs.CloseReason) + { + case ToolStripDropDownCloseReason.AppFocusChange: + if (menu.Tag == null) + { + // Do not allow the close if the tag is not set, this means the user clicked somewhere else. + eventArgs.Cancel = true; + } + else + { + Log.DebugFormat("Letting the menu 'close' as the tag is set to '{0}'", menu.Tag); + } + + break; + case ToolStripDropDownCloseReason.ItemClicked: + case ToolStripDropDownCloseReason.CloseCalled: + // The ContextMenuStrip can be "closed" for these reasons. + break; + case ToolStripDropDownCloseReason.Keyboard: + // Dispose as the close is clicked + if (!captureDetails.HasDestination("Editor")) + { + surface.Dispose(); + surface = null; + } + + break; + default: + eventArgs.Cancel = true; + break; + } + }; + menu.MouseEnter += delegate + { + // in case the menu has been unfocused, focus again so that dropdown menus will still open on mouseenter + if (!menu.ContainsFocus) + { + menu.Focus(); + } + }; + foreach (IDestination destination in destinations) + { + // Fix foreach loop variable for the delegate + ToolStripMenuItem item = destination.GetMenuItem(addDynamics, menu, + delegate(object sender, EventArgs e) + { + ToolStripMenuItem toolStripMenuItem = sender as ToolStripMenuItem; + IDestination clickedDestination = (IDestination) toolStripMenuItem?.Tag; + if (clickedDestination == null) + { + return; + } + + menu.Tag = clickedDestination.Designation; + // Export + exportInformation = clickedDestination.ExportCapture(true, surface, captureDetails); + if (exportInformation != null && exportInformation.ExportMade) + { + Log.InfoFormat("Export to {0} success, closing menu", exportInformation.DestinationDescription); + // close menu if the destination wasn't the editor + menu.Close(); + + // Cleanup surface, only if there is no editor in the destinations and we didn't export to the editor + if (!captureDetails.HasDestination("Editor") && !"Editor".Equals(clickedDestination.Designation)) + { + surface.Dispose(); + surface = null; + } + } + else + { + Log.Info("Export cancelled or failed, showing menu again"); + + // Make sure a click besides the menu don't close it. + menu.Tag = null; + + // This prevents the problem that the context menu shows in the task-bar + ShowMenuAtCursor(menu); + } + } + ); + if (item != null) + { + menu.Items.Add(item); + } + } + + // Close + menu.Items.Add(new ToolStripSeparator()); + ToolStripMenuItem closeItem = new ToolStripMenuItem(Language.GetString("editor_close")) + { + Image = GreenshotResources.GetImage("Close.Image") + }; + closeItem.Click += delegate + { + // This menu entry is the close itself, we can dispose the surface + menu.Close(); + if (!captureDetails.HasDestination("Editor")) + { + surface.Dispose(); + surface = null; + } + }; + menu.Items.Add(closeItem); + + ShowMenuAtCursor(menu); + return exportInformation; + } + + /// + /// This method will show the supplied context menu at the mouse cursor, also makes sure it has focus and it's not visible in the taskbar. + /// + /// + private static void ShowMenuAtCursor(ContextMenuStrip menu) + { + // find a suitable location + Point location = Cursor.Position; + Rectangle menuRectangle = new Rectangle(location, menu.Size); + + menuRectangle.Intersect(WindowCapture.GetScreenBounds()); + if (menuRectangle.Height < menu.Height) + { + location.Offset(-40, -(menuRectangle.Height - menu.Height)); + } + else + { + location.Offset(-40, -10); + } + + // This prevents the problem that the context menu shows in the task-bar + User32.SetForegroundWindow(SimpleServiceProvider.Current.GetInstance().ContextMenuStrip.Handle); + menu.Show(location); + menu.Focus(); + + // Wait for the menu to close, so we can dispose it. + while (true) + { + if (menu.Visible) + { + Application.DoEvents(); + Thread.Sleep(100); + } + else + { + menu.Dispose(); + break; + } + } + } + + /// + /// Return a menu item + /// + /// + /// + /// + /// ToolStripMenuItem + public virtual ToolStripMenuItem GetMenuItem(bool addDynamics, ContextMenuStrip menu, EventHandler destinationClickHandler) + { + var basisMenuItem = new ToolStripMenuItem(Description) + { + Image = DisplayIcon, + Tag = this, + Text = Description + }; + AddTagEvents(basisMenuItem, menu, Description); + basisMenuItem.Click -= destinationClickHandler; + basisMenuItem.Click += destinationClickHandler; + + if (IsDynamic && addDynamics) + { + basisMenuItem.DropDownOpening += delegate + { + if (basisMenuItem.DropDownItems.Count == 0) + { + List subDestinations = new List(); + // Fixing Bug #3536968 by catching the COMException (every exception) and not displaying the "subDestinations" + try + { + subDestinations.AddRange(DynamicDestinations()); + } + catch (Exception ex) + { + Log.ErrorFormat("Skipping {0}, due to the following error: {1}", Description, ex.Message); + } + + if (subDestinations.Count > 0) + { + if (UseDynamicsOnly && subDestinations.Count == 1) + { + basisMenuItem.Tag = subDestinations[0]; + basisMenuItem.Text = subDestinations[0].Description; + basisMenuItem.Click -= destinationClickHandler; + basisMenuItem.Click += destinationClickHandler; + } + else + { + foreach (IDestination subDestination in subDestinations) + { + var destinationMenuItem = new ToolStripMenuItem(subDestination.Description) + { + Tag = subDestination, + Image = subDestination.DisplayIcon + }; + destinationMenuItem.Click += destinationClickHandler; + AddTagEvents(destinationMenuItem, menu, subDestination.Description); + basisMenuItem.DropDownItems.Add(destinationMenuItem); + } + } + } + } + }; + } + + return basisMenuItem; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/AbstractProcessor.cs b/src/Greenshot.Base/Core/AbstractProcessor.cs similarity index 93% rename from src/GreenshotPlugin/Core/AbstractProcessor.cs rename to src/Greenshot.Base/Core/AbstractProcessor.cs index 6e016e857..b82d11e46 100644 --- a/src/GreenshotPlugin/Core/AbstractProcessor.cs +++ b/src/Greenshot.Base/Core/AbstractProcessor.cs @@ -1,68 +1,68 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of AbstractProcessor. - /// - public abstract class AbstractProcessor : IProcessor - { - public virtual int CompareTo(object obj) - { - if (!(obj is IProcessor other)) - { - return 1; - } - - if (Priority == other.Priority) - { - return string.Compare(Description, other.Description, StringComparison.Ordinal); - } - - return Priority - other.Priority; - } - - public abstract string Designation { get; } - - public abstract string Description { get; } - - public virtual int Priority => 10; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - //if (disposing) {} - } - - public virtual bool isActive => true; - - public abstract bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using Greenshot.Base.Interfaces; + +namespace Greenshot.Base.Core +{ + /// + /// Description of AbstractProcessor. + /// + public abstract class AbstractProcessor : IProcessor + { + public virtual int CompareTo(object obj) + { + if (!(obj is IProcessor other)) + { + return 1; + } + + if (Priority == other.Priority) + { + return string.Compare(Description, other.Description, StringComparison.Ordinal); + } + + return Priority - other.Priority; + } + + public abstract string Designation { get; } + + public abstract string Description { get; } + + public virtual int Priority => 10; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + //if (disposing) {} + } + + public virtual bool isActive => true; + + public abstract bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/AccessibleHelper.cs b/src/Greenshot.Base/Core/AccessibleHelper.cs similarity index 96% rename from src/GreenshotPlugin/Core/AccessibleHelper.cs rename to src/Greenshot.Base/Core/AccessibleHelper.cs index 9a88f68b8..31fca4e83 100644 --- a/src/GreenshotPlugin/Core/AccessibleHelper.cs +++ b/src/Greenshot.Base/Core/AccessibleHelper.cs @@ -1,237 +1,237 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using Accessibility; - -namespace GreenshotPlugin.Core -{ - /// - /// See: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/03a8c835-e9e4-405b-8345-6c3d36bc8941 - /// This should really be cleaned up, there is little OO behind this class! - /// Maybe move the basic Accessible functions to WindowDetails!? - /// - public class Accessible - { - private static int AccessibleObjectFromWindow(IntPtr hWnd, OBJID idObject, ref IAccessible acc) - { - var guid = new Guid("{618736e0-3c3d-11cf-810c-00aa00389b71}"); // IAccessible - object obj = null; - int num = AccessibleObjectFromWindow(hWnd, (uint) idObject, ref guid, ref obj); - acc = (IAccessible) obj; - return num; - } - - [DllImport("oleacc.dll")] - private static extern int AccessibleObjectFromWindow(IntPtr hWnd, uint id, ref Guid iid, [In, Out, MarshalAs(UnmanagedType.IUnknown)] - ref object ppvObject); - - [DllImport("oleacc.dll")] - private static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - object[] rgvarChildren, out int pcObtained); - - [DllImport("oleacc.dll", PreserveSig = false)] - [return: MarshalAs(UnmanagedType.Interface)] - public static extern object ObjectFromLresult(UIntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam); - - private enum OBJID : uint - { - OBJID_WINDOW = 0x00000000, - } - - private const int IE_ACTIVE_TAB = 2097154; - private const int CHILDID_SELF = 0; - private readonly IAccessible accessible; - - private Accessible[] Children - { - get - { - object[] res = GetAccessibleChildren(accessible, out var num); - if (res == null) - { - return new Accessible[0]; - } - - List list = new List(res.Length); - foreach (object obj in res) - { - if (obj is IAccessible acc) - { - list.Add(new Accessible(acc)); - } - } - - return list.ToArray(); - } - } - - private string Name - { - get { return accessible.get_accName(CHILDID_SELF); } - } - - private int ChildCount - { - get { return accessible.accChildCount; } - } - - public Accessible(IntPtr hWnd) - { - AccessibleObjectFromWindow(hWnd, OBJID.OBJID_WINDOW, ref accessible); - if (accessible == null) - { - throw new Exception(); - } - } - - public void ActivateIETab(int tabIndexToActivate) - { - var index = 0; - foreach (Accessible accessor in Children) - { - foreach (var child in accessor.Children) - { - foreach (var tab in child.Children) - { - if (tabIndexToActivate >= child.ChildCount - 1) - { - return; - } - - if (index == tabIndexToActivate) - { - tab.Activate(); - return; - } - - index++; - } - } - } - } - - public string IEActiveTabCaption - { - get - { - foreach (Accessible accessor in Children) - { - foreach (var child in accessor.Children) - { - foreach (var tab in child.Children) - { - object tabIndex = tab.accessible.get_accState(0); - - if ((int) tabIndex == IE_ACTIVE_TAB) - { - return tab.Name; - } - } - } - } - - return string.Empty; - } - } - - public List IETabCaptions - { - get - { - var captionList = new List(); - - foreach (Accessible accessor in Children) - { - foreach (var child in accessor.Children) - { - foreach (var tab in child.Children) - { - captionList.Add(tab.Name); - } - } - } - - // TODO: Why again? - if (captionList.Count > 0) - { - captionList.RemoveAt(captionList.Count - 1); - } - - return captionList; - } - } - - - public IEnumerable IETabUrls - { - get - { - foreach (Accessible accessor in Children) - { - foreach (var child in accessor.Children) - { - foreach (var tab in child.Children) - { - object tabIndex = tab.accessible.get_accState(CHILDID_SELF); - var description = tab.accessible.get_accDescription(CHILDID_SELF); - if (!string.IsNullOrEmpty(description)) - { - if (description.Contains(Environment.NewLine)) - { - var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim(); - yield return url; - } - } - } - } - } - } - } - - private Accessible(IAccessible acc) - { - accessible = acc ?? throw new Exception(); - } - - private void Activate() - { - accessible.accDoDefaultAction(CHILDID_SELF); - } - - private static object[] GetAccessibleChildren(IAccessible ao, out int childs) - { - childs = 0; - object[] ret = null; - int count = ao.accChildCount; - - if (count > 0) - { - ret = new object[count]; - AccessibleChildren(ao, 0, count, ret, out childs); - } - - return ret; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Accessibility; + +namespace Greenshot.Base.Core +{ + /// + /// See: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/03a8c835-e9e4-405b-8345-6c3d36bc8941 + /// This should really be cleaned up, there is little OO behind this class! + /// Maybe move the basic Accessible functions to WindowDetails!? + /// + public class Accessible + { + private static int AccessibleObjectFromWindow(IntPtr hWnd, OBJID idObject, ref IAccessible acc) + { + var guid = new Guid("{618736e0-3c3d-11cf-810c-00aa00389b71}"); // IAccessible + object obj = null; + int num = AccessibleObjectFromWindow(hWnd, (uint) idObject, ref guid, ref obj); + acc = (IAccessible) obj; + return num; + } + + [DllImport("oleacc.dll")] + private static extern int AccessibleObjectFromWindow(IntPtr hWnd, uint id, ref Guid iid, [In, Out, MarshalAs(UnmanagedType.IUnknown)] + ref object ppvObject); + + [DllImport("oleacc.dll")] + private static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] + object[] rgvarChildren, out int pcObtained); + + [DllImport("oleacc.dll", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.Interface)] + public static extern object ObjectFromLresult(UIntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam); + + private enum OBJID : uint + { + OBJID_WINDOW = 0x00000000, + } + + private const int IE_ACTIVE_TAB = 2097154; + private const int CHILDID_SELF = 0; + private readonly IAccessible accessible; + + private Accessible[] Children + { + get + { + object[] res = GetAccessibleChildren(accessible, out var num); + if (res == null) + { + return new Accessible[0]; + } + + List list = new List(res.Length); + foreach (object obj in res) + { + if (obj is IAccessible acc) + { + list.Add(new Accessible(acc)); + } + } + + return list.ToArray(); + } + } + + private string Name + { + get { return accessible.get_accName(CHILDID_SELF); } + } + + private int ChildCount + { + get { return accessible.accChildCount; } + } + + public Accessible(IntPtr hWnd) + { + AccessibleObjectFromWindow(hWnd, OBJID.OBJID_WINDOW, ref accessible); + if (accessible == null) + { + throw new Exception(); + } + } + + public void ActivateIETab(int tabIndexToActivate) + { + var index = 0; + foreach (Accessible accessor in Children) + { + foreach (var child in accessor.Children) + { + foreach (var tab in child.Children) + { + if (tabIndexToActivate >= child.ChildCount - 1) + { + return; + } + + if (index == tabIndexToActivate) + { + tab.Activate(); + return; + } + + index++; + } + } + } + } + + public string IEActiveTabCaption + { + get + { + foreach (Accessible accessor in Children) + { + foreach (var child in accessor.Children) + { + foreach (var tab in child.Children) + { + object tabIndex = tab.accessible.get_accState(0); + + if ((int) tabIndex == IE_ACTIVE_TAB) + { + return tab.Name; + } + } + } + } + + return string.Empty; + } + } + + public List IETabCaptions + { + get + { + var captionList = new List(); + + foreach (Accessible accessor in Children) + { + foreach (var child in accessor.Children) + { + foreach (var tab in child.Children) + { + captionList.Add(tab.Name); + } + } + } + + // TODO: Why again? + if (captionList.Count > 0) + { + captionList.RemoveAt(captionList.Count - 1); + } + + return captionList; + } + } + + + public IEnumerable IETabUrls + { + get + { + foreach (Accessible accessor in Children) + { + foreach (var child in accessor.Children) + { + foreach (var tab in child.Children) + { + object tabIndex = tab.accessible.get_accState(CHILDID_SELF); + var description = tab.accessible.get_accDescription(CHILDID_SELF); + if (!string.IsNullOrEmpty(description)) + { + if (description.Contains(Environment.NewLine)) + { + var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim(); + yield return url; + } + } + } + } + } + } + } + + private Accessible(IAccessible acc) + { + accessible = acc ?? throw new Exception(); + } + + private void Activate() + { + accessible.accDoDefaultAction(CHILDID_SELF); + } + + private static object[] GetAccessibleChildren(IAccessible ao, out int childs) + { + childs = 0; + object[] ret = null; + int count = ao.accChildCount; + + if (count > 0) + { + ret = new object[count]; + AccessibleChildren(ao, 0, count, ret, out childs); + } + + return ret; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/AnimationHelpers.cs b/src/Greenshot.Base/Core/AnimationHelpers.cs similarity index 96% rename from src/GreenshotPlugin/Core/AnimationHelpers.cs rename to src/Greenshot.Base/Core/AnimationHelpers.cs index ed8282ac6..0d96016ab 100644 --- a/src/GreenshotPlugin/Core/AnimationHelpers.cs +++ b/src/Greenshot.Base/Core/AnimationHelpers.cs @@ -1,610 +1,610 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Collections.Generic; - -namespace GreenshotPlugin.Core -{ - /// - /// Helper interface for passing base type - /// - public interface IAnimator - { - /// - /// Is there a next frame? - /// - bool HasNext { get; } - - /// - /// The amount of frames - /// - int Frames { get; } - - /// - /// Current frame number - /// - int CurrentFrameNr { get; } - } - - /// - /// This class is used to store a animation leg - /// - internal class AnimationLeg - { - public T Destination { get; set; } - - public int Frames { get; set; } - - public EasingType EasingType { get; set; } - - public EasingMode EasingMode { get; set; } - } - - /// - /// Base class for the animation logic, this only implements Properties and a constructor - /// - /// Type for the animation, like Point/Rectangle/Size - public abstract class AnimatorBase : IAnimator - { - private readonly Queue> _queue = new Queue>(); - - /// - /// Constructor - /// - /// - /// - /// - /// - /// - public AnimatorBase(T first, T last, int frames, EasingType easingType, EasingMode easingMode) - { - First = first; - Last = last; - Frames = frames; - Current = first; - EasingType = easingType; - EasingMode = easingMode; - } - - /// - /// The amount of frames - /// - public int Frames { get; private set; } - - /// - /// Current frame number - /// - public int CurrentFrameNr { get; private set; } - - /// - /// First animation value - /// - public T First { get; private set; } - - /// - /// Last animation value, of this "leg" - /// - public T Last { get; private set; } - - /// - /// Final animation value, this is including the legs - /// - public T Final - { - get - { - if (_queue.Count == 0) - { - return Last; - } - - return _queue.ToArray()[_queue.Count - 1].Destination; - } - } - - /// - /// This restarts the current animation and changes the last frame - /// - /// - public void ChangeDestination(T newDestination) - { - ChangeDestination(newDestination, Frames); - } - - /// - /// This restarts the current animation and changes the last frame - /// - /// - /// - public void ChangeDestination(T newDestination, int frames) - { - _queue.Clear(); - First = Current; - CurrentFrameNr = 0; - Frames = frames; - Last = newDestination; - } - - /// - /// Queue the destination, it will be used to continue at the last frame - /// All values will stay the same - /// - /// - public void QueueDestinationLeg(T queuedDestination) - { - QueueDestinationLeg(queuedDestination, Frames, EasingType, EasingMode); - } - - /// - /// Queue the destination, it will be used to continue at the last frame - /// - /// - /// - public void QueueDestinationLeg(T queuedDestination, int frames) - { - QueueDestinationLeg(queuedDestination, frames, EasingType, EasingMode); - } - - /// - /// Queue the destination, it will be used to continue at the last frame - /// - /// - /// - /// EasingType - public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType) - { - QueueDestinationLeg(queuedDestination, frames, easingType, EasingMode); - } - - /// - /// Queue the destination, it will be used to continue at the last frame - /// - /// - /// - /// - /// - public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType, EasingMode easingMode) - { - AnimationLeg leg = new AnimationLeg - { - Destination = queuedDestination, - Frames = frames, - EasingType = easingType, - EasingMode = easingMode - }; - _queue.Enqueue(leg); - } - - /// - /// The EasingType to use for the animation - /// - public EasingType EasingType { get; set; } - - /// - /// The EasingMode to use for the animation - /// - public EasingMode EasingMode { get; set; } - - /// - /// Get the easing value, which is from 0-1 and depends on the frame - /// - protected double EasingValue - { - get => - EasingMode switch - { - EasingMode.EaseOut => Easing.EaseOut(CurrentFrameNr / (double) Frames, EasingType), - EasingMode.EaseInOut => Easing.EaseInOut(CurrentFrameNr / (double) Frames, EasingType), - EasingMode.EaseIn => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType), - _ => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType) - }; - } - - /// - /// Get the current (previous) frame object - /// - public virtual T Current { get; set; } - - /// - /// Returns if there are any frame left, and if this is the case than the frame is increased. - /// - public virtual bool NextFrame - { - get - { - if (CurrentFrameNr < Frames) - { - CurrentFrameNr++; - return true; - } - - if (_queue.Count > 0) - { - First = Current; - CurrentFrameNr = 0; - AnimationLeg nextLeg = _queue.Dequeue(); - Last = nextLeg.Destination; - Frames = nextLeg.Frames; - EasingType = nextLeg.EasingType; - EasingMode = nextLeg.EasingMode; - return true; - } - - return false; - } - } - - /// - /// Are there more frames to animate? - /// - public virtual bool HasNext - { - get - { - if (CurrentFrameNr < Frames) - { - return true; - } - - return _queue.Count > 0; - } - } - - /// - /// Get the next animation frame value object - /// - /// - public abstract T Next(); - } - - /// - /// Implementation of the RectangleAnimator - /// - public class RectangleAnimator : AnimatorBase - { - public RectangleAnimator(Rectangle first, Rectangle last, int frames) - : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) - { - } - - public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType) - : base(first, last, frames, easingType, EasingMode.EaseIn) - { - } - - public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType, EasingMode easingMode) - : base(first, last, frames, easingType, easingMode) - { - } - - /// - /// Calculate the next frame object - /// - /// Rectangle - public override Rectangle Next() - { - if (NextFrame) - { - double easingValue = EasingValue; - double dx = Last.X - First.X; - double dy = Last.Y - First.Y; - - int x = First.X + (int) (easingValue * dx); - int y = First.Y + (int) (easingValue * dy); - double dw = Last.Width - First.Width; - double dh = Last.Height - First.Height; - int width = First.Width + (int) (easingValue * dw); - int height = First.Height + (int) (easingValue * dh); - Current = new Rectangle(x, y, width, height); - } - - return Current; - } - } - - /// - /// Implementation of the PointAnimator - /// - public class PointAnimator : AnimatorBase - { - public PointAnimator(Point first, Point last, int frames) - : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) - { - } - - public PointAnimator(Point first, Point last, int frames, EasingType easingType) - : base(first, last, frames, easingType, EasingMode.EaseIn) - { - } - - public PointAnimator(Point first, Point last, int frames, EasingType easingType, EasingMode easingMode) - : base(first, last, frames, easingType, easingMode) - { - } - - /// - /// Calculate the next frame value - /// - /// Point - public override Point Next() - { - if (NextFrame) - { - double easingValue = EasingValue; - double dx = Last.X - First.X; - double dy = Last.Y - First.Y; - - int x = First.X + (int) (easingValue * dx); - int y = First.Y + (int) (easingValue * dy); - Current = new Point(x, y); - } - - return Current; - } - } - - /// - /// Implementation of the SizeAnimator - /// - public class SizeAnimator : AnimatorBase - { - public SizeAnimator(Size first, Size last, int frames) - : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) - { - } - - public SizeAnimator(Size first, Size last, int frames, EasingType easingType) - : base(first, last, frames, easingType, EasingMode.EaseIn) - { - } - - public SizeAnimator(Size first, Size last, int frames, EasingType easingType, EasingMode easingMode) - : base(first, last, frames, easingType, easingMode) - { - } - - /// - /// Calculate the next frame values - /// - /// Size - public override Size Next() - { - if (NextFrame) - { - double easingValue = EasingValue; - double dw = Last.Width - First.Width; - double dh = Last.Height - First.Height; - int width = First.Width + (int) (easingValue * dw); - int height = First.Height + (int) (easingValue * dh); - Current = new Size(width, height); - } - - return Current; - } - } - - /// - /// Implementation of the ColorAnimator - /// - public class ColorAnimator : AnimatorBase - { - public ColorAnimator(Color first, Color last, int frames) - : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) - { - } - - public ColorAnimator(Color first, Color last, int frames, EasingType easingType) - : base(first, last, frames, easingType, EasingMode.EaseIn) - { - } - - public ColorAnimator(Color first, Color last, int frames, EasingType easingType, EasingMode easingMode) - : base(first, last, frames, easingType, easingMode) - { - } - - /// - /// Calculate the next frame values - /// - /// Color - public override Color Next() - { - if (NextFrame) - { - double easingValue = EasingValue; - double da = Last.A - First.A; - double dr = Last.R - First.R; - double dg = Last.G - First.G; - double db = Last.B - First.B; - int a = First.A + (int) (easingValue * da); - int r = First.R + (int) (easingValue * dr); - int g = First.G + (int) (easingValue * dg); - int b = First.B + (int) (easingValue * db); - Current = Color.FromArgb(a, r, g, b); - } - - return Current; - } - } - - /// - /// Implementation of the IntAnimator - /// - public class IntAnimator : AnimatorBase - { - public IntAnimator(int first, int last, int frames) - : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) - { - } - - public IntAnimator(int first, int last, int frames, EasingType easingType) - : base(first, last, frames, easingType, EasingMode.EaseIn) - { - } - - public IntAnimator(int first, int last, int frames, EasingType easingType, EasingMode easingMode) - : base(first, last, frames, easingType, easingMode) - { - } - - /// - /// Calculate the next frame values - /// - /// int - public override int Next() - { - if (NextFrame) - { - double easingValue = EasingValue; - double delta = Last - First; - Current = First + (int) (easingValue * delta); - } - - return Current; - } - } - - /// - /// Easing logic, to make the animations more "fluent" - /// - public static class Easing - { - // Adapted from http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf - - public static double Ease(double linearStep, double acceleration, EasingType type) - { - double easedStep = acceleration > 0 ? EaseIn(linearStep, type) : acceleration < 0 ? EaseOut(linearStep, type) : linearStep; - // Lerp: - return ((easedStep - linearStep) * Math.Abs(acceleration) + linearStep); - } - - public static double EaseIn(double linearStep, EasingType type) => - type switch - { - EasingType.Step => (linearStep < 0.5 ? 0 : 1), - EasingType.Linear => linearStep, - EasingType.Sine => Sine.EaseIn(linearStep), - EasingType.Quadratic => Power.EaseIn(linearStep, 2), - EasingType.Cubic => Power.EaseIn(linearStep, 3), - EasingType.Quartic => Power.EaseIn(linearStep, 4), - EasingType.Quintic => Power.EaseIn(linearStep, 5), - _ => throw new NotImplementedException() - }; - - public static double EaseOut(double linearStep, EasingType type) => - type switch - { - EasingType.Step => (linearStep < 0.5 ? 0 : 1), - EasingType.Linear => linearStep, - EasingType.Sine => Sine.EaseOut(linearStep), - EasingType.Quadratic => Power.EaseOut(linearStep, 2), - EasingType.Cubic => Power.EaseOut(linearStep, 3), - EasingType.Quartic => Power.EaseOut(linearStep, 4), - EasingType.Quintic => Power.EaseOut(linearStep, 5), - _ => throw new NotImplementedException() - }; - - public static double EaseInOut(double linearStep, EasingType easeInType, EasingType easeOutType) - { - return linearStep < 0.5 ? EaseInOut(linearStep, easeInType) : EaseInOut(linearStep, easeOutType); - } - - public static double EaseInOut(double linearStep, EasingType type) => - type switch - { - EasingType.Step => (linearStep < 0.5 ? 0 : 1), - EasingType.Linear => linearStep, - EasingType.Sine => Sine.EaseInOut(linearStep), - EasingType.Quadratic => Power.EaseInOut(linearStep, 2), - EasingType.Cubic => Power.EaseInOut(linearStep, 3), - EasingType.Quartic => Power.EaseInOut(linearStep, 4), - EasingType.Quintic => Power.EaseInOut(linearStep, 5), - _ => throw new NotImplementedException() - }; - - private static class Sine - { - public static double EaseIn(double s) - { - return Math.Sin(s * (Math.PI / 2) - (Math.PI / 2)) + 1; - } - - public static double EaseOut(double s) - { - return Math.Sin(s * (Math.PI / 2)); - } - - public static double EaseInOut(double s) - { - return Math.Sin(s * Math.PI - (Math.PI / 2) + 1) / 2; - } - } - - private static class Power - { - public static double EaseIn(double s, int power) - { - return Math.Pow(s, power); - } - - public static double EaseOut(double s, int power) - { - var sign = power % 2 == 0 ? -1 : 1; - return sign * (Math.Pow(s - 1, power) + sign); - } - - public static double EaseInOut(double s, int power) - { - s *= 2; - if (s < 1) - { - return EaseIn(s, power) / 2; - } - - var sign = power % 2 == 0 ? -1 : 1; - return (sign / 2.0 * (Math.Pow(s - 2, power) + sign * 2)); - } - } - } - - /// - /// This defines the way the animation works - /// - public enum EasingType - { - Step, - Linear, - Sine, - Quadratic, - Cubic, - Quartic, - Quintic - } - - public enum EasingMode - { - EaseIn, - EaseOut, - EaseInOut - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace Greenshot.Base.Core +{ + /// + /// Helper interface for passing base type + /// + public interface IAnimator + { + /// + /// Is there a next frame? + /// + bool HasNext { get; } + + /// + /// The amount of frames + /// + int Frames { get; } + + /// + /// Current frame number + /// + int CurrentFrameNr { get; } + } + + /// + /// This class is used to store a animation leg + /// + internal class AnimationLeg + { + public T Destination { get; set; } + + public int Frames { get; set; } + + public EasingType EasingType { get; set; } + + public EasingMode EasingMode { get; set; } + } + + /// + /// Base class for the animation logic, this only implements Properties and a constructor + /// + /// Type for the animation, like Point/Rectangle/Size + public abstract class AnimatorBase : IAnimator + { + private readonly Queue> _queue = new Queue>(); + + /// + /// Constructor + /// + /// + /// + /// + /// + /// + public AnimatorBase(T first, T last, int frames, EasingType easingType, EasingMode easingMode) + { + First = first; + Last = last; + Frames = frames; + Current = first; + EasingType = easingType; + EasingMode = easingMode; + } + + /// + /// The amount of frames + /// + public int Frames { get; private set; } + + /// + /// Current frame number + /// + public int CurrentFrameNr { get; private set; } + + /// + /// First animation value + /// + public T First { get; private set; } + + /// + /// Last animation value, of this "leg" + /// + public T Last { get; private set; } + + /// + /// Final animation value, this is including the legs + /// + public T Final + { + get + { + if (_queue.Count == 0) + { + return Last; + } + + return _queue.ToArray()[_queue.Count - 1].Destination; + } + } + + /// + /// This restarts the current animation and changes the last frame + /// + /// + public void ChangeDestination(T newDestination) + { + ChangeDestination(newDestination, Frames); + } + + /// + /// This restarts the current animation and changes the last frame + /// + /// + /// + public void ChangeDestination(T newDestination, int frames) + { + _queue.Clear(); + First = Current; + CurrentFrameNr = 0; + Frames = frames; + Last = newDestination; + } + + /// + /// Queue the destination, it will be used to continue at the last frame + /// All values will stay the same + /// + /// + public void QueueDestinationLeg(T queuedDestination) + { + QueueDestinationLeg(queuedDestination, Frames, EasingType, EasingMode); + } + + /// + /// Queue the destination, it will be used to continue at the last frame + /// + /// + /// + public void QueueDestinationLeg(T queuedDestination, int frames) + { + QueueDestinationLeg(queuedDestination, frames, EasingType, EasingMode); + } + + /// + /// Queue the destination, it will be used to continue at the last frame + /// + /// + /// + /// EasingType + public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType) + { + QueueDestinationLeg(queuedDestination, frames, easingType, EasingMode); + } + + /// + /// Queue the destination, it will be used to continue at the last frame + /// + /// + /// + /// + /// + public void QueueDestinationLeg(T queuedDestination, int frames, EasingType easingType, EasingMode easingMode) + { + AnimationLeg leg = new AnimationLeg + { + Destination = queuedDestination, + Frames = frames, + EasingType = easingType, + EasingMode = easingMode + }; + _queue.Enqueue(leg); + } + + /// + /// The EasingType to use for the animation + /// + public EasingType EasingType { get; set; } + + /// + /// The EasingMode to use for the animation + /// + public EasingMode EasingMode { get; set; } + + /// + /// Get the easing value, which is from 0-1 and depends on the frame + /// + protected double EasingValue + { + get => + EasingMode switch + { + EasingMode.EaseOut => Easing.EaseOut(CurrentFrameNr / (double) Frames, EasingType), + EasingMode.EaseInOut => Easing.EaseInOut(CurrentFrameNr / (double) Frames, EasingType), + EasingMode.EaseIn => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType), + _ => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType) + }; + } + + /// + /// Get the current (previous) frame object + /// + public virtual T Current { get; set; } + + /// + /// Returns if there are any frame left, and if this is the case than the frame is increased. + /// + public virtual bool NextFrame + { + get + { + if (CurrentFrameNr < Frames) + { + CurrentFrameNr++; + return true; + } + + if (_queue.Count > 0) + { + First = Current; + CurrentFrameNr = 0; + AnimationLeg nextLeg = _queue.Dequeue(); + Last = nextLeg.Destination; + Frames = nextLeg.Frames; + EasingType = nextLeg.EasingType; + EasingMode = nextLeg.EasingMode; + return true; + } + + return false; + } + } + + /// + /// Are there more frames to animate? + /// + public virtual bool HasNext + { + get + { + if (CurrentFrameNr < Frames) + { + return true; + } + + return _queue.Count > 0; + } + } + + /// + /// Get the next animation frame value object + /// + /// + public abstract T Next(); + } + + /// + /// Implementation of the RectangleAnimator + /// + public class RectangleAnimator : AnimatorBase + { + public RectangleAnimator(Rectangle first, Rectangle last, int frames) + : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) + { + } + + public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType) + : base(first, last, frames, easingType, EasingMode.EaseIn) + { + } + + public RectangleAnimator(Rectangle first, Rectangle last, int frames, EasingType easingType, EasingMode easingMode) + : base(first, last, frames, easingType, easingMode) + { + } + + /// + /// Calculate the next frame object + /// + /// Rectangle + public override Rectangle Next() + { + if (NextFrame) + { + double easingValue = EasingValue; + double dx = Last.X - First.X; + double dy = Last.Y - First.Y; + + int x = First.X + (int) (easingValue * dx); + int y = First.Y + (int) (easingValue * dy); + double dw = Last.Width - First.Width; + double dh = Last.Height - First.Height; + int width = First.Width + (int) (easingValue * dw); + int height = First.Height + (int) (easingValue * dh); + Current = new Rectangle(x, y, width, height); + } + + return Current; + } + } + + /// + /// Implementation of the PointAnimator + /// + public class PointAnimator : AnimatorBase + { + public PointAnimator(Point first, Point last, int frames) + : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) + { + } + + public PointAnimator(Point first, Point last, int frames, EasingType easingType) + : base(first, last, frames, easingType, EasingMode.EaseIn) + { + } + + public PointAnimator(Point first, Point last, int frames, EasingType easingType, EasingMode easingMode) + : base(first, last, frames, easingType, easingMode) + { + } + + /// + /// Calculate the next frame value + /// + /// Point + public override Point Next() + { + if (NextFrame) + { + double easingValue = EasingValue; + double dx = Last.X - First.X; + double dy = Last.Y - First.Y; + + int x = First.X + (int) (easingValue * dx); + int y = First.Y + (int) (easingValue * dy); + Current = new Point(x, y); + } + + return Current; + } + } + + /// + /// Implementation of the SizeAnimator + /// + public class SizeAnimator : AnimatorBase + { + public SizeAnimator(Size first, Size last, int frames) + : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) + { + } + + public SizeAnimator(Size first, Size last, int frames, EasingType easingType) + : base(first, last, frames, easingType, EasingMode.EaseIn) + { + } + + public SizeAnimator(Size first, Size last, int frames, EasingType easingType, EasingMode easingMode) + : base(first, last, frames, easingType, easingMode) + { + } + + /// + /// Calculate the next frame values + /// + /// Size + public override Size Next() + { + if (NextFrame) + { + double easingValue = EasingValue; + double dw = Last.Width - First.Width; + double dh = Last.Height - First.Height; + int width = First.Width + (int) (easingValue * dw); + int height = First.Height + (int) (easingValue * dh); + Current = new Size(width, height); + } + + return Current; + } + } + + /// + /// Implementation of the ColorAnimator + /// + public class ColorAnimator : AnimatorBase + { + public ColorAnimator(Color first, Color last, int frames) + : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) + { + } + + public ColorAnimator(Color first, Color last, int frames, EasingType easingType) + : base(first, last, frames, easingType, EasingMode.EaseIn) + { + } + + public ColorAnimator(Color first, Color last, int frames, EasingType easingType, EasingMode easingMode) + : base(first, last, frames, easingType, easingMode) + { + } + + /// + /// Calculate the next frame values + /// + /// Color + public override Color Next() + { + if (NextFrame) + { + double easingValue = EasingValue; + double da = Last.A - First.A; + double dr = Last.R - First.R; + double dg = Last.G - First.G; + double db = Last.B - First.B; + int a = First.A + (int) (easingValue * da); + int r = First.R + (int) (easingValue * dr); + int g = First.G + (int) (easingValue * dg); + int b = First.B + (int) (easingValue * db); + Current = Color.FromArgb(a, r, g, b); + } + + return Current; + } + } + + /// + /// Implementation of the IntAnimator + /// + public class IntAnimator : AnimatorBase + { + public IntAnimator(int first, int last, int frames) + : base(first, last, frames, EasingType.Linear, EasingMode.EaseIn) + { + } + + public IntAnimator(int first, int last, int frames, EasingType easingType) + : base(first, last, frames, easingType, EasingMode.EaseIn) + { + } + + public IntAnimator(int first, int last, int frames, EasingType easingType, EasingMode easingMode) + : base(first, last, frames, easingType, easingMode) + { + } + + /// + /// Calculate the next frame values + /// + /// int + public override int Next() + { + if (NextFrame) + { + double easingValue = EasingValue; + double delta = Last - First; + Current = First + (int) (easingValue * delta); + } + + return Current; + } + } + + /// + /// Easing logic, to make the animations more "fluent" + /// + public static class Easing + { + // Adapted from http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf + + public static double Ease(double linearStep, double acceleration, EasingType type) + { + double easedStep = acceleration > 0 ? EaseIn(linearStep, type) : acceleration < 0 ? EaseOut(linearStep, type) : linearStep; + // Lerp: + return ((easedStep - linearStep) * Math.Abs(acceleration) + linearStep); + } + + public static double EaseIn(double linearStep, EasingType type) => + type switch + { + EasingType.Step => (linearStep < 0.5 ? 0 : 1), + EasingType.Linear => linearStep, + EasingType.Sine => Sine.EaseIn(linearStep), + EasingType.Quadratic => Power.EaseIn(linearStep, 2), + EasingType.Cubic => Power.EaseIn(linearStep, 3), + EasingType.Quartic => Power.EaseIn(linearStep, 4), + EasingType.Quintic => Power.EaseIn(linearStep, 5), + _ => throw new NotImplementedException() + }; + + public static double EaseOut(double linearStep, EasingType type) => + type switch + { + EasingType.Step => (linearStep < 0.5 ? 0 : 1), + EasingType.Linear => linearStep, + EasingType.Sine => Sine.EaseOut(linearStep), + EasingType.Quadratic => Power.EaseOut(linearStep, 2), + EasingType.Cubic => Power.EaseOut(linearStep, 3), + EasingType.Quartic => Power.EaseOut(linearStep, 4), + EasingType.Quintic => Power.EaseOut(linearStep, 5), + _ => throw new NotImplementedException() + }; + + public static double EaseInOut(double linearStep, EasingType easeInType, EasingType easeOutType) + { + return linearStep < 0.5 ? EaseInOut(linearStep, easeInType) : EaseInOut(linearStep, easeOutType); + } + + public static double EaseInOut(double linearStep, EasingType type) => + type switch + { + EasingType.Step => (linearStep < 0.5 ? 0 : 1), + EasingType.Linear => linearStep, + EasingType.Sine => Sine.EaseInOut(linearStep), + EasingType.Quadratic => Power.EaseInOut(linearStep, 2), + EasingType.Cubic => Power.EaseInOut(linearStep, 3), + EasingType.Quartic => Power.EaseInOut(linearStep, 4), + EasingType.Quintic => Power.EaseInOut(linearStep, 5), + _ => throw new NotImplementedException() + }; + + private static class Sine + { + public static double EaseIn(double s) + { + return Math.Sin(s * (Math.PI / 2) - (Math.PI / 2)) + 1; + } + + public static double EaseOut(double s) + { + return Math.Sin(s * (Math.PI / 2)); + } + + public static double EaseInOut(double s) + { + return Math.Sin(s * Math.PI - (Math.PI / 2) + 1) / 2; + } + } + + private static class Power + { + public static double EaseIn(double s, int power) + { + return Math.Pow(s, power); + } + + public static double EaseOut(double s, int power) + { + var sign = power % 2 == 0 ? -1 : 1; + return sign * (Math.Pow(s - 1, power) + sign); + } + + public static double EaseInOut(double s, int power) + { + s *= 2; + if (s < 1) + { + return EaseIn(s, power) / 2; + } + + var sign = power % 2 == 0 ? -1 : 1; + return (sign / 2.0 * (Math.Pow(s - 2, power) + sign * 2)); + } + } + } + + /// + /// This defines the way the animation works + /// + public enum EasingType + { + Step, + Linear, + Sine, + Quadratic, + Cubic, + Quartic, + Quintic + } + + public enum EasingMode + { + EaseIn, + EaseOut, + EaseInOut + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/BinaryStructHelper.cs b/src/Greenshot.Base/Core/BinaryStructHelper.cs similarity index 96% rename from src/GreenshotPlugin/Core/BinaryStructHelper.cs rename to src/Greenshot.Base/Core/BinaryStructHelper.cs index 1da7254f7..257d8dd2c 100644 --- a/src/GreenshotPlugin/Core/BinaryStructHelper.cs +++ b/src/Greenshot.Base/Core/BinaryStructHelper.cs @@ -1,108 +1,108 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Core -{ - /// - /// A helper class which does the mashalling for structs - /// - public static class BinaryStructHelper - { - /// - /// Get a struct from a byte array - /// - /// typeof struct - /// byte[] - /// struct - public static T FromByteArray(byte[] bytes) where T : struct - { - IntPtr ptr = IntPtr.Zero; - try - { - int size = Marshal.SizeOf(typeof(T)); - ptr = Marshal.AllocHGlobal(size); - Marshal.Copy(bytes, 0, ptr, size); - return FromIntPtr(ptr); - } - finally - { - if (ptr != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptr); - } - } - } - - /// - /// Get a struct from a byte array - /// - /// typeof struct - /// Pointer to the structor to return - /// struct - public static T FromIntPtr(IntPtr intPtr) where T : struct - { - object obj = Marshal.PtrToStructure(intPtr, typeof(T)); - return (T) obj; - } - - /// - /// copy a struct to a byte array - /// - /// typeof struct - /// struct - /// byte[] - public static byte[] ToByteArray(T obj) where T : struct - { - IntPtr ptr = IntPtr.Zero; - try - { - int size = Marshal.SizeOf(typeof(T)); - ptr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(obj, ptr, true); - return FromPtrToByteArray(ptr); - } - finally - { - if (ptr != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptr); - } - } - } - - /// - /// copy a struct from a pointer to a byte array - /// - /// typeof struct - /// IntPtr to struct - /// byte[] - public static byte[] FromPtrToByteArray(IntPtr ptr) where T : struct - { - int size = Marshal.SizeOf(typeof(T)); - byte[] bytes = new byte[size]; - Marshal.Copy(ptr, bytes, 0, size); - return bytes; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Core +{ + /// + /// A helper class which does the mashalling for structs + /// + public static class BinaryStructHelper + { + /// + /// Get a struct from a byte array + /// + /// typeof struct + /// byte[] + /// struct + public static T FromByteArray(byte[] bytes) where T : struct + { + IntPtr ptr = IntPtr.Zero; + try + { + int size = Marshal.SizeOf(typeof(T)); + ptr = Marshal.AllocHGlobal(size); + Marshal.Copy(bytes, 0, ptr, size); + return FromIntPtr(ptr); + } + finally + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + } + + /// + /// Get a struct from a byte array + /// + /// typeof struct + /// Pointer to the structor to return + /// struct + public static T FromIntPtr(IntPtr intPtr) where T : struct + { + object obj = Marshal.PtrToStructure(intPtr, typeof(T)); + return (T) obj; + } + + /// + /// copy a struct to a byte array + /// + /// typeof struct + /// struct + /// byte[] + public static byte[] ToByteArray(T obj) where T : struct + { + IntPtr ptr = IntPtr.Zero; + try + { + int size = Marshal.SizeOf(typeof(T)); + ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(obj, ptr, true); + return FromPtrToByteArray(ptr); + } + finally + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + } + + /// + /// copy a struct from a pointer to a byte array + /// + /// typeof struct + /// IntPtr to struct + /// byte[] + public static byte[] FromPtrToByteArray(IntPtr ptr) where T : struct + { + int size = Marshal.SizeOf(typeof(T)); + byte[] bytes = new byte[size]; + Marshal.Copy(ptr, bytes, 0, size); + return bytes; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/Cache.cs b/src/Greenshot.Base/Core/Cache.cs similarity index 96% rename from src/GreenshotPlugin/Core/Cache.cs rename to src/Greenshot.Base/Core/Cache.cs index 5707f2465..f761b8b89 100644 --- a/src/GreenshotPlugin/Core/Cache.cs +++ b/src/Greenshot.Base/Core/Cache.cs @@ -1,259 +1,259 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Timers; -using log4net; - -namespace GreenshotPlugin.Core -{ - /// - /// Cache class - /// - /// Type of key - /// Type of value - public class Cache - { - private static readonly ILog Log = LogManager.GetLogger(typeof(Cache)); - private readonly IDictionary _internalCache = new Dictionary(); - private readonly object _lockObject = new object(); - private readonly int _secondsToExpire = 10; - private readonly CacheObjectExpired _expiredCallback; - - public delegate void CacheObjectExpired(TK key, TV cacheValue); - - /// - /// Initialize the cache - /// - public Cache() - { - } - - /// - /// Initialize the cache - /// - /// - public Cache(CacheObjectExpired expiredCallback) : this() - { - _expiredCallback = expiredCallback; - } - - /// - /// Initialize the cache with a expire setting - /// - /// - public Cache(int secondsToExpire) : this() - { - _secondsToExpire = secondsToExpire; - } - - /// - /// Initialize the cache with a expire setting - /// - /// - /// - public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback) - { - _secondsToExpire = secondsToExpire; - } - - /// - /// Enumerable for the values in the cache - /// - public IEnumerable Elements - { - get - { - List elements = new List(); - - lock (_lockObject) - { - foreach (TV element in _internalCache.Values) - { - elements.Add(element); - } - } - - foreach (TV element in elements) - { - yield return element; - } - } - } - - /// - /// Get the value by key from the cache - /// - /// - /// - public TV this[TK key] - { - get - { - TV result = default; - lock (_lockObject) - { - if (_internalCache.ContainsKey(key)) - { - result = _internalCache[key]; - } - } - - return result; - } - } - - /// - /// Contains - /// - /// - /// true if the cache contains the key - public bool Contains(TK key) - { - lock (_lockObject) - { - return _internalCache.ContainsKey(key); - } - } - - /// - /// Add a value to the cache - /// - /// - /// - public void Add(TK key, TV value) - { - Add(key, value, null); - } - - /// - /// Add a value to the cache - /// - /// - /// - /// optional value for the seconds to expire - public void Add(TK key, TV value, int? secondsToExpire) - { - lock (_lockObject) - { - var cachedItem = new CachedItem(key, value, secondsToExpire ?? _secondsToExpire); - cachedItem.Expired += delegate(TK cacheKey, TV cacheValue) - { - if (_internalCache.ContainsKey(cacheKey)) - { - Log.DebugFormat("Expiring object with Key: {0}", cacheKey); - _expiredCallback?.Invoke(cacheKey, cacheValue); - Remove(cacheKey); - } - else - { - Log.DebugFormat("Expired old object with Key: {0}", cacheKey); - } - }; - - if (_internalCache.ContainsKey(key)) - { - _internalCache[key] = value; - Log.DebugFormat("Updated item with Key: {0}", key); - } - else - { - _internalCache.Add(key, cachedItem); - Log.DebugFormat("Added item with Key: {0}", key); - } - } - } - - /// - /// Remove item from cache - /// - /// - public void Remove(TK key) - { - lock (_lockObject) - { - if (!_internalCache.ContainsKey(key)) - { - throw new ApplicationException($"An object with key ‘{key}’ does not exists in cache"); - } - - _internalCache.Remove(key); - Log.DebugFormat("Removed item with Key: {0}", key); - } - } - - /// - /// A cache item - /// - private class CachedItem - { - public event CacheObjectExpired Expired; - private readonly int _secondsToExpire; - private readonly Timer _timerEvent; - - public CachedItem(TK key, TV item, int secondsToExpire) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - Key = key; - Item = item; - _secondsToExpire = secondsToExpire; - if (secondsToExpire <= 0) - { - return; - } - - _timerEvent = new Timer(secondsToExpire * 1000) - { - AutoReset = false - }; - _timerEvent.Elapsed += timerEvent_Elapsed; - _timerEvent.Start(); - } - - private void ExpireNow() - { - _timerEvent.Stop(); - if (_secondsToExpire > 0) - { - Expired?.Invoke(Key, Item); - } - } - - private void timerEvent_Elapsed(object sender, ElapsedEventArgs e) - { - ExpireNow(); - } - - public TK Key { get; private set; } - public TV Item { get; private set; } - - public static implicit operator TV(CachedItem a) - { - return a.Item; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Timers; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// Cache class + /// + /// Type of key + /// Type of value + public class Cache + { + private static readonly ILog Log = LogManager.GetLogger(typeof(Cache)); + private readonly IDictionary _internalCache = new Dictionary(); + private readonly object _lockObject = new object(); + private readonly int _secondsToExpire = 10; + private readonly CacheObjectExpired _expiredCallback; + + public delegate void CacheObjectExpired(TK key, TV cacheValue); + + /// + /// Initialize the cache + /// + public Cache() + { + } + + /// + /// Initialize the cache + /// + /// + public Cache(CacheObjectExpired expiredCallback) : this() + { + _expiredCallback = expiredCallback; + } + + /// + /// Initialize the cache with a expire setting + /// + /// + public Cache(int secondsToExpire) : this() + { + _secondsToExpire = secondsToExpire; + } + + /// + /// Initialize the cache with a expire setting + /// + /// + /// + public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback) + { + _secondsToExpire = secondsToExpire; + } + + /// + /// Enumerable for the values in the cache + /// + public IEnumerable Elements + { + get + { + List elements = new List(); + + lock (_lockObject) + { + foreach (TV element in _internalCache.Values) + { + elements.Add(element); + } + } + + foreach (TV element in elements) + { + yield return element; + } + } + } + + /// + /// Get the value by key from the cache + /// + /// + /// + public TV this[TK key] + { + get + { + TV result = default; + lock (_lockObject) + { + if (_internalCache.ContainsKey(key)) + { + result = _internalCache[key]; + } + } + + return result; + } + } + + /// + /// Contains + /// + /// + /// true if the cache contains the key + public bool Contains(TK key) + { + lock (_lockObject) + { + return _internalCache.ContainsKey(key); + } + } + + /// + /// Add a value to the cache + /// + /// + /// + public void Add(TK key, TV value) + { + Add(key, value, null); + } + + /// + /// Add a value to the cache + /// + /// + /// + /// optional value for the seconds to expire + public void Add(TK key, TV value, int? secondsToExpire) + { + lock (_lockObject) + { + var cachedItem = new CachedItem(key, value, secondsToExpire ?? _secondsToExpire); + cachedItem.Expired += delegate(TK cacheKey, TV cacheValue) + { + if (_internalCache.ContainsKey(cacheKey)) + { + Log.DebugFormat("Expiring object with Key: {0}", cacheKey); + _expiredCallback?.Invoke(cacheKey, cacheValue); + Remove(cacheKey); + } + else + { + Log.DebugFormat("Expired old object with Key: {0}", cacheKey); + } + }; + + if (_internalCache.ContainsKey(key)) + { + _internalCache[key] = value; + Log.DebugFormat("Updated item with Key: {0}", key); + } + else + { + _internalCache.Add(key, cachedItem); + Log.DebugFormat("Added item with Key: {0}", key); + } + } + } + + /// + /// Remove item from cache + /// + /// + public void Remove(TK key) + { + lock (_lockObject) + { + if (!_internalCache.ContainsKey(key)) + { + throw new ApplicationException($"An object with key ‘{key}’ does not exists in cache"); + } + + _internalCache.Remove(key); + Log.DebugFormat("Removed item with Key: {0}", key); + } + } + + /// + /// A cache item + /// + private class CachedItem + { + public event CacheObjectExpired Expired; + private readonly int _secondsToExpire; + private readonly Timer _timerEvent; + + public CachedItem(TK key, TV item, int secondsToExpire) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + Key = key; + Item = item; + _secondsToExpire = secondsToExpire; + if (secondsToExpire <= 0) + { + return; + } + + _timerEvent = new Timer(secondsToExpire * 1000) + { + AutoReset = false + }; + _timerEvent.Elapsed += timerEvent_Elapsed; + _timerEvent.Start(); + } + + private void ExpireNow() + { + _timerEvent.Stop(); + if (_secondsToExpire > 0) + { + Expired?.Invoke(Key, Item); + } + } + + private void timerEvent_Elapsed(object sender, ElapsedEventArgs e) + { + ExpireNow(); + } + + public TK Key { get; private set; } + public TV Item { get; private set; } + + public static implicit operator TV(CachedItem a) + { + return a.Item; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/Capture.cs b/src/Greenshot.Base/Core/Capture.cs similarity index 98% rename from src/GreenshotPlugin/Core/Capture.cs rename to src/Greenshot.Base/Core/Capture.cs index e5e7d7234..b4d172dc2 100644 --- a/src/GreenshotPlugin/Core/Capture.cs +++ b/src/Greenshot.Base/Core/Capture.cs @@ -22,11 +22,11 @@ using System; using System.Drawing; using System.Drawing.Imaging; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; using log4net; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// This class is used to pass an instance of the "Capture" around diff --git a/src/GreenshotPlugin/Core/CaptureDetails.cs b/src/Greenshot.Base/Core/CaptureDetails.cs similarity index 97% rename from src/GreenshotPlugin/Core/CaptureDetails.cs rename to src/Greenshot.Base/Core/CaptureDetails.cs index 96c9abb41..58e3f19be 100644 --- a/src/GreenshotPlugin/Core/CaptureDetails.cs +++ b/src/Greenshot.Base/Core/CaptureDetails.cs @@ -21,10 +21,10 @@ using System; using System.Collections.Generic; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// This Class is used to pass details about the capture around. diff --git a/src/GreenshotPlugin/Core/CaptureHandler.cs b/src/Greenshot.Base/Core/CaptureHandler.cs similarity index 95% rename from src/GreenshotPlugin/Core/CaptureHandler.cs rename to src/Greenshot.Base/Core/CaptureHandler.cs index 952131330..ea11c464d 100644 --- a/src/GreenshotPlugin/Core/CaptureHandler.cs +++ b/src/Greenshot.Base/Core/CaptureHandler.cs @@ -1,43 +1,43 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; - -namespace GreenshotPlugin.Core -{ - /// - /// This is the method signature which is used to capture a rectangle from the screen. - /// - /// - /// Captured Bitmap - public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds); - - /// - /// This is a hack to experiment with different screen capture routines - /// - public static class CaptureHandler - { - /// - /// By changing this value, null is default - /// - public static CaptureScreenRectangleHandler CaptureScreenRectangle { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; + +namespace Greenshot.Base.Core +{ + /// + /// This is the method signature which is used to capture a rectangle from the screen. + /// + /// + /// Captured Bitmap + public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds); + + /// + /// This is a hack to experiment with different screen capture routines + /// + public static class CaptureHandler + { + /// + /// By changing this value, null is default + /// + public static CaptureScreenRectangleHandler CaptureScreenRectangle { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/ClipboardHelper.cs b/src/Greenshot.Base/Core/ClipboardHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/ClipboardHelper.cs rename to src/Greenshot.Base/Core/ClipboardHelper.cs index f3c57b3d0..cb10a7be3 100644 --- a/src/GreenshotPlugin/Core/ClipboardHelper.cs +++ b/src/Greenshot.Base/Core/ClipboardHelper.cs @@ -1,1077 +1,1076 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Windows.Forms; -using GreenshotPlugin.UnmanagedHelpers; -using System.Runtime.InteropServices; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; -using GreenshotPlugin.Interop; -using log4net; -using HtmlDocument = HtmlAgilityPack.HtmlDocument; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of ClipboardHelper. - /// - public static class ClipboardHelper - { - private static readonly ILog Log = LogManager.GetLogger(typeof(ClipboardHelper)); - private static readonly object ClipboardLockObject = new object(); - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private static readonly string FORMAT_FILECONTENTS = "FileContents"; - private static readonly string FORMAT_HTML = "text/html"; - private static readonly string FORMAT_PNG = "PNG"; - private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art"; - private static readonly string FORMAT_17 = "Format17"; - private static readonly string FORMAT_JPG = "JPG"; - private static readonly string FORMAT_JPEG = "JPEG"; - private static readonly string FORMAT_JFIF = "JFIF"; - private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art"; - private static readonly string FORMAT_GIF = "GIF"; - - private static readonly string FORMAT_BITMAP = "System.Drawing.Bitmap"; - //private static readonly string FORMAT_HTML = "HTML Format"; - - // Template for the HTML Text on the clipboard - // see: http://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx - // or: http://msdn.microsoft.com/en-us/library/Aa767917.aspx - private const string HtmlClipboardString = @"Version:0.9 -StartHTML:<<<<<<<1 -EndHTML:<<<<<<<2 -StartFragment:<<<<<<<3 -EndFragment:<<<<<<<4 -StartSelection:<<<<<<<3 -EndSelection:<<<<<<<4 - - - -Greenshot capture - - - - - - -"; - - private const string HtmlClipboardBase64String = @"Version:0.9 -StartHTML:<<<<<<<1 -EndHTML:<<<<<<<2 -StartFragment:<<<<<<<3 -EndFragment:<<<<<<<4 -StartSelection:<<<<<<<3 -EndSelection:<<<<<<<4 - - - -Greenshot capture - - - - - - -"; - - /// - /// Get the current "ClipboardOwner" but only if it isn't us! - /// - /// current clipboard owner - private static string GetClipboardOwner() - { - string owner = null; - try - { - IntPtr hWnd = User32.GetClipboardOwner(); - if (hWnd != IntPtr.Zero) - { - try - { - User32.GetWindowThreadProcessId(hWnd, out var pid); - using Process me = Process.GetCurrentProcess(); - using Process ownerProcess = Process.GetProcessById(pid); - // Exclude myself - if (me.Id != ownerProcess.Id) - { - // Get Process Name - owner = ownerProcess.ProcessName; - // Try to get the starting Process Filename, this might fail. - try - { - owner = ownerProcess.Modules[0].FileName; - } - catch (Exception) - { - // Ignore - } - } - } - catch (Exception e) - { - Log.Warn("Non critical error: Couldn't get clipboard process, trying to use the title.", e); - var title = new StringBuilder(260, 260); - User32.GetWindowText(hWnd, title, title.Capacity); - owner = title.ToString(); - } - } - } - catch (Exception e) - { - Log.Warn("Non critical error: Couldn't get clipboard owner.", e); - } - - return owner; - } - - /// - /// The SetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. - /// The bool "copy" is used to decided if the information stays on the clipboard after exit. - /// - /// - /// - private static void SetDataObject(IDataObject ido, bool copy) - { - lock (ClipboardLockObject) - { - // Clear first, this seems to solve some issues - try - { - Clipboard.Clear(); - } - catch (Exception clearException) - { - Log.Warn(clearException.Message); - } - - try - { - // For BUG-1935 this was changed from looping ourselfs, or letting MS retry... - Clipboard.SetDataObject(ido, copy, 15, 200); - } - catch (Exception clipboardSetException) - { - string messageText; - string clipboardOwner = GetClipboardOwner(); - if (clipboardOwner != null) - { - messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner); - } - else - { - messageText = Language.GetString("clipboard_error"); - } - - Log.Error(messageText, clipboardSetException); - } - } - } - - /// - /// The GetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. - /// - public static IDataObject GetDataObject() - { - lock (ClipboardLockObject) - { - int retryCount = 2; - while (retryCount >= 0) - { - try - { - return Clipboard.GetDataObject(); - } - catch (Exception ee) - { - if (retryCount == 0) - { - string messageText; - string clipboardOwner = GetClipboardOwner(); - if (clipboardOwner != null) - { - messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner); - } - else - { - messageText = Language.GetString("clipboard_error"); - } - - Log.Error(messageText, ee); - } - else - { - Thread.Sleep(100); - } - } - finally - { - --retryCount; - } - } - } - - return null; - } - - /// - /// Test if the IDataObject contains Text - /// - /// - /// - public static bool ContainsText(IDataObject dataObject) - { - if (dataObject != null) - { - if (dataObject.GetDataPresent(DataFormats.Text) || dataObject.GetDataPresent(DataFormats.UnicodeText)) - { - return true; - } - } - - return false; - } - - /// - /// Wrapper for Clipboard.ContainsImage, specialized for Greenshot, Created for Bug #3432313 - /// - /// boolean if there is an image on the clipboard - public static bool ContainsImage() - { - IDataObject clipboardData = GetDataObject(); - return ContainsImage(clipboardData); - } - - /// - /// Check if the IDataObject has an image - /// - /// - /// true if an image is there - public static bool ContainsImage(IDataObject dataObject) - { - if (dataObject == null) return false; - - if (dataObject.GetDataPresent(DataFormats.Bitmap) - || dataObject.GetDataPresent(DataFormats.Dib) - || dataObject.GetDataPresent(DataFormats.Tiff) - || dataObject.GetDataPresent(DataFormats.EnhancedMetafile) - || dataObject.GetDataPresent(FORMAT_PNG) - || dataObject.GetDataPresent(FORMAT_17) - || dataObject.GetDataPresent(FORMAT_JPG) - || dataObject.GetDataPresent(FORMAT_JFIF) - || dataObject.GetDataPresent(FORMAT_JPEG) - || dataObject.GetDataPresent(FORMAT_GIF)) - { - return true; - } - - var imageFiles = GetImageFilenames(dataObject); - if (imageFiles.Any()) - { - return true; - } - - var fileDescriptor = (MemoryStream) dataObject.GetData("FileGroupDescriptorW"); - var files = FileDescriptorReader.Read(fileDescriptor); - var fileIndex = 0; - foreach (var fileContentFile in files) - { - if ((fileContentFile.FileAttributes & FileAttributes.Directory) != 0) - { - //Do something with directories? - //Note that directories do not have FileContents - //And will throw if we try to read them - continue; - } - - var fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex); - try - { - //Do something with the fileContent Stream - if (IsValidStream(fileData)) - { - fileData.Position = 0; - using (ImageHelper.FromStream(fileData)) - { - // If we get here, there is an image - return true; - } - } - } - finally - { - fileData?.Dispose(); - } - - fileIndex++; - } - - if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) - { - try - { - var clipboardContent = dataObject.GetData(FORMAT_FILECONTENTS, true); - var imageStream = clipboardContent as MemoryStream; - if (IsValidStream(imageStream)) - { - using (ImageHelper.FromStream(imageStream)) - { - // If we get here, there is an image - return true; - } - } - } - catch (Exception) - { - // Ignore - } - } - - // Try to get the image from the HTML code - var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); - if (textObject != null) - { - var doc = new HtmlDocument(); - doc.LoadHtml(textObject); - var imgNodes = doc.DocumentNode.SelectNodes("//img"); - if (imgNodes != null) - { - foreach (var imgNode in imgNodes) - { - var srcAttribute = imgNode.Attributes["src"]; - var imageUrl = srcAttribute.Value; - if (!string.IsNullOrEmpty(imageUrl)) - { - return true; - } - } - } - } - - return false; - } - - /// - /// Get the specified IDataObject format as a string - /// - /// IDataObject - /// string - /// Encoding - /// sting - private static string ContentAsString(IDataObject dataObject, string format, Encoding encoding = null) - { - encoding ??= Encoding.Unicode; - var objectAsFormat = dataObject.GetData(format); - return objectAsFormat switch - { - null => null, - string text => text, - MemoryStream ms => encoding.GetString(ms.ToArray()), - _ => null - }; - } - - /// - /// Simple helper to check the stream - /// - /// - /// - private static bool IsValidStream(MemoryStream memoryStream) - { - return memoryStream != null && memoryStream.Length > 0; - } - - /// - /// Wrapper for Clipboard.GetImage, Created for Bug #3432313 - /// - /// Image if there is an image on the clipboard - public static Image GetImage() - { - IDataObject clipboardData = GetDataObject(); - // Return the first image - foreach (Image clipboardImage in GetImages(clipboardData)) - { - return clipboardImage; - } - - return null; - } - - /// - /// Get all images (multiple if filenames are available) from the dataObject - /// Returned images must be disposed by the calling code! - /// - /// - /// IEnumerable of Image - public static IEnumerable GetImages(IDataObject dataObject) - { - // Get single image, this takes the "best" match - Image singleImage = GetImage(dataObject); - if (singleImage != null) - { - Log.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat); - yield return singleImage; - } - else - { - // check if files are supplied - foreach (string imageFile in GetImageFilenames(dataObject)) - { - Image returnImage = null; - try - { - returnImage = ImageHelper.LoadImage(imageFile); - } - catch (Exception streamImageEx) - { - Log.Error("Problem retrieving Image from clipboard.", streamImageEx); - } - - if (returnImage != null) - { - Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat); - yield return returnImage; - } - } - } - } - - /// - /// Get an Image from the IDataObject, don't check for FileDrop - /// - /// - /// Image or null - private static Image GetImage(IDataObject dataObject) - { - Image returnImage = null; - if (dataObject != null) - { - IList formats = GetFormats(dataObject); - string[] retrieveFormats; - - // Found a weird bug, where PNG's from Outlook 2010 are clipped - // So I build some special logik to get the best format: - if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib)) - { - // Outlook ?? - Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front..."); - retrieveFormats = new[] - { - DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, - DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML - }; - } - else - { - retrieveFormats = new[] - { - FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, - FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML - }; - } - - foreach (string currentFormat in retrieveFormats) - { - if (formats != null && formats.Contains(currentFormat)) - { - Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat); - returnImage = GetImageForFormat(currentFormat, dataObject); - } - else - { - Log.DebugFormat("Couldn't find format {0}.", currentFormat); - } - - if (returnImage != null) - { - return returnImage; - } - } - } - - return null; - } - - /// - /// Helper method to try to get an image in the specified format from the dataObject - /// the DIB reader should solve some issues - /// It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591 - /// - /// string with the format - /// IDataObject - /// Image or null - private static Image GetImageForFormat(string format, IDataObject dataObject) - { - if (format == FORMAT_HTML) - { - var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); - if (textObject != null) - { - var doc = new HtmlDocument(); - doc.LoadHtml(textObject); - var imgNodes = doc.DocumentNode.SelectNodes("//img"); - if (imgNodes != null) - { - foreach (var imgNode in imgNodes) - { - var srcAttribute = imgNode.Attributes["src"]; - var imageUrl = srcAttribute.Value; - Log.Debug(imageUrl); - var image = NetworkHelper.DownloadImage(imageUrl); - if (image != null) - { - return image; - } - } - } - } - } - - object clipboardObject = GetFromDataObject(dataObject, format); - var imageStream = clipboardObject as MemoryStream; - if (!IsValidStream(imageStream)) - { - // TODO: add "HTML Format" support here... - return clipboardObject as Image; - } - - if (CoreConfig.EnableSpecialDIBClipboardReader) - { - if (format == FORMAT_17 || format == DataFormats.Dib) - { - Log.Info("Found DIB stream, trying to process it."); - try - { - if (imageStream != null) - { - byte[] dibBuffer = new byte[imageStream.Length]; - imageStream.Read(dibBuffer, 0, dibBuffer.Length); - var infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); - if (!infoHeader.IsDibV5) - { - Log.InfoFormat("Using special DIB - /// Get Text from the DataObject - /// - /// string if there is text on the clipboard - public static string GetText(IDataObject dataObject) - { - if (ContainsText(dataObject)) - { - return (string) dataObject.GetData(DataFormats.Text); - } - - return null; - } - - /// - /// Set text to the clipboard - /// - /// - public static void SetClipboardData(string text) - { - IDataObject ido = new DataObject(); - ido.SetData(DataFormats.Text, true, text); - SetDataObject(ido, true); - } - - private static string GetHtmlString(ISurface surface, string filename) - { - string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardString)); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString()); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString()); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${file}", filename.Replace("\\", "/")); - StringBuilder sb = new StringBuilder(); - sb.Append(utf8EncodedHtmlString); - sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); - sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); - sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); - sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); - return sb.ToString(); - } - - private static string GetHtmlDataUrlString(ISurface surface, MemoryStream pngStream) - { - string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardBase64String)); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString()); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString()); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${format}", "png"); - utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${data}", Convert.ToBase64String(pngStream.GetBuffer(), 0, (int) pngStream.Length)); - StringBuilder sb = new StringBuilder(); - sb.Append(utf8EncodedHtmlString); - sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); - sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); - sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); - sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); - return sb.ToString(); - } - - private const int BITMAPFILEHEADER_LENGTH = 14; - - /// - /// Set an Image to the clipboard - /// This method will place images to the clipboard depending on the ClipboardFormats setting. - /// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice - /// because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661 - /// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003! - /// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left! - /// For this problem the user should not use the direct paste (=Dib), but select Bitmap - /// - public static void SetClipboardData(ISurface surface) - { - DataObject dataObject = new DataObject(); - - // This will work for Office and most other applications - //ido.SetData(DataFormats.Bitmap, true, image); - - MemoryStream dibStream = null; - MemoryStream dibV5Stream = null; - MemoryStream pngStream = null; - Image imageToSave = null; - bool disposeImage = false; - try - { - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); - // Create the image which is going to be saved so we don't create it multiple times - disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave); - try - { - // Create PNG stream - if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.PNG)) - { - pngStream = new MemoryStream(); - // PNG works for e.g. Powerpoint - SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); - ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings); - pngStream.Seek(0, SeekOrigin.Begin); - // Set the PNG stream - dataObject.SetData(FORMAT_PNG, false, pngStream); - } - } - catch (Exception pngEx) - { - Log.Error("Error creating PNG for the Clipboard.", pngEx); - } - - try - { - if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIB)) - { - using (MemoryStream tmpBmpStream = new MemoryStream()) - { - // Save image as BMP - SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false); - ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings); - - dibStream = new MemoryStream(); - // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14 - dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int) tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH); - } - - // Set the DIB to the clipboard DataObject - dataObject.SetData(DataFormats.Dib, true, dibStream); - } - } - catch (Exception dibEx) - { - Log.Error("Error creating DIB for the Clipboard.", dibEx); - } - - // CF_DibV5 - try - { - if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIBV5)) - { - // Create the stream for the clipboard - dibV5Stream = new MemoryStream(); - - // Create the BITMAPINFOHEADER - BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32) - { - // Make sure we have BI_BITFIELDS, this seems to be normal for Format17? - biCompression = BI_COMPRESSION.BI_BITFIELDS - }; - // Create a byte[] to write - byte[] headerBytes = BinaryStructHelper.ToByteArray(header); - // Write the BITMAPINFOHEADER to the stream - dibV5Stream.Write(headerBytes, 0, headerBytes.Length); - - // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added - BitfieldColorMask colorMask = new BitfieldColorMask(); - // Make sure the values are set - colorMask.InitValues(); - // Create the byte[] from the struct - byte[] colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask); - Array.Reverse(colorMaskBytes); - // Write to the stream - dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length); - - // Create the raw bytes for the pixels only - byte[] bitmapBytes = BitmapToByteArray((Bitmap) imageToSave); - // Write to the stream - dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length); - - // Set the DIBv5 to the clipboard DataObject - dataObject.SetData(FORMAT_17, true, dibV5Stream); - } - } - catch (Exception dibEx) - { - Log.Error("Error creating DIB for the Clipboard.", dibEx); - } - - // Set the HTML - if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTML)) - { - string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null); - string html = GetHtmlString(surface, tmpFile); - dataObject.SetText(html, TextDataFormat.Html); - } - else if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL)) - { - string html; - using (MemoryStream tmpPngStream = new MemoryStream()) - { - SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false) - { - // Do not allow to reduce the colors, some applications dislike 256 color images - // reported with bug #3594681 - DisableReduceColors = true - }; - // Check if we can use the previously used image - if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed) - { - ImageOutput.SaveToStream(imageToSave, surface, tmpPngStream, pngOutputSettings); - } - else - { - ImageOutput.SaveToStream(surface, tmpPngStream, pngOutputSettings); - } - - html = GetHtmlDataUrlString(surface, tmpPngStream); - } - - dataObject.SetText(html, TextDataFormat.Html); - } - } - finally - { - // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone! - // Check if Bitmap is wanted - if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.BITMAP)) - { - dataObject.SetImage(imageToSave); - // Place the DataObject to the clipboard - SetDataObject(dataObject, true); - } - else - { - // Place the DataObject to the clipboard - SetDataObject(dataObject, true); - } - - pngStream?.Dispose(); - dibStream?.Dispose(); - dibV5Stream?.Dispose(); - // cleanup if needed - if (disposeImage) - { - imageToSave?.Dispose(); - } - } - } - - /// - /// Helper method so get the bitmap bytes - /// See: http://stackoverflow.com/a/6570155 - /// - /// Bitmap - /// byte[] - private static byte[] BitmapToByteArray(Bitmap bitmap) - { - // Lock the bitmap's bits. - Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); - BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat); - - int absStride = Math.Abs(bmpData.Stride); - int bytes = absStride * bitmap.Height; - long ptr = bmpData.Scan0.ToInt32(); - // Declare an array to hold the bytes of the bitmap. - byte[] rgbValues = new byte[bytes]; - - for (int i = 0; i < bitmap.Height; i++) - { - IntPtr pointer = new IntPtr(ptr + (bmpData.Stride * i)); - Marshal.Copy(pointer, rgbValues, absStride * (bitmap.Height - i - 1), absStride); - } - - // Unlock the bits. - bitmap.UnlockBits(bmpData); - - return rgbValues; - } - - /// - /// Set Object with type Type to the clipboard - /// - /// Type - /// object - public static void SetClipboardData(Type type, object obj) - { - DataFormats.Format format = DataFormats.GetFormat(type.FullName); - - //now copy to clipboard - IDataObject dataObj = new DataObject(); - dataObj.SetData(format.Name, false, obj); - // Use false to make the object disappear when the application stops. - SetDataObject(dataObj, true); - } - - /// - /// Retrieve a list of all formats currently in the IDataObject - /// - /// List of string with the current formats - public static List GetFormats(IDataObject dataObj) - { - string[] formats = null; - - if (dataObj != null) - { - formats = dataObj.GetFormats(); - } - - if (formats != null) - { - Log.DebugFormat("Got clipboard formats: {0}", string.Join(",", formats)); - return new List(formats); - } - - return new List(); - } - - /// - /// Check if there is currently something on the clipboard which has the supplied format - /// - /// IDataObject - /// string with format - /// true if one the format is found - public static bool ContainsFormat(IDataObject dataObject, string format) - { - return ContainsFormat(dataObject, new[] - { - format - }); - } - - /// - /// Check if there is currently something on the clipboard which has one of the supplied formats - /// - /// string[] with formats - /// true if one of the formats was found - public static bool ContainsFormat(string[] formats) - { - return ContainsFormat(GetDataObject(), formats); - } - - /// - /// Check if there is currently something on the clipboard which has one of the supplied formats - /// - /// IDataObject - /// string[] with formats - /// true if one of the formats was found - public static bool ContainsFormat(IDataObject dataObject, string[] formats) - { - bool formatFound = false; - List currentFormats = GetFormats(dataObject); - if (currentFormats == null || currentFormats.Count == 0 || formats == null || formats.Length == 0) - { - return false; - } - - foreach (string format in formats) - { - if (currentFormats.Contains(format)) - { - formatFound = true; - break; - } - } - - return formatFound; - } - - /// - /// Get Object for format from IDataObject - /// - /// IDataObject - /// Type to get - /// object from IDataObject - public static object GetFromDataObject(IDataObject dataObj, Type type) - { - if (type != null) - { - return GetFromDataObject(dataObj, type.FullName); - } - - return null; - } - - /// - /// Get ImageFilenames from the IDataObject - /// - /// IDataObject - /// - public static IEnumerable GetImageFilenames(IDataObject dataObject) - { - string[] dropFileNames = (string[]) dataObject.GetData(DataFormats.FileDrop); - if (dropFileNames != null && dropFileNames.Length > 0) - { - return dropFileNames - .Where(filename => !string.IsNullOrEmpty(filename)) - .Where(Path.HasExtension) - .Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1))); - } - - return Enumerable.Empty(); - } - - /// - /// Get Object for format from IDataObject - /// - /// IDataObject - /// format to get - /// object from IDataObject - public static object GetFromDataObject(IDataObject dataObj, string format) - { - if (dataObj != null) - { - try - { - return dataObj.GetData(format); - } - catch (Exception e) - { - Log.Error("Error in GetClipboardData.", e); - } - } - - return null; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; +using Greenshot.Base.UnmanagedHelpers; +using log4net; +using HtmlDocument = HtmlAgilityPack.HtmlDocument; + +namespace Greenshot.Base.Core +{ + /// + /// Description of ClipboardHelper. + /// + public static class ClipboardHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(ClipboardHelper)); + private static readonly object ClipboardLockObject = new object(); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private static readonly string FORMAT_FILECONTENTS = "FileContents"; + private static readonly string FORMAT_HTML = "text/html"; + private static readonly string FORMAT_PNG = "PNG"; + private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art"; + private static readonly string FORMAT_17 = "Format17"; + private static readonly string FORMAT_JPG = "JPG"; + private static readonly string FORMAT_JPEG = "JPEG"; + private static readonly string FORMAT_JFIF = "JFIF"; + private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art"; + private static readonly string FORMAT_GIF = "GIF"; + + private static readonly string FORMAT_BITMAP = "System.Drawing.Bitmap"; + //private static readonly string FORMAT_HTML = "HTML Format"; + + // Template for the HTML Text on the clipboard + // see: http://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx + // or: http://msdn.microsoft.com/en-us/library/Aa767917.aspx + private const string HtmlClipboardString = @"Version:0.9 +StartHTML:<<<<<<<1 +EndHTML:<<<<<<<2 +StartFragment:<<<<<<<3 +EndFragment:<<<<<<<4 +StartSelection:<<<<<<<3 +EndSelection:<<<<<<<4 + + + +Greenshot capture + + + + + + +"; + + private const string HtmlClipboardBase64String = @"Version:0.9 +StartHTML:<<<<<<<1 +EndHTML:<<<<<<<2 +StartFragment:<<<<<<<3 +EndFragment:<<<<<<<4 +StartSelection:<<<<<<<3 +EndSelection:<<<<<<<4 + + + +Greenshot capture + + + + + + +"; + + /// + /// Get the current "ClipboardOwner" but only if it isn't us! + /// + /// current clipboard owner + private static string GetClipboardOwner() + { + string owner = null; + try + { + IntPtr hWnd = User32.GetClipboardOwner(); + if (hWnd != IntPtr.Zero) + { + try + { + User32.GetWindowThreadProcessId(hWnd, out var pid); + using Process me = Process.GetCurrentProcess(); + using Process ownerProcess = Process.GetProcessById(pid); + // Exclude myself + if (me.Id != ownerProcess.Id) + { + // Get Process Name + owner = ownerProcess.ProcessName; + // Try to get the starting Process Filename, this might fail. + try + { + owner = ownerProcess.Modules[0].FileName; + } + catch (Exception) + { + // Ignore + } + } + } + catch (Exception e) + { + Log.Warn("Non critical error: Couldn't get clipboard process, trying to use the title.", e); + var title = new StringBuilder(260, 260); + User32.GetWindowText(hWnd, title, title.Capacity); + owner = title.ToString(); + } + } + } + catch (Exception e) + { + Log.Warn("Non critical error: Couldn't get clipboard owner.", e); + } + + return owner; + } + + /// + /// The SetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. + /// The bool "copy" is used to decided if the information stays on the clipboard after exit. + /// + /// + /// + private static void SetDataObject(IDataObject ido, bool copy) + { + lock (ClipboardLockObject) + { + // Clear first, this seems to solve some issues + try + { + Clipboard.Clear(); + } + catch (Exception clearException) + { + Log.Warn(clearException.Message); + } + + try + { + // For BUG-1935 this was changed from looping ourselfs, or letting MS retry... + Clipboard.SetDataObject(ido, copy, 15, 200); + } + catch (Exception clipboardSetException) + { + string messageText; + string clipboardOwner = GetClipboardOwner(); + if (clipboardOwner != null) + { + messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner); + } + else + { + messageText = Language.GetString("clipboard_error"); + } + + Log.Error(messageText, clipboardSetException); + } + } + } + + /// + /// The GetDataObject will lock/try/catch clipboard operations making it save and not show exceptions. + /// + public static IDataObject GetDataObject() + { + lock (ClipboardLockObject) + { + int retryCount = 2; + while (retryCount >= 0) + { + try + { + return Clipboard.GetDataObject(); + } + catch (Exception ee) + { + if (retryCount == 0) + { + string messageText; + string clipboardOwner = GetClipboardOwner(); + if (clipboardOwner != null) + { + messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner); + } + else + { + messageText = Language.GetString("clipboard_error"); + } + + Log.Error(messageText, ee); + } + else + { + Thread.Sleep(100); + } + } + finally + { + --retryCount; + } + } + } + + return null; + } + + /// + /// Test if the IDataObject contains Text + /// + /// + /// + public static bool ContainsText(IDataObject dataObject) + { + if (dataObject != null) + { + if (dataObject.GetDataPresent(DataFormats.Text) || dataObject.GetDataPresent(DataFormats.UnicodeText)) + { + return true; + } + } + + return false; + } + + /// + /// Wrapper for Clipboard.ContainsImage, specialized for Greenshot, Created for Bug #3432313 + /// + /// boolean if there is an image on the clipboard + public static bool ContainsImage() + { + IDataObject clipboardData = GetDataObject(); + return ContainsImage(clipboardData); + } + + /// + /// Check if the IDataObject has an image + /// + /// + /// true if an image is there + public static bool ContainsImage(IDataObject dataObject) + { + if (dataObject == null) return false; + + if (dataObject.GetDataPresent(DataFormats.Bitmap) + || dataObject.GetDataPresent(DataFormats.Dib) + || dataObject.GetDataPresent(DataFormats.Tiff) + || dataObject.GetDataPresent(DataFormats.EnhancedMetafile) + || dataObject.GetDataPresent(FORMAT_PNG) + || dataObject.GetDataPresent(FORMAT_17) + || dataObject.GetDataPresent(FORMAT_JPG) + || dataObject.GetDataPresent(FORMAT_JFIF) + || dataObject.GetDataPresent(FORMAT_JPEG) + || dataObject.GetDataPresent(FORMAT_GIF)) + { + return true; + } + + var imageFiles = GetImageFilenames(dataObject); + if (imageFiles.Any()) + { + return true; + } + + var fileDescriptor = (MemoryStream) dataObject.GetData("FileGroupDescriptorW"); + var files = FileDescriptorReader.Read(fileDescriptor); + var fileIndex = 0; + foreach (var fileContentFile in files) + { + if ((fileContentFile.FileAttributes & FileAttributes.Directory) != 0) + { + //Do something with directories? + //Note that directories do not have FileContents + //And will throw if we try to read them + continue; + } + + var fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex); + try + { + //Do something with the fileContent Stream + if (IsValidStream(fileData)) + { + fileData.Position = 0; + using (ImageHelper.FromStream(fileData)) + { + // If we get here, there is an image + return true; + } + } + } + finally + { + fileData?.Dispose(); + } + + fileIndex++; + } + + if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) + { + try + { + var clipboardContent = dataObject.GetData(FORMAT_FILECONTENTS, true); + var imageStream = clipboardContent as MemoryStream; + if (IsValidStream(imageStream)) + { + using (ImageHelper.FromStream(imageStream)) + { + // If we get here, there is an image + return true; + } + } + } + catch (Exception) + { + // Ignore + } + } + + // Try to get the image from the HTML code + var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); + if (textObject != null) + { + var doc = new HtmlDocument(); + doc.LoadHtml(textObject); + var imgNodes = doc.DocumentNode.SelectNodes("//img"); + if (imgNodes != null) + { + foreach (var imgNode in imgNodes) + { + var srcAttribute = imgNode.Attributes["src"]; + var imageUrl = srcAttribute.Value; + if (!string.IsNullOrEmpty(imageUrl)) + { + return true; + } + } + } + } + + return false; + } + + /// + /// Get the specified IDataObject format as a string + /// + /// IDataObject + /// string + /// Encoding + /// sting + private static string ContentAsString(IDataObject dataObject, string format, Encoding encoding = null) + { + encoding ??= Encoding.Unicode; + var objectAsFormat = dataObject.GetData(format); + return objectAsFormat switch + { + null => null, + string text => text, + MemoryStream ms => encoding.GetString(ms.ToArray()), + _ => null + }; + } + + /// + /// Simple helper to check the stream + /// + /// + /// + private static bool IsValidStream(MemoryStream memoryStream) + { + return memoryStream != null && memoryStream.Length > 0; + } + + /// + /// Wrapper for Clipboard.GetImage, Created for Bug #3432313 + /// + /// Image if there is an image on the clipboard + public static Image GetImage() + { + IDataObject clipboardData = GetDataObject(); + // Return the first image + foreach (Image clipboardImage in GetImages(clipboardData)) + { + return clipboardImage; + } + + return null; + } + + /// + /// Get all images (multiple if filenames are available) from the dataObject + /// Returned images must be disposed by the calling code! + /// + /// + /// IEnumerable of Image + public static IEnumerable GetImages(IDataObject dataObject) + { + // Get single image, this takes the "best" match + Image singleImage = GetImage(dataObject); + if (singleImage != null) + { + Log.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat); + yield return singleImage; + } + else + { + // check if files are supplied + foreach (string imageFile in GetImageFilenames(dataObject)) + { + Image returnImage = null; + try + { + returnImage = ImageHelper.LoadImage(imageFile); + } + catch (Exception streamImageEx) + { + Log.Error("Problem retrieving Image from clipboard.", streamImageEx); + } + + if (returnImage != null) + { + Log.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat); + yield return returnImage; + } + } + } + } + + /// + /// Get an Image from the IDataObject, don't check for FileDrop + /// + /// + /// Image or null + private static Image GetImage(IDataObject dataObject) + { + Image returnImage = null; + if (dataObject != null) + { + IList formats = GetFormats(dataObject); + string[] retrieveFormats; + + // Found a weird bug, where PNG's from Outlook 2010 are clipped + // So I build some special logik to get the best format: + if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib)) + { + // Outlook ?? + Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front..."); + retrieveFormats = new[] + { + DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, + DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML + }; + } + else + { + retrieveFormats = new[] + { + FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, + FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML + }; + } + + foreach (string currentFormat in retrieveFormats) + { + if (formats != null && formats.Contains(currentFormat)) + { + Log.InfoFormat("Found {0}, trying to retrieve.", currentFormat); + returnImage = GetImageForFormat(currentFormat, dataObject); + } + else + { + Log.DebugFormat("Couldn't find format {0}.", currentFormat); + } + + if (returnImage != null) + { + return returnImage; + } + } + } + + return null; + } + + /// + /// Helper method to try to get an image in the specified format from the dataObject + /// the DIB reader should solve some issues + /// It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591 + /// + /// string with the format + /// IDataObject + /// Image or null + private static Image GetImageForFormat(string format, IDataObject dataObject) + { + if (format == FORMAT_HTML) + { + var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); + if (textObject != null) + { + var doc = new HtmlDocument(); + doc.LoadHtml(textObject); + var imgNodes = doc.DocumentNode.SelectNodes("//img"); + if (imgNodes != null) + { + foreach (var imgNode in imgNodes) + { + var srcAttribute = imgNode.Attributes["src"]; + var imageUrl = srcAttribute.Value; + Log.Debug(imageUrl); + var image = NetworkHelper.DownloadImage(imageUrl); + if (image != null) + { + return image; + } + } + } + } + } + + object clipboardObject = GetFromDataObject(dataObject, format); + var imageStream = clipboardObject as MemoryStream; + if (!IsValidStream(imageStream)) + { + // TODO: add "HTML Format" support here... + return clipboardObject as Image; + } + + if (CoreConfig.EnableSpecialDIBClipboardReader) + { + if (format == FORMAT_17 || format == DataFormats.Dib) + { + Log.Info("Found DIB stream, trying to process it."); + try + { + if (imageStream != null) + { + byte[] dibBuffer = new byte[imageStream.Length]; + imageStream.Read(dibBuffer, 0, dibBuffer.Length); + var infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); + if (!infoHeader.IsDibV5) + { + Log.InfoFormat("Using special DIB + /// Get Text from the DataObject + /// + /// string if there is text on the clipboard + public static string GetText(IDataObject dataObject) + { + if (ContainsText(dataObject)) + { + return (string) dataObject.GetData(DataFormats.Text); + } + + return null; + } + + /// + /// Set text to the clipboard + /// + /// + public static void SetClipboardData(string text) + { + IDataObject ido = new DataObject(); + ido.SetData(DataFormats.Text, true, text); + SetDataObject(ido, true); + } + + private static string GetHtmlString(ISurface surface, string filename) + { + string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardString)); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString()); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString()); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${file}", filename.Replace("\\", "/")); + StringBuilder sb = new StringBuilder(); + sb.Append(utf8EncodedHtmlString); + sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); + sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); + sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); + sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); + return sb.ToString(); + } + + private static string GetHtmlDataUrlString(ISurface surface, MemoryStream pngStream) + { + string utf8EncodedHtmlString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HtmlClipboardBase64String)); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${width}", surface.Image.Width.ToString()); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${height}", surface.Image.Height.ToString()); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${format}", "png"); + utf8EncodedHtmlString = utf8EncodedHtmlString.Replace("${data}", Convert.ToBase64String(pngStream.GetBuffer(), 0, (int) pngStream.Length)); + StringBuilder sb = new StringBuilder(); + sb.Append(utf8EncodedHtmlString); + sb.Replace("<<<<<<<1", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); + sb.Replace("<<<<<<<2", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); + sb.Replace("<<<<<<<3", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal) + "".Length).ToString("D8")); + sb.Replace("<<<<<<<4", (utf8EncodedHtmlString.IndexOf("", StringComparison.Ordinal)).ToString("D8")); + return sb.ToString(); + } + + private const int BITMAPFILEHEADER_LENGTH = 14; + + /// + /// Set an Image to the clipboard + /// This method will place images to the clipboard depending on the ClipboardFormats setting. + /// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice + /// because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661 + /// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003! + /// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left! + /// For this problem the user should not use the direct paste (=Dib), but select Bitmap + /// + public static void SetClipboardData(ISurface surface) + { + DataObject dataObject = new DataObject(); + + // This will work for Office and most other applications + //ido.SetData(DataFormats.Bitmap, true, image); + + MemoryStream dibStream = null; + MemoryStream dibV5Stream = null; + MemoryStream pngStream = null; + Image imageToSave = null; + bool disposeImage = false; + try + { + SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); + // Create the image which is going to be saved so we don't create it multiple times + disposeImage = ImageOutput.CreateImageFromSurface(surface, outputSettings, out imageToSave); + try + { + // Create PNG stream + if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.PNG)) + { + pngStream = new MemoryStream(); + // PNG works for e.g. Powerpoint + SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false); + ImageOutput.SaveToStream(imageToSave, null, pngStream, pngOutputSettings); + pngStream.Seek(0, SeekOrigin.Begin); + // Set the PNG stream + dataObject.SetData(FORMAT_PNG, false, pngStream); + } + } + catch (Exception pngEx) + { + Log.Error("Error creating PNG for the Clipboard.", pngEx); + } + + try + { + if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIB)) + { + using (MemoryStream tmpBmpStream = new MemoryStream()) + { + // Save image as BMP + SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false); + ImageOutput.SaveToStream(imageToSave, null, tmpBmpStream, bmpOutputSettings); + + dibStream = new MemoryStream(); + // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14 + dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int) tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH); + } + + // Set the DIB to the clipboard DataObject + dataObject.SetData(DataFormats.Dib, true, dibStream); + } + } + catch (Exception dibEx) + { + Log.Error("Error creating DIB for the Clipboard.", dibEx); + } + + // CF_DibV5 + try + { + if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.DIBV5)) + { + // Create the stream for the clipboard + dibV5Stream = new MemoryStream(); + + // Create the BITMAPINFOHEADER + BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32) + { + // Make sure we have BI_BITFIELDS, this seems to be normal for Format17? + biCompression = BI_COMPRESSION.BI_BITFIELDS + }; + // Create a byte[] to write + byte[] headerBytes = BinaryStructHelper.ToByteArray(header); + // Write the BITMAPINFOHEADER to the stream + dibV5Stream.Write(headerBytes, 0, headerBytes.Length); + + // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added + BitfieldColorMask colorMask = new BitfieldColorMask(); + // Make sure the values are set + colorMask.InitValues(); + // Create the byte[] from the struct + byte[] colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask); + Array.Reverse(colorMaskBytes); + // Write to the stream + dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length); + + // Create the raw bytes for the pixels only + byte[] bitmapBytes = BitmapToByteArray((Bitmap) imageToSave); + // Write to the stream + dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length); + + // Set the DIBv5 to the clipboard DataObject + dataObject.SetData(FORMAT_17, true, dibV5Stream); + } + } + catch (Exception dibEx) + { + Log.Error("Error creating DIB for the Clipboard.", dibEx); + } + + // Set the HTML + if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTML)) + { + string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null); + string html = GetHtmlString(surface, tmpFile); + dataObject.SetText(html, TextDataFormat.Html); + } + else if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL)) + { + string html; + using (MemoryStream tmpPngStream = new MemoryStream()) + { + SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false) + { + // Do not allow to reduce the colors, some applications dislike 256 color images + // reported with bug #3594681 + DisableReduceColors = true + }; + // Check if we can use the previously used image + if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed) + { + ImageOutput.SaveToStream(imageToSave, surface, tmpPngStream, pngOutputSettings); + } + else + { + ImageOutput.SaveToStream(surface, tmpPngStream, pngOutputSettings); + } + + html = GetHtmlDataUrlString(surface, tmpPngStream); + } + + dataObject.SetText(html, TextDataFormat.Html); + } + } + finally + { + // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone! + // Check if Bitmap is wanted + if (CoreConfig.ClipboardFormats.Contains(ClipboardFormat.BITMAP)) + { + dataObject.SetImage(imageToSave); + // Place the DataObject to the clipboard + SetDataObject(dataObject, true); + } + else + { + // Place the DataObject to the clipboard + SetDataObject(dataObject, true); + } + + pngStream?.Dispose(); + dibStream?.Dispose(); + dibV5Stream?.Dispose(); + // cleanup if needed + if (disposeImage) + { + imageToSave?.Dispose(); + } + } + } + + /// + /// Helper method so get the bitmap bytes + /// See: http://stackoverflow.com/a/6570155 + /// + /// Bitmap + /// byte[] + private static byte[] BitmapToByteArray(Bitmap bitmap) + { + // Lock the bitmap's bits. + Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); + BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat); + + int absStride = Math.Abs(bmpData.Stride); + int bytes = absStride * bitmap.Height; + long ptr = bmpData.Scan0.ToInt32(); + // Declare an array to hold the bytes of the bitmap. + byte[] rgbValues = new byte[bytes]; + + for (int i = 0; i < bitmap.Height; i++) + { + IntPtr pointer = new IntPtr(ptr + (bmpData.Stride * i)); + Marshal.Copy(pointer, rgbValues, absStride * (bitmap.Height - i - 1), absStride); + } + + // Unlock the bits. + bitmap.UnlockBits(bmpData); + + return rgbValues; + } + + /// + /// Set Object with type Type to the clipboard + /// + /// Type + /// object + public static void SetClipboardData(Type type, object obj) + { + DataFormats.Format format = DataFormats.GetFormat(type.FullName); + + //now copy to clipboard + IDataObject dataObj = new DataObject(); + dataObj.SetData(format.Name, false, obj); + // Use false to make the object disappear when the application stops. + SetDataObject(dataObj, true); + } + + /// + /// Retrieve a list of all formats currently in the IDataObject + /// + /// List of string with the current formats + public static List GetFormats(IDataObject dataObj) + { + string[] formats = null; + + if (dataObj != null) + { + formats = dataObj.GetFormats(); + } + + if (formats != null) + { + Log.DebugFormat("Got clipboard formats: {0}", string.Join(",", formats)); + return new List(formats); + } + + return new List(); + } + + /// + /// Check if there is currently something on the clipboard which has the supplied format + /// + /// IDataObject + /// string with format + /// true if one the format is found + public static bool ContainsFormat(IDataObject dataObject, string format) + { + return ContainsFormat(dataObject, new[] + { + format + }); + } + + /// + /// Check if there is currently something on the clipboard which has one of the supplied formats + /// + /// string[] with formats + /// true if one of the formats was found + public static bool ContainsFormat(string[] formats) + { + return ContainsFormat(GetDataObject(), formats); + } + + /// + /// Check if there is currently something on the clipboard which has one of the supplied formats + /// + /// IDataObject + /// string[] with formats + /// true if one of the formats was found + public static bool ContainsFormat(IDataObject dataObject, string[] formats) + { + bool formatFound = false; + List currentFormats = GetFormats(dataObject); + if (currentFormats == null || currentFormats.Count == 0 || formats == null || formats.Length == 0) + { + return false; + } + + foreach (string format in formats) + { + if (currentFormats.Contains(format)) + { + formatFound = true; + break; + } + } + + return formatFound; + } + + /// + /// Get Object for format from IDataObject + /// + /// IDataObject + /// Type to get + /// object from IDataObject + public static object GetFromDataObject(IDataObject dataObj, Type type) + { + if (type != null) + { + return GetFromDataObject(dataObj, type.FullName); + } + + return null; + } + + /// + /// Get ImageFilenames from the IDataObject + /// + /// IDataObject + /// + public static IEnumerable GetImageFilenames(IDataObject dataObject) + { + string[] dropFileNames = (string[]) dataObject.GetData(DataFormats.FileDrop); + if (dropFileNames != null && dropFileNames.Length > 0) + { + return dropFileNames + .Where(filename => !string.IsNullOrEmpty(filename)) + .Where(Path.HasExtension) + .Where(filename => ImageHelper.StreamConverters.Keys.Contains(Path.GetExtension(filename).ToLowerInvariant().Substring(1))); + } + + return Enumerable.Empty(); + } + + /// + /// Get Object for format from IDataObject + /// + /// IDataObject + /// format to get + /// object from IDataObject + public static object GetFromDataObject(IDataObject dataObj, string format) + { + if (dataObj != null) + { + try + { + return dataObj.GetData(format); + } + catch (Exception e) + { + Log.Error("Error in GetClipboardData.", e); + } + } + + return null; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/CoreConfiguration.cs b/src/Greenshot.Base/Core/CoreConfiguration.cs similarity index 97% rename from src/GreenshotPlugin/Core/CoreConfiguration.cs rename to src/Greenshot.Base/Core/CoreConfiguration.cs index d099770a7..638613011 100644 --- a/src/GreenshotPlugin/Core/CoreConfiguration.cs +++ b/src/Greenshot.Base/Core/CoreConfiguration.cs @@ -1,737 +1,737 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Reflection; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPlugin.Core -{ - public enum ClipboardFormat - { - PNG, - DIB, - HTML, - HTMLDATAURL, - BITMAP, - DIBV5 - } - - public enum OutputFormat - { - bmp, - gif, - jpg, - png, - tiff, - greenshot, - ico - } - - public enum WindowCaptureMode - { - Screen, - GDI, - Aero, - AeroTransparent, - Auto - } - - public enum BuildStates - { - UNSTABLE, - RELEASE_CANDIDATE, - RELEASE - } - - public enum ClickActions - { - DO_NOTHING, - OPEN_LAST_IN_EXPLORER, - OPEN_LAST_IN_EDITOR, - OPEN_SETTINGS, - SHOW_CONTEXT_MENU - } - - /// - /// Description of CoreConfiguration. - /// - [IniSection("Core", Description = "Greenshot core configuration")] - public class CoreConfiguration : IniSection, INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - [IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")] - public string Language { get; set; } - - [IniProperty("RegionHotkey", Description = "Hotkey for starting the region capture", DefaultValue = "PrintScreen")] - public string RegionHotkey { get; set; } - - [IniProperty("WindowHotkey", Description = "Hotkey for starting the window capture", DefaultValue = "Alt + PrintScreen")] - public string WindowHotkey { get; set; } - - [IniProperty("FullscreenHotkey", Description = "Hotkey for starting the fullscreen capture", DefaultValue = "Ctrl + PrintScreen")] - public string FullscreenHotkey { get; set; } - - [IniProperty("LastregionHotkey", Description = "Hotkey for starting the last region capture", DefaultValue = "Shift + PrintScreen")] - public string LastregionHotkey { get; set; } - - [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")] - public string ClipboardHotkey { get; set; } - - [IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")] - public bool IsFirstLaunch { get; set; } - - [IniProperty("Destinations", Separator = ",", - Description = "Which destinations? Possible options (more might be added by plugins) are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail, Picker", - DefaultValue = "Picker")] - public List OutputDestinations { get; set; } = new List(); - - [IniProperty("ClipboardFormats", Separator = ",", Description = "Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", - DefaultValue = "PNG,DIB")] - public List ClipboardFormats { get; set; } = new List(); - - [IniProperty("CaptureMousepointer", Description = "Should the mouse be captured?", DefaultValue = "true")] - public bool CaptureMousepointer { get; set; } - - [IniProperty("CaptureWindowsInteractive", Description = "Use interactive window selection to capture? (false=Capture active window)", DefaultValue = "false")] - public bool CaptureWindowsInteractive { get; set; } - - [IniProperty("CaptureDelay", Description = "Capture delay in millseconds.", DefaultValue = "100")] - public int CaptureDelay { get; set; } - - [IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")] - public ScreenCaptureMode ScreenCaptureMode { get; set; } - - [IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")] - public int ScreenToCapture { get; set; } - - [IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")] - public WindowCaptureMode WindowCaptureMode { get; set; } - - [IniProperty("WindowCaptureAllChildLocations", - Description = "Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue = "False")] - public bool WindowCaptureAllChildLocations { get; set; } - - [IniProperty("DWMBackgroundColor", Description = "The background color for a DWM window capture.")] - public Color DWMBackgroundColor { get; set; } - - [IniProperty("PlayCameraSound", LanguageKey = "settings_playsound", Description = "Play a camera sound after taking a capture.", DefaultValue = "false")] - public bool PlayCameraSound { get; set; } = false; - - [IniProperty("ShowTrayNotification", LanguageKey = "settings_shownotify", Description = "Show a notification from the systray when a capture is taken.", - DefaultValue = "true")] - public bool ShowTrayNotification { get; set; } = true; - - [IniProperty("OutputFilePath", Description = "Output file path.")] - public string OutputFilePath { get; set; } - - [IniProperty("OutputFileAllowOverwrite", - Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")] - public bool OutputFileAllowOverwrite { get; set; } - - [IniProperty("OutputFileFilenamePattern", Description = "Filename pattern for screenshot.", DefaultValue = "${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")] - public string OutputFileFilenamePattern { get; set; } - - [IniProperty("OutputFileFormat", Description = "Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue = "png")] - public OutputFormat OutputFileFormat { get; set; } = OutputFormat.png; - - [IniProperty("OutputFileReduceColors", Description = "If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue = "false")] - public bool OutputFileReduceColors { get; set; } - - [IniProperty("OutputFileAutoReduceColors", - Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "false")] - public bool OutputFileAutoReduceColors { get; set; } - - [IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")] - public int OutputFileReduceColorsTo { get; set; } - - [IniProperty("OutputFileCopyPathToClipboard", Description = "When saving a screenshot, copy the path to the clipboard?", DefaultValue = "true")] - public bool OutputFileCopyPathToClipboard { get; set; } - - [IniProperty("OutputFileAsFullpath", Description = "SaveAs Full path?")] - public string OutputFileAsFullpath { get; set; } - - [IniProperty("OutputFileJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")] - public int OutputFileJpegQuality { get; set; } - - [IniProperty("OutputFilePromptQuality", Description = "Ask for the quality before saving?", DefaultValue = "false")] - public bool OutputFilePromptQuality { get; set; } - - [IniProperty("OutputFileIncrementingNumber", Description = "The number for the ${NUM} in the filename pattern, is increased automatically after each save.", - DefaultValue = "1")] - public uint OutputFileIncrementingNumber { get; set; } - - [IniProperty("OutputPrintPromptOptions", LanguageKey = "settings_alwaysshowprintoptionsdialog", Description = "Ask for print options when printing?", - DefaultValue = "true")] - public bool OutputPrintPromptOptions { get; set; } - - [IniProperty("OutputPrintAllowRotate", LanguageKey = "printoptions_allowrotate", Description = "Allow rotating the picture for fitting on paper?", DefaultValue = "false")] - public bool OutputPrintAllowRotate { get; set; } - - [IniProperty("OutputPrintAllowEnlarge", LanguageKey = "printoptions_allowenlarge", Description = "Allow growing the picture for fitting on paper?", DefaultValue = "false")] - public bool OutputPrintAllowEnlarge { get; set; } - - [IniProperty("OutputPrintAllowShrink", LanguageKey = "printoptions_allowshrink", Description = "Allow shrinking the picture for fitting on paper?", DefaultValue = "true")] - public bool OutputPrintAllowShrink { get; set; } - - [IniProperty("OutputPrintCenter", LanguageKey = "printoptions_allowcenter", Description = "Center image when printing?", DefaultValue = "true")] - public bool OutputPrintCenter { get; set; } - - [IniProperty("OutputPrintInverted", LanguageKey = "printoptions_inverted", Description = "Print image inverted (use e.g. for console captures)", DefaultValue = "false")] - public bool OutputPrintInverted { get; set; } - - [IniProperty("OutputPrintGrayscale", LanguageKey = "printoptions_printgrayscale", Description = "Force grayscale printing", DefaultValue = "false")] - public bool OutputPrintGrayscale { get; set; } - - [IniProperty("OutputPrintMonochrome", LanguageKey = "printoptions_printmonochrome", Description = "Force monorchrome printing", DefaultValue = "false")] - public bool OutputPrintMonochrome { get; set; } - - [IniProperty("OutputPrintMonochromeThreshold", Description = "Threshold for monochrome filter (0 - 255), lower value means less black", DefaultValue = "127")] - public byte OutputPrintMonochromeThreshold { get; set; } - - [IniProperty("OutputPrintFooter", LanguageKey = "printoptions_timestamp", Description = "Print footer on print?", DefaultValue = "true")] - public bool OutputPrintFooter { get; set; } - - [IniProperty("OutputPrintFooterPattern", Description = "Footer pattern", DefaultValue = "${capturetime:d\"D\"} ${capturetime:d\"T\"} - ${title}")] - public string OutputPrintFooterPattern { get; set; } - - [IniProperty("NotificationSound", Description = "The wav-file to play when a capture is taken, loaded only once at the Greenshot startup", DefaultValue = "default")] - public string NotificationSound { get; set; } - - [IniProperty("UseProxy", Description = "Use your global proxy?", DefaultValue = "True")] - public bool UseProxy { get; set; } - - [IniProperty("IECapture", Description = "Enable/disable IE capture", DefaultValue = "True")] - public bool IECapture { get; set; } - - [IniProperty("IEFieldCapture", Description = "Enable/disable IE field capture, very slow but will make it possible to annotate the fields of a capture in the editor.", - DefaultValue = "False")] - public bool IEFieldCapture { get; set; } - - [IniProperty("WindowClassesToCheckForIE", Description = "Comma separated list of Window-Classes which need to be checked for a IE instance!", - DefaultValue = "AfxFrameOrView70,IMWindowClass")] - public List WindowClassesToCheckForIE { get; set; } - - [IniProperty("AutoCropDifference", - Description = - "Sets how to compare the colors for the autocrop detection, the higher the more is 'selected'. Possible values are from 0 to 255, where everything above ~150 doesn't make much sense!", - DefaultValue = "10")] - public int AutoCropDifference { get; set; } - - [IniProperty("IncludePlugins", - Description = "Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")] - public List IncludePlugins { get; set; } - - [IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")] - public List ExcludePlugins { get; set; } - - [IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")] - public List ExcludeDestinations { get; set; } - - [IniProperty("UpdateCheckInterval", Description = "How many days between every update check? (0=no checks)", DefaultValue = "14")] - public int UpdateCheckInterval { get; set; } - - [IniProperty("LastUpdateCheck", Description = "Last update check")] - public DateTime LastUpdateCheck { get; set; } - - [IniProperty("DisableSettings", Description = "Enable/disable the access to the settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool DisableSettings { get; set; } - - [IniProperty("DisableQuickSettings", Description = "Enable/disable the access to the quick settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool DisableQuickSettings { get; set; } - - [IniProperty("DisableTrayicon", Description = "Disable the trayicon, can only be changed manually in this .ini", DefaultValue = "False")] - public bool HideTrayicon { get; set; } - - [IniProperty("HideExpertSettings", Description = "Hide expert tab in the settings, can only be changed manually in this .ini", DefaultValue = "False")] - public bool HideExpertSettings { get; set; } - - [IniProperty("ThumnailPreview", Description = "Enable/disable thumbnail previews", DefaultValue = "True")] - public bool ThumnailPreview { get; set; } - - [IniProperty("NoGDICaptureForProduct", Description = "List of productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")] - public List NoGDICaptureForProduct { get; set; } - - [IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")] - public List NoDWMCaptureForProduct { get; set; } - - [IniProperty("OptimizeForRDP", Description = "Make some optimizations for usage with remote desktop", DefaultValue = "False")] - public bool OptimizeForRDP { get; set; } - - [IniProperty("DisableRDPOptimizing", Description = "Disable all optimizations for usage with remote desktop", DefaultValue = "False")] - public bool DisableRDPOptimizing { get; set; } - - [IniProperty("MinimizeWorkingSetSize", Description = "Optimize memory footprint, but with a performance penalty!", DefaultValue = "False")] - public bool MinimizeWorkingSetSize { get; set; } - - [IniProperty("WindowCaptureRemoveCorners", Description = "Remove the corners from a window capture", DefaultValue = "True")] - public bool WindowCaptureRemoveCorners { get; set; } - - [IniProperty("CheckForUnstable", Description = "Also check for unstable version updates", DefaultValue = "False")] - public bool CheckForUnstable { get; set; } - - [IniProperty("ActiveTitleFixes", Description = "The fixes that are active.")] - public List ActiveTitleFixes { get; set; } - - [IniProperty("TitleFixMatcher", Description = "The regular expressions to match the title with.")] - public Dictionary TitleFixMatcher { get; set; } - - [IniProperty("TitleFixReplacer", Description = "The replacements for the matchers.")] - public Dictionary TitleFixReplacer { get; set; } - - [IniProperty("ExperimentalFeatures", Description = "A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull = true)] - public List ExperimentalFeatures { get; set; } - - [IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue = "True")] - public bool EnableSpecialDIBClipboardReader { get; set; } - - [IniProperty("WindowCornerCutShape", Description = "The cutshape which is used to remove the window corners, is mirrorred for all corners", DefaultValue = "5,3,2,1,1")] - public List WindowCornerCutShape { get; set; } - - [IniProperty("LeftClickAction", - Description = - "Specify what action is made if the tray icon is left clicked, if a double-click action is specified this action is initiated after a delay (configurable via the windows double-click speed)", - DefaultValue = "SHOW_CONTEXT_MENU")] - public ClickActions LeftClickAction { get; set; } - - [IniProperty("DoubleClickAction", Description = "Specify what action is made if the tray icon is double clicked", DefaultValue = "OPEN_LAST_IN_EXPLORER")] - public ClickActions DoubleClickAction { get; set; } - - [IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")] - public bool ZoomerEnabled { get; set; } - - [IniProperty("ZoomerOpacity", - Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", - DefaultValue = "1")] - public float ZoomerOpacity { get; set; } - - [IniProperty("MaxMenuItemLength", - Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")] - public int MaxMenuItemLength { get; set; } - - [IniProperty("MailApiTo", Description = "The 'to' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiTo { get; set; } - - [IniProperty("MailApiCC", Description = "The 'CC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiCC { get; set; } - - [IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] - public string MailApiBCC { get; set; } - - [IniProperty("OptimizePNGCommand", - Description = - "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", - DefaultValue = "")] - public string OptimizePNGCommand { get; set; } - - [IniProperty("OptimizePNGCommandArguments", - Description = - "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", - DefaultValue = "\"{0}\"")] - public string OptimizePNGCommandArguments { get; set; } - - [IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")] - public string LastSaveWithVersion { get; set; } - - [IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", - DefaultValue = "True")] - public bool ProcessEXIFOrientation { get; set; } - - [IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")] - public Rectangle LastCapturedRegion { get; set; } - - [IniProperty("Win10BorderCrop", Description = "The capture is cropped with these settings, e.g. when you don't want to color around it -1,-1"), DefaultValue("0,0")] - public Size Win10BorderCrop { get; set; } - - private Size _iconSize; - - [IniProperty("BaseIconSize", - Description = "Defines the base size of the icons (e.g. for the buttons in the editor), default value 16,16 and it's scaled to the current DPI", - DefaultValue = "16,16")] - public Size IconSize - { - get { return _iconSize; } - set - { - Size newSize = value; - if (newSize != Size.Empty) - { - if (newSize.Width < 16) - { - newSize.Width = 16; - } - else if (newSize.Width > 256) - { - newSize.Width = 256; - } - - newSize.Width = (newSize.Width / 16) * 16; - if (newSize.Height < 16) - { - newSize.Height = 16; - } - else if (IconSize.Height > 256) - { - newSize.Height = 256; - } - - newSize.Height = (newSize.Height / 16) * 16; - } - - if (_iconSize != newSize) - { - _iconSize = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IconSize")); - } - } - } - - public Size ScaledIconSize => DpiHelper.ScaleWithCurrentDpi(_iconSize); - - [IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")] - public int WebRequestTimeout { get; set; } - - [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")] - public int WebRequestReadWriteTimeout { get; set; } - - public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32; - - /// - /// A helper method which returns true if the supplied experimental feature is enabled - /// - /// - /// - public bool IsExperimentalFeatureEnabled(string experimentalFeature) - { - return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature)); - } - - /// - /// 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) - { - case "PluginWhitelist": - case "PluginBacklist": - return new List(); - case "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 "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 "DWMBackgroundColor": - return Color.Transparent; - case "ActiveTitleFixes": - return new List - { - "Firefox", - "IE", - "Chrome" - }; - case "TitleFixMatcher": - return new Dictionary - { - { - "Firefox", " - Mozilla Firefox.*" - }, - { - "IE", " - (Microsoft|Windows) Internet Explorer.*" - }, - { - "Chrome", " - Google Chrome.*" - } - }; - case "TitleFixReplacer": - return new Dictionary - { - { - "Firefox", string.Empty - }, - { - "IE", string.Empty - }, - { - "Chrome", string.Empty - } - }; - } - - return 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 - /// - /// The name of the property - /// The string value of the property - /// string with the propertyValue, modified or not... - public override string PreCheckValue(string propertyName, string propertyValue) - { - // Changed the separator, now we need to correct this - if ("Destinations".Equals(propertyName)) - { - if (propertyValue != null) - { - return propertyValue.Replace('|', ','); - } - } - - if ("OutputFilePath".Equals(propertyName)) - { - if (string.IsNullOrEmpty(propertyValue)) - { - return null; - } - } - - return base.PreCheckValue(propertyName, propertyValue); - } - - /// - /// This method will be called before writing the configuration - /// - public override void BeforeSave() - { - try - { - // Store version, this can be used later to fix settings after an update - LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); - } - catch - { - // ignored - } - } - - /// - /// This method will be called after reading the configuration, so eventually some corrections can be made - /// - public override void AfterLoad() - { - // Comment with releases - // CheckForUnstable = true; - - if (string.IsNullOrEmpty(LastSaveWithVersion)) - { - try - { - // Store version, this can be used later to fix settings after an update - LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); - } - catch - { - // ignored - } - - // Disable the AutoReduceColors as it causes issues with Mozzila applications and some others - OutputFileAutoReduceColors = false; - } - - // Fix for excessive feed checking - if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && LastSaveWithVersion.StartsWith("1.2")) - { - UpdateCheckInterval = 14; - } - - if (UpdateCheckInterval > 365) - { - UpdateCheckInterval = 365; - } - - // Enable OneNote if upgrading from 1.1 - if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote")) - { - if (LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1")) - { - ExcludeDestinations.Remove("OneNote"); - } - else - { - // TODO: Remove with the release - ExcludeDestinations.Remove("OneNote"); - } - } - - if (OutputDestinations == null) - { - OutputDestinations = new List(); - } - - // Make sure there is an output! - if (OutputDestinations.Count == 0) - { - OutputDestinations.Add("Editor"); - } - - // Prevent both settings at once, bug #3435056 - if (OutputDestinations.Contains("Clipboard") && OutputFileCopyPathToClipboard) - { - OutputFileCopyPathToClipboard = false; - } - - // Make sure we have clipboard formats, otherwise a paste doesn't make sense! - if (ClipboardFormats == null || ClipboardFormats.Count == 0) - { - ClipboardFormats = new List - { - ClipboardFormat.PNG, - ClipboardFormat.HTML, - ClipboardFormat.DIB - }; - } - - // Make sure the lists are lowercase, to speedup the check - if (NoGDICaptureForProduct != null) - { - // Fix error in configuration - if (NoGDICaptureForProduct.Count >= 2) - { - if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1])) - { - NoGDICaptureForProduct.RemoveRange(0, 2); - NoGDICaptureForProduct.Add("Intellij Idea"); - IsDirty = true; - } - } - - for (int i = 0; i < NoGDICaptureForProduct.Count; i++) - { - NoGDICaptureForProduct[i] = NoGDICaptureForProduct[i].ToLower(); - } - } - - if (NoDWMCaptureForProduct != null) - { - // Fix error in configuration - if (NoDWMCaptureForProduct.Count >= 3) - { - if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2])) - { - NoDWMCaptureForProduct.RemoveRange(0, 3); - NoDWMCaptureForProduct.Add("Citrix ICA Client"); - IsDirty = true; - } - } - - for (int i = 0; i < NoDWMCaptureForProduct.Count; i++) - { - NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower(); - } - } - - if (AutoCropDifference < 0) - { - AutoCropDifference = 0; - } - - if (AutoCropDifference > 255) - { - AutoCropDifference = 255; - } - - if (OutputFileReduceColorsTo < 2) - { - OutputFileReduceColorsTo = 2; - } - - if (OutputFileReduceColorsTo > 256) - { - OutputFileReduceColorsTo = 256; - } - - if (WebRequestTimeout <= 10) - { - WebRequestTimeout = 100; - } - - if (WebRequestReadWriteTimeout < 1) - { - WebRequestReadWriteTimeout = 100; - } - } - - /// - /// Validate the OutputFilePath, and if this is not correct it will be set to the default - /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC) - /// - public void ValidateAndCorrectOutputFilePath() - { - if (!Directory.Exists(OutputFilePath)) - { - OutputFilePath = GetDefault(nameof(OutputFilePath)) as string; - } - } - - /// - /// Validate the OutputFileAsFullpath, and if this is not correct it will be set to the default - /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC) - /// - public void ValidateAndCorrectOutputFileAsFullpath() - { - var outputFilePath = Path.GetDirectoryName(OutputFileAsFullpath); - if (outputFilePath == null || (!File.Exists(OutputFileAsFullpath) && !Directory.Exists(outputFilePath))) - { - OutputFileAsFullpath = GetDefault(nameof(OutputFileAsFullpath)) as string; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; + +namespace Greenshot.Base.Core +{ + public enum ClipboardFormat + { + PNG, + DIB, + HTML, + HTMLDATAURL, + BITMAP, + DIBV5 + } + + public enum OutputFormat + { + bmp, + gif, + jpg, + png, + tiff, + greenshot, + ico + } + + public enum WindowCaptureMode + { + Screen, + GDI, + Aero, + AeroTransparent, + Auto + } + + public enum BuildStates + { + UNSTABLE, + RELEASE_CANDIDATE, + RELEASE + } + + public enum ClickActions + { + DO_NOTHING, + OPEN_LAST_IN_EXPLORER, + OPEN_LAST_IN_EDITOR, + OPEN_SETTINGS, + SHOW_CONTEXT_MENU + } + + /// + /// Description of CoreConfiguration. + /// + [IniSection("Core", Description = "Greenshot core configuration")] + public class CoreConfiguration : IniSection, INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + [IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")] + public string Language { get; set; } + + [IniProperty("RegionHotkey", Description = "Hotkey for starting the region capture", DefaultValue = "PrintScreen")] + public string RegionHotkey { get; set; } + + [IniProperty("WindowHotkey", Description = "Hotkey for starting the window capture", DefaultValue = "Alt + PrintScreen")] + public string WindowHotkey { get; set; } + + [IniProperty("FullscreenHotkey", Description = "Hotkey for starting the fullscreen capture", DefaultValue = "Ctrl + PrintScreen")] + public string FullscreenHotkey { get; set; } + + [IniProperty("LastregionHotkey", Description = "Hotkey for starting the last region capture", DefaultValue = "Shift + PrintScreen")] + public string LastregionHotkey { get; set; } + + [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")] + public string ClipboardHotkey { get; set; } + + [IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")] + public bool IsFirstLaunch { get; set; } + + [IniProperty("Destinations", Separator = ",", + Description = "Which destinations? Possible options (more might be added by plugins) are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail, Picker", + DefaultValue = "Picker")] + public List OutputDestinations { get; set; } = new List(); + + [IniProperty("ClipboardFormats", Separator = ",", Description = "Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", + DefaultValue = "PNG,DIB")] + public List ClipboardFormats { get; set; } = new List(); + + [IniProperty("CaptureMousepointer", Description = "Should the mouse be captured?", DefaultValue = "true")] + public bool CaptureMousepointer { get; set; } + + [IniProperty("CaptureWindowsInteractive", Description = "Use interactive window selection to capture? (false=Capture active window)", DefaultValue = "false")] + public bool CaptureWindowsInteractive { get; set; } + + [IniProperty("CaptureDelay", Description = "Capture delay in millseconds.", DefaultValue = "100")] + public int CaptureDelay { get; set; } + + [IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")] + public ScreenCaptureMode ScreenCaptureMode { get; set; } + + [IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")] + public int ScreenToCapture { get; set; } + + [IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")] + public WindowCaptureMode WindowCaptureMode { get; set; } + + [IniProperty("WindowCaptureAllChildLocations", + Description = "Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue = "False")] + public bool WindowCaptureAllChildLocations { get; set; } + + [IniProperty("DWMBackgroundColor", Description = "The background color for a DWM window capture.")] + public Color DWMBackgroundColor { get; set; } + + [IniProperty("PlayCameraSound", LanguageKey = "settings_playsound", Description = "Play a camera sound after taking a capture.", DefaultValue = "false")] + public bool PlayCameraSound { get; set; } = false; + + [IniProperty("ShowTrayNotification", LanguageKey = "settings_shownotify", Description = "Show a notification from the systray when a capture is taken.", + DefaultValue = "true")] + public bool ShowTrayNotification { get; set; } = true; + + [IniProperty("OutputFilePath", Description = "Output file path.")] + public string OutputFilePath { get; set; } + + [IniProperty("OutputFileAllowOverwrite", + Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")] + public bool OutputFileAllowOverwrite { get; set; } + + [IniProperty("OutputFileFilenamePattern", Description = "Filename pattern for screenshot.", DefaultValue = "${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")] + public string OutputFileFilenamePattern { get; set; } + + [IniProperty("OutputFileFormat", Description = "Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue = "png")] + public OutputFormat OutputFileFormat { get; set; } = OutputFormat.png; + + [IniProperty("OutputFileReduceColors", Description = "If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue = "false")] + public bool OutputFileReduceColors { get; set; } + + [IniProperty("OutputFileAutoReduceColors", + Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "false")] + public bool OutputFileAutoReduceColors { get; set; } + + [IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")] + public int OutputFileReduceColorsTo { get; set; } + + [IniProperty("OutputFileCopyPathToClipboard", Description = "When saving a screenshot, copy the path to the clipboard?", DefaultValue = "true")] + public bool OutputFileCopyPathToClipboard { get; set; } + + [IniProperty("OutputFileAsFullpath", Description = "SaveAs Full path?")] + public string OutputFileAsFullpath { get; set; } + + [IniProperty("OutputFileJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")] + public int OutputFileJpegQuality { get; set; } + + [IniProperty("OutputFilePromptQuality", Description = "Ask for the quality before saving?", DefaultValue = "false")] + public bool OutputFilePromptQuality { get; set; } + + [IniProperty("OutputFileIncrementingNumber", Description = "The number for the ${NUM} in the filename pattern, is increased automatically after each save.", + DefaultValue = "1")] + public uint OutputFileIncrementingNumber { get; set; } + + [IniProperty("OutputPrintPromptOptions", LanguageKey = "settings_alwaysshowprintoptionsdialog", Description = "Ask for print options when printing?", + DefaultValue = "true")] + public bool OutputPrintPromptOptions { get; set; } + + [IniProperty("OutputPrintAllowRotate", LanguageKey = "printoptions_allowrotate", Description = "Allow rotating the picture for fitting on paper?", DefaultValue = "false")] + public bool OutputPrintAllowRotate { get; set; } + + [IniProperty("OutputPrintAllowEnlarge", LanguageKey = "printoptions_allowenlarge", Description = "Allow growing the picture for fitting on paper?", DefaultValue = "false")] + public bool OutputPrintAllowEnlarge { get; set; } + + [IniProperty("OutputPrintAllowShrink", LanguageKey = "printoptions_allowshrink", Description = "Allow shrinking the picture for fitting on paper?", DefaultValue = "true")] + public bool OutputPrintAllowShrink { get; set; } + + [IniProperty("OutputPrintCenter", LanguageKey = "printoptions_allowcenter", Description = "Center image when printing?", DefaultValue = "true")] + public bool OutputPrintCenter { get; set; } + + [IniProperty("OutputPrintInverted", LanguageKey = "printoptions_inverted", Description = "Print image inverted (use e.g. for console captures)", DefaultValue = "false")] + public bool OutputPrintInverted { get; set; } + + [IniProperty("OutputPrintGrayscale", LanguageKey = "printoptions_printgrayscale", Description = "Force grayscale printing", DefaultValue = "false")] + public bool OutputPrintGrayscale { get; set; } + + [IniProperty("OutputPrintMonochrome", LanguageKey = "printoptions_printmonochrome", Description = "Force monorchrome printing", DefaultValue = "false")] + public bool OutputPrintMonochrome { get; set; } + + [IniProperty("OutputPrintMonochromeThreshold", Description = "Threshold for monochrome filter (0 - 255), lower value means less black", DefaultValue = "127")] + public byte OutputPrintMonochromeThreshold { get; set; } + + [IniProperty("OutputPrintFooter", LanguageKey = "printoptions_timestamp", Description = "Print footer on print?", DefaultValue = "true")] + public bool OutputPrintFooter { get; set; } + + [IniProperty("OutputPrintFooterPattern", Description = "Footer pattern", DefaultValue = "${capturetime:d\"D\"} ${capturetime:d\"T\"} - ${title}")] + public string OutputPrintFooterPattern { get; set; } + + [IniProperty("NotificationSound", Description = "The wav-file to play when a capture is taken, loaded only once at the Greenshot startup", DefaultValue = "default")] + public string NotificationSound { get; set; } + + [IniProperty("UseProxy", Description = "Use your global proxy?", DefaultValue = "True")] + public bool UseProxy { get; set; } + + [IniProperty("IECapture", Description = "Enable/disable IE capture", DefaultValue = "True")] + public bool IECapture { get; set; } + + [IniProperty("IEFieldCapture", Description = "Enable/disable IE field capture, very slow but will make it possible to annotate the fields of a capture in the editor.", + DefaultValue = "False")] + public bool IEFieldCapture { get; set; } + + [IniProperty("WindowClassesToCheckForIE", Description = "Comma separated list of Window-Classes which need to be checked for a IE instance!", + DefaultValue = "AfxFrameOrView70,IMWindowClass")] + public List WindowClassesToCheckForIE { get; set; } + + [IniProperty("AutoCropDifference", + Description = + "Sets how to compare the colors for the autocrop detection, the higher the more is 'selected'. Possible values are from 0 to 255, where everything above ~150 doesn't make much sense!", + DefaultValue = "10")] + public int AutoCropDifference { get; set; } + + [IniProperty("IncludePlugins", + Description = "Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")] + public List IncludePlugins { get; set; } + + [IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")] + public List ExcludePlugins { get; set; } + + [IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.")] + public List ExcludeDestinations { get; set; } + + [IniProperty("UpdateCheckInterval", Description = "How many days between every update check? (0=no checks)", DefaultValue = "14")] + public int UpdateCheckInterval { get; set; } + + [IniProperty("LastUpdateCheck", Description = "Last update check")] + public DateTime LastUpdateCheck { get; set; } + + [IniProperty("DisableSettings", Description = "Enable/disable the access to the settings, can only be changed manually in this .ini", DefaultValue = "False")] + public bool DisableSettings { get; set; } + + [IniProperty("DisableQuickSettings", Description = "Enable/disable the access to the quick settings, can only be changed manually in this .ini", DefaultValue = "False")] + public bool DisableQuickSettings { get; set; } + + [IniProperty("DisableTrayicon", Description = "Disable the trayicon, can only be changed manually in this .ini", DefaultValue = "False")] + public bool HideTrayicon { get; set; } + + [IniProperty("HideExpertSettings", Description = "Hide expert tab in the settings, can only be changed manually in this .ini", DefaultValue = "False")] + public bool HideExpertSettings { get; set; } + + [IniProperty("ThumnailPreview", Description = "Enable/disable thumbnail previews", DefaultValue = "True")] + public bool ThumnailPreview { get; set; } + + [IniProperty("NoGDICaptureForProduct", Description = "List of productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")] + public List NoGDICaptureForProduct { get; set; } + + [IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", DefaultValue = "Citrix ICA Client")] + public List NoDWMCaptureForProduct { get; set; } + + [IniProperty("OptimizeForRDP", Description = "Make some optimizations for usage with remote desktop", DefaultValue = "False")] + public bool OptimizeForRDP { get; set; } + + [IniProperty("DisableRDPOptimizing", Description = "Disable all optimizations for usage with remote desktop", DefaultValue = "False")] + public bool DisableRDPOptimizing { get; set; } + + [IniProperty("MinimizeWorkingSetSize", Description = "Optimize memory footprint, but with a performance penalty!", DefaultValue = "False")] + public bool MinimizeWorkingSetSize { get; set; } + + [IniProperty("WindowCaptureRemoveCorners", Description = "Remove the corners from a window capture", DefaultValue = "True")] + public bool WindowCaptureRemoveCorners { get; set; } + + [IniProperty("CheckForUnstable", Description = "Also check for unstable version updates", DefaultValue = "False")] + public bool CheckForUnstable { get; set; } + + [IniProperty("ActiveTitleFixes", Description = "The fixes that are active.")] + public List ActiveTitleFixes { get; set; } + + [IniProperty("TitleFixMatcher", Description = "The regular expressions to match the title with.")] + public Dictionary TitleFixMatcher { get; set; } + + [IniProperty("TitleFixReplacer", Description = "The replacements for the matchers.")] + public Dictionary TitleFixReplacer { get; set; } + + [IniProperty("ExperimentalFeatures", Description = "A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull = true)] + public List ExperimentalFeatures { get; set; } + + [IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue = "True")] + public bool EnableSpecialDIBClipboardReader { get; set; } + + [IniProperty("WindowCornerCutShape", Description = "The cutshape which is used to remove the window corners, is mirrorred for all corners", DefaultValue = "5,3,2,1,1")] + public List WindowCornerCutShape { get; set; } + + [IniProperty("LeftClickAction", + Description = + "Specify what action is made if the tray icon is left clicked, if a double-click action is specified this action is initiated after a delay (configurable via the windows double-click speed)", + DefaultValue = "SHOW_CONTEXT_MENU")] + public ClickActions LeftClickAction { get; set; } + + [IniProperty("DoubleClickAction", Description = "Specify what action is made if the tray icon is double clicked", DefaultValue = "OPEN_LAST_IN_EXPLORER")] + public ClickActions DoubleClickAction { get; set; } + + [IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")] + public bool ZoomerEnabled { get; set; } + + [IniProperty("ZoomerOpacity", + Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", + DefaultValue = "1")] + public float ZoomerOpacity { get; set; } + + [IniProperty("MaxMenuItemLength", + Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")] + public int MaxMenuItemLength { get; set; } + + [IniProperty("MailApiTo", Description = "The 'to' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] + public string MailApiTo { get; set; } + + [IniProperty("MailApiCC", Description = "The 'CC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] + public string MailApiCC { get; set; } + + [IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")] + public string MailApiBCC { get; set; } + + [IniProperty("OptimizePNGCommand", + Description = + "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", + DefaultValue = "")] + public string OptimizePNGCommand { get; set; } + + [IniProperty("OptimizePNGCommandArguments", + Description = + "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", + DefaultValue = "\"{0}\"")] + public string OptimizePNGCommandArguments { get; set; } + + [IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")] + public string LastSaveWithVersion { get; set; } + + [IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", + DefaultValue = "True")] + public bool ProcessEXIFOrientation { get; set; } + + [IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")] + public Rectangle LastCapturedRegion { get; set; } + + [IniProperty("Win10BorderCrop", Description = "The capture is cropped with these settings, e.g. when you don't want to color around it -1,-1"), DefaultValue("0,0")] + public Size Win10BorderCrop { get; set; } + + private Size _iconSize; + + [IniProperty("BaseIconSize", + Description = "Defines the base size of the icons (e.g. for the buttons in the editor), default value 16,16 and it's scaled to the current DPI", + DefaultValue = "16,16")] + public Size IconSize + { + get { return _iconSize; } + set + { + Size newSize = value; + if (newSize != Size.Empty) + { + if (newSize.Width < 16) + { + newSize.Width = 16; + } + else if (newSize.Width > 256) + { + newSize.Width = 256; + } + + newSize.Width = (newSize.Width / 16) * 16; + if (newSize.Height < 16) + { + newSize.Height = 16; + } + else if (IconSize.Height > 256) + { + newSize.Height = 256; + } + + newSize.Height = (newSize.Height / 16) * 16; + } + + if (_iconSize != newSize) + { + _iconSize = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IconSize")); + } + } + } + + public Size ScaledIconSize => DpiHelper.ScaleWithCurrentDpi(_iconSize); + + [IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")] + public int WebRequestTimeout { get; set; } + + [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")] + public int WebRequestReadWriteTimeout { get; set; } + + public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32; + + /// + /// A helper method which returns true if the supplied experimental feature is enabled + /// + /// + /// + public bool IsExperimentalFeatureEnabled(string experimentalFeature) + { + return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature)); + } + + /// + /// 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) + { + case "PluginWhitelist": + case "PluginBacklist": + return new List(); + case "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 "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 "DWMBackgroundColor": + return Color.Transparent; + case "ActiveTitleFixes": + return new List + { + "Firefox", + "IE", + "Chrome" + }; + case "TitleFixMatcher": + return new Dictionary + { + { + "Firefox", " - Mozilla Firefox.*" + }, + { + "IE", " - (Microsoft|Windows) Internet Explorer.*" + }, + { + "Chrome", " - Google Chrome.*" + } + }; + case "TitleFixReplacer": + return new Dictionary + { + { + "Firefox", string.Empty + }, + { + "IE", string.Empty + }, + { + "Chrome", string.Empty + } + }; + } + + return 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 + /// + /// The name of the property + /// The string value of the property + /// string with the propertyValue, modified or not... + public override string PreCheckValue(string propertyName, string propertyValue) + { + // Changed the separator, now we need to correct this + if ("Destinations".Equals(propertyName)) + { + if (propertyValue != null) + { + return propertyValue.Replace('|', ','); + } + } + + if ("OutputFilePath".Equals(propertyName)) + { + if (string.IsNullOrEmpty(propertyValue)) + { + return null; + } + } + + return base.PreCheckValue(propertyName, propertyValue); + } + + /// + /// This method will be called before writing the configuration + /// + public override void BeforeSave() + { + try + { + // Store version, this can be used later to fix settings after an update + LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); + } + catch + { + // ignored + } + } + + /// + /// This method will be called after reading the configuration, so eventually some corrections can be made + /// + public override void AfterLoad() + { + // Comment with releases + // CheckForUnstable = true; + + if (string.IsNullOrEmpty(LastSaveWithVersion)) + { + try + { + // Store version, this can be used later to fix settings after an update + LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(); + } + catch + { + // ignored + } + + // Disable the AutoReduceColors as it causes issues with Mozzila applications and some others + OutputFileAutoReduceColors = false; + } + + // Fix for excessive feed checking + if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && LastSaveWithVersion.StartsWith("1.2")) + { + UpdateCheckInterval = 14; + } + + if (UpdateCheckInterval > 365) + { + UpdateCheckInterval = 365; + } + + // Enable OneNote if upgrading from 1.1 + if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote")) + { + if (LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1")) + { + ExcludeDestinations.Remove("OneNote"); + } + else + { + // TODO: Remove with the release + ExcludeDestinations.Remove("OneNote"); + } + } + + if (OutputDestinations == null) + { + OutputDestinations = new List(); + } + + // Make sure there is an output! + if (OutputDestinations.Count == 0) + { + OutputDestinations.Add("Editor"); + } + + // Prevent both settings at once, bug #3435056 + if (OutputDestinations.Contains("Clipboard") && OutputFileCopyPathToClipboard) + { + OutputFileCopyPathToClipboard = false; + } + + // Make sure we have clipboard formats, otherwise a paste doesn't make sense! + if (ClipboardFormats == null || ClipboardFormats.Count == 0) + { + ClipboardFormats = new List + { + ClipboardFormat.PNG, + ClipboardFormat.HTML, + ClipboardFormat.DIB + }; + } + + // Make sure the lists are lowercase, to speedup the check + if (NoGDICaptureForProduct != null) + { + // Fix error in configuration + if (NoGDICaptureForProduct.Count >= 2) + { + if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1])) + { + NoGDICaptureForProduct.RemoveRange(0, 2); + NoGDICaptureForProduct.Add("Intellij Idea"); + IsDirty = true; + } + } + + for (int i = 0; i < NoGDICaptureForProduct.Count; i++) + { + NoGDICaptureForProduct[i] = NoGDICaptureForProduct[i].ToLower(); + } + } + + if (NoDWMCaptureForProduct != null) + { + // Fix error in configuration + if (NoDWMCaptureForProduct.Count >= 3) + { + if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2])) + { + NoDWMCaptureForProduct.RemoveRange(0, 3); + NoDWMCaptureForProduct.Add("Citrix ICA Client"); + IsDirty = true; + } + } + + for (int i = 0; i < NoDWMCaptureForProduct.Count; i++) + { + NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower(); + } + } + + if (AutoCropDifference < 0) + { + AutoCropDifference = 0; + } + + if (AutoCropDifference > 255) + { + AutoCropDifference = 255; + } + + if (OutputFileReduceColorsTo < 2) + { + OutputFileReduceColorsTo = 2; + } + + if (OutputFileReduceColorsTo > 256) + { + OutputFileReduceColorsTo = 256; + } + + if (WebRequestTimeout <= 10) + { + WebRequestTimeout = 100; + } + + if (WebRequestReadWriteTimeout < 1) + { + WebRequestReadWriteTimeout = 100; + } + } + + /// + /// Validate the OutputFilePath, and if this is not correct it will be set to the default + /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC) + /// + public void ValidateAndCorrectOutputFilePath() + { + if (!Directory.Exists(OutputFilePath)) + { + OutputFilePath = GetDefault(nameof(OutputFilePath)) as string; + } + } + + /// + /// Validate the OutputFileAsFullpath, and if this is not correct it will be set to the default + /// Added for BUG-1992, reset the OutputFilePath / OutputFileAsFullpath if they don't exist (e.g. the configuration is used on a different PC) + /// + public void ValidateAndCorrectOutputFileAsFullpath() + { + var outputFilePath = Path.GetDirectoryName(OutputFileAsFullpath); + if (outputFilePath == null || (!File.Exists(OutputFileAsFullpath) && !Directory.Exists(outputFilePath))) + { + OutputFileAsFullpath = GetDefault(nameof(OutputFileAsFullpath)) as string; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/CredentialsHelper.cs b/src/Greenshot.Base/Core/CredentialsHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/CredentialsHelper.cs rename to src/Greenshot.Base/Core/CredentialsHelper.cs index a1140dc46..cc02113a0 100644 --- a/src/GreenshotPlugin/Core/CredentialsHelper.cs +++ b/src/Greenshot.Base/Core/CredentialsHelper.cs @@ -1,525 +1,525 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Windows.Forms; - -namespace GreenshotPlugin.Core -{ - /// - /// The following code comes from: http://www.developerfusion.com/code/4693/using-the-credential-management-api/ - /// and is slightly modified so it works for us. - /// As the "Stored usernames and passwords" which can be accessed by: Start-> Run and type "Control keymgr.dll" - /// doesn't show all credentials use the tool here: http://www.microsoft.com/indonesia/msdn/credmgmt.aspx - /// The following code is an example for a login, it will call the Authenticate with user/password - /// which should return true if the login worked, false if not. - /// private static bool Login(string system, string name) { - /// try { - /// CredentialsDialog dialog = new CredentialsDialog(system); - /// dialog.Name = name; - /// while (dialog.Show(dialog.Name) == DialogResult.OK) { - /// if (Authenticate(dialog.Name, dialog.Password)) { - /// if (dialog.SaveChecked) dialog.Confirm(true); - /// return true; - /// } else { - /// try { - /// dialog.Confirm(false); - /// } catch (ApplicationException) { - /// // exception handling ... - /// } - /// dialog.IncorrectPassword = true; - /// } - /// } - /// } catch (ApplicationException) { - /// // exception handling ... - /// } - /// return false; - /// } - /// - /// Encapsulates dialog functionality from the Credential Management API. - public sealed class CredentialsDialog - { - [DllImport("gdi32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeleteObject(IntPtr hObject); - - /// The only valid bitmap height (in pixels) of a user-defined banner. - private const int ValidBannerHeight = 60; - - /// The only valid bitmap width (in pixels) of a user-defined banner. - private const int ValidBannerWidth = 320; - - /// Initializes a new instance of the class - /// with the specified target. - /// The name of the target for the credentials, typically a server name. - public CredentialsDialog(string target) : this(target, null) - { - } - - /// Initializes a new instance of the class - /// with the specified target and caption. - /// The name of the target for the credentials, typically a server name. - /// The caption of the dialog (null will cause a system default title to be used). - public CredentialsDialog(string target, string caption) : this(target, caption, null) - { - } - - /// Initializes a new instance of the class - /// with the specified target, caption and message. - /// The name of the target for the credentials, typically a server name. - /// The caption of the dialog (null will cause a system default title to be used). - /// The message of the dialog (null will cause a system default message to be used). - public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null) - { - } - - /// Initializes a new instance of the class - /// with the specified target, caption, message and banner. - /// The name of the target for the credentials, typically a server name. - /// The caption of the dialog (null will cause a system default title to be used). - /// The message of the dialog (null will cause a system default message to be used). - /// The image to display on the dialog (null will cause a system default image to be used). - public CredentialsDialog(string target, string caption, string message, Image banner) - { - Target = target; - Caption = caption; - Message = message; - Banner = banner; - } - - /// - /// Gets or sets if the dialog will be shown even if the credentials - /// can be returned from an existing credential in the credential manager. - /// - public bool AlwaysDisplay { get; set; } - - /// Gets or sets if the dialog is populated with name/password only. - public bool ExcludeCertificates { get; set; } = true; - - /// Gets or sets if the credentials are to be persisted in the credential manager. - public bool Persist { get; set; } = true; - - /// Gets or sets if the incorrect password balloontip needs to be shown. Introduced AFTER Windows XP - public bool IncorrectPassword { get; set; } - - /// Gets or sets if the name is read-only. - public bool KeepName { get; set; } - - private string _name = string.Empty; - - /// Gets or sets the name for the credentials. - public string Name - { - get { return _name; } - set - { - if (value?.Length > CredUi.MAX_USERNAME_LENGTH) - { - string message = string.Format( - Thread.CurrentThread.CurrentUICulture, - "The name has a maximum length of {0} characters.", - CredUi.MAX_USERNAME_LENGTH); - throw new ArgumentException(message, nameof(Name)); - } - - _name = value; - } - } - - private string _password = string.Empty; - - /// Gets or sets the password for the credentials. - public string Password - { - get { return _password; } - set - { - if (value?.Length > CredUi.MAX_PASSWORD_LENGTH) - { - string message = string.Format( - Thread.CurrentThread.CurrentUICulture, - "The password has a maximum length of {0} characters.", - CredUi.MAX_PASSWORD_LENGTH); - throw new ArgumentException(message, nameof(Password)); - } - - _password = value; - } - } - - /// Gets or sets if the save checkbox status. - public bool SaveChecked { get; set; } - - /// Gets or sets if the save checkbox is displayed. - /// This value only has effect if Persist is true. - public bool SaveDisplayed { get; set; } = true; - - private string _target = string.Empty; - - /// Gets or sets the name of the target for the credentials, typically a server name. - public string Target - { - get { return _target; } - set - { - if (value == null) - { - throw new ArgumentException("The target cannot be a null value.", nameof(Target)); - } - - if (value.Length > CredUi.MAX_GENERIC_TARGET_LENGTH) - { - string message = string.Format( - Thread.CurrentThread.CurrentUICulture, - "The target has a maximum length of {0} characters.", - CredUi.MAX_GENERIC_TARGET_LENGTH); - throw new ArgumentException(message, nameof(Target)); - } - - _target = value; - } - } - - private string _caption = string.Empty; - - /// Gets or sets the caption of the dialog. - /// A null value will cause a system default caption to be used. - public string Caption - { - get { return _caption; } - set - { - if (value?.Length > CredUi.MAX_CAPTION_LENGTH) - { - string message = string.Format( - Thread.CurrentThread.CurrentUICulture, - "The caption has a maximum length of {0} characters.", - CredUi.MAX_CAPTION_LENGTH); - throw new ArgumentException(message, nameof(Caption)); - } - - _caption = value; - } - } - - private string _message = string.Empty; - - /// Gets or sets the message of the dialog. - /// A null value will cause a system default message to be used. - public string Message - { - get { return _message; } - set - { - if (value?.Length > CredUi.MAX_MESSAGE_LENGTH) - { - string message = string.Format( - Thread.CurrentThread.CurrentUICulture, - "The message has a maximum length of {0} characters.", - CredUi.MAX_MESSAGE_LENGTH); - throw new ArgumentException(message, nameof(Message)); - } - - _message = value; - } - } - - private Image _banner; - - /// Gets or sets the image to display on the dialog. - /// A null value will cause a system default image to be used. - public Image Banner - { - get { return _banner; } - set - { - if (value != null) - { - if (value.Width != ValidBannerWidth) - { - throw new ArgumentException("The banner image width must be 320 pixels.", nameof(Banner)); - } - - if (value.Height != ValidBannerHeight) - { - throw new ArgumentException("The banner image height must be 60 pixels.", nameof(Banner)); - } - } - - _banner = value; - } - } - - /// Shows the credentials dialog with the specified name. - /// The name for the credentials. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(string name) - { - return Show(null, name, Password, SaveChecked); - } - - /// Shows the credentials dialog with the specified owner, name, password and save checkbox status. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - /// The name for the credentials. - /// The password for the credentials. - /// True if the save checkbox is checked. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(IWin32Window owner, string name, string password, bool saveChecked) - { - if ((Environment.OSVersion.Version.Major < 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor < 1))) - { - throw new ApplicationException("The Credential Management API requires Windows XP / Windows Server 2003 or later."); - } - - Name = name; - Password = password; - SaveChecked = saveChecked; - - return ShowDialog(owner); - } - - /// Confirmation action to be applied. - /// True if the credentials should be persisted. - public void Confirm(bool value) - { - var confirmResult = CredUi.CredUIConfirmCredentials(Target, value); - switch (confirmResult) - { - case CredUi.ReturnCodes.NO_ERROR: - break; - case CredUi.ReturnCodes.ERROR_INVALID_PARAMETER: - // for some reason, this is encountered when credentials are overwritten - break; - default: - throw new ApplicationException($"Credential confirmation failed: {confirmResult}"); - } - } - - /// Returns a DialogResult indicating the user action. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - /// - /// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user. - /// - private DialogResult ShowDialog(IWin32Window owner) - { - // set the api call parameters - StringBuilder name = new StringBuilder(CredUi.MAX_USERNAME_LENGTH); - name.Append(Name); - - StringBuilder password = new StringBuilder(CredUi.MAX_PASSWORD_LENGTH); - password.Append(Password); - - int saveChecked = Convert.ToInt32(SaveChecked); - - CredUi.INFO info = GetInfo(owner); - CredUi.CredFlags credFlags = GetFlags(); - - // make the api call - CredUi.ReturnCodes code = CredUi.CredUIPromptForCredentials( - ref info, - Target, - IntPtr.Zero, 0, - name, CredUi.MAX_USERNAME_LENGTH, - password, CredUi.MAX_PASSWORD_LENGTH, - ref saveChecked, - credFlags - ); - - // clean up resources - if (Banner != null) - { - DeleteObject(info.hbmBanner); - } - - // set the accessors from the api call parameters - Name = name.ToString(); - Password = password.ToString(); - SaveChecked = Convert.ToBoolean(saveChecked); - - return GetDialogResult(code); - } - - /// Returns the info structure for dialog display settings. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - private CredUi.INFO GetInfo(IWin32Window owner) - { - CredUi.INFO info = new CredUi.INFO(); - if (owner != null) info.hWndParent = owner.Handle; - info.pszCaptionText = Caption; - info.pszMessageText = Message; - if (Banner != null) - { - info.hbmBanner = new Bitmap(Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap(); - } - - info.cbSize = Marshal.SizeOf(info); - return info; - } - - /// Returns the flags for dialog display options. - private CredUi.CredFlags GetFlags() - { - CredUi.CredFlags credFlags = CredUi.CredFlags.GENERIC_CREDENTIALS; - - if (IncorrectPassword) - { - credFlags |= CredUi.CredFlags.INCORRECT_PASSWORD; - } - - if (AlwaysDisplay) - { - credFlags |= CredUi.CredFlags.ALWAYS_SHOW_UI; - } - - if (ExcludeCertificates) - { - credFlags |= CredUi.CredFlags.EXCLUDE_CERTIFICATES; - } - - if (Persist) - { - credFlags |= CredUi.CredFlags.EXPECT_CONFIRMATION; - if (SaveDisplayed) - { - credFlags |= CredUi.CredFlags.SHOW_SAVE_CHECK_BOX; - } - else - { - credFlags |= CredUi.CredFlags.PERSIST; - } - } - else - { - credFlags |= CredUi.CredFlags.DO_NOT_PERSIST; - } - - if (KeepName) - { - credFlags |= CredUi.CredFlags.KEEP_USERNAME; - } - - return credFlags; - } - - /// Returns a DialogResult from the specified code. - /// The credential return code. - private DialogResult GetDialogResult(CredUi.ReturnCodes code) => - code switch - { - CredUi.ReturnCodes.NO_ERROR => DialogResult.OK, - CredUi.ReturnCodes.ERROR_CANCELLED => DialogResult.Cancel, - CredUi.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION => throw new ApplicationException( - "No such logon session."), - CredUi.ReturnCodes.ERROR_NOT_FOUND => throw new ApplicationException("Not found."), - CredUi.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME => - throw new ApplicationException("Invalid account name."), - CredUi.ReturnCodes.ERROR_INSUFFICIENT_BUFFER => throw new ApplicationException("Insufficient buffer."), - CredUi.ReturnCodes.ERROR_INVALID_PARAMETER => throw new ApplicationException("Invalid parameter."), - CredUi.ReturnCodes.ERROR_INVALID_FLAGS => throw new ApplicationException("Invalid flags."), - _ => throw new ApplicationException("Unknown credential result encountered.") - }; - } - - internal static class CredUi - { - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/authentication_constants.asp - public const int MAX_MESSAGE_LENGTH = 100; - - public const int MAX_CAPTION_LENGTH = 100; - public const int MAX_GENERIC_TARGET_LENGTH = 100; - public const int MAX_USERNAME_LENGTH = 100; - public const int MAX_PASSWORD_LENGTH = 100; - - /// - /// http://www.pinvoke.net/default.aspx/Enums.CREDUI_FLAGS - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp - /// - [Flags] - public enum CredFlags - { - INCORRECT_PASSWORD = 0x1, - DO_NOT_PERSIST = 0x2, - EXCLUDE_CERTIFICATES = 0x8, - SHOW_SAVE_CHECK_BOX = 0x40, - ALWAYS_SHOW_UI = 0x80, - PERSIST = 0x1000, - EXPECT_CONFIRMATION = 0x20000, - GENERIC_CREDENTIALS = 0x40000, - KEEP_USERNAME = 0x100000, - } - - /// http://www.pinvoke.net/default.aspx/Enums.CredUIReturnCodes - public enum ReturnCodes - { - NO_ERROR = 0, - ERROR_INVALID_PARAMETER = 87, - ERROR_INSUFFICIENT_BUFFER = 122, - ERROR_INVALID_FLAGS = 1004, - ERROR_NOT_FOUND = 1168, - ERROR_CANCELLED = 1223, - ERROR_NO_SUCH_LOGON_SESSION = 1312, - ERROR_INVALID_ACCOUNT_NAME = 1315 - } - - /// - /// http://www.pinvoke.net/default.aspx/Structures.CREDUI_INFO - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/credui_info.asp - /// - public struct INFO - { - public int cbSize; - public IntPtr hWndParent; - [MarshalAs(UnmanagedType.LPWStr)] public string pszMessageText; - [MarshalAs(UnmanagedType.LPWStr)] public string pszCaptionText; - public IntPtr hbmBanner; - } - - /// - /// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp - /// - [DllImport("credui", CharSet = CharSet.Unicode)] - public static extern ReturnCodes CredUIPromptForCredentials( - ref INFO creditUR, - string targetName, - IntPtr reserved1, - int iError, - StringBuilder userName, - int maxUserName, - StringBuilder password, - int maxPassword, - ref int iSave, - CredFlags credFlags - ); - - /// - /// http://www.pinvoke.net/default.aspx/credui.CredUIConfirmCredentials - /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduiconfirmcredentials.asp - /// - [DllImport("credui.dll", CharSet = CharSet.Unicode)] - public static extern ReturnCodes CredUIConfirmCredentials(string targetName, [MarshalAs(UnmanagedType.Bool)] bool confirm); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace Greenshot.Base.Core +{ + /// + /// The following code comes from: http://www.developerfusion.com/code/4693/using-the-credential-management-api/ + /// and is slightly modified so it works for us. + /// As the "Stored usernames and passwords" which can be accessed by: Start-> Run and type "Control keymgr.dll" + /// doesn't show all credentials use the tool here: http://www.microsoft.com/indonesia/msdn/credmgmt.aspx + /// The following code is an example for a login, it will call the Authenticate with user/password + /// which should return true if the login worked, false if not. + /// private static bool Login(string system, string name) { + /// try { + /// CredentialsDialog dialog = new CredentialsDialog(system); + /// dialog.Name = name; + /// while (dialog.Show(dialog.Name) == DialogResult.OK) { + /// if (Authenticate(dialog.Name, dialog.Password)) { + /// if (dialog.SaveChecked) dialog.Confirm(true); + /// return true; + /// } else { + /// try { + /// dialog.Confirm(false); + /// } catch (ApplicationException) { + /// // exception handling ... + /// } + /// dialog.IncorrectPassword = true; + /// } + /// } + /// } catch (ApplicationException) { + /// // exception handling ... + /// } + /// return false; + /// } + /// + /// Encapsulates dialog functionality from the Credential Management API. + public sealed class CredentialsDialog + { + [DllImport("gdi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DeleteObject(IntPtr hObject); + + /// The only valid bitmap height (in pixels) of a user-defined banner. + private const int ValidBannerHeight = 60; + + /// The only valid bitmap width (in pixels) of a user-defined banner. + private const int ValidBannerWidth = 320; + + /// Initializes a new instance of the class + /// with the specified target. + /// The name of the target for the credentials, typically a server name. + public CredentialsDialog(string target) : this(target, null) + { + } + + /// Initializes a new instance of the class + /// with the specified target and caption. + /// The name of the target for the credentials, typically a server name. + /// The caption of the dialog (null will cause a system default title to be used). + public CredentialsDialog(string target, string caption) : this(target, caption, null) + { + } + + /// Initializes a new instance of the class + /// with the specified target, caption and message. + /// The name of the target for the credentials, typically a server name. + /// The caption of the dialog (null will cause a system default title to be used). + /// The message of the dialog (null will cause a system default message to be used). + public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null) + { + } + + /// Initializes a new instance of the class + /// with the specified target, caption, message and banner. + /// The name of the target for the credentials, typically a server name. + /// The caption of the dialog (null will cause a system default title to be used). + /// The message of the dialog (null will cause a system default message to be used). + /// The image to display on the dialog (null will cause a system default image to be used). + public CredentialsDialog(string target, string caption, string message, Image banner) + { + Target = target; + Caption = caption; + Message = message; + Banner = banner; + } + + /// + /// Gets or sets if the dialog will be shown even if the credentials + /// can be returned from an existing credential in the credential manager. + /// + public bool AlwaysDisplay { get; set; } + + /// Gets or sets if the dialog is populated with name/password only. + public bool ExcludeCertificates { get; set; } = true; + + /// Gets or sets if the credentials are to be persisted in the credential manager. + public bool Persist { get; set; } = true; + + /// Gets or sets if the incorrect password balloontip needs to be shown. Introduced AFTER Windows XP + public bool IncorrectPassword { get; set; } + + /// Gets or sets if the name is read-only. + public bool KeepName { get; set; } + + private string _name = string.Empty; + + /// Gets or sets the name for the credentials. + public string Name + { + get { return _name; } + set + { + if (value?.Length > CredUi.MAX_USERNAME_LENGTH) + { + string message = string.Format( + Thread.CurrentThread.CurrentUICulture, + "The name has a maximum length of {0} characters.", + CredUi.MAX_USERNAME_LENGTH); + throw new ArgumentException(message, nameof(Name)); + } + + _name = value; + } + } + + private string _password = string.Empty; + + /// Gets or sets the password for the credentials. + public string Password + { + get { return _password; } + set + { + if (value?.Length > CredUi.MAX_PASSWORD_LENGTH) + { + string message = string.Format( + Thread.CurrentThread.CurrentUICulture, + "The password has a maximum length of {0} characters.", + CredUi.MAX_PASSWORD_LENGTH); + throw new ArgumentException(message, nameof(Password)); + } + + _password = value; + } + } + + /// Gets or sets if the save checkbox status. + public bool SaveChecked { get; set; } + + /// Gets or sets if the save checkbox is displayed. + /// This value only has effect if Persist is true. + public bool SaveDisplayed { get; set; } = true; + + private string _target = string.Empty; + + /// Gets or sets the name of the target for the credentials, typically a server name. + public string Target + { + get { return _target; } + set + { + if (value == null) + { + throw new ArgumentException("The target cannot be a null value.", nameof(Target)); + } + + if (value.Length > CredUi.MAX_GENERIC_TARGET_LENGTH) + { + string message = string.Format( + Thread.CurrentThread.CurrentUICulture, + "The target has a maximum length of {0} characters.", + CredUi.MAX_GENERIC_TARGET_LENGTH); + throw new ArgumentException(message, nameof(Target)); + } + + _target = value; + } + } + + private string _caption = string.Empty; + + /// Gets or sets the caption of the dialog. + /// A null value will cause a system default caption to be used. + public string Caption + { + get { return _caption; } + set + { + if (value?.Length > CredUi.MAX_CAPTION_LENGTH) + { + string message = string.Format( + Thread.CurrentThread.CurrentUICulture, + "The caption has a maximum length of {0} characters.", + CredUi.MAX_CAPTION_LENGTH); + throw new ArgumentException(message, nameof(Caption)); + } + + _caption = value; + } + } + + private string _message = string.Empty; + + /// Gets or sets the message of the dialog. + /// A null value will cause a system default message to be used. + public string Message + { + get { return _message; } + set + { + if (value?.Length > CredUi.MAX_MESSAGE_LENGTH) + { + string message = string.Format( + Thread.CurrentThread.CurrentUICulture, + "The message has a maximum length of {0} characters.", + CredUi.MAX_MESSAGE_LENGTH); + throw new ArgumentException(message, nameof(Message)); + } + + _message = value; + } + } + + private Image _banner; + + /// Gets or sets the image to display on the dialog. + /// A null value will cause a system default image to be used. + public Image Banner + { + get { return _banner; } + set + { + if (value != null) + { + if (value.Width != ValidBannerWidth) + { + throw new ArgumentException("The banner image width must be 320 pixels.", nameof(Banner)); + } + + if (value.Height != ValidBannerHeight) + { + throw new ArgumentException("The banner image height must be 60 pixels.", nameof(Banner)); + } + } + + _banner = value; + } + } + + /// Shows the credentials dialog with the specified name. + /// The name for the credentials. + /// Returns a DialogResult indicating the user action. + public DialogResult Show(string name) + { + return Show(null, name, Password, SaveChecked); + } + + /// Shows the credentials dialog with the specified owner, name, password and save checkbox status. + /// The System.Windows.Forms.IWin32Window the dialog will display in front of. + /// The name for the credentials. + /// The password for the credentials. + /// True if the save checkbox is checked. + /// Returns a DialogResult indicating the user action. + public DialogResult Show(IWin32Window owner, string name, string password, bool saveChecked) + { + if ((Environment.OSVersion.Version.Major < 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor < 1))) + { + throw new ApplicationException("The Credential Management API requires Windows XP / Windows Server 2003 or later."); + } + + Name = name; + Password = password; + SaveChecked = saveChecked; + + return ShowDialog(owner); + } + + /// Confirmation action to be applied. + /// True if the credentials should be persisted. + public void Confirm(bool value) + { + var confirmResult = CredUi.CredUIConfirmCredentials(Target, value); + switch (confirmResult) + { + case CredUi.ReturnCodes.NO_ERROR: + break; + case CredUi.ReturnCodes.ERROR_INVALID_PARAMETER: + // for some reason, this is encountered when credentials are overwritten + break; + default: + throw new ApplicationException($"Credential confirmation failed: {confirmResult}"); + } + } + + /// Returns a DialogResult indicating the user action. + /// The System.Windows.Forms.IWin32Window the dialog will display in front of. + /// + /// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user. + /// + private DialogResult ShowDialog(IWin32Window owner) + { + // set the api call parameters + StringBuilder name = new StringBuilder(CredUi.MAX_USERNAME_LENGTH); + name.Append(Name); + + StringBuilder password = new StringBuilder(CredUi.MAX_PASSWORD_LENGTH); + password.Append(Password); + + int saveChecked = Convert.ToInt32(SaveChecked); + + CredUi.INFO info = GetInfo(owner); + CredUi.CredFlags credFlags = GetFlags(); + + // make the api call + CredUi.ReturnCodes code = CredUi.CredUIPromptForCredentials( + ref info, + Target, + IntPtr.Zero, 0, + name, CredUi.MAX_USERNAME_LENGTH, + password, CredUi.MAX_PASSWORD_LENGTH, + ref saveChecked, + credFlags + ); + + // clean up resources + if (Banner != null) + { + DeleteObject(info.hbmBanner); + } + + // set the accessors from the api call parameters + Name = name.ToString(); + Password = password.ToString(); + SaveChecked = Convert.ToBoolean(saveChecked); + + return GetDialogResult(code); + } + + /// Returns the info structure for dialog display settings. + /// The System.Windows.Forms.IWin32Window the dialog will display in front of. + private CredUi.INFO GetInfo(IWin32Window owner) + { + CredUi.INFO info = new CredUi.INFO(); + if (owner != null) info.hWndParent = owner.Handle; + info.pszCaptionText = Caption; + info.pszMessageText = Message; + if (Banner != null) + { + info.hbmBanner = new Bitmap(Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap(); + } + + info.cbSize = Marshal.SizeOf(info); + return info; + } + + /// Returns the flags for dialog display options. + private CredUi.CredFlags GetFlags() + { + CredUi.CredFlags credFlags = CredUi.CredFlags.GENERIC_CREDENTIALS; + + if (IncorrectPassword) + { + credFlags |= CredUi.CredFlags.INCORRECT_PASSWORD; + } + + if (AlwaysDisplay) + { + credFlags |= CredUi.CredFlags.ALWAYS_SHOW_UI; + } + + if (ExcludeCertificates) + { + credFlags |= CredUi.CredFlags.EXCLUDE_CERTIFICATES; + } + + if (Persist) + { + credFlags |= CredUi.CredFlags.EXPECT_CONFIRMATION; + if (SaveDisplayed) + { + credFlags |= CredUi.CredFlags.SHOW_SAVE_CHECK_BOX; + } + else + { + credFlags |= CredUi.CredFlags.PERSIST; + } + } + else + { + credFlags |= CredUi.CredFlags.DO_NOT_PERSIST; + } + + if (KeepName) + { + credFlags |= CredUi.CredFlags.KEEP_USERNAME; + } + + return credFlags; + } + + /// Returns a DialogResult from the specified code. + /// The credential return code. + private DialogResult GetDialogResult(CredUi.ReturnCodes code) => + code switch + { + CredUi.ReturnCodes.NO_ERROR => DialogResult.OK, + CredUi.ReturnCodes.ERROR_CANCELLED => DialogResult.Cancel, + CredUi.ReturnCodes.ERROR_NO_SUCH_LOGON_SESSION => throw new ApplicationException( + "No such logon session."), + CredUi.ReturnCodes.ERROR_NOT_FOUND => throw new ApplicationException("Not found."), + CredUi.ReturnCodes.ERROR_INVALID_ACCOUNT_NAME => + throw new ApplicationException("Invalid account name."), + CredUi.ReturnCodes.ERROR_INSUFFICIENT_BUFFER => throw new ApplicationException("Insufficient buffer."), + CredUi.ReturnCodes.ERROR_INVALID_PARAMETER => throw new ApplicationException("Invalid parameter."), + CredUi.ReturnCodes.ERROR_INVALID_FLAGS => throw new ApplicationException("Invalid flags."), + _ => throw new ApplicationException("Unknown credential result encountered.") + }; + } + + internal static class CredUi + { + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/authentication_constants.asp + public const int MAX_MESSAGE_LENGTH = 100; + + public const int MAX_CAPTION_LENGTH = 100; + public const int MAX_GENERIC_TARGET_LENGTH = 100; + public const int MAX_USERNAME_LENGTH = 100; + public const int MAX_PASSWORD_LENGTH = 100; + + /// + /// http://www.pinvoke.net/default.aspx/Enums.CREDUI_FLAGS + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp + /// + [Flags] + public enum CredFlags + { + INCORRECT_PASSWORD = 0x1, + DO_NOT_PERSIST = 0x2, + EXCLUDE_CERTIFICATES = 0x8, + SHOW_SAVE_CHECK_BOX = 0x40, + ALWAYS_SHOW_UI = 0x80, + PERSIST = 0x1000, + EXPECT_CONFIRMATION = 0x20000, + GENERIC_CREDENTIALS = 0x40000, + KEEP_USERNAME = 0x100000, + } + + /// http://www.pinvoke.net/default.aspx/Enums.CredUIReturnCodes + public enum ReturnCodes + { + NO_ERROR = 0, + ERROR_INVALID_PARAMETER = 87, + ERROR_INSUFFICIENT_BUFFER = 122, + ERROR_INVALID_FLAGS = 1004, + ERROR_NOT_FOUND = 1168, + ERROR_CANCELLED = 1223, + ERROR_NO_SUCH_LOGON_SESSION = 1312, + ERROR_INVALID_ACCOUNT_NAME = 1315 + } + + /// + /// http://www.pinvoke.net/default.aspx/Structures.CREDUI_INFO + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/credui_info.asp + /// + public struct INFO + { + public int cbSize; + public IntPtr hWndParent; + [MarshalAs(UnmanagedType.LPWStr)] public string pszMessageText; + [MarshalAs(UnmanagedType.LPWStr)] public string pszCaptionText; + public IntPtr hbmBanner; + } + + /// + /// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp + /// + [DllImport("credui", CharSet = CharSet.Unicode)] + public static extern ReturnCodes CredUIPromptForCredentials( + ref INFO creditUR, + string targetName, + IntPtr reserved1, + int iError, + StringBuilder userName, + int maxUserName, + StringBuilder password, + int maxPassword, + ref int iSave, + CredFlags credFlags + ); + + /// + /// http://www.pinvoke.net/default.aspx/credui.CredUIConfirmCredentials + /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduiconfirmcredentials.asp + /// + [DllImport("credui.dll", CharSet = CharSet.Unicode)] + public static extern ReturnCodes CredUIConfirmCredentials(string targetName, [MarshalAs(UnmanagedType.Bool)] bool confirm); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/DisplayKeyAttribute.cs b/src/Greenshot.Base/Core/DisplayKeyAttribute.cs similarity index 94% rename from src/GreenshotPlugin/Core/DisplayKeyAttribute.cs rename to src/Greenshot.Base/Core/DisplayKeyAttribute.cs index 1719e0092..39ac43b13 100644 --- a/src/GreenshotPlugin/Core/DisplayKeyAttribute.cs +++ b/src/Greenshot.Base/Core/DisplayKeyAttribute.cs @@ -1,40 +1,40 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.Core -{ - [AttributeUsage(AttributeTargets.Field)] - public sealed class DisplayKeyAttribute : Attribute - { - public string Value { get; } - - public DisplayKeyAttribute(string v) - { - Value = v; - } - - public DisplayKeyAttribute() - { - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.Core +{ + [AttributeUsage(AttributeTargets.Field)] + public sealed class DisplayKeyAttribute : Attribute + { + public string Value { get; } + + public DisplayKeyAttribute(string v) + { + Value = v; + } + + public DisplayKeyAttribute() + { + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/DpiHelper.cs b/src/Greenshot.Base/Core/DpiHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/DpiHelper.cs rename to src/Greenshot.Base/Core/DpiHelper.cs index ec9ae8f41..bcb3314b6 100644 --- a/src/GreenshotPlugin/Core/DpiHelper.cs +++ b/src/Greenshot.Base/Core/DpiHelper.cs @@ -19,15 +19,15 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core.Enums; -using GreenshotPlugin.UnmanagedHelpers; using System; using System.Drawing; using System.Runtime.InteropServices; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; +using Greenshot.Base.Core.Enums; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// This handles DPI changes see diff --git a/src/GreenshotPlugin/Core/EffectConverter.cs b/src/Greenshot.Base/Core/EffectConverter.cs similarity index 96% rename from src/GreenshotPlugin/Core/EffectConverter.cs rename to src/Greenshot.Base/Core/EffectConverter.cs index 1b69dc3ed..40cb1f5ae 100644 --- a/src/GreenshotPlugin/Core/EffectConverter.cs +++ b/src/Greenshot.Base/Core/EffectConverter.cs @@ -1,233 +1,233 @@ -using System; -using System.ComponentModel; -using System.Drawing; -using System.Globalization; -using System.Text; -using GreenshotPlugin.Effects; - -namespace GreenshotPlugin.Core -{ - public class EffectConverter : TypeConverter - { - // Fix to prevent BUG-1753 - private readonly NumberFormatInfo _numberFormatInfo = new NumberFormatInfo(); - - public EffectConverter() - { - _numberFormatInfo.NumberDecimalSeparator = "."; - _numberFormatInfo.NumberGroupSeparator = ","; - } - - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - - return base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - - if (destinationType == typeof(DropShadowEffect)) - { - return true; - } - - if (destinationType == typeof(TornEdgeEffect)) - { - return true; - } - - return base.CanConvertTo(context, destinationType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - // to string - if (destinationType == typeof(string)) - { - StringBuilder sb = new StringBuilder(); - if (value.GetType() == typeof(DropShadowEffect)) - { - DropShadowEffect effect = value as DropShadowEffect; - RetrieveDropShadowEffectValues(effect, sb); - return sb.ToString(); - } - - if (value.GetType() == typeof(TornEdgeEffect)) - { - TornEdgeEffect effect = value as TornEdgeEffect; - RetrieveDropShadowEffectValues(effect, sb); - sb.Append("|"); - RetrieveTornEdgeEffectValues(effect, sb); - return sb.ToString(); - } - } - - // from string - if (value is string) - { - string settings = value as string; - if (destinationType == typeof(DropShadowEffect)) - { - DropShadowEffect effect = new DropShadowEffect(); - ApplyDropShadowEffectValues(settings, effect); - return effect; - } - - if (destinationType == typeof(TornEdgeEffect)) - { - TornEdgeEffect effect = new TornEdgeEffect(); - ApplyDropShadowEffectValues(settings, effect); - ApplyTornEdgeEffectValues(settings, effect); - return effect; - } - } - - return base.ConvertTo(context, culture, value, destinationType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string settings) - { - if (settings.Contains("ToothHeight")) - { - return ConvertTo(context, culture, settings, typeof(TornEdgeEffect)); - } - - return ConvertTo(context, culture, settings, typeof(DropShadowEffect)); - } - - return base.ConvertFrom(context, culture, value); - } - - private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect) - { - string[] values = valuesString.Split('|'); - foreach (string nameValuePair in values) - { - string[] pair = nameValuePair.Split(':'); - switch (pair[0]) - { - case "Darkness": - // Fix to prevent BUG-1753 - if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, _numberFormatInfo, out var darkness)) - { - if (darkness <= 1.0) - { - effect.Darkness = darkness; - } - } - - break; - case "ShadowSize": - if (int.TryParse(pair[1], out var shadowSize)) - { - effect.ShadowSize = shadowSize; - } - - break; - case "ShadowOffset": - Point shadowOffset = new Point(); - string[] coordinates = pair[1].Split(','); - if (int.TryParse(coordinates[0], out var shadowOffsetX)) - { - shadowOffset.X = shadowOffsetX; - } - - if (int.TryParse(coordinates[1], out var shadowOffsetY)) - { - shadowOffset.Y = shadowOffsetY; - } - - effect.ShadowOffset = shadowOffset; - break; - } - } - } - - private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect) - { - string[] values = valuesString.Split('|'); - foreach (string nameValuePair in values) - { - string[] pair = nameValuePair.Split(':'); - switch (pair[0]) - { - case "GenerateShadow": - if (bool.TryParse(pair[1], out var generateShadow)) - { - effect.GenerateShadow = generateShadow; - } - - break; - case "ToothHeight": - if (int.TryParse(pair[1], out var toothHeight)) - { - effect.ToothHeight = toothHeight; - } - - break; - case "HorizontalToothRange": - if (int.TryParse(pair[1], out var horizontalToothRange)) - { - effect.HorizontalToothRange = horizontalToothRange; - } - - break; - case "VerticalToothRange": - if (int.TryParse(pair[1], out var verticalToothRange)) - { - effect.VerticalToothRange = verticalToothRange; - } - - break; - case "Edges": - string[] edges = pair[1].Split(','); - if (bool.TryParse(edges[0], out var edge)) - { - effect.Edges[0] = edge; - } - - if (bool.TryParse(edges[1], out edge)) - { - effect.Edges[1] = edge; - } - - if (bool.TryParse(edges[2], out edge)) - { - effect.Edges[2] = edge; - } - - if (bool.TryParse(edges[3], out edge)) - { - effect.Edges[3] = edge; - } - - break; - } - } - } - - private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb) - { - // Fix to prevent BUG-1753 is to use the numberFormatInfo - sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", _numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, - effect.ShadowOffset.Y); - } - - private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb) - { - sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, - effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]); - } - } +using System; +using System.ComponentModel; +using System.Drawing; +using System.Globalization; +using System.Text; +using Greenshot.Base.Effects; + +namespace Greenshot.Base.Core +{ + public class EffectConverter : TypeConverter + { + // Fix to prevent BUG-1753 + private readonly NumberFormatInfo _numberFormatInfo = new NumberFormatInfo(); + + public EffectConverter() + { + _numberFormatInfo.NumberDecimalSeparator = "."; + _numberFormatInfo.NumberGroupSeparator = ","; + } + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + + return base.CanConvertFrom(context, sourceType); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string)) + { + return true; + } + + if (destinationType == typeof(DropShadowEffect)) + { + return true; + } + + if (destinationType == typeof(TornEdgeEffect)) + { + return true; + } + + return base.CanConvertTo(context, destinationType); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + // to string + if (destinationType == typeof(string)) + { + StringBuilder sb = new StringBuilder(); + if (value.GetType() == typeof(DropShadowEffect)) + { + DropShadowEffect effect = value as DropShadowEffect; + RetrieveDropShadowEffectValues(effect, sb); + return sb.ToString(); + } + + if (value.GetType() == typeof(TornEdgeEffect)) + { + TornEdgeEffect effect = value as TornEdgeEffect; + RetrieveDropShadowEffectValues(effect, sb); + sb.Append("|"); + RetrieveTornEdgeEffectValues(effect, sb); + return sb.ToString(); + } + } + + // from string + if (value is string) + { + string settings = value as string; + if (destinationType == typeof(DropShadowEffect)) + { + DropShadowEffect effect = new DropShadowEffect(); + ApplyDropShadowEffectValues(settings, effect); + return effect; + } + + if (destinationType == typeof(TornEdgeEffect)) + { + TornEdgeEffect effect = new TornEdgeEffect(); + ApplyDropShadowEffectValues(settings, effect); + ApplyTornEdgeEffectValues(settings, effect); + return effect; + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string settings) + { + if (settings.Contains("ToothHeight")) + { + return ConvertTo(context, culture, settings, typeof(TornEdgeEffect)); + } + + return ConvertTo(context, culture, settings, typeof(DropShadowEffect)); + } + + return base.ConvertFrom(context, culture, value); + } + + private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect) + { + string[] values = valuesString.Split('|'); + foreach (string nameValuePair in values) + { + string[] pair = nameValuePair.Split(':'); + switch (pair[0]) + { + case "Darkness": + // Fix to prevent BUG-1753 + if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, _numberFormatInfo, out var darkness)) + { + if (darkness <= 1.0) + { + effect.Darkness = darkness; + } + } + + break; + case "ShadowSize": + if (int.TryParse(pair[1], out var shadowSize)) + { + effect.ShadowSize = shadowSize; + } + + break; + case "ShadowOffset": + Point shadowOffset = new Point(); + string[] coordinates = pair[1].Split(','); + if (int.TryParse(coordinates[0], out var shadowOffsetX)) + { + shadowOffset.X = shadowOffsetX; + } + + if (int.TryParse(coordinates[1], out var shadowOffsetY)) + { + shadowOffset.Y = shadowOffsetY; + } + + effect.ShadowOffset = shadowOffset; + break; + } + } + } + + private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect) + { + string[] values = valuesString.Split('|'); + foreach (string nameValuePair in values) + { + string[] pair = nameValuePair.Split(':'); + switch (pair[0]) + { + case "GenerateShadow": + if (bool.TryParse(pair[1], out var generateShadow)) + { + effect.GenerateShadow = generateShadow; + } + + break; + case "ToothHeight": + if (int.TryParse(pair[1], out var toothHeight)) + { + effect.ToothHeight = toothHeight; + } + + break; + case "HorizontalToothRange": + if (int.TryParse(pair[1], out var horizontalToothRange)) + { + effect.HorizontalToothRange = horizontalToothRange; + } + + break; + case "VerticalToothRange": + if (int.TryParse(pair[1], out var verticalToothRange)) + { + effect.VerticalToothRange = verticalToothRange; + } + + break; + case "Edges": + string[] edges = pair[1].Split(','); + if (bool.TryParse(edges[0], out var edge)) + { + effect.Edges[0] = edge; + } + + if (bool.TryParse(edges[1], out edge)) + { + effect.Edges[1] = edge; + } + + if (bool.TryParse(edges[2], out edge)) + { + effect.Edges[2] = edge; + } + + if (bool.TryParse(edges[3], out edge)) + { + effect.Edges[3] = edge; + } + + break; + } + } + } + + private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb) + { + // Fix to prevent BUG-1753 is to use the numberFormatInfo + sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", _numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, + effect.ShadowOffset.Y); + } + + private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb) + { + sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, + effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/Enums/HResult.cs b/src/Greenshot.Base/Core/Enums/HResult.cs similarity index 97% rename from src/GreenshotPlugin/Core/Enums/HResult.cs rename to src/Greenshot.Base/Core/Enums/HResult.cs index 96e867c6c..e278162f9 100644 --- a/src/GreenshotPlugin/Core/Enums/HResult.cs +++ b/src/Greenshot.Base/Core/Enums/HResult.cs @@ -19,7 +19,7 @@ using System.Diagnostics.CodeAnalysis; -namespace GreenshotPlugin.Core.Enums +namespace Greenshot.Base.Core.Enums { /// /// The HRESULT represents Windows error codes diff --git a/src/GreenshotPlugin/Core/Enums/MonitorDpiType.cs b/src/Greenshot.Base/Core/Enums/MonitorDpiType.cs similarity index 97% rename from src/GreenshotPlugin/Core/Enums/MonitorDpiType.cs rename to src/Greenshot.Base/Core/Enums/MonitorDpiType.cs index c1db8ce18..e434f5bb3 100644 --- a/src/GreenshotPlugin/Core/Enums/MonitorDpiType.cs +++ b/src/Greenshot.Base/Core/Enums/MonitorDpiType.cs @@ -3,7 +3,7 @@ using System; -namespace GreenshotPlugin.Core.Enums +namespace Greenshot.Base.Core.Enums { /// /// See diff --git a/src/GreenshotPlugin/Core/Enums/MonitorFrom.cs b/src/Greenshot.Base/Core/Enums/MonitorFrom.cs similarity index 96% rename from src/GreenshotPlugin/Core/Enums/MonitorFrom.cs rename to src/Greenshot.Base/Core/Enums/MonitorFrom.cs index 40f25961b..f9d9fcc2b 100644 --- a/src/GreenshotPlugin/Core/Enums/MonitorFrom.cs +++ b/src/Greenshot.Base/Core/Enums/MonitorFrom.cs @@ -3,7 +3,7 @@ using System; -namespace GreenshotPlugin.Core.Enums +namespace Greenshot.Base.Core.Enums { /// /// Flags for the MonitorFromRect / MonitorFromWindow "flags" field diff --git a/src/GreenshotPlugin/Core/EnvironmentInfo.cs b/src/Greenshot.Base/Core/EnvironmentInfo.cs similarity index 99% rename from src/GreenshotPlugin/Core/EnvironmentInfo.cs rename to src/Greenshot.Base/Core/EnvironmentInfo.cs index 27a3eeda1..9c23cd2df 100644 --- a/src/GreenshotPlugin/Core/EnvironmentInfo.cs +++ b/src/Greenshot.Base/Core/EnvironmentInfo.cs @@ -23,11 +23,11 @@ using System; using System.Reflection; using System.Runtime.InteropServices; using System.Text; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.UnmanagedHelpers; +using Greenshot.Base.IniFile; +using Greenshot.Base.UnmanagedHelpers; using Microsoft.Win32; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// Description of EnvironmentInfo. diff --git a/src/GreenshotPlugin/Core/EventDelay.cs b/src/Greenshot.Base/Core/EventDelay.cs similarity index 97% rename from src/GreenshotPlugin/Core/EventDelay.cs rename to src/Greenshot.Base/Core/EventDelay.cs index 1c6ec235c..c1a41a1be 100644 --- a/src/GreenshotPlugin/Core/EventDelay.cs +++ b/src/Greenshot.Base/Core/EventDelay.cs @@ -21,7 +21,7 @@ using System; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { public class EventDelay { diff --git a/src/GreenshotPlugin/Core/ExplorerHelper.cs b/src/Greenshot.Base/Core/ExplorerHelper.cs similarity index 94% rename from src/GreenshotPlugin/Core/ExplorerHelper.cs rename to src/Greenshot.Base/Core/ExplorerHelper.cs index 934d0ed74..0ebb88db3 100644 --- a/src/GreenshotPlugin/Core/ExplorerHelper.cs +++ b/src/Greenshot.Base/Core/ExplorerHelper.cs @@ -1,55 +1,55 @@ -using System; -using System.Diagnostics; -using System.IO; - -namespace GreenshotPlugin.Core -{ - /// - /// Simple utility for the explorer - /// - public static class ExplorerHelper - { - /// - /// Open the path in the windows explorer. - /// If the path is a directory, it will just open the explorer with that directory. - /// If the path is a file, the explorer is opened with the directory and the file is selected. - /// - /// Path to file or directory - public static bool OpenInExplorer(string path) - { - if (path == null) - { - return false; - } - - try - { - // Check if path is a directory - if (Directory.Exists(path)) - { - using (Process.Start(path)) - { - return true; - } - } - - // Check if path is a file - if (File.Exists(path)) - { - // Start the explorer process and select the file - using var explorer = Process.Start("explorer.exe", $"/select,\"{path}\""); - explorer?.WaitForInputIdle(500); - return true; - } - } - catch (Exception ex) - { - // Make sure we show what we tried to open in the exception - ex.Data.Add("path", path); - throw; - } - - return false; - } - } +using System; +using System.Diagnostics; +using System.IO; + +namespace Greenshot.Base.Core +{ + /// + /// Simple utility for the explorer + /// + public static class ExplorerHelper + { + /// + /// Open the path in the windows explorer. + /// If the path is a directory, it will just open the explorer with that directory. + /// If the path is a file, the explorer is opened with the directory and the file is selected. + /// + /// Path to file or directory + public static bool OpenInExplorer(string path) + { + if (path == null) + { + return false; + } + + try + { + // Check if path is a directory + if (Directory.Exists(path)) + { + using (Process.Start(path)) + { + return true; + } + } + + // Check if path is a file + if (File.Exists(path)) + { + // Start the explorer process and select the file + using var explorer = Process.Start("explorer.exe", $"/select,\"{path}\""); + explorer?.WaitForInputIdle(500); + return true; + } + } + catch (Exception ex) + { + // Make sure we show what we tried to open in the exception + ex.Data.Add("path", path); + throw; + } + + return false; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/FastBitmap.cs b/src/Greenshot.Base/Core/FastBitmap.cs similarity index 97% rename from src/GreenshotPlugin/Core/FastBitmap.cs rename to src/Greenshot.Base/Core/FastBitmap.cs index 2ef28af93..3b6685dd0 100644 --- a/src/GreenshotPlugin/Core/FastBitmap.cs +++ b/src/Greenshot.Base/Core/FastBitmap.cs @@ -1,1055 +1,1055 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; - -namespace GreenshotPlugin.Core -{ - /// - /// The interface for the FastBitmap - /// - public interface IFastBitmap : IDisposable - { - /// - /// Get the color at x,y - /// The returned Color object depends on the underlying pixel format - /// - /// int x - /// int y - /// Color - Color GetColorAt(int x, int y); - - /// - /// Set the color at the specified location - /// - /// int x - /// int y - /// Color - void SetColorAt(int x, int y, Color color); - - /// - /// Get the color at x,y - /// The returned byte[] color depends on the underlying pixel format - /// - /// int x - /// int y - /// byte array - void GetColorAt(int x, int y, byte[] color); - - /// - /// Set the color at the specified location - /// - /// int x - /// int y - /// byte[] color - void SetColorAt(int x, int y, byte[] color); - - /// - /// Lock the bitmap - /// - void Lock(); - - /// - /// Unlock the bitmap - /// - void Unlock(); - - /// - /// Unlock the bitmap and get the underlying bitmap in one call - /// - /// - Bitmap UnlockAndReturnBitmap(); - - /// - /// Size of the underlying image - /// - Size Size { get; } - - /// - /// Height of the image area that this fastbitmap covers - /// - int Height { get; } - - /// - /// Width of the image area that this fastbitmap covers - /// - int Width { get; } - - /// - /// Top of the image area that this fastbitmap covers - /// - int Top { get; } - - /// - /// Left of the image area that this fastbitmap covers - /// - int Left { get; } - - /// - /// Right of the image area that this fastbitmap covers - /// - int Right { get; } - - /// - /// Bottom of the image area that this fastbitmap covers - /// - int Bottom { get; } - - /// - /// Does the underlying image need to be disposed - /// - bool NeedsDispose { get; set; } - - /// - /// Returns if this FastBitmap has an alpha channel - /// - bool HasAlphaChannel { get; } - - /// - /// Draw the stored bitmap to the destionation bitmap at the supplied point - /// - /// Graphics - /// Point with location - void DrawTo(Graphics graphics, Point destination); - - /// - /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle - /// Be aware that the stored bitmap will be resized to the specified rectangle!! - /// - /// Graphics - /// Rectangle with destination - void DrawTo(Graphics graphics, Rectangle destinationRect); - - /// - /// Return true if the coordinates are inside the FastBitmap - /// - /// - /// - /// - bool Contains(int x, int y); - - /// - /// Set the bitmap resolution - /// - /// - /// - void SetResolution(float horizontal, float vertical); - } - - /// - /// This interface can be used for when offsetting is needed - /// - public interface IFastBitmapWithOffset : IFastBitmap - { - /// - /// Return true if the coordinates are inside the FastBitmap - /// - /// - /// - /// - new bool Contains(int x, int y); - - /// - /// Set the color at the specified location, using offsetting so the original coordinates can be used - /// - /// int x - /// int y - /// Color color - new void SetColorAt(int x, int y, Color color); - - /// - /// Set the color at the specified location, using offsetting so the original coordinates can be used - /// - /// int x - /// int y - /// byte[] color - new void SetColorAt(int x, int y, byte[] color); - - /// - /// Get the color at x,y - /// The returned Color object depends on the underlying pixel format - /// - /// int x - /// int y - /// Color - new Color GetColorAt(int x, int y); - - /// - /// Get the color at x,y, using offsetting so the original coordinates can be used - /// The returned byte[] color depends on the underlying pixel format - /// - /// int x - /// int y - /// byte array - new void GetColorAt(int x, int y, byte[] color); - - new int Left { get; set; } - - new int Top { get; set; } - } - - /// - /// This interface can be used for when clipping is needed - /// - public interface IFastBitmapWithClip : IFastBitmap - { - Rectangle Clip { get; set; } - - bool InvertClip { get; set; } - - /// - /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping - /// - /// int x - /// int y - /// Color color - new void SetColorAt(int x, int y, Color color); - - /// - /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping - /// - /// int x - /// int y - /// byte[] color - new void SetColorAt(int x, int y, byte[] color); - - /// - /// Return true if the coordinates are inside the FastBitmap and not clipped - /// - /// - /// - /// - new bool Contains(int x, int y); - } - - /// - /// This interface is implemented when there is a alpha-blending possibility - /// - public interface IFastBitmapWithBlend : IFastBitmap - { - Color BackgroundBlendColor { get; set; } - Color GetBlendedColorAt(int x, int y); - } - - /// - /// The base class for the fast bitmap implementation - /// - public abstract unsafe class FastBitmap : IFastBitmapWithClip, IFastBitmapWithOffset - { - protected const int PixelformatIndexA = 3; - protected const int PixelformatIndexR = 2; - protected const int PixelformatIndexG = 1; - protected const int PixelformatIndexB = 0; - - public const int ColorIndexR = 0; - public const int ColorIndexG = 1; - public const int ColorIndexB = 2; - public const int ColorIndexA = 3; - - protected Rectangle Area; - - /// - /// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap - /// - public bool NeedsDispose { get; set; } - - public Rectangle Clip { get; set; } - - public bool InvertClip { get; set; } - - /// - /// The bitmap for which the FastBitmap is creating access - /// - protected Bitmap Bitmap; - - protected BitmapData BmData; - protected int Stride; /* bytes per pixel row */ - protected bool BitsLocked; - protected byte* Pointer; - - public static IFastBitmap Create(Bitmap source) - { - return Create(source, Rectangle.Empty); - } - - public void SetResolution(float horizontal, float vertical) - { - Bitmap.SetResolution(horizontal, vertical); - } - - /// - /// Factory for creating a FastBitmap depending on the pixelformat of the source - /// The supplied rectangle specifies the area for which the FastBitmap does its thing - /// - /// Bitmap to access - /// Rectangle which specifies the area to have access to, can be Rectangle.Empty for the whole image - /// IFastBitmap - public static IFastBitmap Create(Bitmap source, Rectangle area) - { - switch (source.PixelFormat) - { - case PixelFormat.Format8bppIndexed: - return new FastChunkyBitmap(source, area); - case PixelFormat.Format24bppRgb: - return new Fast24RgbBitmap(source, area); - case PixelFormat.Format32bppRgb: - return new Fast32RgbBitmap(source, area); - case PixelFormat.Format32bppArgb: - case PixelFormat.Format32bppPArgb: - return new Fast32ArgbBitmap(source, area); - default: - throw new NotSupportedException($"Not supported Pixelformat {source.PixelFormat}"); - } - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// new Pixelformat - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) - { - return CreateCloneOf(source, pixelFormat, Rectangle.Empty); - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// Area of the bitmap to access, can be Rectangle.Empty for the whole - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, Rectangle area) - { - return CreateCloneOf(source, PixelFormat.DontCare, area); - } - - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// Pixelformat of the cloned bitmap - /// Area of the bitmap to access, can be Rectangle.Empty for the whole - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat, Rectangle area) - { - Bitmap destination = ImageHelper.CloneArea(source, area, pixelFormat); - FastBitmap fastBitmap = Create(destination) as FastBitmap; - if (fastBitmap != null) - { - fastBitmap.NeedsDispose = true; - fastBitmap.Left = area.Left; - fastBitmap.Top = area.Top; - } - - return fastBitmap; - } - - /// - /// Factory for creating a FastBitmap as a destination - /// - /// - /// - /// - /// IFastBitmap - public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) - { - Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f); - IFastBitmap fastBitmap = Create(destination); - fastBitmap.NeedsDispose = true; - return fastBitmap; - } - - /// - /// Constructor which stores the image and locks it when called - /// - /// Bitmap - /// Rectangle - protected FastBitmap(Bitmap bitmap, Rectangle area) - { - Bitmap = bitmap; - Rectangle bitmapArea = new Rectangle(Point.Empty, bitmap.Size); - if (area != Rectangle.Empty) - { - area.Intersect(bitmapArea); - Area = area; - } - else - { - Area = bitmapArea; - } - - // As the lock takes care that only the specified area is made available we need to calculate the offset - Left = area.Left; - Top = area.Top; - // Default cliping is done to the area without invert - Clip = Area; - InvertClip = false; - // Always lock, so we don't need to do this ourselves - Lock(); - } - - /// - /// Return the size of the image - /// - public Size Size - { - get - { - if (Area == Rectangle.Empty) - { - return Bitmap.Size; - } - - return Area.Size; - } - } - - /// - /// Return the width of the image - /// - public int Width - { - get - { - if (Area == Rectangle.Empty) - { - return Bitmap.Width; - } - - return Area.Width; - } - } - - /// - /// Return the height of the image - /// - public int Height - { - get - { - if (Area == Rectangle.Empty) - { - return Bitmap.Height; - } - - return Area.Height; - } - } - - private int _left; - - /// - /// Return the left of the fastbitmap, this is also used as an offset - /// - public int Left - { - get { return 0; } - set { _left = value; } - } - - /// - /// Return the left of the fastbitmap, this is also used as an offset - /// - int IFastBitmapWithOffset.Left - { - get { return _left; } - set { _left = value; } - } - - private int _top; - - /// - /// Return the top of the fastbitmap, this is also used as an offset - /// - public int Top - { - get { return 0; } - set { _top = value; } - } - - /// - /// Return the top of the fastbitmap, this is also used as an offset - /// - int IFastBitmapWithOffset.Top - { - get { return _top; } - set { _top = value; } - } - - /// - /// Return the right of the fastbitmap - /// - public int Right => Left + Width; - - /// - /// Return the bottom of the fastbitmap - /// - public int Bottom => Top + Height; - - /// - /// Returns the underlying bitmap, unlocks it and prevents that it will be disposed - /// - public Bitmap UnlockAndReturnBitmap() - { - if (BitsLocked) - { - Unlock(); - } - - NeedsDispose = false; - return Bitmap; - } - - public virtual bool HasAlphaChannel => false; - - /// - /// Destructor - /// - ~FastBitmap() - { - Dispose(false); - } - - /// - /// The public accessible Dispose - /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - // The bulk of the clean-up code is implemented in Dispose(bool) - - /// - /// This Dispose is called from the Dispose and the Destructor. - /// When disposing==true all non-managed resources should be freed too! - /// - /// - protected virtual void Dispose(bool disposing) - { - Unlock(); - if (disposing) - { - if (Bitmap != null && NeedsDispose) - { - Bitmap.Dispose(); - } - } - - Bitmap = null; - BmData = null; - Pointer = null; - } - - /// - /// Lock the bitmap so we have direct access to the memory - /// - public void Lock() - { - if (Width <= 0 || Height <= 0 || BitsLocked) - { - return; - } - - BmData = Bitmap.LockBits(Area, ImageLockMode.ReadWrite, Bitmap.PixelFormat); - BitsLocked = true; - - IntPtr scan0 = BmData.Scan0; - Pointer = (byte*) (void*) scan0; - Stride = BmData.Stride; - } - - /// - /// Unlock the System Memory - /// - public void Unlock() - { - if (BitsLocked) - { - Bitmap.UnlockBits(BmData); - BitsLocked = false; - } - } - - /// - /// Draw the stored bitmap to the destionation bitmap at the supplied point - /// - /// - /// - public void DrawTo(Graphics graphics, Point destination) - { - DrawTo(graphics, new Rectangle(destination, Area.Size)); - } - - /// - /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle - /// Be aware that the stored bitmap will be resized to the specified rectangle!! - /// - /// - /// - public void DrawTo(Graphics graphics, Rectangle destinationRect) - { - // Make sure this.bitmap is unlocked, if it was locked - bool isLocked = BitsLocked; - if (isLocked) - { - Unlock(); - } - - graphics.DrawImage(Bitmap, destinationRect, Area, GraphicsUnit.Pixel); - } - - /// - /// returns true if x & y are inside the FastBitmap - /// - /// - /// - /// true if x & y are inside the FastBitmap - public bool Contains(int x, int y) - { - return Area.Contains(x - Left, y - Top); - } - - public abstract Color GetColorAt(int x, int y); - public abstract void SetColorAt(int x, int y, Color color); - public abstract void GetColorAt(int x, int y, byte[] color); - public abstract void SetColorAt(int x, int y, byte[] color); - - bool IFastBitmapWithClip.Contains(int x, int y) - { - bool contains = Clip.Contains(x, y); - if (InvertClip) - { - return !contains; - } - else - { - return contains; - } - } - - void IFastBitmapWithClip.SetColorAt(int x, int y, byte[] color) - { - bool contains = Clip.Contains(x, y); - if ((InvertClip && contains) || (!InvertClip && !contains)) - { - return; - } - - SetColorAt(x, y, color); - } - - void IFastBitmapWithClip.SetColorAt(int x, int y, Color color) - { - bool contains = Clip.Contains(x, y); - if ((InvertClip && contains) || (!InvertClip && !contains)) - { - return; - } - - SetColorAt(x, y, color); - } - - /// - /// returns true if x & y are inside the FastBitmap - /// - /// - /// - /// true if x & y are inside the FastBitmap - bool IFastBitmapWithOffset.Contains(int x, int y) - { - return Area.Contains(x - Left, y - Top); - } - - Color IFastBitmapWithOffset.GetColorAt(int x, int y) - { - x -= _left; - y -= _top; - return GetColorAt(x, y); - } - - void IFastBitmapWithOffset.GetColorAt(int x, int y, byte[] color) - { - x -= _left; - y -= _top; - GetColorAt(x, y, color); - } - - void IFastBitmapWithOffset.SetColorAt(int x, int y, byte[] color) - { - x -= _left; - y -= _top; - SetColorAt(x, y, color); - } - - void IFastBitmapWithOffset.SetColorAt(int x, int y, Color color) - { - x -= _left; - y -= _top; - SetColorAt(x, y, color); - } - } - - /// - /// This is the implementation of the FastBitmat for the 8BPP pixelformat - /// - public unsafe class FastChunkyBitmap : FastBitmap - { - // Used for indexed images - private readonly Color[] _colorEntries; - private readonly Dictionary _colorCache = new Dictionary(); - - public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area) - { - _colorEntries = Bitmap.Palette.Entries; - } - - /// - /// Get the color from the specified location - /// - /// - /// - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = x + (y * Stride); - byte colorIndex = Pointer[offset]; - return _colorEntries[colorIndex]; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference - public override void GetColorAt(int x, int y, byte[] color) - { - throw new NotImplementedException("No performance gain!"); - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference - public override void SetColorAt(int x, int y, byte[] color) - { - throw new NotImplementedException("No performance gain!"); - } - - /// - /// Get the color-index from the specified location - /// - /// - /// - /// byte with index - public byte GetColorIndexAt(int x, int y) - { - int offset = x + (y * Stride); - return Pointer[offset]; - } - - /// - /// Set the color-index at the specified location - /// - /// - /// - /// - public void SetColorIndexAt(int x, int y, byte colorIndex) - { - int offset = x + (y * Stride); - Pointer[offset] = colorIndex; - } - - /// - /// Set the supplied color at the specified location. - /// Throws an ArgumentException if the color is not in the palette - /// - /// - /// - /// Color to set - public override void SetColorAt(int x, int y, Color color) - { - int offset = x + (y * Stride); - if (!_colorCache.TryGetValue(color, out var colorIndex)) - { - bool foundColor = false; - for (colorIndex = 0; colorIndex < _colorEntries.Length; colorIndex++) - { - if (color == _colorEntries[colorIndex]) - { - _colorCache.Add(color, colorIndex); - foundColor = true; - break; - } - } - - if (!foundColor) - { - throw new ArgumentException("No such color!"); - } - } - - Pointer[offset] = colorIndex; - } - } - - /// - /// This is the implementation of the IFastBitmap for 24 bit images (no Alpha) - /// - public unsafe class Fast24RgbBitmap : FastBitmap - { - public Fast24RgbBitmap(Bitmap source, Rectangle area) : base(source, area) - { - } - - /// - /// Retrieve the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 3) + (y * Stride); - return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 3) + (y * Stride); - Pointer[PixelformatIndexR + offset] = color.R; - Pointer[PixelformatIndexG + offset] = color.G; - Pointer[PixelformatIndexB + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 3) + (y * Stride); - color[PixelformatIndexR] = Pointer[PixelformatIndexR + offset]; - color[PixelformatIndexG] = Pointer[PixelformatIndexG + offset]; - color[PixelformatIndexB] = Pointer[PixelformatIndexB + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 3) + (y * Stride); - Pointer[PixelformatIndexR + offset] = color[PixelformatIndexR]; - Pointer[PixelformatIndexG + offset] = color[PixelformatIndexG]; - Pointer[PixelformatIndexB + offset] = color[PixelformatIndexB]; - } - } - - /// - /// This is the implementation of the IFastBitmap for 32 bit images (no Alpha) - /// - public unsafe class Fast32RgbBitmap : FastBitmap - { - public Fast32RgbBitmap(Bitmap source, Rectangle area) : base(source, area) - { - } - - /// - /// Retrieve the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 4) + (y * Stride); - return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 4) + (y * Stride); - Pointer[PixelformatIndexR + offset] = color.R; - Pointer[PixelformatIndexG + offset] = color.G; - Pointer[PixelformatIndexB + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (a,r,g,b) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * Stride); - color[ColorIndexR] = Pointer[PixelformatIndexR + offset]; - color[ColorIndexG] = Pointer[PixelformatIndexG + offset]; - color[ColorIndexB] = Pointer[PixelformatIndexB + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * Stride); - Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R - Pointer[PixelformatIndexG + offset] = color[ColorIndexG]; - Pointer[PixelformatIndexB + offset] = color[ColorIndexB]; - } - } - - /// - /// This is the implementation of the IFastBitmap for 32 bit images with Alpha - /// - public unsafe class Fast32ArgbBitmap : FastBitmap, IFastBitmapWithBlend - { - public override bool HasAlphaChannel => true; - - public Color BackgroundBlendColor { get; set; } - - public Fast32ArgbBitmap(Bitmap source, Rectangle area) : base(source, area) - { - BackgroundBlendColor = Color.White; - } - - /// - /// Retrieve the color at location x,y - /// - /// X coordinate - /// Y Coordinate - /// Color - public override Color GetColorAt(int x, int y) - { - int offset = (x * 4) + (y * Stride); - return Color.FromArgb(Pointer[PixelformatIndexA + offset], Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], - Pointer[PixelformatIndexB + offset]); - } - - /// - /// Set the color at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// - /// - /// - public override void SetColorAt(int x, int y, Color color) - { - int offset = (x * 4) + (y * Stride); - Pointer[PixelformatIndexA + offset] = color.A; - Pointer[PixelformatIndexR + offset] = color.R; - Pointer[PixelformatIndexG + offset] = color.G; - Pointer[PixelformatIndexB + offset] = color.B; - } - - /// - /// Get the color from the specified location into the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b,a) - public override void GetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * Stride); - color[ColorIndexR] = Pointer[PixelformatIndexR + offset]; - color[ColorIndexG] = Pointer[PixelformatIndexG + offset]; - color[ColorIndexB] = Pointer[PixelformatIndexB + offset]; - color[ColorIndexA] = Pointer[PixelformatIndexA + offset]; - } - - /// - /// Set the color at the specified location from the specified array - /// - /// - /// - /// byte[4] as reference (r,g,b,a) - public override void SetColorAt(int x, int y, byte[] color) - { - int offset = (x * 4) + (y * Stride); - Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R - Pointer[PixelformatIndexG + offset] = color[ColorIndexG]; - Pointer[PixelformatIndexB + offset] = color[ColorIndexB]; - Pointer[PixelformatIndexA + offset] = color[ColorIndexA]; - } - - /// - /// Retrieve the color, without alpha (is blended), at location x,y - /// Before the first time this is called the Lock() should be called once! - /// - /// X coordinate - /// Y Coordinate - /// Color - public Color GetBlendedColorAt(int x, int y) - { - int offset = (x * 4) + (y * Stride); - int a = Pointer[PixelformatIndexA + offset]; - int red = Pointer[PixelformatIndexR + offset]; - int green = Pointer[PixelformatIndexG + offset]; - int blue = Pointer[PixelformatIndexB + offset]; - - if (a < 255) - { - // As the request is to get without alpha, we blend. - int rem = 255 - a; - red = (red * a + BackgroundBlendColor.R * rem) / 255; - green = (green * a + BackgroundBlendColor.G * rem) / 255; - blue = (blue * a + BackgroundBlendColor.B * rem) / 255; - } - - return Color.FromArgb(255, red, green, blue); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; + +namespace Greenshot.Base.Core +{ + /// + /// The interface for the FastBitmap + /// + public interface IFastBitmap : IDisposable + { + /// + /// Get the color at x,y + /// The returned Color object depends on the underlying pixel format + /// + /// int x + /// int y + /// Color + Color GetColorAt(int x, int y); + + /// + /// Set the color at the specified location + /// + /// int x + /// int y + /// Color + void SetColorAt(int x, int y, Color color); + + /// + /// Get the color at x,y + /// The returned byte[] color depends on the underlying pixel format + /// + /// int x + /// int y + /// byte array + void GetColorAt(int x, int y, byte[] color); + + /// + /// Set the color at the specified location + /// + /// int x + /// int y + /// byte[] color + void SetColorAt(int x, int y, byte[] color); + + /// + /// Lock the bitmap + /// + void Lock(); + + /// + /// Unlock the bitmap + /// + void Unlock(); + + /// + /// Unlock the bitmap and get the underlying bitmap in one call + /// + /// + Bitmap UnlockAndReturnBitmap(); + + /// + /// Size of the underlying image + /// + Size Size { get; } + + /// + /// Height of the image area that this fastbitmap covers + /// + int Height { get; } + + /// + /// Width of the image area that this fastbitmap covers + /// + int Width { get; } + + /// + /// Top of the image area that this fastbitmap covers + /// + int Top { get; } + + /// + /// Left of the image area that this fastbitmap covers + /// + int Left { get; } + + /// + /// Right of the image area that this fastbitmap covers + /// + int Right { get; } + + /// + /// Bottom of the image area that this fastbitmap covers + /// + int Bottom { get; } + + /// + /// Does the underlying image need to be disposed + /// + bool NeedsDispose { get; set; } + + /// + /// Returns if this FastBitmap has an alpha channel + /// + bool HasAlphaChannel { get; } + + /// + /// Draw the stored bitmap to the destionation bitmap at the supplied point + /// + /// Graphics + /// Point with location + void DrawTo(Graphics graphics, Point destination); + + /// + /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle + /// Be aware that the stored bitmap will be resized to the specified rectangle!! + /// + /// Graphics + /// Rectangle with destination + void DrawTo(Graphics graphics, Rectangle destinationRect); + + /// + /// Return true if the coordinates are inside the FastBitmap + /// + /// + /// + /// + bool Contains(int x, int y); + + /// + /// Set the bitmap resolution + /// + /// + /// + void SetResolution(float horizontal, float vertical); + } + + /// + /// This interface can be used for when offsetting is needed + /// + public interface IFastBitmapWithOffset : IFastBitmap + { + /// + /// Return true if the coordinates are inside the FastBitmap + /// + /// + /// + /// + new bool Contains(int x, int y); + + /// + /// Set the color at the specified location, using offsetting so the original coordinates can be used + /// + /// int x + /// int y + /// Color color + new void SetColorAt(int x, int y, Color color); + + /// + /// Set the color at the specified location, using offsetting so the original coordinates can be used + /// + /// int x + /// int y + /// byte[] color + new void SetColorAt(int x, int y, byte[] color); + + /// + /// Get the color at x,y + /// The returned Color object depends on the underlying pixel format + /// + /// int x + /// int y + /// Color + new Color GetColorAt(int x, int y); + + /// + /// Get the color at x,y, using offsetting so the original coordinates can be used + /// The returned byte[] color depends on the underlying pixel format + /// + /// int x + /// int y + /// byte array + new void GetColorAt(int x, int y, byte[] color); + + new int Left { get; set; } + + new int Top { get; set; } + } + + /// + /// This interface can be used for when clipping is needed + /// + public interface IFastBitmapWithClip : IFastBitmap + { + Rectangle Clip { get; set; } + + bool InvertClip { get; set; } + + /// + /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping + /// + /// int x + /// int y + /// Color color + new void SetColorAt(int x, int y, Color color); + + /// + /// Set the color at the specified location, this doesn't do anything if the location is excluded due to clipping + /// + /// int x + /// int y + /// byte[] color + new void SetColorAt(int x, int y, byte[] color); + + /// + /// Return true if the coordinates are inside the FastBitmap and not clipped + /// + /// + /// + /// + new bool Contains(int x, int y); + } + + /// + /// This interface is implemented when there is a alpha-blending possibility + /// + public interface IFastBitmapWithBlend : IFastBitmap + { + Color BackgroundBlendColor { get; set; } + Color GetBlendedColorAt(int x, int y); + } + + /// + /// The base class for the fast bitmap implementation + /// + public abstract unsafe class FastBitmap : IFastBitmapWithClip, IFastBitmapWithOffset + { + protected const int PixelformatIndexA = 3; + protected const int PixelformatIndexR = 2; + protected const int PixelformatIndexG = 1; + protected const int PixelformatIndexB = 0; + + public const int ColorIndexR = 0; + public const int ColorIndexG = 1; + public const int ColorIndexB = 2; + public const int ColorIndexA = 3; + + protected Rectangle Area; + + /// + /// If this is set to true, the bitmap will be disposed when disposing the IFastBitmap + /// + public bool NeedsDispose { get; set; } + + public Rectangle Clip { get; set; } + + public bool InvertClip { get; set; } + + /// + /// The bitmap for which the FastBitmap is creating access + /// + protected Bitmap Bitmap; + + protected BitmapData BmData; + protected int Stride; /* bytes per pixel row */ + protected bool BitsLocked; + protected byte* Pointer; + + public static IFastBitmap Create(Bitmap source) + { + return Create(source, Rectangle.Empty); + } + + public void SetResolution(float horizontal, float vertical) + { + Bitmap.SetResolution(horizontal, vertical); + } + + /// + /// Factory for creating a FastBitmap depending on the pixelformat of the source + /// The supplied rectangle specifies the area for which the FastBitmap does its thing + /// + /// Bitmap to access + /// Rectangle which specifies the area to have access to, can be Rectangle.Empty for the whole image + /// IFastBitmap + public static IFastBitmap Create(Bitmap source, Rectangle area) + { + switch (source.PixelFormat) + { + case PixelFormat.Format8bppIndexed: + return new FastChunkyBitmap(source, area); + case PixelFormat.Format24bppRgb: + return new Fast24RgbBitmap(source, area); + case PixelFormat.Format32bppRgb: + return new Fast32RgbBitmap(source, area); + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + return new Fast32ArgbBitmap(source, area); + default: + throw new NotSupportedException($"Not supported Pixelformat {source.PixelFormat}"); + } + } + + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to clone + /// new Pixelformat + /// IFastBitmap + public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat) + { + return CreateCloneOf(source, pixelFormat, Rectangle.Empty); + } + + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to clone + /// Area of the bitmap to access, can be Rectangle.Empty for the whole + /// IFastBitmap + public static IFastBitmap CreateCloneOf(Image source, Rectangle area) + { + return CreateCloneOf(source, PixelFormat.DontCare, area); + } + + /// + /// Factory for creating a FastBitmap as a destination for the source + /// + /// Bitmap to clone + /// Pixelformat of the cloned bitmap + /// Area of the bitmap to access, can be Rectangle.Empty for the whole + /// IFastBitmap + public static IFastBitmap CreateCloneOf(Image source, PixelFormat pixelFormat, Rectangle area) + { + Bitmap destination = ImageHelper.CloneArea(source, area, pixelFormat); + FastBitmap fastBitmap = Create(destination) as FastBitmap; + if (fastBitmap != null) + { + fastBitmap.NeedsDispose = true; + fastBitmap.Left = area.Left; + fastBitmap.Top = area.Top; + } + + return fastBitmap; + } + + /// + /// Factory for creating a FastBitmap as a destination + /// + /// + /// + /// + /// IFastBitmap + public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) + { + Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f); + IFastBitmap fastBitmap = Create(destination); + fastBitmap.NeedsDispose = true; + return fastBitmap; + } + + /// + /// Constructor which stores the image and locks it when called + /// + /// Bitmap + /// Rectangle + protected FastBitmap(Bitmap bitmap, Rectangle area) + { + Bitmap = bitmap; + Rectangle bitmapArea = new Rectangle(Point.Empty, bitmap.Size); + if (area != Rectangle.Empty) + { + area.Intersect(bitmapArea); + Area = area; + } + else + { + Area = bitmapArea; + } + + // As the lock takes care that only the specified area is made available we need to calculate the offset + Left = area.Left; + Top = area.Top; + // Default cliping is done to the area without invert + Clip = Area; + InvertClip = false; + // Always lock, so we don't need to do this ourselves + Lock(); + } + + /// + /// Return the size of the image + /// + public Size Size + { + get + { + if (Area == Rectangle.Empty) + { + return Bitmap.Size; + } + + return Area.Size; + } + } + + /// + /// Return the width of the image + /// + public int Width + { + get + { + if (Area == Rectangle.Empty) + { + return Bitmap.Width; + } + + return Area.Width; + } + } + + /// + /// Return the height of the image + /// + public int Height + { + get + { + if (Area == Rectangle.Empty) + { + return Bitmap.Height; + } + + return Area.Height; + } + } + + private int _left; + + /// + /// Return the left of the fastbitmap, this is also used as an offset + /// + public int Left + { + get { return 0; } + set { _left = value; } + } + + /// + /// Return the left of the fastbitmap, this is also used as an offset + /// + int IFastBitmapWithOffset.Left + { + get { return _left; } + set { _left = value; } + } + + private int _top; + + /// + /// Return the top of the fastbitmap, this is also used as an offset + /// + public int Top + { + get { return 0; } + set { _top = value; } + } + + /// + /// Return the top of the fastbitmap, this is also used as an offset + /// + int IFastBitmapWithOffset.Top + { + get { return _top; } + set { _top = value; } + } + + /// + /// Return the right of the fastbitmap + /// + public int Right => Left + Width; + + /// + /// Return the bottom of the fastbitmap + /// + public int Bottom => Top + Height; + + /// + /// Returns the underlying bitmap, unlocks it and prevents that it will be disposed + /// + public Bitmap UnlockAndReturnBitmap() + { + if (BitsLocked) + { + Unlock(); + } + + NeedsDispose = false; + return Bitmap; + } + + public virtual bool HasAlphaChannel => false; + + /// + /// Destructor + /// + ~FastBitmap() + { + Dispose(false); + } + + /// + /// The public accessible Dispose + /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // The bulk of the clean-up code is implemented in Dispose(bool) + + /// + /// This Dispose is called from the Dispose and the Destructor. + /// When disposing==true all non-managed resources should be freed too! + /// + /// + protected virtual void Dispose(bool disposing) + { + Unlock(); + if (disposing) + { + if (Bitmap != null && NeedsDispose) + { + Bitmap.Dispose(); + } + } + + Bitmap = null; + BmData = null; + Pointer = null; + } + + /// + /// Lock the bitmap so we have direct access to the memory + /// + public void Lock() + { + if (Width <= 0 || Height <= 0 || BitsLocked) + { + return; + } + + BmData = Bitmap.LockBits(Area, ImageLockMode.ReadWrite, Bitmap.PixelFormat); + BitsLocked = true; + + IntPtr scan0 = BmData.Scan0; + Pointer = (byte*) (void*) scan0; + Stride = BmData.Stride; + } + + /// + /// Unlock the System Memory + /// + public void Unlock() + { + if (BitsLocked) + { + Bitmap.UnlockBits(BmData); + BitsLocked = false; + } + } + + /// + /// Draw the stored bitmap to the destionation bitmap at the supplied point + /// + /// + /// + public void DrawTo(Graphics graphics, Point destination) + { + DrawTo(graphics, new Rectangle(destination, Area.Size)); + } + + /// + /// Draw the stored Bitmap on the Destination bitmap with the specified rectangle + /// Be aware that the stored bitmap will be resized to the specified rectangle!! + /// + /// + /// + public void DrawTo(Graphics graphics, Rectangle destinationRect) + { + // Make sure this.bitmap is unlocked, if it was locked + bool isLocked = BitsLocked; + if (isLocked) + { + Unlock(); + } + + graphics.DrawImage(Bitmap, destinationRect, Area, GraphicsUnit.Pixel); + } + + /// + /// returns true if x & y are inside the FastBitmap + /// + /// + /// + /// true if x & y are inside the FastBitmap + public bool Contains(int x, int y) + { + return Area.Contains(x - Left, y - Top); + } + + public abstract Color GetColorAt(int x, int y); + public abstract void SetColorAt(int x, int y, Color color); + public abstract void GetColorAt(int x, int y, byte[] color); + public abstract void SetColorAt(int x, int y, byte[] color); + + bool IFastBitmapWithClip.Contains(int x, int y) + { + bool contains = Clip.Contains(x, y); + if (InvertClip) + { + return !contains; + } + else + { + return contains; + } + } + + void IFastBitmapWithClip.SetColorAt(int x, int y, byte[] color) + { + bool contains = Clip.Contains(x, y); + if ((InvertClip && contains) || (!InvertClip && !contains)) + { + return; + } + + SetColorAt(x, y, color); + } + + void IFastBitmapWithClip.SetColorAt(int x, int y, Color color) + { + bool contains = Clip.Contains(x, y); + if ((InvertClip && contains) || (!InvertClip && !contains)) + { + return; + } + + SetColorAt(x, y, color); + } + + /// + /// returns true if x & y are inside the FastBitmap + /// + /// + /// + /// true if x & y are inside the FastBitmap + bool IFastBitmapWithOffset.Contains(int x, int y) + { + return Area.Contains(x - Left, y - Top); + } + + Color IFastBitmapWithOffset.GetColorAt(int x, int y) + { + x -= _left; + y -= _top; + return GetColorAt(x, y); + } + + void IFastBitmapWithOffset.GetColorAt(int x, int y, byte[] color) + { + x -= _left; + y -= _top; + GetColorAt(x, y, color); + } + + void IFastBitmapWithOffset.SetColorAt(int x, int y, byte[] color) + { + x -= _left; + y -= _top; + SetColorAt(x, y, color); + } + + void IFastBitmapWithOffset.SetColorAt(int x, int y, Color color) + { + x -= _left; + y -= _top; + SetColorAt(x, y, color); + } + } + + /// + /// This is the implementation of the FastBitmat for the 8BPP pixelformat + /// + public unsafe class FastChunkyBitmap : FastBitmap + { + // Used for indexed images + private readonly Color[] _colorEntries; + private readonly Dictionary _colorCache = new Dictionary(); + + public FastChunkyBitmap(Bitmap source, Rectangle area) : base(source, area) + { + _colorEntries = Bitmap.Palette.Entries; + } + + /// + /// Get the color from the specified location + /// + /// + /// + /// Color + public override Color GetColorAt(int x, int y) + { + int offset = x + (y * Stride); + byte colorIndex = Pointer[offset]; + return _colorEntries[colorIndex]; + } + + /// + /// Get the color from the specified location into the specified array + /// + /// + /// + /// byte[4] as reference + public override void GetColorAt(int x, int y, byte[] color) + { + throw new NotImplementedException("No performance gain!"); + } + + /// + /// Set the color at the specified location from the specified array + /// + /// + /// + /// byte[4] as reference + public override void SetColorAt(int x, int y, byte[] color) + { + throw new NotImplementedException("No performance gain!"); + } + + /// + /// Get the color-index from the specified location + /// + /// + /// + /// byte with index + public byte GetColorIndexAt(int x, int y) + { + int offset = x + (y * Stride); + return Pointer[offset]; + } + + /// + /// Set the color-index at the specified location + /// + /// + /// + /// + public void SetColorIndexAt(int x, int y, byte colorIndex) + { + int offset = x + (y * Stride); + Pointer[offset] = colorIndex; + } + + /// + /// Set the supplied color at the specified location. + /// Throws an ArgumentException if the color is not in the palette + /// + /// + /// + /// Color to set + public override void SetColorAt(int x, int y, Color color) + { + int offset = x + (y * Stride); + if (!_colorCache.TryGetValue(color, out var colorIndex)) + { + bool foundColor = false; + for (colorIndex = 0; colorIndex < _colorEntries.Length; colorIndex++) + { + if (color == _colorEntries[colorIndex]) + { + _colorCache.Add(color, colorIndex); + foundColor = true; + break; + } + } + + if (!foundColor) + { + throw new ArgumentException("No such color!"); + } + } + + Pointer[offset] = colorIndex; + } + } + + /// + /// This is the implementation of the IFastBitmap for 24 bit images (no Alpha) + /// + public unsafe class Fast24RgbBitmap : FastBitmap + { + public Fast24RgbBitmap(Bitmap source, Rectangle area) : base(source, area) + { + } + + /// + /// Retrieve the color at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// X coordinate + /// Y Coordinate + /// Color + public override Color GetColorAt(int x, int y) + { + int offset = (x * 3) + (y * Stride); + return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]); + } + + /// + /// Set the color at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// + /// + /// + public override void SetColorAt(int x, int y, Color color) + { + int offset = (x * 3) + (y * Stride); + Pointer[PixelformatIndexR + offset] = color.R; + Pointer[PixelformatIndexG + offset] = color.G; + Pointer[PixelformatIndexB + offset] = color.B; + } + + /// + /// Get the color from the specified location into the specified array + /// + /// + /// + /// byte[4] as reference (r,g,b) + public override void GetColorAt(int x, int y, byte[] color) + { + int offset = (x * 3) + (y * Stride); + color[PixelformatIndexR] = Pointer[PixelformatIndexR + offset]; + color[PixelformatIndexG] = Pointer[PixelformatIndexG + offset]; + color[PixelformatIndexB] = Pointer[PixelformatIndexB + offset]; + } + + /// + /// Set the color at the specified location from the specified array + /// + /// + /// + /// byte[4] as reference (r,g,b) + public override void SetColorAt(int x, int y, byte[] color) + { + int offset = (x * 3) + (y * Stride); + Pointer[PixelformatIndexR + offset] = color[PixelformatIndexR]; + Pointer[PixelformatIndexG + offset] = color[PixelformatIndexG]; + Pointer[PixelformatIndexB + offset] = color[PixelformatIndexB]; + } + } + + /// + /// This is the implementation of the IFastBitmap for 32 bit images (no Alpha) + /// + public unsafe class Fast32RgbBitmap : FastBitmap + { + public Fast32RgbBitmap(Bitmap source, Rectangle area) : base(source, area) + { + } + + /// + /// Retrieve the color at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// X coordinate + /// Y Coordinate + /// Color + public override Color GetColorAt(int x, int y) + { + int offset = (x * 4) + (y * Stride); + return Color.FromArgb(255, Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], Pointer[PixelformatIndexB + offset]); + } + + /// + /// Set the color at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// + /// + /// + public override void SetColorAt(int x, int y, Color color) + { + int offset = (x * 4) + (y * Stride); + Pointer[PixelformatIndexR + offset] = color.R; + Pointer[PixelformatIndexG + offset] = color.G; + Pointer[PixelformatIndexB + offset] = color.B; + } + + /// + /// Get the color from the specified location into the specified array + /// + /// + /// + /// byte[4] as reference (a,r,g,b) + public override void GetColorAt(int x, int y, byte[] color) + { + int offset = (x * 4) + (y * Stride); + color[ColorIndexR] = Pointer[PixelformatIndexR + offset]; + color[ColorIndexG] = Pointer[PixelformatIndexG + offset]; + color[ColorIndexB] = Pointer[PixelformatIndexB + offset]; + } + + /// + /// Set the color at the specified location from the specified array + /// + /// + /// + /// byte[4] as reference (r,g,b) + public override void SetColorAt(int x, int y, byte[] color) + { + int offset = (x * 4) + (y * Stride); + Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R + Pointer[PixelformatIndexG + offset] = color[ColorIndexG]; + Pointer[PixelformatIndexB + offset] = color[ColorIndexB]; + } + } + + /// + /// This is the implementation of the IFastBitmap for 32 bit images with Alpha + /// + public unsafe class Fast32ArgbBitmap : FastBitmap, IFastBitmapWithBlend + { + public override bool HasAlphaChannel => true; + + public Color BackgroundBlendColor { get; set; } + + public Fast32ArgbBitmap(Bitmap source, Rectangle area) : base(source, area) + { + BackgroundBlendColor = Color.White; + } + + /// + /// Retrieve the color at location x,y + /// + /// X coordinate + /// Y Coordinate + /// Color + public override Color GetColorAt(int x, int y) + { + int offset = (x * 4) + (y * Stride); + return Color.FromArgb(Pointer[PixelformatIndexA + offset], Pointer[PixelformatIndexR + offset], Pointer[PixelformatIndexG + offset], + Pointer[PixelformatIndexB + offset]); + } + + /// + /// Set the color at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// + /// + /// + public override void SetColorAt(int x, int y, Color color) + { + int offset = (x * 4) + (y * Stride); + Pointer[PixelformatIndexA + offset] = color.A; + Pointer[PixelformatIndexR + offset] = color.R; + Pointer[PixelformatIndexG + offset] = color.G; + Pointer[PixelformatIndexB + offset] = color.B; + } + + /// + /// Get the color from the specified location into the specified array + /// + /// + /// + /// byte[4] as reference (r,g,b,a) + public override void GetColorAt(int x, int y, byte[] color) + { + int offset = (x * 4) + (y * Stride); + color[ColorIndexR] = Pointer[PixelformatIndexR + offset]; + color[ColorIndexG] = Pointer[PixelformatIndexG + offset]; + color[ColorIndexB] = Pointer[PixelformatIndexB + offset]; + color[ColorIndexA] = Pointer[PixelformatIndexA + offset]; + } + + /// + /// Set the color at the specified location from the specified array + /// + /// + /// + /// byte[4] as reference (r,g,b,a) + public override void SetColorAt(int x, int y, byte[] color) + { + int offset = (x * 4) + (y * Stride); + Pointer[PixelformatIndexR + offset] = color[ColorIndexR]; // R + Pointer[PixelformatIndexG + offset] = color[ColorIndexG]; + Pointer[PixelformatIndexB + offset] = color[ColorIndexB]; + Pointer[PixelformatIndexA + offset] = color[ColorIndexA]; + } + + /// + /// Retrieve the color, without alpha (is blended), at location x,y + /// Before the first time this is called the Lock() should be called once! + /// + /// X coordinate + /// Y Coordinate + /// Color + public Color GetBlendedColorAt(int x, int y) + { + int offset = (x * 4) + (y * Stride); + int a = Pointer[PixelformatIndexA + offset]; + int red = Pointer[PixelformatIndexR + offset]; + int green = Pointer[PixelformatIndexG + offset]; + int blue = Pointer[PixelformatIndexB + offset]; + + if (a < 255) + { + // As the request is to get without alpha, we blend. + int rem = 255 - a; + red = (red * a + BackgroundBlendColor.R * rem) / 255; + green = (green * a + BackgroundBlendColor.G * rem) / 255; + blue = (blue * a + BackgroundBlendColor.B * rem) / 255; + } + + return Color.FromArgb(255, red, green, blue); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/FilenameHelper.cs b/src/Greenshot.Base/Core/FilenameHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/FilenameHelper.cs rename to src/Greenshot.Base/Core/FilenameHelper.cs index 6d8073843..83a76f438 100644 --- a/src/GreenshotPlugin/Core/FilenameHelper.cs +++ b/src/Greenshot.Base/Core/FilenameHelper.cs @@ -1,705 +1,705 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections; -using System.IO; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using log4net; -using System.Collections.Generic; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPlugin.Core -{ - public static class FilenameHelper - { - private static readonly ILog Log = LogManager.GetLogger(typeof(FilenameHelper)); - - // Specify the regular expression for the filename formatting: - // Starting with ${ - // than the varname, which ends with a : or } - // If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters. - // The parameter format is a single alpha followed by the value belonging to the parameter, e.g. : - // ${capturetime:d"yyyy-MM-dd HH_mm_ss"} - private static readonly Regex VarRegexp = new Regex(@"\${(?[^:}]+)[:]?(?[^}]*)}", RegexOptions.Compiled); - private static readonly Regex CmdVarRegexp = new Regex(@"%(?[^%]+)%", RegexOptions.Compiled); - - private static readonly Regex SplitRegexp = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled); - private const int MaxTitleLength = 80; - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private const string UnsafeReplacement = "_"; - private static readonly Random RandomNumberGen = new Random(); - private static readonly Regex RandRegexp = new Regex("^R+$", RegexOptions.Compiled); - - /// - /// Remove invalid characters from the fully qualified filename - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakeFqFilenameSafe(string fullPath) - { - string path = MakePathSafe(Path.GetDirectoryName(fullPath)); - string filename = MakeFilenameSafe(Path.GetFileName(fullPath)); - // Make the fullpath again and return - return Path.Combine(path, filename); - } - - /// - /// Remove invalid characters from the filename - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakeFilenameSafe(string filename) - { - // Make the filename save! - if (filename != null) - { - foreach (char disallowed in Path.GetInvalidFileNameChars()) - { - filename = filename.Replace(disallowed.ToString(), UnsafeReplacement); - } - } - - return filename; - } - - /// - /// Remove invalid characters from the path - /// - /// string with the full path to a file - /// string with the full path to a file, without invalid characters - public static string MakePathSafe(string path) - { - // Make the path save! - if (path != null) - { - foreach (char disallowed in Path.GetInvalidPathChars()) - { - path = path.Replace(disallowed.ToString(), UnsafeReplacement); - } - } - - return path; - } - - public static string GetFilenameWithoutExtensionFromPattern(string pattern) - { - return GetFilenameWithoutExtensionFromPattern(pattern, null); - } - - public static string GetFilenameWithoutExtensionFromPattern(string pattern, ICaptureDetails captureDetails) - { - return FillPattern(pattern, captureDetails, true); - } - - public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat) - { - return GetFilenameFromPattern(pattern, imageFormat, null); - } - - public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat, ICaptureDetails captureDetails) - { - return FillPattern(pattern, captureDetails, true) + "." + imageFormat.ToString().ToLower(); - } - - /// - /// Return a filename for the current image format (png,jpg etc) with the default file pattern - /// that is specified in the configuration - /// - /// A string with the format - /// - /// The filename which should be used to save the image - public static string GetFilename(OutputFormat format, ICaptureDetails captureDetails) - { - string pattern = CoreConfig.OutputFileFilenamePattern; - if (string.IsNullOrEmpty(pattern?.Trim())) - { - pattern = "greenshot ${capturetime}"; - } - - return GetFilenameFromPattern(pattern, format, captureDetails); - } - - - /// - /// This method will be called by the regexp.replace as a MatchEvaluator delegate! - /// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions - /// - /// What are we matching? - /// The detail, can be null - /// Variables from the process - /// Variables from the user - /// Variables from the machine - /// - /// string with the match replacement - private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, - bool filenameSafeMode) - { - try - { - return MatchVarEvaluatorInternal(match, captureDetails, processVars, userVars, machineVars, filenameSafeMode); - } - catch (Exception e) - { - Log.Error("Error in MatchVarEvaluatorInternal", e); - } - - return string.Empty; - } - - /// - /// This method will be called by the regexp.replace as a MatchEvaluator delegate! - /// - /// What are we matching? - /// The detail, can be null - /// - /// - /// - /// - /// - private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, - bool filenameSafeMode) - { - // some defaults - int padWidth = 0; - int startIndex = 0; - int endIndex = 0; - char padChar = ' '; - string dateFormat = "yyyy-MM-dd HH-mm-ss"; - IDictionary replacements = new Dictionary(); - string replaceValue = string.Empty; - string variable = match.Groups["variable"].Value; - string parameters = match.Groups["parameters"].Value; - string randomChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - if (parameters.Length > 0) - { - string[] parms = SplitRegexp.Split(parameters); - foreach (string parameter in parms) - { - switch (parameter.Substring(0, 1)) - { - // Padding p[,pad-character] - case "p": - string[] padParams = parameter.Substring(1).Split(','); - try - { - padWidth = int.Parse(padParams[0]); - } - catch - { - // ignored - } - - if (padParams.Length > 1) - { - padChar = padParams[1][0]; - } - - break; - // replace - // r, - case "r": - string[] replaceParameters = parameter.Substring(1).Split(','); - if (replaceParameters != null && replaceParameters.Length == 2) - { - replacements.Add(replaceParameters[0], replaceParameters[1]); - } - - break; - // Dateformat d - // Format can be anything that is used in C# date formatting - case "d": - dateFormat = parameter.Substring(1); - if (dateFormat.StartsWith("\"")) - { - dateFormat = dateFormat.Substring(1); - } - - if (dateFormat.EndsWith("\"")) - { - dateFormat = dateFormat.Substring(0, dateFormat.Length - 1); - } - - break; - // Substring: - // s[,length] - case "s": - string range = parameter.Substring(1); - string[] rangelist = range.Split(','); - if (rangelist.Length > 0) - { - try - { - startIndex = int.Parse(rangelist[0]); - } - catch - { - // Ignore - } - } - - if (rangelist.Length > 1) - { - try - { - endIndex = int.Parse(rangelist[1]); - } - catch - { - // Ignore - } - } - - break; - } - } - } - - if (processVars != null && processVars.Contains(variable)) - { - replaceValue = (string) processVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (userVars != null && userVars.Contains(variable)) - { - replaceValue = (string) userVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (machineVars != null && machineVars.Contains(variable)) - { - replaceValue = (string) machineVars[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (captureDetails?.MetaData != null && captureDetails.MetaData.ContainsKey(variable)) - { - replaceValue = captureDetails.MetaData[variable]; - if (filenameSafeMode) - { - replaceValue = MakePathSafe(replaceValue); - } - } - else if (RandRegexp.IsMatch(variable)) - { - for (int i = 0; i < variable.Length; i++) - { - replaceValue += randomChars[RandomNumberGen.Next(randomChars.Length)]; - } - } - else - { - // Handle other variables - // Default use "now" for the capture take´n - DateTime capturetime = DateTime.Now; - // Use default application name for title - string title = Application.ProductName; - - // Check if we have capture details - if (captureDetails != null) - { - capturetime = captureDetails.DateTime; - if (captureDetails.Title != null) - { - title = captureDetails.Title; - if (title.Length > MaxTitleLength) - { - title = title.Substring(0, MaxTitleLength); - } - } - } - - switch (variable) - { - case "domain": - replaceValue = Environment.UserDomainName; - break; - case "user": - replaceValue = Environment.UserName; - break; - case "hostname": - replaceValue = Environment.MachineName; - break; - case "YYYY": - if (padWidth == 0) - { - padWidth = -4; - padChar = '0'; - } - - replaceValue = capturetime.Year.ToString(); - break; - case "MM": - replaceValue = capturetime.Month.ToString(); - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - - break; - case "DD": - replaceValue = capturetime.Day.ToString(); - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - - break; - case "hh": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - - replaceValue = capturetime.Hour.ToString(); - break; - case "mm": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - - replaceValue = capturetime.Minute.ToString(); - break; - case "ss": - if (padWidth == 0) - { - padWidth = -2; - padChar = '0'; - } - - replaceValue = capturetime.Second.ToString(); - break; - case "now": - replaceValue = DateTime.Now.ToString(dateFormat); - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - - break; - case "capturetime": - replaceValue = capturetime.ToString(dateFormat); - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - - break; - case "NUM": - CoreConfig.OutputFileIncrementingNumber++; - IniConfig.Save(); - replaceValue = CoreConfig.OutputFileIncrementingNumber.ToString(); - if (padWidth == 0) - { - padWidth = -6; - padChar = '0'; - } - - break; - case "title": - replaceValue = title; - if (filenameSafeMode) - { - replaceValue = MakeFilenameSafe(replaceValue); - } - - break; - case "MyPictures": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - break; - case "MyMusic": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic); - break; - case "MyDocuments": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - break; - case "Personal": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Personal); - break; - case "Desktop": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); - break; - case "ApplicationData": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - break; - case "LocalApplicationData": - replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - break; - } - } - - // do padding - if (padWidth > 0) - { - replaceValue = replaceValue.PadRight(padWidth, padChar); - } - else if (padWidth < 0) - { - replaceValue = replaceValue.PadLeft(-padWidth, padChar); - } - - // do substring - if (startIndex != 0 || endIndex != 0) - { - if (startIndex < 0) - { - startIndex = replaceValue.Length + startIndex; - } - - if (endIndex < 0) - { - endIndex = replaceValue.Length + endIndex; - } - - if (endIndex != 0) - { - try - { - replaceValue = replaceValue.Substring(startIndex, endIndex); - } - catch - { - // Ignore - } - } - else - { - try - { - replaceValue = replaceValue.Substring(startIndex); - } - catch - { - // Ignore - } - } - } - - // new for feature #697 - if (replacements.Count > 0) - { - foreach (string oldValue in replacements.Keys) - { - replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]); - } - } - - return replaceValue; - } - - /// - /// "Simply" fill the pattern with environment variables - /// - /// String with pattern %var% - /// true to make sure everything is filenamesafe - /// Filled string - public static string FillCmdVariables(string pattern, bool filenameSafeMode = true) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - return CmdVarRegexp.Replace(pattern, - m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode) - ); - } - - /// - /// "Simply" fill the pattern with environment variables - /// - /// String with pattern ${var} - /// true to make sure everything is filenamesafe - /// Filled string - public static string FillVariables(string pattern, bool filenameSafeMode) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - return VarRegexp.Replace(pattern, - m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode) - ); - } - - /// - /// Fill the pattern wit the supplied details - /// - /// Pattern - /// CaptureDetails, can be null - /// Should the result be made "filename" safe? - /// Filled pattern - public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode) - { - IDictionary processVars = null; - IDictionary userVars = null; - IDictionary machineVars = null; - try - { - processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); - } - - try - { - userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.User", e); - } - - try - { - machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); - } - catch (Exception e) - { - Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); - } - - try - { - return VarRegexp.Replace(pattern, - m => MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode) - ); - } - catch (Exception e) - { - // adding additional data for bug tracking - if (captureDetails != null) - { - e.Data.Add("title", captureDetails.Title); - } - - e.Data.Add("pattern", pattern); - throw; - } - } - - /// - /// Checks whether a directory name is valid in the current file system - /// - /// directory name (not path!) - /// true if directory name is valid - public static bool IsDirectoryNameValid(string directoryName) - { - var forbiddenChars = Path.GetInvalidPathChars(); - foreach (var forbiddenChar in forbiddenChars) - { - if (directoryName == null || directoryName.Contains(forbiddenChar.ToString())) - { - return false; - } - } - - return true; - } - - /// - /// Checks whether a filename is valid in the current file system - /// - /// name of the file - /// true if filename is valid - public static bool IsFilenameValid(string filename) - { - var forbiddenChars = Path.GetInvalidFileNameChars(); - foreach (var forbiddenChar in forbiddenChars) - { - if (filename == null || filename.Contains(forbiddenChar.ToString())) - { - return false; - } - } - - return true; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using log4net; + +namespace Greenshot.Base.Core +{ + public static class FilenameHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(FilenameHelper)); + + // Specify the regular expression for the filename formatting: + // Starting with ${ + // than the varname, which ends with a : or } + // If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters. + // The parameter format is a single alpha followed by the value belonging to the parameter, e.g. : + // ${capturetime:d"yyyy-MM-dd HH_mm_ss"} + private static readonly Regex VarRegexp = new Regex(@"\${(?[^:}]+)[:]?(?[^}]*)}", RegexOptions.Compiled); + private static readonly Regex CmdVarRegexp = new Regex(@"%(?[^%]+)%", RegexOptions.Compiled); + + private static readonly Regex SplitRegexp = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled); + private const int MaxTitleLength = 80; + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private const string UnsafeReplacement = "_"; + private static readonly Random RandomNumberGen = new Random(); + private static readonly Regex RandRegexp = new Regex("^R+$", RegexOptions.Compiled); + + /// + /// Remove invalid characters from the fully qualified filename + /// + /// string with the full path to a file + /// string with the full path to a file, without invalid characters + public static string MakeFqFilenameSafe(string fullPath) + { + string path = MakePathSafe(Path.GetDirectoryName(fullPath)); + string filename = MakeFilenameSafe(Path.GetFileName(fullPath)); + // Make the fullpath again and return + return Path.Combine(path, filename); + } + + /// + /// Remove invalid characters from the filename + /// + /// string with the full path to a file + /// string with the full path to a file, without invalid characters + public static string MakeFilenameSafe(string filename) + { + // Make the filename save! + if (filename != null) + { + foreach (char disallowed in Path.GetInvalidFileNameChars()) + { + filename = filename.Replace(disallowed.ToString(), UnsafeReplacement); + } + } + + return filename; + } + + /// + /// Remove invalid characters from the path + /// + /// string with the full path to a file + /// string with the full path to a file, without invalid characters + public static string MakePathSafe(string path) + { + // Make the path save! + if (path != null) + { + foreach (char disallowed in Path.GetInvalidPathChars()) + { + path = path.Replace(disallowed.ToString(), UnsafeReplacement); + } + } + + return path; + } + + public static string GetFilenameWithoutExtensionFromPattern(string pattern) + { + return GetFilenameWithoutExtensionFromPattern(pattern, null); + } + + public static string GetFilenameWithoutExtensionFromPattern(string pattern, ICaptureDetails captureDetails) + { + return FillPattern(pattern, captureDetails, true); + } + + public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat) + { + return GetFilenameFromPattern(pattern, imageFormat, null); + } + + public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat, ICaptureDetails captureDetails) + { + return FillPattern(pattern, captureDetails, true) + "." + imageFormat.ToString().ToLower(); + } + + /// + /// Return a filename for the current image format (png,jpg etc) with the default file pattern + /// that is specified in the configuration + /// + /// A string with the format + /// + /// The filename which should be used to save the image + public static string GetFilename(OutputFormat format, ICaptureDetails captureDetails) + { + string pattern = CoreConfig.OutputFileFilenamePattern; + if (string.IsNullOrEmpty(pattern?.Trim())) + { + pattern = "greenshot ${capturetime}"; + } + + return GetFilenameFromPattern(pattern, format, captureDetails); + } + + + /// + /// This method will be called by the regexp.replace as a MatchEvaluator delegate! + /// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions + /// + /// What are we matching? + /// The detail, can be null + /// Variables from the process + /// Variables from the user + /// Variables from the machine + /// + /// string with the match replacement + private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, + bool filenameSafeMode) + { + try + { + return MatchVarEvaluatorInternal(match, captureDetails, processVars, userVars, machineVars, filenameSafeMode); + } + catch (Exception e) + { + Log.Error("Error in MatchVarEvaluatorInternal", e); + } + + return string.Empty; + } + + /// + /// This method will be called by the regexp.replace as a MatchEvaluator delegate! + /// + /// What are we matching? + /// The detail, can be null + /// + /// + /// + /// + /// + private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, + bool filenameSafeMode) + { + // some defaults + int padWidth = 0; + int startIndex = 0; + int endIndex = 0; + char padChar = ' '; + string dateFormat = "yyyy-MM-dd HH-mm-ss"; + IDictionary replacements = new Dictionary(); + string replaceValue = string.Empty; + string variable = match.Groups["variable"].Value; + string parameters = match.Groups["parameters"].Value; + string randomChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + if (parameters.Length > 0) + { + string[] parms = SplitRegexp.Split(parameters); + foreach (string parameter in parms) + { + switch (parameter.Substring(0, 1)) + { + // Padding p[,pad-character] + case "p": + string[] padParams = parameter.Substring(1).Split(','); + try + { + padWidth = int.Parse(padParams[0]); + } + catch + { + // ignored + } + + if (padParams.Length > 1) + { + padChar = padParams[1][0]; + } + + break; + // replace + // r, + case "r": + string[] replaceParameters = parameter.Substring(1).Split(','); + if (replaceParameters != null && replaceParameters.Length == 2) + { + replacements.Add(replaceParameters[0], replaceParameters[1]); + } + + break; + // Dateformat d + // Format can be anything that is used in C# date formatting + case "d": + dateFormat = parameter.Substring(1); + if (dateFormat.StartsWith("\"")) + { + dateFormat = dateFormat.Substring(1); + } + + if (dateFormat.EndsWith("\"")) + { + dateFormat = dateFormat.Substring(0, dateFormat.Length - 1); + } + + break; + // Substring: + // s[,length] + case "s": + string range = parameter.Substring(1); + string[] rangelist = range.Split(','); + if (rangelist.Length > 0) + { + try + { + startIndex = int.Parse(rangelist[0]); + } + catch + { + // Ignore + } + } + + if (rangelist.Length > 1) + { + try + { + endIndex = int.Parse(rangelist[1]); + } + catch + { + // Ignore + } + } + + break; + } + } + } + + if (processVars != null && processVars.Contains(variable)) + { + replaceValue = (string) processVars[variable]; + if (filenameSafeMode) + { + replaceValue = MakePathSafe(replaceValue); + } + } + else if (userVars != null && userVars.Contains(variable)) + { + replaceValue = (string) userVars[variable]; + if (filenameSafeMode) + { + replaceValue = MakePathSafe(replaceValue); + } + } + else if (machineVars != null && machineVars.Contains(variable)) + { + replaceValue = (string) machineVars[variable]; + if (filenameSafeMode) + { + replaceValue = MakePathSafe(replaceValue); + } + } + else if (captureDetails?.MetaData != null && captureDetails.MetaData.ContainsKey(variable)) + { + replaceValue = captureDetails.MetaData[variable]; + if (filenameSafeMode) + { + replaceValue = MakePathSafe(replaceValue); + } + } + else if (RandRegexp.IsMatch(variable)) + { + for (int i = 0; i < variable.Length; i++) + { + replaceValue += randomChars[RandomNumberGen.Next(randomChars.Length)]; + } + } + else + { + // Handle other variables + // Default use "now" for the capture take´n + DateTime capturetime = DateTime.Now; + // Use default application name for title + string title = Application.ProductName; + + // Check if we have capture details + if (captureDetails != null) + { + capturetime = captureDetails.DateTime; + if (captureDetails.Title != null) + { + title = captureDetails.Title; + if (title.Length > MaxTitleLength) + { + title = title.Substring(0, MaxTitleLength); + } + } + } + + switch (variable) + { + case "domain": + replaceValue = Environment.UserDomainName; + break; + case "user": + replaceValue = Environment.UserName; + break; + case "hostname": + replaceValue = Environment.MachineName; + break; + case "YYYY": + if (padWidth == 0) + { + padWidth = -4; + padChar = '0'; + } + + replaceValue = capturetime.Year.ToString(); + break; + case "MM": + replaceValue = capturetime.Month.ToString(); + if (padWidth == 0) + { + padWidth = -2; + padChar = '0'; + } + + break; + case "DD": + replaceValue = capturetime.Day.ToString(); + if (padWidth == 0) + { + padWidth = -2; + padChar = '0'; + } + + break; + case "hh": + if (padWidth == 0) + { + padWidth = -2; + padChar = '0'; + } + + replaceValue = capturetime.Hour.ToString(); + break; + case "mm": + if (padWidth == 0) + { + padWidth = -2; + padChar = '0'; + } + + replaceValue = capturetime.Minute.ToString(); + break; + case "ss": + if (padWidth == 0) + { + padWidth = -2; + padChar = '0'; + } + + replaceValue = capturetime.Second.ToString(); + break; + case "now": + replaceValue = DateTime.Now.ToString(dateFormat); + if (filenameSafeMode) + { + replaceValue = MakeFilenameSafe(replaceValue); + } + + break; + case "capturetime": + replaceValue = capturetime.ToString(dateFormat); + if (filenameSafeMode) + { + replaceValue = MakeFilenameSafe(replaceValue); + } + + break; + case "NUM": + CoreConfig.OutputFileIncrementingNumber++; + IniConfig.Save(); + replaceValue = CoreConfig.OutputFileIncrementingNumber.ToString(); + if (padWidth == 0) + { + padWidth = -6; + padChar = '0'; + } + + break; + case "title": + replaceValue = title; + if (filenameSafeMode) + { + replaceValue = MakeFilenameSafe(replaceValue); + } + + break; + case "MyPictures": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); + break; + case "MyMusic": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic); + break; + case "MyDocuments": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + break; + case "Personal": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + break; + case "Desktop": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); + break; + case "ApplicationData": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + break; + case "LocalApplicationData": + replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + break; + } + } + + // do padding + if (padWidth > 0) + { + replaceValue = replaceValue.PadRight(padWidth, padChar); + } + else if (padWidth < 0) + { + replaceValue = replaceValue.PadLeft(-padWidth, padChar); + } + + // do substring + if (startIndex != 0 || endIndex != 0) + { + if (startIndex < 0) + { + startIndex = replaceValue.Length + startIndex; + } + + if (endIndex < 0) + { + endIndex = replaceValue.Length + endIndex; + } + + if (endIndex != 0) + { + try + { + replaceValue = replaceValue.Substring(startIndex, endIndex); + } + catch + { + // Ignore + } + } + else + { + try + { + replaceValue = replaceValue.Substring(startIndex); + } + catch + { + // Ignore + } + } + } + + // new for feature #697 + if (replacements.Count > 0) + { + foreach (string oldValue in replacements.Keys) + { + replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]); + } + } + + return replaceValue; + } + + /// + /// "Simply" fill the pattern with environment variables + /// + /// String with pattern %var% + /// true to make sure everything is filenamesafe + /// Filled string + public static string FillCmdVariables(string pattern, bool filenameSafeMode = true) + { + IDictionary processVars = null; + IDictionary userVars = null; + IDictionary machineVars = null; + try + { + processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); + } + + try + { + userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.User", e); + } + + try + { + machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); + } + + return CmdVarRegexp.Replace(pattern, + m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode) + ); + } + + /// + /// "Simply" fill the pattern with environment variables + /// + /// String with pattern ${var} + /// true to make sure everything is filenamesafe + /// Filled string + public static string FillVariables(string pattern, bool filenameSafeMode) + { + IDictionary processVars = null; + IDictionary userVars = null; + IDictionary machineVars = null; + try + { + processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); + } + + try + { + userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.User", e); + } + + try + { + machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); + } + + return VarRegexp.Replace(pattern, + m => MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode) + ); + } + + /// + /// Fill the pattern wit the supplied details + /// + /// Pattern + /// CaptureDetails, can be null + /// Should the result be made "filename" safe? + /// Filled pattern + public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode) + { + IDictionary processVars = null; + IDictionary userVars = null; + IDictionary machineVars = null; + try + { + processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Process", e); + } + + try + { + userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.User", e); + } + + try + { + machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine); + } + catch (Exception e) + { + Log.Error("Error retrieving EnvironmentVariableTarget.Machine", e); + } + + try + { + return VarRegexp.Replace(pattern, + m => MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode) + ); + } + catch (Exception e) + { + // adding additional data for bug tracking + if (captureDetails != null) + { + e.Data.Add("title", captureDetails.Title); + } + + e.Data.Add("pattern", pattern); + throw; + } + } + + /// + /// Checks whether a directory name is valid in the current file system + /// + /// directory name (not path!) + /// true if directory name is valid + public static bool IsDirectoryNameValid(string directoryName) + { + var forbiddenChars = Path.GetInvalidPathChars(); + foreach (var forbiddenChar in forbiddenChars) + { + if (directoryName == null || directoryName.Contains(forbiddenChar.ToString())) + { + return false; + } + } + + return true; + } + + /// + /// Checks whether a filename is valid in the current file system + /// + /// name of the file + /// true if filename is valid + public static bool IsFilenameValid(string filename) + { + var forbiddenChars = Path.GetInvalidFileNameChars(); + foreach (var forbiddenChar in forbiddenChars) + { + if (filename == null || filename.Contains(forbiddenChar.ToString())) + { + return false; + } + } + + return true; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/Fraction.cs b/src/Greenshot.Base/Core/Fraction.cs similarity index 99% rename from src/GreenshotPlugin/Core/Fraction.cs rename to src/Greenshot.Base/Core/Fraction.cs index 94c4fddf4..e7d999445 100644 --- a/src/GreenshotPlugin/Core/Fraction.cs +++ b/src/Greenshot.Base/Core/Fraction.cs @@ -1,7 +1,7 @@ using System; using System.Text.RegularExpressions; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// Basic Fraction (Rational) numbers with features only needed to represent scale factors. diff --git a/src/GreenshotPlugin/Core/GreenshotResources.cs b/src/Greenshot.Base/Core/GreenshotResources.cs similarity index 95% rename from src/GreenshotPlugin/Core/GreenshotResources.cs rename to src/Greenshot.Base/Core/GreenshotResources.cs index b4de5d007..29248012e 100644 --- a/src/GreenshotPlugin/Core/GreenshotResources.cs +++ b/src/Greenshot.Base/Core/GreenshotResources.cs @@ -1,49 +1,49 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Drawing; - -namespace GreenshotPlugin.Core -{ - /// - /// Centralized storage of the icons & bitmaps - /// - public static class GreenshotResources - { - private static readonly ComponentResourceManager GreenshotResourceManager = new ComponentResourceManager(typeof(GreenshotResources)); - - public static Image GetImage(string imageName) - { - return (Image) GreenshotResourceManager.GetObject(imageName); - } - - public static Icon GetIcon(string imageName) - { - return (Icon) GreenshotResourceManager.GetObject(imageName); - } - - public static Icon GetGreenshotIcon() - { - return GetIcon("Greenshot.Icon"); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Drawing; + +namespace Greenshot.Base.Core +{ + /// + /// Centralized storage of the icons & bitmaps + /// + public static class GreenshotResources + { + private static readonly ComponentResourceManager GreenshotResourceManager = new ComponentResourceManager(typeof(GreenshotResources)); + + public static Image GetImage(string imageName) + { + return (Image) GreenshotResourceManager.GetObject(imageName); + } + + public static Icon GetIcon(string imageName) + { + return (Icon) GreenshotResourceManager.GetObject(imageName); + } + + public static Icon GetGreenshotIcon() + { + return GetIcon("Greenshot.Icon"); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/GreenshotResources.resx b/src/Greenshot.Base/Core/GreenshotResources.resx similarity index 98% rename from src/GreenshotPlugin/Core/GreenshotResources.resx rename to src/Greenshot.Base/Core/GreenshotResources.resx index 521a6125f..ea1760d58 100644 --- a/src/GreenshotPlugin/Core/GreenshotResources.resx +++ b/src/Greenshot.Base/Core/GreenshotResources.resx @@ -1,471 +1,471 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA - CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA - ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP - 6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By - cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB - ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC - QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF - gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES - lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97 - 7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz - fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64 - hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2 - bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G - m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE - k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6 - zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E - IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j - vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF - Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6 - zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t - xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb - REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK - 0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt - mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd - I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm - Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0 - uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH - 6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz - l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q - iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr - hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM - BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R - q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g - PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp - NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP - 4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1 - VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF - IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS - Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW - hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5 - FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/ - SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU - wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A - MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY - dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D - lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y - ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct - KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p - 5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0 - JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n - AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y - dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx - KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO - IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo - NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn - RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY - cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv - TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH - 5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb - jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq - WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO - Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB - ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg - wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV - /xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ - 2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25 - rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM - ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7 - r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT - iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o - zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw - +u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw - CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC - 27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N - 7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1 - zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl - Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3 - kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO - PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl - AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt - xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC - NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E - zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq - ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg - d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ - 6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa - w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa - /8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t - ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK - QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb - LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN - eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF - zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW - 20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM - 1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh - NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt - iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr - m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01 - bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt - CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh - HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ - 6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb - mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8 - PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu - ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk - i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX - smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL - 2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx - /50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb - /1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK - /zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR - /xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw - wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP - WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw - CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ - ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw - AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL - AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb - AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA - AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/ - //8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C - SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA - AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA - BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA - AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA - AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB - HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA - AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA - AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs - SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA - AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke - AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA - AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo - HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA - AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK - SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M - SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA - AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA - AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx - SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA - AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA - AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA - AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4 - TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq - d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg - lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR - xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB - +ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE - UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU - LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA - AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/ - //8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/ - 9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/ - 0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/ - l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/ - cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/ - UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy - Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ - Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs - APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA - AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA - AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA - Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA - JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA - AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS - REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA - ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W - ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw - CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+ - FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB - AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1 - VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk - iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV - uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE - 7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA - kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG - cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi - UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm - LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA - AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/ - //8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/ - 5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/ - trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/ - kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/ - cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0 - Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm - Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+ - Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR - LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn - OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD - AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA - AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka - AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO - OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo - DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA - AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy - XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg - mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL - 2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA - z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA - sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI - kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw - cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA - UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv - JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA - AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/ - //8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/ - 1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/ - scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/ - kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2 - cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0 - Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY - Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV - AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA - AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF - JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - - - - - iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA//// - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA - Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I - k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU - HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw - zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK - 0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH - 70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+ - ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j - 12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM - sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+ - 2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ - abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ - EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I - U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE - HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry - j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF - IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+ - Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh - u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l - 1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq - 4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl - /P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP - MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4 - Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L - QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv - 5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm - A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf - f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/ - zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX - CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2 - mXizAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL - AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU - wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ - UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw - vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p - ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC - 4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son - bfJW/NwRDyIAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L - QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6 - 9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg - uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8 - VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt - t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+ - IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA + CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA + ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP + 6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By + cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB + ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC + QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF + gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES + lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97 + 7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz + fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64 + hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2 + bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G + m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE + k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6 + zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E + IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j + vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF + Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6 + zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t + xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb + REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK + 0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt + mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd + I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm + Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0 + uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH + 6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz + l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q + iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr + hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM + BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R + q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g + PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp + NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP + 4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1 + VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF + IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS + Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW + hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5 + FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/ + SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU + wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A + MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY + dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D + lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y + ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct + KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p + 5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0 + JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n + AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y + dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx + KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO + IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo + NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn + RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY + cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv + TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH + 5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb + jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq + WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO + Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB + ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg + wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV + /xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ + 2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25 + rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM + ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7 + r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT + iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o + zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw + +u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw + CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC + 27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N + 7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1 + zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl + Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3 + kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO + PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl + AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt + xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC + NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E + zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq + ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg + d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ + 6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa + w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa + /8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t + ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK + QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb + LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN + eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF + zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW + 20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM + 1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh + NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt + iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr + m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01 + bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt + CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh + HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ + 6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb + mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8 + PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu + ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk + i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX + smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL + 2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx + /50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb + /1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK + /zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR + /xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw + wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP + WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw + CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ + ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw + AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL + AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb + AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA + AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/ + //8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C + SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA + AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA + BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA + AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA + AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB + HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA + AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA + AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs + SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA + AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke + AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA + AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo + HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA + AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK + SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M + SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA + AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx + SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA + AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA + AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA + AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA + AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA + AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA + AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA + AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4 + TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq + d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg + lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR + xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB + +ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE + UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU + LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA + AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/ + //8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/ + 9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/ + 0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/ + l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/ + cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/ + UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy + Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ + Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs + APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA + AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA + AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA + Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA + JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA + AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS + REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA + ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W + ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw + CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+ + FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB + AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1 + VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk + iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV + uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE + 7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA + kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG + cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi + UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm + LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA + AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/ + //8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/ + 5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/ + trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/ + kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/ + cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0 + Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm + Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+ + Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR + LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn + OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD + AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA + AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka + AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO + OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo + DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA + AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy + XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg + mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL + 2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA + z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA + sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI + kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw + cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA + UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv + JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA + AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/ + //8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/ + 1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/ + scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/ + kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2 + cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0 + Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY + Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV + AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA + AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF + JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + + + + iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA//// + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA + Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I + k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU + HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw + zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK + 0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH + 70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+ + ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j + 12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM + sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+ + 2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ + abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ + EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I + U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE + HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry + j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF + IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+ + Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh + u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l + 1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq + 4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl + /P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP + MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4 + Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L + QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv + 5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm + A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf + f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/ + zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX + CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2 + mXizAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL + AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU + wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ + UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw + vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p + ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC + 4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son + bfJW/NwRDyIAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L + QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6 + 9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg + uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8 + VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt + t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+ + IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC + + \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/HResultExtensions.cs b/src/Greenshot.Base/Core/HResultExtensions.cs similarity index 96% rename from src/GreenshotPlugin/Core/HResultExtensions.cs rename to src/Greenshot.Base/Core/HResultExtensions.cs index 891f48908..9550101fd 100644 --- a/src/GreenshotPlugin/Core/HResultExtensions.cs +++ b/src/Greenshot.Base/Core/HResultExtensions.cs @@ -17,10 +17,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using GreenshotPlugin.Core.Enums; using System.Diagnostics.Contracts; +using Greenshot.Base.Core.Enums; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// Extensions to handle the HResult diff --git a/src/GreenshotPlugin/Core/IEHelper.cs b/src/Greenshot.Base/Core/IEHelper.cs similarity index 96% rename from src/GreenshotPlugin/Core/IEHelper.cs rename to src/Greenshot.Base/Core/IEHelper.cs index 5fb52032f..7f01b73a2 100644 --- a/src/GreenshotPlugin/Core/IEHelper.cs +++ b/src/Greenshot.Base/Core/IEHelper.cs @@ -1,203 +1,203 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using log4net; -using Microsoft.Win32; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of IEHelper. - /// - public static class IEHelper - { - private static readonly ILog Log = LogManager.GetLogger(typeof(IEHelper)); - - // Internet explorer Registry key - private const string IeKey = @"Software\Microsoft\Internet Explorer"; - - /// - /// Get the current browser version - /// - /// int with browser version - public static int IEVersion - { - get - { - var maxVer = 7; - using (var ieKey = Registry.LocalMachine.OpenSubKey(IeKey, false)) - { - foreach (var value in new[] - { - "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" - }) - { - var objVal = ieKey.GetValue(value, "0"); - var strVal = Convert.ToString(objVal); - - var iPos = strVal.IndexOf('.'); - if (iPos > 0) - { - strVal = strVal.Substring(0, iPos); - } - - if (int.TryParse(strVal, out var res)) - { - maxVer = Math.Max(maxVer, res); - } - } - } - - return maxVer; - } - } - - /// - /// Get the highest possible version for the embedded browser - /// - /// true to ignore the doctype when loading a page - /// IE Feature - public static int GetEmbVersion(bool ignoreDoctype = true) - { - var ieVersion = IEVersion; - - if (ieVersion > 9) - { - return ieVersion * 1000 + (ignoreDoctype ? 1 : 0); - } - - if (ieVersion > 7) - { - return ieVersion * 1111; - } - - return 7000; - } - - /// - /// Fix browser version to the highest possible - /// - /// true to ignore the doctype when loading a page - public static void FixBrowserVersion(bool ignoreDoctype = true) - { - var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); - FixBrowserVersion(applicationName, ignoreDoctype); - } - - /// - /// Fix the browser version for the specified application - /// - /// Name of the process - /// true to ignore the doctype when loading a page - public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true) - { - FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype)); - } - - /// - /// Fix the browser version for the specified application - /// - /// Name of the process - /// - /// Version, see - /// Browser Emulation - /// - public static void FixBrowserVersion(string applicationName, int ieVersion) - { - ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".exe", ieVersion); -#if DEBUG - ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".vshost.exe", ieVersion); -#endif - } - - /// - /// Make the change to the registry - /// - /// HKEY_CURRENT_USER or something - /// Name of the executable - /// Version to use - private static void ModifyRegistry(string root, string applicationName, int ieFeatureVersion) - { - var regKey = root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"; - try - { - Registry.SetValue(regKey, applicationName, ieFeatureVersion); - } - catch (Exception ex) - { - // some config will hit access rights exceptions - // this is why we try with both LOCAL_MACHINE and CURRENT_USER - Log.Error(ex); - Log.ErrorFormat("couldn't modify the registry key {0}", regKey); - } - } - - /// - /// Find the DirectUI window for MSAA (Accessible) - /// - /// The browser WindowDetails - /// WindowDetails for the DirectUI window - public static WindowDetails GetDirectUI(WindowDetails browserWindowDetails) - { - if (browserWindowDetails == null) - { - return null; - } - - WindowDetails tmpWd = browserWindowDetails; - // Since IE 9 the TabBandClass is less deep! - if (IEVersion < 9) - { - tmpWd = tmpWd.GetChild("CommandBarClass"); - tmpWd = tmpWd?.GetChild("ReBarWindow32"); - } - - tmpWd = tmpWd?.GetChild("TabBandClass"); - tmpWd = tmpWd?.GetChild("DirectUIHWND"); - return tmpWd; - } - - /// - /// Return an IEnumerable with the currently opened IE urls - /// - /// - public static IEnumerable GetIEUrls() - { - // Find the IE window - foreach (WindowDetails ieWindow in WindowDetails.GetAllWindows("IEFrame")) - { - WindowDetails directUIWD = GetDirectUI(ieWindow); - if (directUIWD != null) - { - Accessible ieAccessible = new Accessible(directUIWD.Handle); - foreach (string url in ieAccessible.IETabUrls) - { - yield return url; - } - } - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using log4net; +using Microsoft.Win32; + +namespace Greenshot.Base.Core +{ + /// + /// Description of IEHelper. + /// + public static class IEHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(IEHelper)); + + // Internet explorer Registry key + private const string IeKey = @"Software\Microsoft\Internet Explorer"; + + /// + /// Get the current browser version + /// + /// int with browser version + public static int IEVersion + { + get + { + var maxVer = 7; + using (var ieKey = Registry.LocalMachine.OpenSubKey(IeKey, false)) + { + foreach (var value in new[] + { + "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" + }) + { + var objVal = ieKey.GetValue(value, "0"); + var strVal = Convert.ToString(objVal); + + var iPos = strVal.IndexOf('.'); + if (iPos > 0) + { + strVal = strVal.Substring(0, iPos); + } + + if (int.TryParse(strVal, out var res)) + { + maxVer = Math.Max(maxVer, res); + } + } + } + + return maxVer; + } + } + + /// + /// Get the highest possible version for the embedded browser + /// + /// true to ignore the doctype when loading a page + /// IE Feature + public static int GetEmbVersion(bool ignoreDoctype = true) + { + var ieVersion = IEVersion; + + if (ieVersion > 9) + { + return ieVersion * 1000 + (ignoreDoctype ? 1 : 0); + } + + if (ieVersion > 7) + { + return ieVersion * 1111; + } + + return 7000; + } + + /// + /// Fix browser version to the highest possible + /// + /// true to ignore the doctype when loading a page + public static void FixBrowserVersion(bool ignoreDoctype = true) + { + var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); + FixBrowserVersion(applicationName, ignoreDoctype); + } + + /// + /// Fix the browser version for the specified application + /// + /// Name of the process + /// true to ignore the doctype when loading a page + public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true) + { + FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype)); + } + + /// + /// Fix the browser version for the specified application + /// + /// Name of the process + /// + /// Version, see + /// Browser Emulation + /// + public static void FixBrowserVersion(string applicationName, int ieVersion) + { + ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".exe", ieVersion); +#if DEBUG + ModifyRegistry("HKEY_CURRENT_USER", applicationName + ".vshost.exe", ieVersion); +#endif + } + + /// + /// Make the change to the registry + /// + /// HKEY_CURRENT_USER or something + /// Name of the executable + /// Version to use + private static void ModifyRegistry(string root, string applicationName, int ieFeatureVersion) + { + var regKey = root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"; + try + { + Registry.SetValue(regKey, applicationName, ieFeatureVersion); + } + catch (Exception ex) + { + // some config will hit access rights exceptions + // this is why we try with both LOCAL_MACHINE and CURRENT_USER + Log.Error(ex); + Log.ErrorFormat("couldn't modify the registry key {0}", regKey); + } + } + + /// + /// Find the DirectUI window for MSAA (Accessible) + /// + /// The browser WindowDetails + /// WindowDetails for the DirectUI window + public static WindowDetails GetDirectUI(WindowDetails browserWindowDetails) + { + if (browserWindowDetails == null) + { + return null; + } + + WindowDetails tmpWd = browserWindowDetails; + // Since IE 9 the TabBandClass is less deep! + if (IEVersion < 9) + { + tmpWd = tmpWd.GetChild("CommandBarClass"); + tmpWd = tmpWd?.GetChild("ReBarWindow32"); + } + + tmpWd = tmpWd?.GetChild("TabBandClass"); + tmpWd = tmpWd?.GetChild("DirectUIHWND"); + return tmpWd; + } + + /// + /// Return an IEnumerable with the currently opened IE urls + /// + /// + public static IEnumerable GetIEUrls() + { + // Find the IE window + foreach (WindowDetails ieWindow in WindowDetails.GetAllWindows("IEFrame")) + { + WindowDetails directUIWD = GetDirectUI(ieWindow); + if (directUIWD != null) + { + Accessible ieAccessible = new Accessible(directUIWD.Handle); + foreach (string url in ieAccessible.IETabUrls) + { + yield return url; + } + } + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/IImage.cs b/src/Greenshot.Base/Core/IImage.cs similarity index 95% rename from src/GreenshotPlugin/Core/IImage.cs rename to src/Greenshot.Base/Core/IImage.cs index ffeff3d24..2204d5739 100644 --- a/src/GreenshotPlugin/Core/IImage.cs +++ b/src/Greenshot.Base/Core/IImage.cs @@ -1,68 +1,68 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; - -namespace GreenshotPlugin.Core -{ - /// - /// The image interface, this abstracts an image - /// - public interface IImage : IDisposable - { - /// - /// Height of the image, can be set to change - /// - int Height { get; set; } - - /// - /// Width of the image, can be set to change. - /// - int Width { get; set; } - - /// - /// Size of the image - /// - Size Size { get; } - - /// - /// Pixelformat of the underlying image - /// - PixelFormat PixelFormat { get; } - - /// - /// Vertical resolution of the underlying image - /// - float VerticalResolution { get; } - - /// - /// Horizontal resolution of the underlying image - /// - float HorizontalResolution { get; } - - /// - /// Unterlying image, or an on demand rendered version with different attributes as the original - /// - Image Image { get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Drawing.Imaging; + +namespace Greenshot.Base.Core +{ + /// + /// The image interface, this abstracts an image + /// + public interface IImage : IDisposable + { + /// + /// Height of the image, can be set to change + /// + int Height { get; set; } + + /// + /// Width of the image, can be set to change. + /// + int Width { get; set; } + + /// + /// Size of the image + /// + Size Size { get; } + + /// + /// Pixelformat of the underlying image + /// + PixelFormat PixelFormat { get; } + + /// + /// Vertical resolution of the underlying image + /// + float VerticalResolution { get; } + + /// + /// Horizontal resolution of the underlying image + /// + float HorizontalResolution { get; } + + /// + /// Unterlying image, or an on demand rendered version with different attributes as the original + /// + Image Image { get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/ImageHelper.cs b/src/Greenshot.Base/Core/ImageHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/ImageHelper.cs rename to src/Greenshot.Base/Core/ImageHelper.cs index d6263813c..e93307717 100644 --- a/src/GreenshotPlugin/Core/ImageHelper.cs +++ b/src/Greenshot.Base/Core/ImageHelper.cs @@ -1,1807 +1,1807 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using log4net; - -namespace GreenshotPlugin.Core -{ - internal enum ExifOrientations : byte - { - Unknown = 0, - TopLeft = 1, - TopRight = 2, - BottomRight = 3, - BottomLeft = 4, - LeftTop = 5, - RightTop = 6, - RightBottom = 7, - LeftBottom = 8, - } - - /// - /// Description of ImageHelper. - /// - public static class ImageHelper - { - private static readonly ILog Log = LogManager.GetLogger(typeof(ImageHelper)); - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private const int ExifOrientationId = 0x0112; - - static ImageHelper() - { - StreamConverters["greenshot"] = (stream, s) => - { - var surface = SimpleServiceProvider.Current.GetInstance>().Invoke(); - return surface.GetImageForExport(); - }; - - // Add a SVG converter - StreamConverters["svg"] = (stream, s) => - { - stream.Position = 0; - try - { - return SvgImage.FromStream(stream).Image; - } - catch (Exception ex) - { - Log.Error("Can't load SVG", ex); - } - - return null; - }; - - static Image DefaultConverter(Stream stream, string s) - { - stream.Position = 0; - using var tmpImage = Image.FromStream(stream, true, true); - Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); - return Clone(tmpImage, PixelFormat.Format32bppArgb); - } - - // Fallback - StreamConverters[string.Empty] = DefaultConverter; - StreamConverters["gif"] = DefaultConverter; - StreamConverters["bmp"] = DefaultConverter; - StreamConverters["jpg"] = DefaultConverter; - StreamConverters["jpeg"] = DefaultConverter; - StreamConverters["png"] = DefaultConverter; - StreamConverters["wmf"] = DefaultConverter; - - StreamConverters["ico"] = (stream, extension) => - { - // Icon logic, try to get the Vista icon, else the biggest possible - try - { - using Image tmpImage = ExtractVistaIcon(stream); - if (tmpImage != null) - { - return Clone(tmpImage, PixelFormat.Format32bppArgb); - } - } - catch (Exception vistaIconException) - { - Log.Warn("Can't read icon", vistaIconException); - } - - try - { - // No vista icon, try normal icon - stream.Position = 0; - // We create a copy of the bitmap, so everything else can be disposed - using Icon tmpIcon = new Icon(stream, new Size(1024, 1024)); - using Image tmpImage = tmpIcon.ToBitmap(); - return Clone(tmpImage, PixelFormat.Format32bppArgb); - } - catch (Exception iconException) - { - Log.Warn("Can't read icon", iconException); - } - - stream.Position = 0; - return DefaultConverter(stream, extension); - }; - } - - public static IDictionary> StreamConverters { get; } = new Dictionary>(); - - /// - /// Make sure the image is orientated correctly - /// - /// - public static void Orientate(Image image) - { - if (!CoreConfig.ProcessEXIFOrientation) - { - return; - } - - try - { - // Get the index of the orientation property. - int orientationIndex = Array.IndexOf(image.PropertyIdList, ExifOrientationId); - // If there is no such property, return Unknown. - if (orientationIndex < 0) - { - return; - } - - PropertyItem item = image.GetPropertyItem(ExifOrientationId); - - ExifOrientations orientation = (ExifOrientations) item.Value[0]; - // Orient the image. - switch (orientation) - { - case ExifOrientations.Unknown: - case ExifOrientations.TopLeft: - break; - case ExifOrientations.TopRight: - image.RotateFlip(RotateFlipType.RotateNoneFlipX); - break; - case ExifOrientations.BottomRight: - image.RotateFlip(RotateFlipType.Rotate180FlipNone); - break; - case ExifOrientations.BottomLeft: - image.RotateFlip(RotateFlipType.RotateNoneFlipY); - break; - case ExifOrientations.LeftTop: - image.RotateFlip(RotateFlipType.Rotate90FlipX); - break; - case ExifOrientations.RightTop: - image.RotateFlip(RotateFlipType.Rotate90FlipNone); - break; - case ExifOrientations.RightBottom: - image.RotateFlip(RotateFlipType.Rotate90FlipY); - break; - case ExifOrientations.LeftBottom: - image.RotateFlip(RotateFlipType.Rotate270FlipNone); - break; - } - - // Set the orientation to be normal, as we rotated the image. - item.Value[0] = (byte) ExifOrientations.TopLeft; - image.SetPropertyItem(item); - } - catch (Exception orientEx) - { - Log.Warn("Problem orientating the image: ", orientEx); - } - } - - /// - /// Create a Thumbnail - /// - /// - /// - /// - /// - /// - /// - public static Image CreateThumbnail(Image image, int thumbWidth, int thumbHeight, int maxWidth = -1, int maxHeight = -1) - { - int srcWidth = image.Width; - int srcHeight = image.Height; - if (thumbHeight < 0) - { - thumbHeight = (int) (thumbWidth * (srcHeight / (float) srcWidth)); - } - - if (thumbWidth < 0) - { - thumbWidth = (int) (thumbHeight * (srcWidth / (float) srcHeight)); - } - - if (maxWidth > 0 && thumbWidth > maxWidth) - { - thumbWidth = Math.Min(thumbWidth, maxWidth); - thumbHeight = (int) (thumbWidth * (srcHeight / (float) srcWidth)); - } - - if (maxHeight > 0 && thumbHeight > maxHeight) - { - thumbHeight = Math.Min(thumbHeight, maxHeight); - thumbWidth = (int) (thumbHeight * (srcWidth / (float) srcHeight)); - } - - Bitmap bmp = new Bitmap(thumbWidth, thumbHeight); - using (Graphics graphics = Graphics.FromImage(bmp)) - { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - Rectangle rectDestination = new Rectangle(0, 0, thumbWidth, thumbHeight); - graphics.DrawImage(image, rectDestination, 0, 0, srcWidth, srcHeight, GraphicsUnit.Pixel); - } - - return bmp; - } - - /// - /// Crops the image to the specified rectangle - /// - /// Image to crop - /// Rectangle with bitmap coordinates, will be "intersected" to the bitmap - public static bool Crop(ref Image image, ref Rectangle cropRectangle) - { - if (image is Bitmap && (image.Width * image.Height > 0)) - { - cropRectangle.Intersect(new Rectangle(0, 0, image.Width, image.Height)); - if (cropRectangle.Width != 0 || cropRectangle.Height != 0) - { - Image returnImage = CloneArea(image, cropRectangle, PixelFormat.DontCare); - image.Dispose(); - image = returnImage; - return true; - } - } - - Log.Warn("Can't crop a null/zero size image!"); - return false; - } - - /// - /// Private helper method for the FindAutoCropRectangle - /// - /// - /// - /// - /// Rectangle - private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference) - { - Rectangle cropRectangle = Rectangle.Empty; - Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y); - Point min = new Point(int.MaxValue, int.MaxValue); - Point max = new Point(int.MinValue, int.MinValue); - - if (cropDifference > 0) - { - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color currentColor = fastBitmap.GetColorAt(x, y); - int diffR = Math.Abs(currentColor.R - referenceColor.R); - int diffG = Math.Abs(currentColor.G - referenceColor.G); - int diffB = Math.Abs(currentColor.B - referenceColor.B); - if ((diffR + diffG + diffB) / 3 <= cropDifference) - { - continue; - } - - if (x < min.X) min.X = x; - if (y < min.Y) min.Y = y; - if (x > max.X) max.X = x; - if (y > max.Y) max.Y = y; - } - } - } - else - { - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color currentColor = fastBitmap.GetColorAt(x, y); - if (!referenceColor.Equals(currentColor)) - { - continue; - } - - if (x < min.X) min.X = x; - if (y < min.Y) min.Y = y; - if (x > max.X) max.X = x; - if (y > max.Y) max.Y = y; - } - } - } - - if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1)))) - { - if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue)) - { - cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1); - } - } - - return cropRectangle; - } - - /// - /// Get a rectangle for the image which crops the image of all colors equal to that on 0,0 - /// - /// - /// - /// Rectangle - public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) - { - Rectangle cropRectangle = Rectangle.Empty; - var checkPoints = new List - { - new Point(0, 0), - new Point(0, image.Height - 1), - new Point(image.Width - 1, 0), - new Point(image.Width - 1, image.Height - 1) - }; - // Top Left - // Bottom Left - // Top Right - // Bottom Right - using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap) image)) - { - // find biggest area - foreach (Point checkPoint in checkPoints) - { - var currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference); - if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) - { - cropRectangle = currentRectangle; - } - } - } - - return cropRectangle; - } - - /// - /// Load an image from file - /// - /// - /// - public static Image LoadImage(string filename) - { - if (string.IsNullOrEmpty(filename)) - { - return null; - } - - if (!File.Exists(filename)) - { - return null; - } - - Image fileImage; - Log.InfoFormat("Loading image from file {0}", filename); - // Fixed lock problem Bug #3431881 - using (Stream imageFileStream = File.OpenRead(filename)) - { - fileImage = FromStream(imageFileStream, Path.GetExtension(filename)); - } - - if (fileImage != null) - { - Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat, - fileImage.HorizontalResolution, fileImage.VerticalResolution); - } - - return fileImage; - } - - /// - /// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx - /// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx - /// - /// Stream with the icon information - /// Bitmap with the Vista Icon (256x256) - private static Bitmap ExtractVistaIcon(Stream iconStream) - { - const int sizeIconDir = 6; - const int sizeIconDirEntry = 16; - Bitmap bmpPngExtracted = null; - try - { - byte[] srcBuf = new byte[iconStream.Length]; - iconStream.Read(srcBuf, 0, (int) iconStream.Length); - int iCount = BitConverter.ToInt16(srcBuf, 4); - for (int iIndex = 0; iIndex < iCount; iIndex++) - { - int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex]; - int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1]; - if (iWidth == 0 && iHeight == 0) - { - int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8); - int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12); - using MemoryStream destStream = new MemoryStream(); - destStream.Write(srcBuf, iImageOffset, iImageSize); - destStream.Seek(0, SeekOrigin.Begin); - bmpPngExtracted = new Bitmap(destStream); // This is PNG! :) - break; - } - } - } - catch - { - return null; - } - - return bmpPngExtracted; - } - - /// - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx - /// - /// The file (EXE or DLL) to get the icon from - /// Index of the icon - /// true if the large icon is wanted - /// Icon - public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge) - { - Shell32.ExtractIconEx(location, index, out var large, out var small, 1); - Icon returnIcon = null; - bool isLarge = false; - bool isSmall = false; - try - { - if (takeLarge && !IntPtr.Zero.Equals(large)) - { - returnIcon = Icon.FromHandle(large); - isLarge = true; - } - else if (!IntPtr.Zero.Equals(small)) - { - returnIcon = Icon.FromHandle(small); - isSmall = true; - } - else if (!IntPtr.Zero.Equals(large)) - { - returnIcon = Icon.FromHandle(large); - isLarge = true; - } - } - finally - { - if (isLarge && !IntPtr.Zero.Equals(small)) - { - User32.DestroyIcon(small); - } - - if (isSmall && !IntPtr.Zero.Equals(large)) - { - User32.DestroyIcon(large); - } - } - - return returnIcon; - } - - /// - /// Apply the effect to the bitmap - /// - /// Bitmap - /// IEffect - /// - /// Bitmap - public static Image ApplyEffect(Image sourceImage, IEffect effect, Matrix matrix) - { - var effects = new List - { - effect - }; - return ApplyEffects(sourceImage, effects, matrix); - } - - /// - /// Apply the effects in the supplied order to the bitmap - /// - /// Bitmap - /// List of IEffect - /// - /// Bitmap - public static Image ApplyEffects(Image sourceImage, IEnumerable effects, Matrix matrix) - { - var currentImage = sourceImage; - bool disposeImage = false; - foreach (var effect in effects) - { - var tmpImage = effect.Apply(currentImage, matrix); - if (tmpImage != null) - { - if (disposeImage) - { - currentImage.Dispose(); - } - - currentImage = tmpImage; - // Make sure the "new" image is disposed - disposeImage = true; - } - } - - return currentImage; - } - - /// - /// Helper method for the tornedge - /// - /// Path to draw to - /// Points for the lines to draw - private static void DrawLines(GraphicsPath path, List points) - { - path.AddLine(points[0], points[1]); - for (int i = 0; i < points.Count - 1; i++) - { - path.AddLine(points[i], points[i + 1]); - } - } - - /// - /// Make the picture look like it's torn - /// - /// Bitmap to make torn edge off - /// How large (height) is each tooth - /// How wide is a horizontal tooth - /// How wide is a vertical tooth - /// bool[] with information on if the edge needs torn or not. Order is clockwise: 0=top,1=right,2=bottom,3=left - /// Changed bitmap - public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges) - { - Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution, - sourceImage.VerticalResolution); - using (var path = new GraphicsPath()) - { - Random random = new Random(); - int horizontalRegions = (int) Math.Round((float) sourceImage.Width / horizontalToothRange); - int verticalRegions = (int) Math.Round((float) sourceImage.Height / verticalToothRange); - - Point topLeft = new Point(0, 0); - Point topRight = new Point(sourceImage.Width, 0); - Point bottomLeft = new Point(0, sourceImage.Height); - Point bottomRight = new Point(sourceImage.Width, sourceImage.Height); - - List points = new List(); - - if (edges[0]) - { - // calculate starting point only if the left edge is torn - if (!edges[3]) - { - points.Add(topLeft); - } - else - { - points.Add(new Point(random.Next(1, toothHeight), random.Next(1, toothHeight))); - } - - for (int i = 1; i < horizontalRegions - 1; i++) - { - points.Add(new Point(i * horizontalToothRange, random.Next(1, toothHeight))); - } - - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), random.Next(1, toothHeight))); - } - else - { - // set start & endpoint to be the default "whole-line" - points.Add(topLeft); - points.Add(topRight); - } - - // Right - if (edges[1]) - { - for (int i = 1; i < verticalRegions - 1; i++) - { - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), i * verticalToothRange)); - } - - points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); - } - else - { - // correct previous ending point - points[points.Count - 1] = topRight; - // set endpoint to be the default "whole-line" - points.Add(bottomRight); - } - - // Bottom - if (edges[2]) - { - for (int i = 1; i < horizontalRegions - 1; i++) - { - points.Add(new Point(sourceImage.Width - i * horizontalToothRange, sourceImage.Height - random.Next(1, toothHeight))); - } - - points.Add(new Point(random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); - } - else - { - // correct previous ending point - points[points.Count - 1] = bottomRight; - // set endpoint to be the default "whole-line" - points.Add(bottomLeft); - } - - // Left - if (edges[3]) - { - // One fewer as the end point is the starting point - for (int i = 1; i < verticalRegions - 1; i++) - { - points.Add(new Point(random.Next(1, toothHeight), points[points.Count - 1].Y - verticalToothRange)); - } - } - else - { - // correct previous ending point - points[points.Count - 1] = bottomLeft; - // set endpoint to be the default "whole-line" - points.Add(topLeft); - } - - // End point always is the starting point - points[points.Count - 1] = points[0]; - - DrawLines(path, points); - - path.CloseFigure(); - - // Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing - using Graphics graphics = Graphics.FromImage(returnImage); - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using Brush brush = new TextureBrush(sourceImage); - // Important note: If the target wouldn't be at 0,0 we need to translate-transform!! - graphics.FillPath(brush, path); - } - - return returnImage; - } - - /// - /// Apply BoxBlur to the destinationBitmap - /// - /// Bitmap to blur - /// Must be ODD! - public static void ApplyBoxBlur(Bitmap destinationBitmap, int range) - { - // We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V) - using IFastBitmap fastBitmap = FastBitmap.Create(destinationBitmap); - ApplyBoxBlur(fastBitmap, range); - } - - /// - /// Apply BoxBlur to the fastBitmap - /// - /// IFastBitmap to blur - /// Must be ODD! - public static void ApplyBoxBlur(IFastBitmap fastBitmap, int range) - { - // Range must be odd! - if ((range & 1) == 0) - { - range++; - } - - if (range <= 1) - { - return; - } - - // Box blurs are frequently used to approximate a Gaussian blur. - // By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel. - // This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur. - // (Might also be a mistake in our blur, but for now it looks great) - if (fastBitmap.HasAlphaChannel) - { - BoxBlurHorizontalAlpha(fastBitmap, range); - BoxBlurVerticalAlpha(fastBitmap, range); - BoxBlurHorizontalAlpha(fastBitmap, range); - BoxBlurVerticalAlpha(fastBitmap, range); - } - else - { - BoxBlurHorizontal(fastBitmap, range); - BoxBlurVertical(fastBitmap, range); - BoxBlurHorizontal(fastBitmap, range); - BoxBlurVertical(fastBitmap, range); - } - } - - /// - /// BoxBlurHorizontal is a private helper method for the BoxBlur - /// - /// Target BitmapBuffer - /// Range must be odd! - private static void BoxBlurHorizontal(IFastBitmap targetFastBitmap, int range) - { - if (targetFastBitmap.HasAlphaChannel) - { - throw new NotSupportedException("BoxBlurHorizontal should NOT be called for bitmaps with alpha channel"); - } - - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Width]; - byte[] tmpColor = new byte[3]; - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) - { - int oldPixel = x - halfRange - 1; - if (oldPixel >= targetFastBitmap.Left) - { - targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); - r -= tmpColor[FastBitmap.ColorIndexR]; - g -= tmpColor[FastBitmap.ColorIndexG]; - b -= tmpColor[FastBitmap.ColorIndexB]; - hits--; - } - - int newPixel = x + halfRange; - if (newPixel < targetFastBitmap.Right) - { - targetFastBitmap.GetColorAt(newPixel, y, tmpColor); - r += tmpColor[FastBitmap.ColorIndexR]; - g += tmpColor[FastBitmap.ColorIndexG]; - b += tmpColor[FastBitmap.ColorIndexB]; - hits++; - } - - if (x >= targetFastBitmap.Left) - { - newColors[x - targetFastBitmap.Left] = Color.FromArgb(255, (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); - } - } - - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); - } - } - } - - /// - /// BoxBlurHorizontal is a private helper method for the BoxBlur, only for IFastBitmaps with alpha channel - /// - /// Target BitmapBuffer - /// Range must be odd! - private static void BoxBlurHorizontalAlpha(IFastBitmap targetFastBitmap, int range) - { - if (!targetFastBitmap.HasAlphaChannel) - { - throw new NotSupportedException("BoxBlurHorizontalAlpha should be called for bitmaps with alpha channel"); - } - - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Width]; - byte[] tmpColor = new byte[4]; - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - int hits = 0; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) - { - int oldPixel = x - halfRange - 1; - if (oldPixel >= targetFastBitmap.Left) - { - targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); - a -= tmpColor[FastBitmap.ColorIndexA]; - r -= tmpColor[FastBitmap.ColorIndexR]; - g -= tmpColor[FastBitmap.ColorIndexG]; - b -= tmpColor[FastBitmap.ColorIndexB]; - hits--; - } - - int newPixel = x + halfRange; - if (newPixel < targetFastBitmap.Right) - { - targetFastBitmap.GetColorAt(newPixel, y, tmpColor); - a += tmpColor[FastBitmap.ColorIndexA]; - r += tmpColor[FastBitmap.ColorIndexR]; - g += tmpColor[FastBitmap.ColorIndexG]; - b += tmpColor[FastBitmap.ColorIndexB]; - hits++; - } - - if (x >= targetFastBitmap.Left) - { - newColors[x - targetFastBitmap.Left] = Color.FromArgb((byte) (a / hits), (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); - } - } - - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); - } - } - } - - /// - /// BoxBlurVertical is a private helper method for the BoxBlur - /// - /// BitmapBuffer which previously was created with BoxBlurHorizontal - /// Range must be odd! - private static void BoxBlurVertical(IFastBitmap targetFastBitmap, int range) - { - if (targetFastBitmap.HasAlphaChannel) - { - throw new NotSupportedException("BoxBlurVertical should NOT be called for bitmaps with alpha channel"); - } - - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Height]; - byte[] tmpColor = new byte[4]; - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) - { - int oldPixel = y - halfRange - 1; - if (oldPixel >= targetFastBitmap.Top) - { - targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); - r -= tmpColor[FastBitmap.ColorIndexR]; - g -= tmpColor[FastBitmap.ColorIndexG]; - b -= tmpColor[FastBitmap.ColorIndexB]; - hits--; - } - - int newPixel = y + halfRange; - if (newPixel < targetFastBitmap.Bottom) - { - targetFastBitmap.GetColorAt(x, newPixel, tmpColor); - r += tmpColor[FastBitmap.ColorIndexR]; - g += tmpColor[FastBitmap.ColorIndexG]; - b += tmpColor[FastBitmap.ColorIndexB]; - hits++; - } - - if (y >= targetFastBitmap.Top) - { - newColors[y - targetFastBitmap.Top] = Color.FromArgb(255, (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); - } - } - - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); - } - } - } - - /// - /// BoxBlurVertical is a private helper method for the BoxBlur - /// - /// BitmapBuffer which previously was created with BoxBlurHorizontal - /// Range must be odd! - private static void BoxBlurVerticalAlpha(IFastBitmap targetFastBitmap, int range) - { - if (!targetFastBitmap.HasAlphaChannel) - { - throw new NotSupportedException("BoxBlurVerticalAlpha should be called for bitmaps with alpha channel"); - } - - int halfRange = range / 2; - Color[] newColors = new Color[targetFastBitmap.Height]; - byte[] tmpColor = new byte[4]; - for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) - { - int hits = 0; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) - { - int oldPixel = y - halfRange - 1; - if (oldPixel >= targetFastBitmap.Top) - { - targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); - a -= tmpColor[FastBitmap.ColorIndexA]; - r -= tmpColor[FastBitmap.ColorIndexR]; - g -= tmpColor[FastBitmap.ColorIndexG]; - b -= tmpColor[FastBitmap.ColorIndexB]; - hits--; - } - - int newPixel = y + halfRange; - if (newPixel < targetFastBitmap.Bottom) - { - //int colorg = pixels[index + newPixelOffset]; - targetFastBitmap.GetColorAt(x, newPixel, tmpColor); - a += tmpColor[FastBitmap.ColorIndexA]; - r += tmpColor[FastBitmap.ColorIndexR]; - g += tmpColor[FastBitmap.ColorIndexG]; - b += tmpColor[FastBitmap.ColorIndexB]; - hits++; - } - - if (y >= targetFastBitmap.Top) - { - newColors[y - targetFastBitmap.Top] = Color.FromArgb((byte) (a / hits), (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); - } - } - - for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) - { - targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); - } - } - } - - /// - /// This method fixes the problem that we can't apply a filter outside the target bitmap, - /// therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap. - /// It will also account for the Invert flag. - /// - /// - /// - /// - /// - public static Rectangle CreateIntersectRectangle(Size applySize, Rectangle rect, bool invert) - { - Rectangle myRect; - if (invert) - { - myRect = new Rectangle(0, 0, applySize.Width, applySize.Height); - } - else - { - Rectangle applyRect = new Rectangle(0, 0, applySize.Width, applySize.Height); - myRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); - myRect.Intersect(applyRect); - } - - return myRect; - } - - /// - /// Create a new bitmap where the sourceBitmap has a shadow - /// - /// Bitmap to make a shadow on - /// How dark is the shadow - /// Size of the shadow - /// What pixel format must the returning bitmap have - /// - /// The transform matrix which describes how the elements need to be transformed to stay at the same location - /// Bitmap with the shadow, is bigger than the sourceBitmap!! - public static Bitmap CreateShadow(Image sourceBitmap, float darkness, int shadowSize, Point shadowOffset, Matrix matrix, PixelFormat targetPixelformat) - { - Point offset = shadowOffset; - offset.X += shadowSize - 1; - offset.Y += shadowSize - 1; - matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); - // Create a new "clean" image - Bitmap returnImage = CreateEmpty(sourceBitmap.Width + shadowSize * 2, sourceBitmap.Height + shadowSize * 2, targetPixelformat, Color.Empty, - sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); - // Make sure the shadow is odd, there is no reason for an even blur! - if ((shadowSize & 1) == 0) - { - shadowSize++; - } - - bool useGdiBlur = GDIplus.IsBlurPossible(shadowSize); - // Create "mask" for the shadow - ColorMatrix maskMatrix = new ColorMatrix - { - Matrix00 = 0, - Matrix11 = 0, - Matrix22 = 0 - }; - if (useGdiBlur) - { - maskMatrix.Matrix33 = darkness + 0.1f; - } - else - { - maskMatrix.Matrix33 = darkness; - } - - Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); - ApplyColorMatrix((Bitmap) sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); - - // blur "shadow", apply to whole new image - if (useGdiBlur) - { - // Use GDI Blur - Rectangle newImageRectangle = new Rectangle(0, 0, returnImage.Width, returnImage.Height); - GDIplus.ApplyBlur(returnImage, newImageRectangle, shadowSize + 1, false); - } - else - { - // try normal software blur - //returnImage = CreateBlur(returnImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle); - ApplyBoxBlur(returnImage, shadowSize); - } - - // Draw the original image over the shadow - using (Graphics graphics = Graphics.FromImage(returnImage)) - { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - // draw original with a TextureBrush so we have nice antialiasing! - using Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp); - // We need to do a translate-transform otherwise the image is wrapped - graphics.TranslateTransform(offset.X, offset.Y); - graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); - } - - return returnImage; - } - - /// - /// Return negative of Bitmap - /// - /// Bitmap to create a negative off - /// Negative bitmap - public static Bitmap CreateNegative(Image sourceImage) - { - Bitmap clone = (Bitmap) Clone(sourceImage); - ColorMatrix invertMatrix = new ColorMatrix(new[] - { - new float[] - { - -1, 0, 0, 0, 0 - }, - new float[] - { - 0, -1, 0, 0, 0 - }, - new float[] - { - 0, 0, -1, 0, 0 - }, - new float[] - { - 0, 0, 0, 1, 0 - }, - new float[] - { - 1, 1, 1, 1, 1 - } - }); - ApplyColorMatrix(clone, invertMatrix); - return clone; - } - - /// - /// Apply a color matrix to the image - /// - /// Image to apply matrix to - /// ColorMatrix to apply - public static void ApplyColorMatrix(Bitmap source, ColorMatrix colorMatrix) - { - ApplyColorMatrix(source, Rectangle.Empty, source, Rectangle.Empty, colorMatrix); - } - - /// - /// Apply a color matrix by copying from the source to the destination - /// - /// Image to copy from - /// Rectangle to copy from - /// Rectangle to copy to - /// Image to copy to - /// ColorMatrix to apply - public static void ApplyColorMatrix(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ColorMatrix colorMatrix) - { - using ImageAttributes imageAttributes = new ImageAttributes(); - imageAttributes.ClearColorMatrix(); - imageAttributes.SetColorMatrix(colorMatrix); - ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); - } - - /// - /// Apply a color matrix by copying from the source to the destination - /// - /// Image to copy from - /// Rectangle to copy from - /// Rectangle to copy to - /// Image to copy to - /// ImageAttributes to apply - public static void ApplyImageAttributes(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ImageAttributes imageAttributes) - { - if (sourceRect == Rectangle.Empty) - { - sourceRect = new Rectangle(0, 0, source.Width, source.Height); - } - - if (dest == null) - { - dest = source; - } - - if (destRect == Rectangle.Empty) - { - destRect = new Rectangle(0, 0, dest.Width, dest.Height); - } - - using Graphics graphics = Graphics.FromImage(dest); - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingMode = CompositingMode.SourceCopy; - - graphics.DrawImage(source, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes); - } - - /// - /// Returns a b/w of Bitmap - /// - /// Bitmap to create a b/w of - /// Threshold for monochrome filter (0 - 255), lower value means less black - /// b/w bitmap - public static Bitmap CreateMonochrome(Image sourceImage, byte threshold) - { - using IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat); - for (int y = 0; y < fastBitmap.Height; y++) - { - for (int x = 0; x < fastBitmap.Width; x++) - { - Color color = fastBitmap.GetColorAt(x, y); - int colorBrightness = (color.R + color.G + color.B) / 3 > threshold ? 255 : 0; - Color monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness); - fastBitmap.SetColorAt(x, y, monoColor); - } - } - - return fastBitmap.UnlockAndReturnBitmap(); - } - - /// - /// Create a new bitmap where the sourceBitmap has a Simple border around it - /// - /// Bitmap to make a border on - /// Size of the border - /// Color of the border - /// What pixel format must the returning bitmap have - /// The transform matrix which describes how the elements need to be transformed to stay at the same location - /// Bitmap with the shadow, is bigger than the sourceBitmap!! - public static Image CreateBorder(Image sourceImage, int borderSize, Color borderColor, PixelFormat targetPixelformat, Matrix matrix) - { - // "return" the shifted offset, so the caller can e.g. move elements - Point offset = new Point(borderSize, borderSize); - matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); - - // Create a new "clean" image - Bitmap newImage = CreateEmpty(sourceImage.Width + borderSize * 2, sourceImage.Height + borderSize * 2, targetPixelformat, Color.Empty, sourceImage.HorizontalResolution, - sourceImage.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(newImage)) - { - // Make sure we draw with the best quality! - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using (GraphicsPath path = new GraphicsPath()) - { - path.AddRectangle(new Rectangle(borderSize >> 1, borderSize >> 1, newImage.Width - borderSize, newImage.Height - borderSize)); - using Pen pen = new Pen(borderColor, borderSize) - { - LineJoin = LineJoin.Round, - StartCap = LineCap.Round, - EndCap = LineCap.Round - }; - graphics.DrawPath(pen, path); - } - - // draw original with a TextureBrush so we have nice antialiasing! - using Brush textureBrush = new TextureBrush(sourceImage, WrapMode.Clamp); - // We need to do a translate-tranform otherwise the image is wrapped - graphics.TranslateTransform(offset.X, offset.Y); - graphics.FillRectangle(textureBrush, 0, 0, sourceImage.Width, sourceImage.Height); - } - - return newImage; - } - - /// - /// Create ImageAttributes to modify - /// - /// - /// - /// - /// ImageAttributes - public static ImageAttributes CreateAdjustAttributes(float brightness, float contrast, float gamma) - { - float adjustedBrightness = brightness - 1.0f; - ColorMatrix applyColorMatrix = new ColorMatrix( - new[] - { - new[] - { - contrast, 0, 0, 0, 0 - }, // scale red - new[] - { - 0, contrast, 0, 0, 0 - }, // scale green - new[] - { - 0, 0, contrast, 0, 0 - }, // scale blue - new[] - { - 0, 0, 0, 1.0f, 0 - }, // don't scale alpha - new[] - { - adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1 - } - }); - - //create some image attributes - ImageAttributes attributes = new ImageAttributes(); - attributes.ClearColorMatrix(); - attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - attributes.SetGamma(gamma, ColorAdjustType.Bitmap); - return attributes; - } - - /// - /// Adjust the brightness, contract or gamma of an image. - /// Use the value "1.0f" for no changes. - /// - /// Original bitmap - /// - /// - /// - /// Bitmap with grayscale - public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) - { - //create a blank bitmap the same size as original - // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. - Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, - sourceImage.VerticalResolution); - using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma)) - { - ApplyImageAttributes((Bitmap) sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes); - } - - return newBitmap; - } - - /// - /// Create a new bitmap where the sourceBitmap is in grayscale - /// - /// Original bitmap - /// Bitmap with grayscale - public static Image CreateGrayscale(Image sourceImage) - { - Bitmap clone = (Bitmap) Clone(sourceImage); - ColorMatrix grayscaleMatrix = new ColorMatrix(new[] - { - new[] - { - .3f, .3f, .3f, 0, 0 - }, - new[] - { - .59f, .59f, .59f, 0, 0 - }, - new[] - { - .11f, .11f, .11f, 0, 0 - }, - new float[] - { - 0, 0, 0, 1, 0 - }, - new float[] - { - 0, 0, 0, 0, 1 - } - }); - ApplyColorMatrix(clone, grayscaleMatrix); - return clone; - } - - /// - /// Checks if we support the pixel format - /// - /// PixelFormat to check - /// bool if we support it - public static bool SupportsPixelFormat(PixelFormat pixelformat) - { - return pixelformat.Equals(PixelFormat.Format32bppArgb) || - pixelformat.Equals(PixelFormat.Format32bppPArgb) || - pixelformat.Equals(PixelFormat.Format32bppRgb) || - pixelformat.Equals(PixelFormat.Format24bppRgb); - } - - /// - /// Wrapper for just cloning which calls the CloneArea - /// - /// Image to clone - /// Bitmap with clone image data - public static Image Clone(Image sourceImage) - { - if (sourceImage is Metafile) - { - return (Image) sourceImage.Clone(); - } - - return CloneArea(sourceImage, Rectangle.Empty, PixelFormat.DontCare); - } - - /// - /// Wrapper for just cloning & TargetFormat which calls the CloneArea - /// - /// Image to clone - /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) - /// Bitmap with clone image data - public static Bitmap Clone(Image sourceBitmap, PixelFormat targetFormat) - { - return CloneArea(sourceBitmap, Rectangle.Empty, targetFormat); - } - - /// - /// Clone an image, taking some rules into account: - /// 1) When sourceRect is the whole bitmap there is a GDI+ bug in Clone - /// Clone will than return the same PixelFormat as the source - /// a quick workaround is using new Bitmap which uses a default of Format32bppArgb - /// 2) When going from a transparent to a non transparent bitmap, we draw the background white! - /// - /// Source bitmap to clone - /// Rectangle to copy from the source, use Rectangle.Empty for all - /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) - /// - public static Bitmap CloneArea(Image sourceImage, Rectangle sourceRect, PixelFormat targetFormat) - { - Bitmap newImage; - Rectangle bitmapRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); - - // Make sure the source is not Rectangle.Empty - if (Rectangle.Empty.Equals(sourceRect)) - { - sourceRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); - } - else - { - sourceRect.Intersect(bitmapRect); - } - - // If no pixelformat is supplied - if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat) - { - if (SupportsPixelFormat(sourceImage.PixelFormat)) - { - targetFormat = sourceImage.PixelFormat; - } - else if (Image.IsAlphaPixelFormat(sourceImage.PixelFormat)) - { - targetFormat = PixelFormat.Format32bppArgb; - } - else - { - targetFormat = PixelFormat.Format24bppRgb; - } - } - - // check the target format - if (!SupportsPixelFormat(targetFormat)) - { - targetFormat = Image.IsAlphaPixelFormat(targetFormat) ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb; - } - - bool destinationIsTransparent = Image.IsAlphaPixelFormat(targetFormat); - bool sourceIsTransparent = Image.IsAlphaPixelFormat(sourceImage.PixelFormat); - bool fromTransparentToNon = !destinationIsTransparent && sourceIsTransparent; - bool isBitmap = sourceImage is Bitmap; - bool isAreaEqual = sourceRect.Equals(bitmapRect); - if (isAreaEqual || fromTransparentToNon || !isBitmap) - { - // Rule 1: if the areas are equal, always copy ourselves - newImage = new Bitmap(bitmapRect.Width, bitmapRect.Height, targetFormat); - // Make sure both images have the same resolution - newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - - using Graphics graphics = Graphics.FromImage(newImage); - if (fromTransparentToNon) - { - // Rule 2: Make sure the background color is white - graphics.Clear(Color.White); - } - - // decide fastest copy method - if (isAreaEqual) - { - graphics.DrawImageUnscaled(sourceImage, 0, 0); - } - else - { - graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel); - } - } - else - { - // Let GDI+ decide how to convert, need to test what is quicker... - newImage = (sourceImage as Bitmap).Clone(sourceRect, targetFormat); - // Make sure both images have the same resolution - newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - } - - // In WINE someone getting the PropertyItems doesn't work - try - { - // Clone property items (EXIF information etc) - foreach (var propertyItem in sourceImage.PropertyItems) - { - try - { - newImage.SetPropertyItem(propertyItem); - } - catch (Exception innerEx) - { - Log.Warn("Problem cloning a propertyItem.", innerEx); - } - } - } - catch (Exception ex) - { - Log.Warn("Problem cloning a propertyItem.", ex); - } - - return newImage; - } - - /// - /// Rotate the bitmap - /// - /// - /// - /// - public static Image RotateFlip(Image sourceImage, RotateFlipType rotateFlipType) - { - Image returnImage = Clone(sourceImage); - returnImage.RotateFlip(rotateFlipType); - return returnImage; - } - - /// - /// A generic way to create an empty image - /// - /// the source bitmap as the specifications for the new bitmap - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - public static Bitmap CreateEmptyLike(Image sourceImage, Color backgroundColor) - { - PixelFormat pixelFormat = sourceImage.PixelFormat; - if (backgroundColor.A < 255) - { - pixelFormat = PixelFormat.Format32bppArgb; - } - - return CreateEmpty(sourceImage.Width, sourceImage.Height, pixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - } - - /// - /// A generic way to create an empty image - /// - /// - /// - /// - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - /// - /// Bitmap - public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution, float verticalResolution) - { - // Create a new "clean" image - Bitmap newImage = new Bitmap(width, height, format); - newImage.SetResolution(horizontalResolution, verticalResolution); - if (format != PixelFormat.Format8bppIndexed) - { - using Graphics graphics = Graphics.FromImage(newImage); - // Make sure the background color is what we want (transparent or white, depending on the pixel format) - if (!Color.Empty.Equals(backgroundColor)) - { - graphics.Clear(backgroundColor); - } - else if (Image.IsAlphaPixelFormat(format)) - { - graphics.Clear(Color.Transparent); - } - else - { - graphics.Clear(Color.White); - } - } - - return newImage; - } - - /// - /// Resize canvas with pixel to the left, right, top and bottom - /// - /// - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// - /// - /// - /// - /// - /// a new bitmap with the source copied on it - public static Image ResizeCanvas(Image sourceImage, Color backgroundColor, int left, int right, int top, int bottom, Matrix matrix) - { - matrix.Translate(left, top, MatrixOrder.Append); - Bitmap newBitmap = CreateEmpty(sourceImage.Width + left + right, sourceImage.Height + top + bottom, sourceImage.PixelFormat, backgroundColor, - sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(newBitmap)) - { - graphics.DrawImageUnscaled(sourceImage, left, top); - } - - return newBitmap; - } - - /// - /// Wrapper for the more complex Resize, this resize could be used for e.g. Thumbnails - /// - /// - /// true to maintain the aspect ratio - /// - /// - /// - /// - public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, int newWidth, int newHeight, Matrix matrix) - { - return ResizeImage(sourceImage, maintainAspectRatio, false, Color.Empty, newWidth, newHeight, matrix); - } - - /// - /// Count how many times the supplied color exists - /// - /// Image to count the pixels of - /// Color to count - /// true if Alpha needs to be checked - /// int with the number of pixels which have colorToCount - public static int CountColor(Image sourceImage, Color colorToCount, bool includeAlpha) - { - int colors = 0; - int toCount = colorToCount.ToArgb(); - if (!includeAlpha) - { - toCount &= 0xffffff; - } - - using IFastBitmap bb = FastBitmap.Create((Bitmap) sourceImage); - for (int y = 0; y < bb.Height; y++) - { - for (int x = 0; x < bb.Width; x++) - { - int bitmapcolor = bb.GetColorAt(x, y).ToArgb(); - if (!includeAlpha) - { - bitmapcolor &= 0xffffff; - } - - if (bitmapcolor == toCount) - { - colors++; - } - } - } - - return colors; - } - - /// - /// Scale the bitmap, keeping aspect ratio, but the canvas will always have the specified size. - /// - /// Image to scale - /// true to maintain the aspect ratio - /// Makes the image maintain aspect ratio, but the canvas get's the specified size - /// The color to fill with, or Color.Empty to take the default depending on the pixel format - /// new width - /// new height - /// - /// a new bitmap with the specified size, the source-Image scaled to fit with aspect ratio locked - public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, bool canvasUseNewSize, Color backgroundColor, int newWidth, int newHeight, Matrix matrix) - { - int destX = 0; - int destY = 0; - - var nPercentW = newWidth / (float) sourceImage.Width; - var nPercentH = newHeight / (float) sourceImage.Height; - if (maintainAspectRatio) - { - if ((int) nPercentW == 1) - { - nPercentW = nPercentH; - if (canvasUseNewSize) - { - destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2)); - } - } - else if ((int) nPercentH == 1) - { - nPercentH = nPercentW; - if (canvasUseNewSize) - { - destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2)); - } - } - else if ((int) nPercentH != 0 && nPercentH < nPercentW) - { - nPercentW = nPercentH; - if (canvasUseNewSize) - { - destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2)); - } - } - else - { - nPercentH = nPercentW; - if (canvasUseNewSize) - { - destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2)); - } - } - } - - int destWidth = (int) (sourceImage.Width * nPercentW); - int destHeight = (int) (sourceImage.Height * nPercentH); - if (newWidth == 0) - { - newWidth = destWidth; - } - - if (newHeight == 0) - { - newHeight = destHeight; - } - - Image newImage; - if (maintainAspectRatio && canvasUseNewSize) - { - newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - matrix?.Scale((float) newWidth / sourceImage.Width, (float) newHeight / sourceImage.Height, MatrixOrder.Append); - } - else - { - newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - matrix?.Scale((float) destWidth / sourceImage.Width, (float) destHeight / sourceImage.Height, MatrixOrder.Append); - } - - using (Graphics graphics = Graphics.FromImage(newImage)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - using ImageAttributes wrapMode = new ImageAttributes(); - wrapMode.SetWrapMode(WrapMode.TileFlipXY); - graphics.DrawImage(sourceImage, new Rectangle(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode); - } - - return newImage; - } - - /// - /// Load a Greenshot surface from a stream - /// - /// Stream - /// - /// ISurface - public static ISurface LoadGreenshotSurface(Stream surfaceFileStream, ISurface returnSurface) - { - Image fileImage; - // Fixed problem that the bitmap stream is disposed... by Cloning the image - // This also ensures the bitmap is correctly created - - // We create a copy of the bitmap, so everything else can be disposed - surfaceFileStream.Position = 0; - using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true)) - { - Log.DebugFormat("Loaded .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); - fileImage = Clone(tmpImage); - } - - // Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor) - const int markerSize = 14; - surfaceFileStream.Seek(-markerSize, SeekOrigin.End); - using (StreamReader streamReader = new StreamReader(surfaceFileStream)) - { - var greenshotMarker = streamReader.ReadToEnd(); - if (!greenshotMarker.StartsWith("Greenshot")) - { - throw new ArgumentException("Stream is not a Greenshot file!"); - } - - Log.InfoFormat("Greenshot file format: {0}", greenshotMarker); - const int filesizeLocation = 8 + markerSize; - surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End); - using BinaryReader reader = new BinaryReader(surfaceFileStream); - long bytesWritten = reader.ReadInt64(); - surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End); - returnSurface.LoadElementsFromStream(surfaceFileStream); - } - - if (fileImage != null) - { - returnSurface.Image = fileImage; - Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", fileImage.Width, fileImage.Height, fileImage.PixelFormat, - fileImage.HorizontalResolution, fileImage.VerticalResolution); - } - - return returnSurface; - } - - /// - /// Create an image from a stream, if an extension is supplied more formats are supported. - /// - /// Stream - /// - /// Image - public static Image FromStream(Stream stream, string extension = null) - { - if (stream == null) - { - return null; - } - - if (!string.IsNullOrEmpty(extension)) - { - extension = extension.Replace(".", string.Empty); - } - - // Make sure we can try multiple times - if (!stream.CanSeek) - { - var memoryStream = new MemoryStream(); - stream.CopyTo(memoryStream); - stream = memoryStream; - } - - Image returnImage = null; - if (StreamConverters.TryGetValue(extension ?? string.Empty, out var converter)) - { - returnImage = converter(stream, extension); - } - - // Fallback - if (returnImage == null) - { - // We create a copy of the bitmap, so everything else can be disposed - stream.Position = 0; - using var tmpImage = Image.FromStream(stream, true, true); - Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); - returnImage = Clone(tmpImage, PixelFormat.Format32bppArgb); - } - - return returnImage; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.UnmanagedHelpers; +using log4net; + +namespace Greenshot.Base.Core +{ + internal enum ExifOrientations : byte + { + Unknown = 0, + TopLeft = 1, + TopRight = 2, + BottomRight = 3, + BottomLeft = 4, + LeftTop = 5, + RightTop = 6, + RightBottom = 7, + LeftBottom = 8, + } + + /// + /// Description of ImageHelper. + /// + public static class ImageHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(ImageHelper)); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private const int ExifOrientationId = 0x0112; + + static ImageHelper() + { + StreamConverters["greenshot"] = (stream, s) => + { + var surface = SimpleServiceProvider.Current.GetInstance>().Invoke(); + return surface.GetImageForExport(); + }; + + // Add a SVG converter + StreamConverters["svg"] = (stream, s) => + { + stream.Position = 0; + try + { + return SvgImage.FromStream(stream).Image; + } + catch (Exception ex) + { + Log.Error("Can't load SVG", ex); + } + + return null; + }; + + static Image DefaultConverter(Stream stream, string s) + { + stream.Position = 0; + using var tmpImage = Image.FromStream(stream, true, true); + Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); + return Clone(tmpImage, PixelFormat.Format32bppArgb); + } + + // Fallback + StreamConverters[string.Empty] = DefaultConverter; + StreamConverters["gif"] = DefaultConverter; + StreamConverters["bmp"] = DefaultConverter; + StreamConverters["jpg"] = DefaultConverter; + StreamConverters["jpeg"] = DefaultConverter; + StreamConverters["png"] = DefaultConverter; + StreamConverters["wmf"] = DefaultConverter; + + StreamConverters["ico"] = (stream, extension) => + { + // Icon logic, try to get the Vista icon, else the biggest possible + try + { + using Image tmpImage = ExtractVistaIcon(stream); + if (tmpImage != null) + { + return Clone(tmpImage, PixelFormat.Format32bppArgb); + } + } + catch (Exception vistaIconException) + { + Log.Warn("Can't read icon", vistaIconException); + } + + try + { + // No vista icon, try normal icon + stream.Position = 0; + // We create a copy of the bitmap, so everything else can be disposed + using Icon tmpIcon = new Icon(stream, new Size(1024, 1024)); + using Image tmpImage = tmpIcon.ToBitmap(); + return Clone(tmpImage, PixelFormat.Format32bppArgb); + } + catch (Exception iconException) + { + Log.Warn("Can't read icon", iconException); + } + + stream.Position = 0; + return DefaultConverter(stream, extension); + }; + } + + public static IDictionary> StreamConverters { get; } = new Dictionary>(); + + /// + /// Make sure the image is orientated correctly + /// + /// + public static void Orientate(Image image) + { + if (!CoreConfig.ProcessEXIFOrientation) + { + return; + } + + try + { + // Get the index of the orientation property. + int orientationIndex = Array.IndexOf(image.PropertyIdList, ExifOrientationId); + // If there is no such property, return Unknown. + if (orientationIndex < 0) + { + return; + } + + PropertyItem item = image.GetPropertyItem(ExifOrientationId); + + ExifOrientations orientation = (ExifOrientations) item.Value[0]; + // Orient the image. + switch (orientation) + { + case ExifOrientations.Unknown: + case ExifOrientations.TopLeft: + break; + case ExifOrientations.TopRight: + image.RotateFlip(RotateFlipType.RotateNoneFlipX); + break; + case ExifOrientations.BottomRight: + image.RotateFlip(RotateFlipType.Rotate180FlipNone); + break; + case ExifOrientations.BottomLeft: + image.RotateFlip(RotateFlipType.RotateNoneFlipY); + break; + case ExifOrientations.LeftTop: + image.RotateFlip(RotateFlipType.Rotate90FlipX); + break; + case ExifOrientations.RightTop: + image.RotateFlip(RotateFlipType.Rotate90FlipNone); + break; + case ExifOrientations.RightBottom: + image.RotateFlip(RotateFlipType.Rotate90FlipY); + break; + case ExifOrientations.LeftBottom: + image.RotateFlip(RotateFlipType.Rotate270FlipNone); + break; + } + + // Set the orientation to be normal, as we rotated the image. + item.Value[0] = (byte) ExifOrientations.TopLeft; + image.SetPropertyItem(item); + } + catch (Exception orientEx) + { + Log.Warn("Problem orientating the image: ", orientEx); + } + } + + /// + /// Create a Thumbnail + /// + /// + /// + /// + /// + /// + /// + public static Image CreateThumbnail(Image image, int thumbWidth, int thumbHeight, int maxWidth = -1, int maxHeight = -1) + { + int srcWidth = image.Width; + int srcHeight = image.Height; + if (thumbHeight < 0) + { + thumbHeight = (int) (thumbWidth * (srcHeight / (float) srcWidth)); + } + + if (thumbWidth < 0) + { + thumbWidth = (int) (thumbHeight * (srcWidth / (float) srcHeight)); + } + + if (maxWidth > 0 && thumbWidth > maxWidth) + { + thumbWidth = Math.Min(thumbWidth, maxWidth); + thumbHeight = (int) (thumbWidth * (srcHeight / (float) srcWidth)); + } + + if (maxHeight > 0 && thumbHeight > maxHeight) + { + thumbHeight = Math.Min(thumbHeight, maxHeight); + thumbWidth = (int) (thumbHeight * (srcWidth / (float) srcHeight)); + } + + Bitmap bmp = new Bitmap(thumbWidth, thumbHeight); + using (Graphics graphics = Graphics.FromImage(bmp)) + { + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + Rectangle rectDestination = new Rectangle(0, 0, thumbWidth, thumbHeight); + graphics.DrawImage(image, rectDestination, 0, 0, srcWidth, srcHeight, GraphicsUnit.Pixel); + } + + return bmp; + } + + /// + /// Crops the image to the specified rectangle + /// + /// Image to crop + /// Rectangle with bitmap coordinates, will be "intersected" to the bitmap + public static bool Crop(ref Image image, ref Rectangle cropRectangle) + { + if (image is Bitmap && (image.Width * image.Height > 0)) + { + cropRectangle.Intersect(new Rectangle(0, 0, image.Width, image.Height)); + if (cropRectangle.Width != 0 || cropRectangle.Height != 0) + { + Image returnImage = CloneArea(image, cropRectangle, PixelFormat.DontCare); + image.Dispose(); + image = returnImage; + return true; + } + } + + Log.Warn("Can't crop a null/zero size image!"); + return false; + } + + /// + /// Private helper method for the FindAutoCropRectangle + /// + /// + /// + /// + /// Rectangle + private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference) + { + Rectangle cropRectangle = Rectangle.Empty; + Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y); + Point min = new Point(int.MaxValue, int.MaxValue); + Point max = new Point(int.MinValue, int.MinValue); + + if (cropDifference > 0) + { + for (int y = 0; y < fastBitmap.Height; y++) + { + for (int x = 0; x < fastBitmap.Width; x++) + { + Color currentColor = fastBitmap.GetColorAt(x, y); + int diffR = Math.Abs(currentColor.R - referenceColor.R); + int diffG = Math.Abs(currentColor.G - referenceColor.G); + int diffB = Math.Abs(currentColor.B - referenceColor.B); + if ((diffR + diffG + diffB) / 3 <= cropDifference) + { + continue; + } + + if (x < min.X) min.X = x; + if (y < min.Y) min.Y = y; + if (x > max.X) max.X = x; + if (y > max.Y) max.Y = y; + } + } + } + else + { + for (int y = 0; y < fastBitmap.Height; y++) + { + for (int x = 0; x < fastBitmap.Width; x++) + { + Color currentColor = fastBitmap.GetColorAt(x, y); + if (!referenceColor.Equals(currentColor)) + { + continue; + } + + if (x < min.X) min.X = x; + if (y < min.Y) min.Y = y; + if (x > max.X) max.X = x; + if (y > max.Y) max.Y = y; + } + } + } + + if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1)))) + { + if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue)) + { + cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1); + } + } + + return cropRectangle; + } + + /// + /// Get a rectangle for the image which crops the image of all colors equal to that on 0,0 + /// + /// + /// + /// Rectangle + public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) + { + Rectangle cropRectangle = Rectangle.Empty; + var checkPoints = new List + { + new Point(0, 0), + new Point(0, image.Height - 1), + new Point(image.Width - 1, 0), + new Point(image.Width - 1, image.Height - 1) + }; + // Top Left + // Bottom Left + // Top Right + // Bottom Right + using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap) image)) + { + // find biggest area + foreach (Point checkPoint in checkPoints) + { + var currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference); + if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) + { + cropRectangle = currentRectangle; + } + } + } + + return cropRectangle; + } + + /// + /// Load an image from file + /// + /// + /// + public static Image LoadImage(string filename) + { + if (string.IsNullOrEmpty(filename)) + { + return null; + } + + if (!File.Exists(filename)) + { + return null; + } + + Image fileImage; + Log.InfoFormat("Loading image from file {0}", filename); + // Fixed lock problem Bug #3431881 + using (Stream imageFileStream = File.OpenRead(filename)) + { + fileImage = FromStream(imageFileStream, Path.GetExtension(filename)); + } + + if (fileImage != null) + { + Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", filename, fileImage.Width, fileImage.Height, fileImage.PixelFormat, + fileImage.HorizontalResolution, fileImage.VerticalResolution); + } + + return fileImage; + } + + /// + /// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx + /// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx + /// + /// Stream with the icon information + /// Bitmap with the Vista Icon (256x256) + private static Bitmap ExtractVistaIcon(Stream iconStream) + { + const int sizeIconDir = 6; + const int sizeIconDirEntry = 16; + Bitmap bmpPngExtracted = null; + try + { + byte[] srcBuf = new byte[iconStream.Length]; + iconStream.Read(srcBuf, 0, (int) iconStream.Length); + int iCount = BitConverter.ToInt16(srcBuf, 4); + for (int iIndex = 0; iIndex < iCount; iIndex++) + { + int iWidth = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex]; + int iHeight = srcBuf[sizeIconDir + sizeIconDirEntry * iIndex + 1]; + if (iWidth == 0 && iHeight == 0) + { + int iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8); + int iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12); + using MemoryStream destStream = new MemoryStream(); + destStream.Write(srcBuf, iImageOffset, iImageSize); + destStream.Seek(0, SeekOrigin.Begin); + bmpPngExtracted = new Bitmap(destStream); // This is PNG! :) + break; + } + } + } + catch + { + return null; + } + + return bmpPngExtracted; + } + + /// + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648069%28v=vs.85%29.aspx + /// + /// The file (EXE or DLL) to get the icon from + /// Index of the icon + /// true if the large icon is wanted + /// Icon + public static Icon ExtractAssociatedIcon(string location, int index, bool takeLarge) + { + Shell32.ExtractIconEx(location, index, out var large, out var small, 1); + Icon returnIcon = null; + bool isLarge = false; + bool isSmall = false; + try + { + if (takeLarge && !IntPtr.Zero.Equals(large)) + { + returnIcon = Icon.FromHandle(large); + isLarge = true; + } + else if (!IntPtr.Zero.Equals(small)) + { + returnIcon = Icon.FromHandle(small); + isSmall = true; + } + else if (!IntPtr.Zero.Equals(large)) + { + returnIcon = Icon.FromHandle(large); + isLarge = true; + } + } + finally + { + if (isLarge && !IntPtr.Zero.Equals(small)) + { + User32.DestroyIcon(small); + } + + if (isSmall && !IntPtr.Zero.Equals(large)) + { + User32.DestroyIcon(large); + } + } + + return returnIcon; + } + + /// + /// Apply the effect to the bitmap + /// + /// Bitmap + /// IEffect + /// + /// Bitmap + public static Image ApplyEffect(Image sourceImage, IEffect effect, Matrix matrix) + { + var effects = new List + { + effect + }; + return ApplyEffects(sourceImage, effects, matrix); + } + + /// + /// Apply the effects in the supplied order to the bitmap + /// + /// Bitmap + /// List of IEffect + /// + /// Bitmap + public static Image ApplyEffects(Image sourceImage, IEnumerable effects, Matrix matrix) + { + var currentImage = sourceImage; + bool disposeImage = false; + foreach (var effect in effects) + { + var tmpImage = effect.Apply(currentImage, matrix); + if (tmpImage != null) + { + if (disposeImage) + { + currentImage.Dispose(); + } + + currentImage = tmpImage; + // Make sure the "new" image is disposed + disposeImage = true; + } + } + + return currentImage; + } + + /// + /// Helper method for the tornedge + /// + /// Path to draw to + /// Points for the lines to draw + private static void DrawLines(GraphicsPath path, List points) + { + path.AddLine(points[0], points[1]); + for (int i = 0; i < points.Count - 1; i++) + { + path.AddLine(points[i], points[i + 1]); + } + } + + /// + /// Make the picture look like it's torn + /// + /// Bitmap to make torn edge off + /// How large (height) is each tooth + /// How wide is a horizontal tooth + /// How wide is a vertical tooth + /// bool[] with information on if the edge needs torn or not. Order is clockwise: 0=top,1=right,2=bottom,3=left + /// Changed bitmap + public static Image CreateTornEdge(Image sourceImage, int toothHeight, int horizontalToothRange, int verticalToothRange, bool[] edges) + { + Image returnImage = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb, Color.Empty, sourceImage.HorizontalResolution, + sourceImage.VerticalResolution); + using (var path = new GraphicsPath()) + { + Random random = new Random(); + int horizontalRegions = (int) Math.Round((float) sourceImage.Width / horizontalToothRange); + int verticalRegions = (int) Math.Round((float) sourceImage.Height / verticalToothRange); + + Point topLeft = new Point(0, 0); + Point topRight = new Point(sourceImage.Width, 0); + Point bottomLeft = new Point(0, sourceImage.Height); + Point bottomRight = new Point(sourceImage.Width, sourceImage.Height); + + List points = new List(); + + if (edges[0]) + { + // calculate starting point only if the left edge is torn + if (!edges[3]) + { + points.Add(topLeft); + } + else + { + points.Add(new Point(random.Next(1, toothHeight), random.Next(1, toothHeight))); + } + + for (int i = 1; i < horizontalRegions - 1; i++) + { + points.Add(new Point(i * horizontalToothRange, random.Next(1, toothHeight))); + } + + points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), random.Next(1, toothHeight))); + } + else + { + // set start & endpoint to be the default "whole-line" + points.Add(topLeft); + points.Add(topRight); + } + + // Right + if (edges[1]) + { + for (int i = 1; i < verticalRegions - 1; i++) + { + points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), i * verticalToothRange)); + } + + points.Add(new Point(sourceImage.Width - random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); + } + else + { + // correct previous ending point + points[points.Count - 1] = topRight; + // set endpoint to be the default "whole-line" + points.Add(bottomRight); + } + + // Bottom + if (edges[2]) + { + for (int i = 1; i < horizontalRegions - 1; i++) + { + points.Add(new Point(sourceImage.Width - i * horizontalToothRange, sourceImage.Height - random.Next(1, toothHeight))); + } + + points.Add(new Point(random.Next(1, toothHeight), sourceImage.Height - random.Next(1, toothHeight))); + } + else + { + // correct previous ending point + points[points.Count - 1] = bottomRight; + // set endpoint to be the default "whole-line" + points.Add(bottomLeft); + } + + // Left + if (edges[3]) + { + // One fewer as the end point is the starting point + for (int i = 1; i < verticalRegions - 1; i++) + { + points.Add(new Point(random.Next(1, toothHeight), points[points.Count - 1].Y - verticalToothRange)); + } + } + else + { + // correct previous ending point + points[points.Count - 1] = bottomLeft; + // set endpoint to be the default "whole-line" + points.Add(topLeft); + } + + // End point always is the starting point + points[points.Count - 1] = points[0]; + + DrawLines(path, points); + + path.CloseFigure(); + + // Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing + using Graphics graphics = Graphics.FromImage(returnImage); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + using Brush brush = new TextureBrush(sourceImage); + // Important note: If the target wouldn't be at 0,0 we need to translate-transform!! + graphics.FillPath(brush, path); + } + + return returnImage; + } + + /// + /// Apply BoxBlur to the destinationBitmap + /// + /// Bitmap to blur + /// Must be ODD! + public static void ApplyBoxBlur(Bitmap destinationBitmap, int range) + { + // We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V) + using IFastBitmap fastBitmap = FastBitmap.Create(destinationBitmap); + ApplyBoxBlur(fastBitmap, range); + } + + /// + /// Apply BoxBlur to the fastBitmap + /// + /// IFastBitmap to blur + /// Must be ODD! + public static void ApplyBoxBlur(IFastBitmap fastBitmap, int range) + { + // Range must be odd! + if ((range & 1) == 0) + { + range++; + } + + if (range <= 1) + { + return; + } + + // Box blurs are frequently used to approximate a Gaussian blur. + // By the central limit theorem, if applied 3 times on the same image, a box blur approximates the Gaussian kernel to within about 3%, yielding the same result as a quadratic convolution kernel. + // This might be true, but the GDI+ BlurEffect doesn't look the same, a 2x blur is more simular and we only make 2x Box-Blur. + // (Might also be a mistake in our blur, but for now it looks great) + if (fastBitmap.HasAlphaChannel) + { + BoxBlurHorizontalAlpha(fastBitmap, range); + BoxBlurVerticalAlpha(fastBitmap, range); + BoxBlurHorizontalAlpha(fastBitmap, range); + BoxBlurVerticalAlpha(fastBitmap, range); + } + else + { + BoxBlurHorizontal(fastBitmap, range); + BoxBlurVertical(fastBitmap, range); + BoxBlurHorizontal(fastBitmap, range); + BoxBlurVertical(fastBitmap, range); + } + } + + /// + /// BoxBlurHorizontal is a private helper method for the BoxBlur + /// + /// Target BitmapBuffer + /// Range must be odd! + private static void BoxBlurHorizontal(IFastBitmap targetFastBitmap, int range) + { + if (targetFastBitmap.HasAlphaChannel) + { + throw new NotSupportedException("BoxBlurHorizontal should NOT be called for bitmaps with alpha channel"); + } + + int halfRange = range / 2; + Color[] newColors = new Color[targetFastBitmap.Width]; + byte[] tmpColor = new byte[3]; + for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) + { + int hits = 0; + int r = 0; + int g = 0; + int b = 0; + for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) + { + int oldPixel = x - halfRange - 1; + if (oldPixel >= targetFastBitmap.Left) + { + targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); + r -= tmpColor[FastBitmap.ColorIndexR]; + g -= tmpColor[FastBitmap.ColorIndexG]; + b -= tmpColor[FastBitmap.ColorIndexB]; + hits--; + } + + int newPixel = x + halfRange; + if (newPixel < targetFastBitmap.Right) + { + targetFastBitmap.GetColorAt(newPixel, y, tmpColor); + r += tmpColor[FastBitmap.ColorIndexR]; + g += tmpColor[FastBitmap.ColorIndexG]; + b += tmpColor[FastBitmap.ColorIndexB]; + hits++; + } + + if (x >= targetFastBitmap.Left) + { + newColors[x - targetFastBitmap.Left] = Color.FromArgb(255, (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); + } + } + + for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) + { + targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); + } + } + } + + /// + /// BoxBlurHorizontal is a private helper method for the BoxBlur, only for IFastBitmaps with alpha channel + /// + /// Target BitmapBuffer + /// Range must be odd! + private static void BoxBlurHorizontalAlpha(IFastBitmap targetFastBitmap, int range) + { + if (!targetFastBitmap.HasAlphaChannel) + { + throw new NotSupportedException("BoxBlurHorizontalAlpha should be called for bitmaps with alpha channel"); + } + + int halfRange = range / 2; + Color[] newColors = new Color[targetFastBitmap.Width]; + byte[] tmpColor = new byte[4]; + for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) + { + int hits = 0; + int a = 0; + int r = 0; + int g = 0; + int b = 0; + for (int x = targetFastBitmap.Left - halfRange; x < targetFastBitmap.Right; x++) + { + int oldPixel = x - halfRange - 1; + if (oldPixel >= targetFastBitmap.Left) + { + targetFastBitmap.GetColorAt(oldPixel, y, tmpColor); + a -= tmpColor[FastBitmap.ColorIndexA]; + r -= tmpColor[FastBitmap.ColorIndexR]; + g -= tmpColor[FastBitmap.ColorIndexG]; + b -= tmpColor[FastBitmap.ColorIndexB]; + hits--; + } + + int newPixel = x + halfRange; + if (newPixel < targetFastBitmap.Right) + { + targetFastBitmap.GetColorAt(newPixel, y, tmpColor); + a += tmpColor[FastBitmap.ColorIndexA]; + r += tmpColor[FastBitmap.ColorIndexR]; + g += tmpColor[FastBitmap.ColorIndexG]; + b += tmpColor[FastBitmap.ColorIndexB]; + hits++; + } + + if (x >= targetFastBitmap.Left) + { + newColors[x - targetFastBitmap.Left] = Color.FromArgb((byte) (a / hits), (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); + } + } + + for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) + { + targetFastBitmap.SetColorAt(x, y, newColors[x - targetFastBitmap.Left]); + } + } + } + + /// + /// BoxBlurVertical is a private helper method for the BoxBlur + /// + /// BitmapBuffer which previously was created with BoxBlurHorizontal + /// Range must be odd! + private static void BoxBlurVertical(IFastBitmap targetFastBitmap, int range) + { + if (targetFastBitmap.HasAlphaChannel) + { + throw new NotSupportedException("BoxBlurVertical should NOT be called for bitmaps with alpha channel"); + } + + int halfRange = range / 2; + Color[] newColors = new Color[targetFastBitmap.Height]; + byte[] tmpColor = new byte[4]; + for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) + { + int hits = 0; + int r = 0; + int g = 0; + int b = 0; + for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) + { + int oldPixel = y - halfRange - 1; + if (oldPixel >= targetFastBitmap.Top) + { + targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); + r -= tmpColor[FastBitmap.ColorIndexR]; + g -= tmpColor[FastBitmap.ColorIndexG]; + b -= tmpColor[FastBitmap.ColorIndexB]; + hits--; + } + + int newPixel = y + halfRange; + if (newPixel < targetFastBitmap.Bottom) + { + targetFastBitmap.GetColorAt(x, newPixel, tmpColor); + r += tmpColor[FastBitmap.ColorIndexR]; + g += tmpColor[FastBitmap.ColorIndexG]; + b += tmpColor[FastBitmap.ColorIndexB]; + hits++; + } + + if (y >= targetFastBitmap.Top) + { + newColors[y - targetFastBitmap.Top] = Color.FromArgb(255, (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); + } + } + + for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) + { + targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); + } + } + } + + /// + /// BoxBlurVertical is a private helper method for the BoxBlur + /// + /// BitmapBuffer which previously was created with BoxBlurHorizontal + /// Range must be odd! + private static void BoxBlurVerticalAlpha(IFastBitmap targetFastBitmap, int range) + { + if (!targetFastBitmap.HasAlphaChannel) + { + throw new NotSupportedException("BoxBlurVerticalAlpha should be called for bitmaps with alpha channel"); + } + + int halfRange = range / 2; + Color[] newColors = new Color[targetFastBitmap.Height]; + byte[] tmpColor = new byte[4]; + for (int x = targetFastBitmap.Left; x < targetFastBitmap.Right; x++) + { + int hits = 0; + int a = 0; + int r = 0; + int g = 0; + int b = 0; + for (int y = targetFastBitmap.Top - halfRange; y < targetFastBitmap.Bottom; y++) + { + int oldPixel = y - halfRange - 1; + if (oldPixel >= targetFastBitmap.Top) + { + targetFastBitmap.GetColorAt(x, oldPixel, tmpColor); + a -= tmpColor[FastBitmap.ColorIndexA]; + r -= tmpColor[FastBitmap.ColorIndexR]; + g -= tmpColor[FastBitmap.ColorIndexG]; + b -= tmpColor[FastBitmap.ColorIndexB]; + hits--; + } + + int newPixel = y + halfRange; + if (newPixel < targetFastBitmap.Bottom) + { + //int colorg = pixels[index + newPixelOffset]; + targetFastBitmap.GetColorAt(x, newPixel, tmpColor); + a += tmpColor[FastBitmap.ColorIndexA]; + r += tmpColor[FastBitmap.ColorIndexR]; + g += tmpColor[FastBitmap.ColorIndexG]; + b += tmpColor[FastBitmap.ColorIndexB]; + hits++; + } + + if (y >= targetFastBitmap.Top) + { + newColors[y - targetFastBitmap.Top] = Color.FromArgb((byte) (a / hits), (byte) (r / hits), (byte) (g / hits), (byte) (b / hits)); + } + } + + for (int y = targetFastBitmap.Top; y < targetFastBitmap.Bottom; y++) + { + targetFastBitmap.SetColorAt(x, y, newColors[y - targetFastBitmap.Top]); + } + } + } + + /// + /// This method fixes the problem that we can't apply a filter outside the target bitmap, + /// therefor the filtered-bitmap will be shifted if we try to draw it outside the target bitmap. + /// It will also account for the Invert flag. + /// + /// + /// + /// + /// + public static Rectangle CreateIntersectRectangle(Size applySize, Rectangle rect, bool invert) + { + Rectangle myRect; + if (invert) + { + myRect = new Rectangle(0, 0, applySize.Width, applySize.Height); + } + else + { + Rectangle applyRect = new Rectangle(0, 0, applySize.Width, applySize.Height); + myRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); + myRect.Intersect(applyRect); + } + + return myRect; + } + + /// + /// Create a new bitmap where the sourceBitmap has a shadow + /// + /// Bitmap to make a shadow on + /// How dark is the shadow + /// Size of the shadow + /// What pixel format must the returning bitmap have + /// + /// The transform matrix which describes how the elements need to be transformed to stay at the same location + /// Bitmap with the shadow, is bigger than the sourceBitmap!! + public static Bitmap CreateShadow(Image sourceBitmap, float darkness, int shadowSize, Point shadowOffset, Matrix matrix, PixelFormat targetPixelformat) + { + Point offset = shadowOffset; + offset.X += shadowSize - 1; + offset.Y += shadowSize - 1; + matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); + // Create a new "clean" image + Bitmap returnImage = CreateEmpty(sourceBitmap.Width + shadowSize * 2, sourceBitmap.Height + shadowSize * 2, targetPixelformat, Color.Empty, + sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); + // Make sure the shadow is odd, there is no reason for an even blur! + if ((shadowSize & 1) == 0) + { + shadowSize++; + } + + bool useGdiBlur = GDIplus.IsBlurPossible(shadowSize); + // Create "mask" for the shadow + ColorMatrix maskMatrix = new ColorMatrix + { + Matrix00 = 0, + Matrix11 = 0, + Matrix22 = 0 + }; + if (useGdiBlur) + { + maskMatrix.Matrix33 = darkness + 0.1f; + } + else + { + maskMatrix.Matrix33 = darkness; + } + + Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); + ApplyColorMatrix((Bitmap) sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); + + // blur "shadow", apply to whole new image + if (useGdiBlur) + { + // Use GDI Blur + Rectangle newImageRectangle = new Rectangle(0, 0, returnImage.Width, returnImage.Height); + GDIplus.ApplyBlur(returnImage, newImageRectangle, shadowSize + 1, false); + } + else + { + // try normal software blur + //returnImage = CreateBlur(returnImage, newImageRectangle, true, shadowSize, 1d, false, newImageRectangle); + ApplyBoxBlur(returnImage, shadowSize); + } + + // Draw the original image over the shadow + using (Graphics graphics = Graphics.FromImage(returnImage)) + { + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + // draw original with a TextureBrush so we have nice antialiasing! + using Brush textureBrush = new TextureBrush(sourceBitmap, WrapMode.Clamp); + // We need to do a translate-transform otherwise the image is wrapped + graphics.TranslateTransform(offset.X, offset.Y); + graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height); + } + + return returnImage; + } + + /// + /// Return negative of Bitmap + /// + /// Bitmap to create a negative off + /// Negative bitmap + public static Bitmap CreateNegative(Image sourceImage) + { + Bitmap clone = (Bitmap) Clone(sourceImage); + ColorMatrix invertMatrix = new ColorMatrix(new[] + { + new float[] + { + -1, 0, 0, 0, 0 + }, + new float[] + { + 0, -1, 0, 0, 0 + }, + new float[] + { + 0, 0, -1, 0, 0 + }, + new float[] + { + 0, 0, 0, 1, 0 + }, + new float[] + { + 1, 1, 1, 1, 1 + } + }); + ApplyColorMatrix(clone, invertMatrix); + return clone; + } + + /// + /// Apply a color matrix to the image + /// + /// Image to apply matrix to + /// ColorMatrix to apply + public static void ApplyColorMatrix(Bitmap source, ColorMatrix colorMatrix) + { + ApplyColorMatrix(source, Rectangle.Empty, source, Rectangle.Empty, colorMatrix); + } + + /// + /// Apply a color matrix by copying from the source to the destination + /// + /// Image to copy from + /// Rectangle to copy from + /// Rectangle to copy to + /// Image to copy to + /// ColorMatrix to apply + public static void ApplyColorMatrix(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ColorMatrix colorMatrix) + { + using ImageAttributes imageAttributes = new ImageAttributes(); + imageAttributes.ClearColorMatrix(); + imageAttributes.SetColorMatrix(colorMatrix); + ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); + } + + /// + /// Apply a color matrix by copying from the source to the destination + /// + /// Image to copy from + /// Rectangle to copy from + /// Rectangle to copy to + /// Image to copy to + /// ImageAttributes to apply + public static void ApplyImageAttributes(Bitmap source, Rectangle sourceRect, Bitmap dest, Rectangle destRect, ImageAttributes imageAttributes) + { + if (sourceRect == Rectangle.Empty) + { + sourceRect = new Rectangle(0, 0, source.Width, source.Height); + } + + if (dest == null) + { + dest = source; + } + + if (destRect == Rectangle.Empty) + { + destRect = new Rectangle(0, 0, dest.Width, dest.Height); + } + + using Graphics graphics = Graphics.FromImage(dest); + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingMode = CompositingMode.SourceCopy; + + graphics.DrawImage(source, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes); + } + + /// + /// Returns a b/w of Bitmap + /// + /// Bitmap to create a b/w of + /// Threshold for monochrome filter (0 - 255), lower value means less black + /// b/w bitmap + public static Bitmap CreateMonochrome(Image sourceImage, byte threshold) + { + using IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(sourceImage, sourceImage.PixelFormat); + for (int y = 0; y < fastBitmap.Height; y++) + { + for (int x = 0; x < fastBitmap.Width; x++) + { + Color color = fastBitmap.GetColorAt(x, y); + int colorBrightness = (color.R + color.G + color.B) / 3 > threshold ? 255 : 0; + Color monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness); + fastBitmap.SetColorAt(x, y, monoColor); + } + } + + return fastBitmap.UnlockAndReturnBitmap(); + } + + /// + /// Create a new bitmap where the sourceBitmap has a Simple border around it + /// + /// Bitmap to make a border on + /// Size of the border + /// Color of the border + /// What pixel format must the returning bitmap have + /// The transform matrix which describes how the elements need to be transformed to stay at the same location + /// Bitmap with the shadow, is bigger than the sourceBitmap!! + public static Image CreateBorder(Image sourceImage, int borderSize, Color borderColor, PixelFormat targetPixelformat, Matrix matrix) + { + // "return" the shifted offset, so the caller can e.g. move elements + Point offset = new Point(borderSize, borderSize); + matrix.Translate(offset.X, offset.Y, MatrixOrder.Append); + + // Create a new "clean" image + Bitmap newImage = CreateEmpty(sourceImage.Width + borderSize * 2, sourceImage.Height + borderSize * 2, targetPixelformat, Color.Empty, sourceImage.HorizontalResolution, + sourceImage.VerticalResolution); + using (Graphics graphics = Graphics.FromImage(newImage)) + { + // Make sure we draw with the best quality! + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + using (GraphicsPath path = new GraphicsPath()) + { + path.AddRectangle(new Rectangle(borderSize >> 1, borderSize >> 1, newImage.Width - borderSize, newImage.Height - borderSize)); + using Pen pen = new Pen(borderColor, borderSize) + { + LineJoin = LineJoin.Round, + StartCap = LineCap.Round, + EndCap = LineCap.Round + }; + graphics.DrawPath(pen, path); + } + + // draw original with a TextureBrush so we have nice antialiasing! + using Brush textureBrush = new TextureBrush(sourceImage, WrapMode.Clamp); + // We need to do a translate-tranform otherwise the image is wrapped + graphics.TranslateTransform(offset.X, offset.Y); + graphics.FillRectangle(textureBrush, 0, 0, sourceImage.Width, sourceImage.Height); + } + + return newImage; + } + + /// + /// Create ImageAttributes to modify + /// + /// + /// + /// + /// ImageAttributes + public static ImageAttributes CreateAdjustAttributes(float brightness, float contrast, float gamma) + { + float adjustedBrightness = brightness - 1.0f; + ColorMatrix applyColorMatrix = new ColorMatrix( + new[] + { + new[] + { + contrast, 0, 0, 0, 0 + }, // scale red + new[] + { + 0, contrast, 0, 0, 0 + }, // scale green + new[] + { + 0, 0, contrast, 0, 0 + }, // scale blue + new[] + { + 0, 0, 0, 1.0f, 0 + }, // don't scale alpha + new[] + { + adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1 + } + }); + + //create some image attributes + ImageAttributes attributes = new ImageAttributes(); + attributes.ClearColorMatrix(); + attributes.SetColorMatrix(applyColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + attributes.SetGamma(gamma, ColorAdjustType.Bitmap); + return attributes; + } + + /// + /// Adjust the brightness, contract or gamma of an image. + /// Use the value "1.0f" for no changes. + /// + /// Original bitmap + /// + /// + /// + /// Bitmap with grayscale + public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) + { + //create a blank bitmap the same size as original + // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. + Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, + sourceImage.VerticalResolution); + using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma)) + { + ApplyImageAttributes((Bitmap) sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes); + } + + return newBitmap; + } + + /// + /// Create a new bitmap where the sourceBitmap is in grayscale + /// + /// Original bitmap + /// Bitmap with grayscale + public static Image CreateGrayscale(Image sourceImage) + { + Bitmap clone = (Bitmap) Clone(sourceImage); + ColorMatrix grayscaleMatrix = new ColorMatrix(new[] + { + new[] + { + .3f, .3f, .3f, 0, 0 + }, + new[] + { + .59f, .59f, .59f, 0, 0 + }, + new[] + { + .11f, .11f, .11f, 0, 0 + }, + new float[] + { + 0, 0, 0, 1, 0 + }, + new float[] + { + 0, 0, 0, 0, 1 + } + }); + ApplyColorMatrix(clone, grayscaleMatrix); + return clone; + } + + /// + /// Checks if we support the pixel format + /// + /// PixelFormat to check + /// bool if we support it + public static bool SupportsPixelFormat(PixelFormat pixelformat) + { + return pixelformat.Equals(PixelFormat.Format32bppArgb) || + pixelformat.Equals(PixelFormat.Format32bppPArgb) || + pixelformat.Equals(PixelFormat.Format32bppRgb) || + pixelformat.Equals(PixelFormat.Format24bppRgb); + } + + /// + /// Wrapper for just cloning which calls the CloneArea + /// + /// Image to clone + /// Bitmap with clone image data + public static Image Clone(Image sourceImage) + { + if (sourceImage is Metafile) + { + return (Image) sourceImage.Clone(); + } + + return CloneArea(sourceImage, Rectangle.Empty, PixelFormat.DontCare); + } + + /// + /// Wrapper for just cloning & TargetFormat which calls the CloneArea + /// + /// Image to clone + /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) + /// Bitmap with clone image data + public static Bitmap Clone(Image sourceBitmap, PixelFormat targetFormat) + { + return CloneArea(sourceBitmap, Rectangle.Empty, targetFormat); + } + + /// + /// Clone an image, taking some rules into account: + /// 1) When sourceRect is the whole bitmap there is a GDI+ bug in Clone + /// Clone will than return the same PixelFormat as the source + /// a quick workaround is using new Bitmap which uses a default of Format32bppArgb + /// 2) When going from a transparent to a non transparent bitmap, we draw the background white! + /// + /// Source bitmap to clone + /// Rectangle to copy from the source, use Rectangle.Empty for all + /// Target Format, use PixelFormat.DontCare if you want the original (or a default if the source PixelFormat is not supported) + /// + public static Bitmap CloneArea(Image sourceImage, Rectangle sourceRect, PixelFormat targetFormat) + { + Bitmap newImage; + Rectangle bitmapRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); + + // Make sure the source is not Rectangle.Empty + if (Rectangle.Empty.Equals(sourceRect)) + { + sourceRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height); + } + else + { + sourceRect.Intersect(bitmapRect); + } + + // If no pixelformat is supplied + if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat) + { + if (SupportsPixelFormat(sourceImage.PixelFormat)) + { + targetFormat = sourceImage.PixelFormat; + } + else if (Image.IsAlphaPixelFormat(sourceImage.PixelFormat)) + { + targetFormat = PixelFormat.Format32bppArgb; + } + else + { + targetFormat = PixelFormat.Format24bppRgb; + } + } + + // check the target format + if (!SupportsPixelFormat(targetFormat)) + { + targetFormat = Image.IsAlphaPixelFormat(targetFormat) ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb; + } + + bool destinationIsTransparent = Image.IsAlphaPixelFormat(targetFormat); + bool sourceIsTransparent = Image.IsAlphaPixelFormat(sourceImage.PixelFormat); + bool fromTransparentToNon = !destinationIsTransparent && sourceIsTransparent; + bool isBitmap = sourceImage is Bitmap; + bool isAreaEqual = sourceRect.Equals(bitmapRect); + if (isAreaEqual || fromTransparentToNon || !isBitmap) + { + // Rule 1: if the areas are equal, always copy ourselves + newImage = new Bitmap(bitmapRect.Width, bitmapRect.Height, targetFormat); + // Make sure both images have the same resolution + newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + + using Graphics graphics = Graphics.FromImage(newImage); + if (fromTransparentToNon) + { + // Rule 2: Make sure the background color is white + graphics.Clear(Color.White); + } + + // decide fastest copy method + if (isAreaEqual) + { + graphics.DrawImageUnscaled(sourceImage, 0, 0); + } + else + { + graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel); + } + } + else + { + // Let GDI+ decide how to convert, need to test what is quicker... + newImage = (sourceImage as Bitmap).Clone(sourceRect, targetFormat); + // Make sure both images have the same resolution + newImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + } + + // In WINE someone getting the PropertyItems doesn't work + try + { + // Clone property items (EXIF information etc) + foreach (var propertyItem in sourceImage.PropertyItems) + { + try + { + newImage.SetPropertyItem(propertyItem); + } + catch (Exception innerEx) + { + Log.Warn("Problem cloning a propertyItem.", innerEx); + } + } + } + catch (Exception ex) + { + Log.Warn("Problem cloning a propertyItem.", ex); + } + + return newImage; + } + + /// + /// Rotate the bitmap + /// + /// + /// + /// + public static Image RotateFlip(Image sourceImage, RotateFlipType rotateFlipType) + { + Image returnImage = Clone(sourceImage); + returnImage.RotateFlip(rotateFlipType); + return returnImage; + } + + /// + /// A generic way to create an empty image + /// + /// the source bitmap as the specifications for the new bitmap + /// The color to fill with, or Color.Empty to take the default depending on the pixel format + /// + public static Bitmap CreateEmptyLike(Image sourceImage, Color backgroundColor) + { + PixelFormat pixelFormat = sourceImage.PixelFormat; + if (backgroundColor.A < 255) + { + pixelFormat = PixelFormat.Format32bppArgb; + } + + return CreateEmpty(sourceImage.Width, sourceImage.Height, pixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + } + + /// + /// A generic way to create an empty image + /// + /// + /// + /// + /// The color to fill with, or Color.Empty to take the default depending on the pixel format + /// + /// + /// Bitmap + public static Bitmap CreateEmpty(int width, int height, PixelFormat format, Color backgroundColor, float horizontalResolution, float verticalResolution) + { + // Create a new "clean" image + Bitmap newImage = new Bitmap(width, height, format); + newImage.SetResolution(horizontalResolution, verticalResolution); + if (format != PixelFormat.Format8bppIndexed) + { + using Graphics graphics = Graphics.FromImage(newImage); + // Make sure the background color is what we want (transparent or white, depending on the pixel format) + if (!Color.Empty.Equals(backgroundColor)) + { + graphics.Clear(backgroundColor); + } + else if (Image.IsAlphaPixelFormat(format)) + { + graphics.Clear(Color.Transparent); + } + else + { + graphics.Clear(Color.White); + } + } + + return newImage; + } + + /// + /// Resize canvas with pixel to the left, right, top and bottom + /// + /// + /// The color to fill with, or Color.Empty to take the default depending on the pixel format + /// + /// + /// + /// + /// + /// a new bitmap with the source copied on it + public static Image ResizeCanvas(Image sourceImage, Color backgroundColor, int left, int right, int top, int bottom, Matrix matrix) + { + matrix.Translate(left, top, MatrixOrder.Append); + Bitmap newBitmap = CreateEmpty(sourceImage.Width + left + right, sourceImage.Height + top + bottom, sourceImage.PixelFormat, backgroundColor, + sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + using (Graphics graphics = Graphics.FromImage(newBitmap)) + { + graphics.DrawImageUnscaled(sourceImage, left, top); + } + + return newBitmap; + } + + /// + /// Wrapper for the more complex Resize, this resize could be used for e.g. Thumbnails + /// + /// + /// true to maintain the aspect ratio + /// + /// + /// + /// + public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, int newWidth, int newHeight, Matrix matrix) + { + return ResizeImage(sourceImage, maintainAspectRatio, false, Color.Empty, newWidth, newHeight, matrix); + } + + /// + /// Count how many times the supplied color exists + /// + /// Image to count the pixels of + /// Color to count + /// true if Alpha needs to be checked + /// int with the number of pixels which have colorToCount + public static int CountColor(Image sourceImage, Color colorToCount, bool includeAlpha) + { + int colors = 0; + int toCount = colorToCount.ToArgb(); + if (!includeAlpha) + { + toCount &= 0xffffff; + } + + using IFastBitmap bb = FastBitmap.Create((Bitmap) sourceImage); + for (int y = 0; y < bb.Height; y++) + { + for (int x = 0; x < bb.Width; x++) + { + int bitmapcolor = bb.GetColorAt(x, y).ToArgb(); + if (!includeAlpha) + { + bitmapcolor &= 0xffffff; + } + + if (bitmapcolor == toCount) + { + colors++; + } + } + } + + return colors; + } + + /// + /// Scale the bitmap, keeping aspect ratio, but the canvas will always have the specified size. + /// + /// Image to scale + /// true to maintain the aspect ratio + /// Makes the image maintain aspect ratio, but the canvas get's the specified size + /// The color to fill with, or Color.Empty to take the default depending on the pixel format + /// new width + /// new height + /// + /// a new bitmap with the specified size, the source-Image scaled to fit with aspect ratio locked + public static Image ResizeImage(Image sourceImage, bool maintainAspectRatio, bool canvasUseNewSize, Color backgroundColor, int newWidth, int newHeight, Matrix matrix) + { + int destX = 0; + int destY = 0; + + var nPercentW = newWidth / (float) sourceImage.Width; + var nPercentH = newHeight / (float) sourceImage.Height; + if (maintainAspectRatio) + { + if ((int) nPercentW == 1) + { + nPercentW = nPercentH; + if (canvasUseNewSize) + { + destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2)); + } + } + else if ((int) nPercentH == 1) + { + nPercentH = nPercentW; + if (canvasUseNewSize) + { + destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2)); + } + } + else if ((int) nPercentH != 0 && nPercentH < nPercentW) + { + nPercentW = nPercentH; + if (canvasUseNewSize) + { + destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2)); + } + } + else + { + nPercentH = nPercentW; + if (canvasUseNewSize) + { + destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2)); + } + } + } + + int destWidth = (int) (sourceImage.Width * nPercentW); + int destHeight = (int) (sourceImage.Height * nPercentH); + if (newWidth == 0) + { + newWidth = destWidth; + } + + if (newHeight == 0) + { + newHeight = destHeight; + } + + Image newImage; + if (maintainAspectRatio && canvasUseNewSize) + { + newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + matrix?.Scale((float) newWidth / sourceImage.Width, (float) newHeight / sourceImage.Height, MatrixOrder.Append); + } + else + { + newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); + matrix?.Scale((float) destWidth / sourceImage.Width, (float) destHeight / sourceImage.Height, MatrixOrder.Append); + } + + using (Graphics graphics = Graphics.FromImage(newImage)) + { + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + using ImageAttributes wrapMode = new ImageAttributes(); + wrapMode.SetWrapMode(WrapMode.TileFlipXY); + graphics.DrawImage(sourceImage, new Rectangle(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode); + } + + return newImage; + } + + /// + /// Load a Greenshot surface from a stream + /// + /// Stream + /// + /// ISurface + public static ISurface LoadGreenshotSurface(Stream surfaceFileStream, ISurface returnSurface) + { + Image fileImage; + // Fixed problem that the bitmap stream is disposed... by Cloning the image + // This also ensures the bitmap is correctly created + + // We create a copy of the bitmap, so everything else can be disposed + surfaceFileStream.Position = 0; + using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true)) + { + Log.DebugFormat("Loaded .greenshot file with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); + fileImage = Clone(tmpImage); + } + + // Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor) + const int markerSize = 14; + surfaceFileStream.Seek(-markerSize, SeekOrigin.End); + using (StreamReader streamReader = new StreamReader(surfaceFileStream)) + { + var greenshotMarker = streamReader.ReadToEnd(); + if (!greenshotMarker.StartsWith("Greenshot")) + { + throw new ArgumentException("Stream is not a Greenshot file!"); + } + + Log.InfoFormat("Greenshot file format: {0}", greenshotMarker); + const int filesizeLocation = 8 + markerSize; + surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End); + using BinaryReader reader = new BinaryReader(surfaceFileStream); + long bytesWritten = reader.ReadInt64(); + surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End); + returnSurface.LoadElementsFromStream(surfaceFileStream); + } + + if (fileImage != null) + { + returnSurface.Image = fileImage; + Log.InfoFormat("Information about .greenshot file: {0}x{1}-{2} Resolution {3}x{4}", fileImage.Width, fileImage.Height, fileImage.PixelFormat, + fileImage.HorizontalResolution, fileImage.VerticalResolution); + } + + return returnSurface; + } + + /// + /// Create an image from a stream, if an extension is supplied more formats are supported. + /// + /// Stream + /// + /// Image + public static Image FromStream(Stream stream, string extension = null) + { + if (stream == null) + { + return null; + } + + if (!string.IsNullOrEmpty(extension)) + { + extension = extension.Replace(".", string.Empty); + } + + // Make sure we can try multiple times + if (!stream.CanSeek) + { + var memoryStream = new MemoryStream(); + stream.CopyTo(memoryStream); + stream = memoryStream; + } + + Image returnImage = null; + if (StreamConverters.TryGetValue(extension ?? string.Empty, out var converter)) + { + returnImage = converter(stream, extension); + } + + // Fallback + if (returnImage == null) + { + // We create a copy of the bitmap, so everything else can be disposed + stream.Position = 0; + using var tmpImage = Image.FromStream(stream, true, true); + Log.DebugFormat("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat); + returnImage = Clone(tmpImage, PixelFormat.Format32bppArgb); + } + + return returnImage; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/ImageOutput.cs b/src/Greenshot.Base/Core/ImageOutput.cs similarity index 97% rename from src/GreenshotPlugin/Core/ImageOutput.cs rename to src/Greenshot.Base/Core/ImageOutput.cs index 233ffe377..d6a42a7d9 100644 --- a/src/GreenshotPlugin/Core/ImageOutput.cs +++ b/src/Greenshot.Base/Core/ImageOutput.cs @@ -1,798 +1,798 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using GreenshotPlugin.Controls; -using log4net; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; -using Encoder = System.Drawing.Imaging.Encoder; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of ImageOutput. - /// - public static class ImageOutput - { - private static readonly ILog Log = LogManager.GetLogger(typeof(ImageOutput)); - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131; - private static readonly Cache TmpFileCache = new Cache(10 * 60 * 60, RemoveExpiredTmpFile); - - /// - /// Creates a PropertyItem (Metadata) to store with the image. - /// For the possible ID's see: http://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx - /// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that! - /// - /// ID - /// Text - /// - private static PropertyItem CreatePropertyItem(int id, string text) - { - PropertyItem propertyItem = null; - try - { - ConstructorInfo ci = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] - { - }, null); - propertyItem = (PropertyItem) ci.Invoke(null); - // Make sure it's of type string - propertyItem.Type = 2; - // Set the ID - propertyItem.Id = id; - // Set the text - byte[] byteString = Encoding.ASCII.GetBytes(text + " "); - // Set Zero byte for String end. - byteString[byteString.Length - 1] = 0; - propertyItem.Value = byteString; - propertyItem.Len = text.Length + 1; - } - catch (Exception e) - { - Log.WarnFormat("Error creating a PropertyItem: {0}", e.Message); - } - - return propertyItem; - } - - /// - /// Saves ISurface to stream with specified output settings - /// - /// ISurface to save - /// Stream to save to - /// SurfaceOutputSettings - public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) - { - bool disposeImage = CreateImageFromSurface(surface, outputSettings, out var imageToSave); - SaveToStream(imageToSave, surface, stream, outputSettings); - // cleanup if needed - if (disposeImage) - { - imageToSave?.Dispose(); - } - } - - /// - /// Saves image to stream with specified quality - /// To prevent problems with GDI version of before Windows 7: - /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used. - /// - /// image to save - /// surface for the elements, needed if the greenshot format is used - /// Stream to save to - /// SurfaceOutputSettings - public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) - { - bool useMemoryStream = false; - MemoryStream memoryStream = null; - if (outputSettings.Format == OutputFormat.greenshot && surface == null) - { - throw new ArgumentException("Surface needs to be set when using OutputFormat.Greenshot"); - } - - try - { - var imageFormat = outputSettings.Format switch - { - OutputFormat.bmp => ImageFormat.Bmp, - OutputFormat.gif => ImageFormat.Gif, - OutputFormat.jpg => ImageFormat.Jpeg, - OutputFormat.tiff => ImageFormat.Tiff, - OutputFormat.ico => ImageFormat.Icon, - _ => ImageFormat.Png - }; - Log.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat); - - // Check if we want to use a memory stream, to prevent issues with non seakable streams - // The save is made to the targetStream, this is directed to either the MemoryStream or the original - Stream targetStream = stream; - if (!stream.CanSeek) - { - useMemoryStream = true; - Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); - memoryStream = new MemoryStream(); - targetStream = memoryStream; - } - - if (Equals(imageFormat, ImageFormat.Jpeg)) - { - bool foundEncoder = false; - foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders()) - { - if (imageCodec.FormatID == imageFormat.Guid) - { - EncoderParameters parameters = new EncoderParameters(1) - { - Param = - { - [0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality) - } - }; - // Removing transparency if it's not supported in the output - if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) - { - Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); - AddTag(nonAlphaImage); - nonAlphaImage.Save(targetStream, imageCodec, parameters); - nonAlphaImage.Dispose(); - } - else - { - AddTag(imageToSave); - imageToSave.Save(targetStream, imageCodec, parameters); - } - - foundEncoder = true; - break; - } - } - - if (!foundEncoder) - { - throw new ApplicationException("No JPG encoder found, this should not happen."); - } - } - else if (Equals(imageFormat, ImageFormat.Icon)) - { - // FEATURE-916: Added Icon support - IList images = new List - { - imageToSave - }; - WriteIcon(stream, images); - } - else - { - bool needsDispose = false; - // Removing transparency if it's not supported in the output - if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) - { - imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); - needsDispose = true; - } - - AddTag(imageToSave); - // Added for OptiPNG - bool processed = false; - if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) - { - processed = ProcessPngImageExternally(imageToSave, targetStream); - } - - if (!processed) - { - imageToSave.Save(targetStream, imageFormat); - } - - if (needsDispose) - { - imageToSave.Dispose(); - } - } - - // If we used a memory stream, we need to stream the memory stream to the original stream. - if (useMemoryStream) - { - memoryStream.WriteTo(stream); - } - - // Output the surface elements, size and marker to the stream - if (outputSettings.Format != OutputFormat.greenshot) - { - return; - } - - using MemoryStream tmpStream = new MemoryStream(); - long bytesWritten = surface.SaveElementsToStream(tmpStream); - using BinaryWriter writer = new BinaryWriter(tmpStream); - writer.Write(bytesWritten); - Version v = Assembly.GetExecutingAssembly().GetName().Version; - byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}"); - writer.Write(marker); - tmpStream.WriteTo(stream); - } - finally - { - memoryStream?.Dispose(); - } - } - - /// - /// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream - /// - /// Image to pass to the external process - /// stream to write the processed image to - /// - private static bool ProcessPngImageExternally(Image imageToProcess, Stream targetStream) - { - if (string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) - { - return false; - } - - if (!File.Exists(CoreConfig.OptimizePNGCommand)) - { - Log.WarnFormat("Can't find 'OptimizePNGCommand' {0}", CoreConfig.OptimizePNGCommand); - return false; - } - - string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png"); - try - { - using (FileStream tmpStream = File.Create(tmpFileName)) - { - Log.DebugFormat("Writing png to tmp file: {0}", tmpFileName); - imageToProcess.Save(tmpStream, ImageFormat.Png); - if (Log.IsDebugEnabled) - { - Log.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length); - } - } - - if (Log.IsDebugEnabled) - { - Log.DebugFormat("Starting : {0}", CoreConfig.OptimizePNGCommand); - } - - ProcessStartInfo processStartInfo = new ProcessStartInfo(CoreConfig.OptimizePNGCommand) - { - Arguments = string.Format(CoreConfig.OptimizePNGCommandArguments, tmpFileName), - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false - }; - using Process process = Process.Start(processStartInfo); - if (process != null) - { - process.WaitForExit(); - if (process.ExitCode == 0) - { - if (Log.IsDebugEnabled) - { - Log.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length); - Log.DebugFormat("Reading back tmp file: {0}", tmpFileName); - } - - byte[] processedImage = File.ReadAllBytes(tmpFileName); - targetStream.Write(processedImage, 0, processedImage.Length); - return true; - } - - Log.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode); - Log.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd()); - Log.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd()); - } - } - catch (Exception e) - { - Log.Error("Error while processing PNG image: ", e); - } - finally - { - if (File.Exists(tmpFileName)) - { - Log.DebugFormat("Cleaning up tmp file: {0}", tmpFileName); - File.Delete(tmpFileName); - } - } - - return false; - } - - /// - /// Create an image from a surface with the settings from the output settings applied - /// - /// - /// - /// - /// true if the image must be disposed - public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) - { - bool disposeImage = false; - - if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) - { - // We save the image of the surface, this should not be disposed - imageToSave = surface.Image; - } - else - { - // We create the export image of the surface to save - imageToSave = surface.GetImageForExport(); - disposeImage = true; - } - - // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! - if (outputSettings.Format == OutputFormat.greenshot) - { - return disposeImage; - } - - Image tmpImage; - if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) - { - // apply effects, if there are any - using (Matrix matrix = new Matrix()) - { - tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix); - } - - if (tmpImage != null) - { - if (disposeImage) - { - imageToSave.Dispose(); - } - - imageToSave = tmpImage; - disposeImage = true; - } - } - - // check for color reduction, forced or automatically, only when the DisableReduceColors is false - if (outputSettings.DisableReduceColors || (!CoreConfig.OutputFileAutoReduceColors && !outputSettings.ReduceColors)) - { - return disposeImage; - } - - bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); - if (outputSettings.ReduceColors || (!isAlpha && CoreConfig.OutputFileAutoReduceColors)) - { - using var quantizer = new WuQuantizer((Bitmap) imageToSave); - int colorCount = quantizer.GetColorCount(); - Log.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); - if (!outputSettings.ReduceColors && colorCount >= 256) - { - return disposeImage; - } - - try - { - Log.Info("Reducing colors on bitmap to 256."); - tmpImage = quantizer.GetQuantizedImage(CoreConfig.OutputFileReduceColorsTo); - if (disposeImage) - { - imageToSave.Dispose(); - } - - imageToSave = tmpImage; - // Make sure the "new" image is disposed - disposeImage = true; - } - catch (Exception e) - { - Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); - } - } - else if (isAlpha && !outputSettings.ReduceColors) - { - Log.Info("Skipping 'optional' color reduction as the image has alpha"); - } - - return disposeImage; - } - - /// - /// Add the greenshot property! - /// - /// - private static void AddTag(Image imageToSave) - { - // Create meta-data - PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot"); - if (softwareUsedPropertyItem != null) - { - try - { - imageToSave.SetPropertyItem(softwareUsedPropertyItem); - } - catch (Exception) - { - Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id); - } - } - } - - /// - /// Load a Greenshot surface - /// - /// - /// - /// - public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface) - { - if (string.IsNullOrEmpty(fullPath)) - { - return null; - } - - Log.InfoFormat("Loading image from file {0}", fullPath); - // Fixed lock problem Bug #3431881 - using (Stream surfaceFileStream = File.OpenRead(fullPath)) - { - returnSurface = ImageHelper.LoadGreenshotSurface(surfaceFileStream, returnSurface); - } - - if (returnSurface != null) - { - Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, returnSurface.Image.Width, returnSurface.Image.Height, - returnSurface.Image.PixelFormat, returnSurface.Image.HorizontalResolution, returnSurface.Image.VerticalResolution); - } - - return returnSurface; - } - - /// - /// Saves image to specific path with specified quality - /// - public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings outputSettings, bool copyPathToClipboard) - { - fullPath = FilenameHelper.MakeFqFilenameSafe(fullPath); - string path = Path.GetDirectoryName(fullPath); - - // check whether path exists - if not create it - if (path != null) - { - DirectoryInfo di = new DirectoryInfo(path); - if (!di.Exists) - { - Directory.CreateDirectory(di.FullName); - } - } - - if (!allowOverwrite && File.Exists(fullPath)) - { - ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists."); - throwingException.Data.Add("fullPath", fullPath); - throw throwingException; - } - - Log.DebugFormat("Saving surface to {0}", fullPath); - // Create the stream and call SaveToStream - using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) - { - SaveToStream(surface, stream, outputSettings); - } - - if (copyPathToClipboard) - { - ClipboardHelper.SetClipboardData(fullPath); - } - } - - /// - /// Get the OutputFormat for a filename - /// - /// filename (can be a complete path) - /// OutputFormat - public static OutputFormat FormatForFilename(string fullPath) - { - // Fix for bug 2912959 - string extension = fullPath.Substring(fullPath.LastIndexOf(".", StringComparison.Ordinal) + 1); - OutputFormat format = OutputFormat.png; - try - { - format = (OutputFormat) Enum.Parse(typeof(OutputFormat), extension.ToLower()); - } - catch (ArgumentException ae) - { - Log.Warn("Couldn't parse extension: " + extension, ae); - } - - return format; - } - - /// - /// Save with showing a dialog - /// - /// - /// - /// Path to filename - public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails) - { - string returnValue = null; - using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails)) - { - DialogResult dialogResult = saveImageFileDialog.ShowDialog(); - if (dialogResult.Equals(DialogResult.OK)) - { - try - { - string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension; - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension)); - if (CoreConfig.OutputFilePromptQuality) - { - QualityDialog qualityDialog = new QualityDialog(outputSettings); - qualityDialog.ShowDialog(); - } - - // TODO: For now we always overwrite, should be changed - Save(surface, fileNameWithExtension, true, outputSettings, CoreConfig.OutputFileCopyPathToClipboard); - returnValue = fileNameWithExtension; - IniConfig.Save(); - } - catch (ExternalException) - { - MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error")); - } - } - } - - return returnValue; - } - - /// - /// Create a tmpfile which has the name like in the configured pattern. - /// Used e.g. by the email export - /// - /// - /// - /// - /// Path to image file - public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, SurfaceOutputSettings outputSettings) - { - string pattern = CoreConfig.OutputFileFilenamePattern; - if (string.IsNullOrEmpty(pattern?.Trim())) - { - pattern = "greenshot ${capturetime}"; - } - - string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails); - // Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML - filename = Regex.Replace(filename, @"[^\d\w\.]", "_"); - // Remove multiple "_" - filename = Regex.Replace(filename, @"_+", "_"); - string tmpFile = Path.Combine(Path.GetTempPath(), filename); - - Log.Debug("Creating TMP File: " + tmpFile); - - // Catching any exception to prevent that the user can't write in the directory. - // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218 - try - { - Save(surface, tmpFile, true, outputSettings, false); - TmpFileCache.Add(tmpFile, tmpFile); - } - catch (Exception e) - { - // Show the problem - MessageBox.Show(e.Message, "Error"); - // when save failed we present a SaveWithDialog - tmpFile = SaveWithDialog(surface, captureDetails); - } - - return tmpFile; - } - - /// - /// Remove a tmpfile which was created by SaveNamedTmpFile - /// Used e.g. by the email export - /// - /// - /// true if it worked - public static bool DeleteNamedTmpFile(string tmpfile) - { - Log.Debug("Deleting TMP File: " + tmpfile); - try - { - if (File.Exists(tmpfile)) - { - File.Delete(tmpfile); - TmpFileCache.Remove(tmpfile); - } - - return true; - } - catch (Exception ex) - { - Log.Warn("Error deleting tmp file: ", ex); - } - - return false; - } - - /// - /// Helper method to create a temp image file - /// - /// - /// - /// - /// - public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath) - { - string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format; - // Prevent problems with "other characters", which could cause problems - tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", string.Empty); - if (destinationPath == null) - { - destinationPath = Path.GetTempPath(); - } - - string tmpPath = Path.Combine(destinationPath, tmpFile); - Log.Debug("Creating TMP File : " + tmpPath); - - try - { - Save(surface, tmpPath, true, outputSettings, false); - TmpFileCache.Add(tmpPath, tmpPath); - } - catch (Exception) - { - return null; - } - - return tmpPath; - } - - /// - /// Cleanup all created tmpfiles - /// - public static void RemoveTmpFiles() - { - foreach (string tmpFile in TmpFileCache.Elements) - { - if (File.Exists(tmpFile)) - { - Log.DebugFormat("Removing old temp file {0}", tmpFile); - File.Delete(tmpFile); - } - - TmpFileCache.Remove(tmpFile); - } - } - - /// - /// Cleanup handler for expired tempfiles - /// - /// - /// - private static void RemoveExpiredTmpFile(string filekey, object filename) - { - if (filename is string path && File.Exists(path)) - { - Log.DebugFormat("Removing expired file {0}", path); - File.Delete(path); - } - } - - /// - /// Write the images to the stream as icon - /// Every image is resized to 256x256 (but the content maintains the aspect ratio) - /// - /// Stream to write to - /// List of images - public static void WriteIcon(Stream stream, IList images) - { - var binaryWriter = new BinaryWriter(stream); - // - // ICONDIR structure - // - binaryWriter.Write((short) 0); // reserved - binaryWriter.Write((short) 1); // image type (icon) - binaryWriter.Write((short) images.Count); // number of images - - IList imageSizes = new List(); - IList encodedImages = new List(); - foreach (var image in images) - { - // Pick the best fit - var sizes = new[] - { - 16, 32, 48 - }; - int size = 256; - foreach (var possibleSize in sizes) - { - if (image.Width <= possibleSize && image.Height <= possibleSize) - { - size = possibleSize; - break; - } - } - - var imageStream = new MemoryStream(); - if (image.Width == size && image.Height == size) - { - using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); - clonedImage.Save(imageStream, ImageFormat.Png); - imageSizes.Add(new Size(size, size)); - } - else - { - // Resize to the specified size, first make sure the image is 32bpp - using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); - using var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null); - resizedImage.Save(imageStream, ImageFormat.Png); - imageSizes.Add(resizedImage.Size); - } - - imageStream.Seek(0, SeekOrigin.Begin); - encodedImages.Add(imageStream); - } - - // - // ICONDIRENTRY structure - // - const int iconDirSize = 6; - const int iconDirEntrySize = 16; - - var offset = iconDirSize + (images.Count * iconDirEntrySize); - for (int i = 0; i < images.Count; i++) - { - var imageSize = imageSizes[i]; - // Write the width / height, 0 means 256 - binaryWriter.Write(imageSize.Width == 256 ? (byte) 0 : (byte) imageSize.Width); - binaryWriter.Write(imageSize.Height == 256 ? (byte) 0 : (byte) imageSize.Height); - binaryWriter.Write((byte) 0); // no pallete - binaryWriter.Write((byte) 0); // reserved - binaryWriter.Write((short) 0); // no color planes - binaryWriter.Write((short) 32); // 32 bpp - binaryWriter.Write((int) encodedImages[i].Length); // image data length - binaryWriter.Write(offset); - offset += (int) encodedImages[i].Length; - } - - binaryWriter.Flush(); - // - // Write image data - // - foreach (var encodedImage in encodedImages) - { - encodedImage.WriteTo(stream); - encodedImage.Dispose(); - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; +using log4net; +using Encoder = System.Drawing.Imaging.Encoder; + +namespace Greenshot.Base.Core +{ + /// + /// Description of ImageOutput. + /// + public static class ImageOutput + { + private static readonly ILog Log = LogManager.GetLogger(typeof(ImageOutput)); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131; + private static readonly Cache TmpFileCache = new Cache(10 * 60 * 60, RemoveExpiredTmpFile); + + /// + /// Creates a PropertyItem (Metadata) to store with the image. + /// For the possible ID's see: http://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx + /// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that! + /// + /// ID + /// Text + /// + private static PropertyItem CreatePropertyItem(int id, string text) + { + PropertyItem propertyItem = null; + try + { + ConstructorInfo ci = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] + { + }, null); + propertyItem = (PropertyItem) ci.Invoke(null); + // Make sure it's of type string + propertyItem.Type = 2; + // Set the ID + propertyItem.Id = id; + // Set the text + byte[] byteString = Encoding.ASCII.GetBytes(text + " "); + // Set Zero byte for String end. + byteString[byteString.Length - 1] = 0; + propertyItem.Value = byteString; + propertyItem.Len = text.Length + 1; + } + catch (Exception e) + { + Log.WarnFormat("Error creating a PropertyItem: {0}", e.Message); + } + + return propertyItem; + } + + /// + /// Saves ISurface to stream with specified output settings + /// + /// ISurface to save + /// Stream to save to + /// SurfaceOutputSettings + public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) + { + bool disposeImage = CreateImageFromSurface(surface, outputSettings, out var imageToSave); + SaveToStream(imageToSave, surface, stream, outputSettings); + // cleanup if needed + if (disposeImage) + { + imageToSave?.Dispose(); + } + } + + /// + /// Saves image to stream with specified quality + /// To prevent problems with GDI version of before Windows 7: + /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used. + /// + /// image to save + /// surface for the elements, needed if the greenshot format is used + /// Stream to save to + /// SurfaceOutputSettings + public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) + { + bool useMemoryStream = false; + MemoryStream memoryStream = null; + if (outputSettings.Format == OutputFormat.greenshot && surface == null) + { + throw new ArgumentException("Surface needs to be set when using OutputFormat.Greenshot"); + } + + try + { + var imageFormat = outputSettings.Format switch + { + OutputFormat.bmp => ImageFormat.Bmp, + OutputFormat.gif => ImageFormat.Gif, + OutputFormat.jpg => ImageFormat.Jpeg, + OutputFormat.tiff => ImageFormat.Tiff, + OutputFormat.ico => ImageFormat.Icon, + _ => ImageFormat.Png + }; + Log.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat); + + // Check if we want to use a memory stream, to prevent issues with non seakable streams + // The save is made to the targetStream, this is directed to either the MemoryStream or the original + Stream targetStream = stream; + if (!stream.CanSeek) + { + useMemoryStream = true; + Log.Warn("Using memorystream prevent an issue with saving to a non seekable stream."); + memoryStream = new MemoryStream(); + targetStream = memoryStream; + } + + if (Equals(imageFormat, ImageFormat.Jpeg)) + { + bool foundEncoder = false; + foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders()) + { + if (imageCodec.FormatID == imageFormat.Guid) + { + EncoderParameters parameters = new EncoderParameters(1) + { + Param = + { + [0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality) + } + }; + // Removing transparency if it's not supported in the output + if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) + { + Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); + AddTag(nonAlphaImage); + nonAlphaImage.Save(targetStream, imageCodec, parameters); + nonAlphaImage.Dispose(); + } + else + { + AddTag(imageToSave); + imageToSave.Save(targetStream, imageCodec, parameters); + } + + foundEncoder = true; + break; + } + } + + if (!foundEncoder) + { + throw new ApplicationException("No JPG encoder found, this should not happen."); + } + } + else if (Equals(imageFormat, ImageFormat.Icon)) + { + // FEATURE-916: Added Icon support + IList images = new List + { + imageToSave + }; + WriteIcon(stream, images); + } + else + { + bool needsDispose = false; + // Removing transparency if it's not supported in the output + if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) + { + imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); + needsDispose = true; + } + + AddTag(imageToSave); + // Added for OptiPNG + bool processed = false; + if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) + { + processed = ProcessPngImageExternally(imageToSave, targetStream); + } + + if (!processed) + { + imageToSave.Save(targetStream, imageFormat); + } + + if (needsDispose) + { + imageToSave.Dispose(); + } + } + + // If we used a memory stream, we need to stream the memory stream to the original stream. + if (useMemoryStream) + { + memoryStream.WriteTo(stream); + } + + // Output the surface elements, size and marker to the stream + if (outputSettings.Format != OutputFormat.greenshot) + { + return; + } + + using MemoryStream tmpStream = new MemoryStream(); + long bytesWritten = surface.SaveElementsToStream(tmpStream); + using BinaryWriter writer = new BinaryWriter(tmpStream); + writer.Write(bytesWritten); + Version v = Assembly.GetExecutingAssembly().GetName().Version; + byte[] marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}"); + writer.Write(marker); + tmpStream.WriteTo(stream); + } + finally + { + memoryStream?.Dispose(); + } + } + + /// + /// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream + /// + /// Image to pass to the external process + /// stream to write the processed image to + /// + private static bool ProcessPngImageExternally(Image imageToProcess, Stream targetStream) + { + if (string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) + { + return false; + } + + if (!File.Exists(CoreConfig.OptimizePNGCommand)) + { + Log.WarnFormat("Can't find 'OptimizePNGCommand' {0}", CoreConfig.OptimizePNGCommand); + return false; + } + + string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png"); + try + { + using (FileStream tmpStream = File.Create(tmpFileName)) + { + Log.DebugFormat("Writing png to tmp file: {0}", tmpFileName); + imageToProcess.Save(tmpStream, ImageFormat.Png); + if (Log.IsDebugEnabled) + { + Log.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length); + } + } + + if (Log.IsDebugEnabled) + { + Log.DebugFormat("Starting : {0}", CoreConfig.OptimizePNGCommand); + } + + ProcessStartInfo processStartInfo = new ProcessStartInfo(CoreConfig.OptimizePNGCommand) + { + Arguments = string.Format(CoreConfig.OptimizePNGCommandArguments, tmpFileName), + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false + }; + using Process process = Process.Start(processStartInfo); + if (process != null) + { + process.WaitForExit(); + if (process.ExitCode == 0) + { + if (Log.IsDebugEnabled) + { + Log.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length); + Log.DebugFormat("Reading back tmp file: {0}", tmpFileName); + } + + byte[] processedImage = File.ReadAllBytes(tmpFileName); + targetStream.Write(processedImage, 0, processedImage.Length); + return true; + } + + Log.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode); + Log.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd()); + Log.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd()); + } + } + catch (Exception e) + { + Log.Error("Error while processing PNG image: ", e); + } + finally + { + if (File.Exists(tmpFileName)) + { + Log.DebugFormat("Cleaning up tmp file: {0}", tmpFileName); + File.Delete(tmpFileName); + } + } + + return false; + } + + /// + /// Create an image from a surface with the settings from the output settings applied + /// + /// + /// + /// + /// true if the image must be disposed + public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) + { + bool disposeImage = false; + + if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) + { + // We save the image of the surface, this should not be disposed + imageToSave = surface.Image; + } + else + { + // We create the export image of the surface to save + imageToSave = surface.GetImageForExport(); + disposeImage = true; + } + + // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! + if (outputSettings.Format == OutputFormat.greenshot) + { + return disposeImage; + } + + Image tmpImage; + if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) + { + // apply effects, if there are any + using (Matrix matrix = new Matrix()) + { + tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix); + } + + if (tmpImage != null) + { + if (disposeImage) + { + imageToSave.Dispose(); + } + + imageToSave = tmpImage; + disposeImage = true; + } + } + + // check for color reduction, forced or automatically, only when the DisableReduceColors is false + if (outputSettings.DisableReduceColors || (!CoreConfig.OutputFileAutoReduceColors && !outputSettings.ReduceColors)) + { + return disposeImage; + } + + bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); + if (outputSettings.ReduceColors || (!isAlpha && CoreConfig.OutputFileAutoReduceColors)) + { + using var quantizer = new WuQuantizer((Bitmap) imageToSave); + int colorCount = quantizer.GetColorCount(); + Log.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); + if (!outputSettings.ReduceColors && colorCount >= 256) + { + return disposeImage; + } + + try + { + Log.Info("Reducing colors on bitmap to 256."); + tmpImage = quantizer.GetQuantizedImage(CoreConfig.OutputFileReduceColorsTo); + if (disposeImage) + { + imageToSave.Dispose(); + } + + imageToSave = tmpImage; + // Make sure the "new" image is disposed + disposeImage = true; + } + catch (Exception e) + { + Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); + } + } + else if (isAlpha && !outputSettings.ReduceColors) + { + Log.Info("Skipping 'optional' color reduction as the image has alpha"); + } + + return disposeImage; + } + + /// + /// Add the greenshot property! + /// + /// + private static void AddTag(Image imageToSave) + { + // Create meta-data + PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot"); + if (softwareUsedPropertyItem != null) + { + try + { + imageToSave.SetPropertyItem(softwareUsedPropertyItem); + } + catch (Exception) + { + Log.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id); + } + } + } + + /// + /// Load a Greenshot surface + /// + /// + /// + /// + public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface) + { + if (string.IsNullOrEmpty(fullPath)) + { + return null; + } + + Log.InfoFormat("Loading image from file {0}", fullPath); + // Fixed lock problem Bug #3431881 + using (Stream surfaceFileStream = File.OpenRead(fullPath)) + { + returnSurface = ImageHelper.LoadGreenshotSurface(surfaceFileStream, returnSurface); + } + + if (returnSurface != null) + { + Log.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, returnSurface.Image.Width, returnSurface.Image.Height, + returnSurface.Image.PixelFormat, returnSurface.Image.HorizontalResolution, returnSurface.Image.VerticalResolution); + } + + return returnSurface; + } + + /// + /// Saves image to specific path with specified quality + /// + public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings outputSettings, bool copyPathToClipboard) + { + fullPath = FilenameHelper.MakeFqFilenameSafe(fullPath); + string path = Path.GetDirectoryName(fullPath); + + // check whether path exists - if not create it + if (path != null) + { + DirectoryInfo di = new DirectoryInfo(path); + if (!di.Exists) + { + Directory.CreateDirectory(di.FullName); + } + } + + if (!allowOverwrite && File.Exists(fullPath)) + { + ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists."); + throwingException.Data.Add("fullPath", fullPath); + throw throwingException; + } + + Log.DebugFormat("Saving surface to {0}", fullPath); + // Create the stream and call SaveToStream + using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write)) + { + SaveToStream(surface, stream, outputSettings); + } + + if (copyPathToClipboard) + { + ClipboardHelper.SetClipboardData(fullPath); + } + } + + /// + /// Get the OutputFormat for a filename + /// + /// filename (can be a complete path) + /// OutputFormat + public static OutputFormat FormatForFilename(string fullPath) + { + // Fix for bug 2912959 + string extension = fullPath.Substring(fullPath.LastIndexOf(".", StringComparison.Ordinal) + 1); + OutputFormat format = OutputFormat.png; + try + { + format = (OutputFormat) Enum.Parse(typeof(OutputFormat), extension.ToLower()); + } + catch (ArgumentException ae) + { + Log.Warn("Couldn't parse extension: " + extension, ae); + } + + return format; + } + + /// + /// Save with showing a dialog + /// + /// + /// + /// Path to filename + public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails) + { + string returnValue = null; + using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails)) + { + DialogResult dialogResult = saveImageFileDialog.ShowDialog(); + if (dialogResult.Equals(DialogResult.OK)) + { + try + { + string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension; + SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension)); + if (CoreConfig.OutputFilePromptQuality) + { + QualityDialog qualityDialog = new QualityDialog(outputSettings); + qualityDialog.ShowDialog(); + } + + // TODO: For now we always overwrite, should be changed + Save(surface, fileNameWithExtension, true, outputSettings, CoreConfig.OutputFileCopyPathToClipboard); + returnValue = fileNameWithExtension; + IniConfig.Save(); + } + catch (ExternalException) + { + MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error")); + } + } + } + + return returnValue; + } + + /// + /// Create a tmpfile which has the name like in the configured pattern. + /// Used e.g. by the email export + /// + /// + /// + /// + /// Path to image file + public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, SurfaceOutputSettings outputSettings) + { + string pattern = CoreConfig.OutputFileFilenamePattern; + if (string.IsNullOrEmpty(pattern?.Trim())) + { + pattern = "greenshot ${capturetime}"; + } + + string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails); + // Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML + filename = Regex.Replace(filename, @"[^\d\w\.]", "_"); + // Remove multiple "_" + filename = Regex.Replace(filename, @"_+", "_"); + string tmpFile = Path.Combine(Path.GetTempPath(), filename); + + Log.Debug("Creating TMP File: " + tmpFile); + + // Catching any exception to prevent that the user can't write in the directory. + // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218 + try + { + Save(surface, tmpFile, true, outputSettings, false); + TmpFileCache.Add(tmpFile, tmpFile); + } + catch (Exception e) + { + // Show the problem + MessageBox.Show(e.Message, "Error"); + // when save failed we present a SaveWithDialog + tmpFile = SaveWithDialog(surface, captureDetails); + } + + return tmpFile; + } + + /// + /// Remove a tmpfile which was created by SaveNamedTmpFile + /// Used e.g. by the email export + /// + /// + /// true if it worked + public static bool DeleteNamedTmpFile(string tmpfile) + { + Log.Debug("Deleting TMP File: " + tmpfile); + try + { + if (File.Exists(tmpfile)) + { + File.Delete(tmpfile); + TmpFileCache.Remove(tmpfile); + } + + return true; + } + catch (Exception ex) + { + Log.Warn("Error deleting tmp file: ", ex); + } + + return false; + } + + /// + /// Helper method to create a temp image file + /// + /// + /// + /// + /// + public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath) + { + string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format; + // Prevent problems with "other characters", which could cause problems + tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", string.Empty); + if (destinationPath == null) + { + destinationPath = Path.GetTempPath(); + } + + string tmpPath = Path.Combine(destinationPath, tmpFile); + Log.Debug("Creating TMP File : " + tmpPath); + + try + { + Save(surface, tmpPath, true, outputSettings, false); + TmpFileCache.Add(tmpPath, tmpPath); + } + catch (Exception) + { + return null; + } + + return tmpPath; + } + + /// + /// Cleanup all created tmpfiles + /// + public static void RemoveTmpFiles() + { + foreach (string tmpFile in TmpFileCache.Elements) + { + if (File.Exists(tmpFile)) + { + Log.DebugFormat("Removing old temp file {0}", tmpFile); + File.Delete(tmpFile); + } + + TmpFileCache.Remove(tmpFile); + } + } + + /// + /// Cleanup handler for expired tempfiles + /// + /// + /// + private static void RemoveExpiredTmpFile(string filekey, object filename) + { + if (filename is string path && File.Exists(path)) + { + Log.DebugFormat("Removing expired file {0}", path); + File.Delete(path); + } + } + + /// + /// Write the images to the stream as icon + /// Every image is resized to 256x256 (but the content maintains the aspect ratio) + /// + /// Stream to write to + /// List of images + public static void WriteIcon(Stream stream, IList images) + { + var binaryWriter = new BinaryWriter(stream); + // + // ICONDIR structure + // + binaryWriter.Write((short) 0); // reserved + binaryWriter.Write((short) 1); // image type (icon) + binaryWriter.Write((short) images.Count); // number of images + + IList imageSizes = new List(); + IList encodedImages = new List(); + foreach (var image in images) + { + // Pick the best fit + var sizes = new[] + { + 16, 32, 48 + }; + int size = 256; + foreach (var possibleSize in sizes) + { + if (image.Width <= possibleSize && image.Height <= possibleSize) + { + size = possibleSize; + break; + } + } + + var imageStream = new MemoryStream(); + if (image.Width == size && image.Height == size) + { + using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); + clonedImage.Save(imageStream, ImageFormat.Png); + imageSizes.Add(new Size(size, size)); + } + else + { + // Resize to the specified size, first make sure the image is 32bpp + using var clonedImage = ImageHelper.Clone(image, PixelFormat.Format32bppArgb); + using var resizedImage = ImageHelper.ResizeImage(clonedImage, true, true, Color.Empty, size, size, null); + resizedImage.Save(imageStream, ImageFormat.Png); + imageSizes.Add(resizedImage.Size); + } + + imageStream.Seek(0, SeekOrigin.Begin); + encodedImages.Add(imageStream); + } + + // + // ICONDIRENTRY structure + // + const int iconDirSize = 6; + const int iconDirEntrySize = 16; + + var offset = iconDirSize + (images.Count * iconDirEntrySize); + for (int i = 0; i < images.Count; i++) + { + var imageSize = imageSizes[i]; + // Write the width / height, 0 means 256 + binaryWriter.Write(imageSize.Width == 256 ? (byte) 0 : (byte) imageSize.Width); + binaryWriter.Write(imageSize.Height == 256 ? (byte) 0 : (byte) imageSize.Height); + binaryWriter.Write((byte) 0); // no pallete + binaryWriter.Write((byte) 0); // reserved + binaryWriter.Write((short) 0); // no color planes + binaryWriter.Write((short) 32); // 32 bpp + binaryWriter.Write((int) encodedImages[i].Length); // image data length + binaryWriter.Write(offset); + offset += (int) encodedImages[i].Length; + } + + binaryWriter.Flush(); + // + // Write image data + // + foreach (var encodedImage in encodedImages) + { + encodedImage.WriteTo(stream); + encodedImage.Dispose(); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/ImageWrapper.cs b/src/Greenshot.Base/Core/ImageWrapper.cs similarity index 95% rename from src/GreenshotPlugin/Core/ImageWrapper.cs rename to src/Greenshot.Base/Core/ImageWrapper.cs index 720d2ce50..517249534 100644 --- a/src/GreenshotPlugin/Core/ImageWrapper.cs +++ b/src/Greenshot.Base/Core/ImageWrapper.cs @@ -1,77 +1,77 @@ -using System.Drawing; -using System.Drawing.Imaging; - -namespace GreenshotPlugin.Core -{ - /// - /// Wrap an image, make it resizeable - /// - public class ImageWrapper : IImage - { - // Underlying image, is used to generate a resized version of it when needed - private readonly Image _image; - private Image _imageClone; - - public ImageWrapper(Image image) - { - // Make sure the orientation is set correctly so Greenshot can process the image correctly - ImageHelper.Orientate(image); - _image = image; - Width = _image.Width; - Height = _image.Height; - } - - public void Dispose() - { - _image.Dispose(); - _imageClone?.Dispose(); - } - - /// - /// Height of the image, can be set to change - /// - public int Height { get; set; } - - /// - /// Width of the image, can be set to change. - /// - public int Width { get; set; } - - /// - /// Size of the image - /// - public Size Size => new Size(Width, Height); - - /// - /// Pixelformat of the underlying image - /// - public PixelFormat PixelFormat => Image.PixelFormat; - - public float HorizontalResolution => Image.HorizontalResolution; - public float VerticalResolution => Image.VerticalResolution; - - public Image Image - { - get - { - if (_imageClone == null) - { - if (_image.Height == Height && _image.Width == Width) - { - return _image; - } - } - - if (_imageClone?.Height == Height && _imageClone?.Width == Width) - { - return _imageClone; - } - - // Calculate new image clone - _imageClone?.Dispose(); - _imageClone = ImageHelper.ResizeImage(_image, false, Width, Height, null); - return _imageClone; - } - } - } +using System.Drawing; +using System.Drawing.Imaging; + +namespace Greenshot.Base.Core +{ + /// + /// Wrap an image, make it resizeable + /// + public class ImageWrapper : IImage + { + // Underlying image, is used to generate a resized version of it when needed + private readonly Image _image; + private Image _imageClone; + + public ImageWrapper(Image image) + { + // Make sure the orientation is set correctly so Greenshot can process the image correctly + ImageHelper.Orientate(image); + _image = image; + Width = _image.Width; + Height = _image.Height; + } + + public void Dispose() + { + _image.Dispose(); + _imageClone?.Dispose(); + } + + /// + /// Height of the image, can be set to change + /// + public int Height { get; set; } + + /// + /// Width of the image, can be set to change. + /// + public int Width { get; set; } + + /// + /// Size of the image + /// + public Size Size => new Size(Width, Height); + + /// + /// Pixelformat of the underlying image + /// + public PixelFormat PixelFormat => Image.PixelFormat; + + public float HorizontalResolution => Image.HorizontalResolution; + public float VerticalResolution => Image.VerticalResolution; + + public Image Image + { + get + { + if (_imageClone == null) + { + if (_image.Height == Height && _image.Width == Width) + { + return _image; + } + } + + if (_imageClone?.Height == Height && _imageClone?.Width == Width) + { + return _imageClone; + } + + // Calculate new image clone + _imageClone?.Dispose(); + _imageClone = ImageHelper.ResizeImage(_image, false, Width, Height, null); + return _imageClone; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/InterfaceUtils.cs b/src/Greenshot.Base/Core/InterfaceUtils.cs similarity index 96% rename from src/GreenshotPlugin/Core/InterfaceUtils.cs rename to src/Greenshot.Base/Core/InterfaceUtils.cs index c71c7b6ad..c93f24b56 100644 --- a/src/GreenshotPlugin/Core/InterfaceUtils.cs +++ b/src/Greenshot.Base/Core/InterfaceUtils.cs @@ -1,73 +1,73 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Threading; -using log4net; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of InterfaceUtils. - /// - public static class InterfaceUtils - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils)); - - public static List GetSubclassesOf(Type type, bool excludeSystemTypes) - { - var list = new List(); - foreach (var currentAssembly in Thread.GetDomain().GetAssemblies()) - { - try - { - Type[] types = currentAssembly.GetTypes(); - if (excludeSystemTypes && (!excludeSystemTypes || currentAssembly.FullName.StartsWith("System."))) - { - continue; - } - - foreach (var currentType in types) - { - if (type.IsInterface) - { - if (currentType.GetInterface(type.FullName) != null) - { - list.Add(currentType); - } - } - else if (currentType.IsSubclassOf(type)) - { - list.Add(currentType); - } - } - } - catch (Exception ex) - { - LOG.WarnFormat("Problem getting subclasses of type: {0}, message: {1}", type.FullName, ex.Message); - } - } - - return list; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Threading; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// Description of InterfaceUtils. + /// + public static class InterfaceUtils + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils)); + + public static List GetSubclassesOf(Type type, bool excludeSystemTypes) + { + var list = new List(); + foreach (var currentAssembly in Thread.GetDomain().GetAssemblies()) + { + try + { + Type[] types = currentAssembly.GetTypes(); + if (excludeSystemTypes && (!excludeSystemTypes || currentAssembly.FullName.StartsWith("System."))) + { + continue; + } + + foreach (var currentType in types) + { + if (type.IsInterface) + { + if (currentType.GetInterface(type.FullName) != null) + { + list.Add(currentType); + } + } + else if (currentType.IsSubclassOf(type)) + { + list.Add(currentType); + } + } + } + catch (Exception ex) + { + LOG.WarnFormat("Problem getting subclasses of type: {0}, message: {1}", type.FullName, ex.Message); + } + } + + return list; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/JSONHelper.cs b/src/Greenshot.Base/Core/JSONHelper.cs similarity index 96% rename from src/GreenshotPlugin/Core/JSONHelper.cs rename to src/Greenshot.Base/Core/JSONHelper.cs index 28a76a71d..37da4972b 100644 --- a/src/GreenshotPlugin/Core/JSONHelper.cs +++ b/src/Greenshot.Base/Core/JSONHelper.cs @@ -1,436 +1,436 @@ -/* -Copyright (C) 2008 Patrick van Bergen - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -using System.Collections.Generic; -using System.Globalization; -using System.Text; - -namespace GreenshotPlugin.Core -{ - /// - /// This parses a JSON response, a modified version of the code found at: - /// See: http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html - /// - /// This file is under the MIT License, which is GPL Compatible and according to: http://en.wikipedia.org/wiki/MIT_License - /// can be used under the GPL "umbrella". - /// - /// TODO: code should be replaced when upgrading to .NET 3.5 or higher!! - /// - public class JSONHelper - { - public const int TOKEN_NONE = 0; - public const int TOKEN_CURLY_OPEN = 1; - public const int TOKEN_CURLY_CLOSE = 2; - public const int TOKEN_SQUARED_OPEN = 3; - public const int TOKEN_SQUARED_CLOSE = 4; - public const int TOKEN_COLON = 5; - public const int TOKEN_COMMA = 6; - public const int TOKEN_STRING = 7; - public const int TOKEN_NUMBER = 8; - public const int TOKEN_TRUE = 9; - public const int TOKEN_FALSE = 10; - public const int TOKEN_NULL = 11; - - private const int BUILDER_CAPACITY = 2000; - - /// - /// Parses the string json into a value - /// - /// A JSON string. - /// An ArrayList, a Hashtable, a double, a string, null, true, or false - public static IDictionary JsonDecode(string json) - { - bool success = true; - - return JsonDecode(json, ref success); - } - - /// - /// Parses the string json into a value; and fills 'success' with the successfullness of the parse. - /// - /// A JSON string. - /// Successful parse? - /// An ArrayList, a Hashtable, a double, a string, null, true, or false - public static IDictionary JsonDecode(string json, ref bool success) - { - success = true; - if (json != null) - { - char[] charArray = json.ToCharArray(); - int index = 0; - IDictionary value = ParseValue(charArray, ref index, ref success) as IDictionary; - return value; - } - - return null; - } - - protected static IDictionary ParseObject(char[] json, ref int index, ref bool success) - { - IDictionary table = new Dictionary(); - int token; - - // { - NextToken(json, ref index); - - bool done = false; - while (!done) - { - token = LookAhead(json, index); - if (token == TOKEN_NONE) - { - success = false; - return null; - } - else if (token == TOKEN_COMMA) - { - NextToken(json, ref index); - } - else if (token == TOKEN_CURLY_CLOSE) - { - NextToken(json, ref index); - return table; - } - else - { - // name - string name = ParseString(json, ref index, ref success); - if (!success) - { - success = false; - return null; - } - - // : - token = NextToken(json, ref index); - if (token != TOKEN_COLON) - { - success = false; - return null; - } - - // value - object value = ParseValue(json, ref index, ref success); - if (!success) - { - success = false; - return null; - } - - table.Add(name, value); - } - } - - return table; - } - - protected static IList ParseArray(char[] json, ref int index, ref bool success) - { - IList array = new List(); - - // [ - NextToken(json, ref index); - - bool done = false; - while (!done) - { - int token = LookAhead(json, index); - if (token == TOKEN_NONE) - { - success = false; - return null; - } - else if (token == TOKEN_COMMA) - { - NextToken(json, ref index); - } - else if (token == TOKEN_SQUARED_CLOSE) - { - NextToken(json, ref index); - break; - } - else - { - object value = ParseValue(json, ref index, ref success); - if (!success) - { - return null; - } - - array.Add(value); - } - } - - return array; - } - - protected static object ParseValue(char[] json, ref int index, ref bool success) - { - switch (LookAhead(json, index)) - { - case TOKEN_STRING: - return ParseString(json, ref index, ref success); - case TOKEN_NUMBER: - return ParseNumber(json, ref index, ref success); - case TOKEN_CURLY_OPEN: - return ParseObject(json, ref index, ref success); - case TOKEN_SQUARED_OPEN: - return ParseArray(json, ref index, ref success); - case TOKEN_TRUE: - NextToken(json, ref index); - return true; - case TOKEN_FALSE: - NextToken(json, ref index); - return false; - case TOKEN_NULL: - NextToken(json, ref index); - return null; - case TOKEN_NONE: - break; - } - - success = false; - return null; - } - - protected static string ParseString(char[] json, ref int index, ref bool success) - { - StringBuilder s = new StringBuilder(BUILDER_CAPACITY); - - EatWhitespace(json, ref index); - - // " - var c = json[index++]; - - bool complete = false; - while (!complete) - { - if (index == json.Length) - { - break; - } - - c = json[index++]; - if (c == '"') - { - complete = true; - break; - } - else if (c == '\\') - { - if (index == json.Length) - { - break; - } - - c = json[index++]; - if (c == '"') - { - s.Append('"'); - } - else if (c == '\\') - { - s.Append('\\'); - } - else if (c == '/') - { - s.Append('/'); - } - else if (c == 'b') - { - s.Append('\b'); - } - else if (c == 'f') - { - s.Append('\f'); - } - else if (c == 'n') - { - s.Append('\n'); - } - else if (c == 'r') - { - s.Append('\r'); - } - else if (c == 't') - { - s.Append('\t'); - } - else if (c == 'u') - { - int remainingLength = json.Length - index; - if (remainingLength >= 4) - { - // parse the 32 bit hex into an integer codepoint - if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var codePoint))) - { - return string.Empty; - } - - // convert the integer codepoint to a unicode char and add to string - s.Append(char.ConvertFromUtf32((int) codePoint)); - // skip 4 chars - index += 4; - } - else - { - break; - } - } - } - else - { - s.Append(c); - } - } - - if (!complete) - { - success = false; - return null; - } - - return s.ToString(); - } - - protected static double ParseNumber(char[] json, ref int index, ref bool success) - { - EatWhitespace(json, ref index); - - int lastIndex = GetLastIndexOfNumber(json, index); - int charLength = (lastIndex - index) + 1; - - success = double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out var number); - - index = lastIndex + 1; - return number; - } - - protected static int GetLastIndexOfNumber(char[] json, int index) - { - int lastIndex; - - for (lastIndex = index; lastIndex < json.Length; lastIndex++) - { - if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) - { - break; - } - } - - return lastIndex - 1; - } - - protected static void EatWhitespace(char[] json, ref int index) - { - for (; index < json.Length; index++) - { - if (" \t\n\r".IndexOf(json[index]) == -1) - { - break; - } - } - } - - protected static int LookAhead(char[] json, int index) - { - int saveIndex = index; - return NextToken(json, ref saveIndex); - } - - protected static int NextToken(char[] json, ref int index) - { - EatWhitespace(json, ref index); - - if (index == json.Length) - { - return TOKEN_NONE; - } - - char c = json[index]; - index++; - switch (c) - { - case '{': - return TOKEN_CURLY_OPEN; - case '}': - return TOKEN_CURLY_CLOSE; - case '[': - return TOKEN_SQUARED_OPEN; - case ']': - return TOKEN_SQUARED_CLOSE; - case ',': - return TOKEN_COMMA; - case '"': - return TOKEN_STRING; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - return TOKEN_NUMBER; - case ':': - return TOKEN_COLON; - } - - index--; - - int remainingLength = json.Length - index; - - // false - if (remainingLength >= 5) - { - if (json[index] == 'f' && - json[index + 1] == 'a' && - json[index + 2] == 'l' && - json[index + 3] == 's' && - json[index + 4] == 'e') - { - index += 5; - return TOKEN_FALSE; - } - } - - // true - if (remainingLength >= 4) - { - if (json[index] == 't' && - json[index + 1] == 'r' && - json[index + 2] == 'u' && - json[index + 3] == 'e') - { - index += 4; - return TOKEN_TRUE; - } - } - - // null - if (remainingLength >= 4) - { - if (json[index] == 'n' && - json[index + 1] == 'u' && - json[index + 2] == 'l' && - json[index + 3] == 'l') - { - index += 4; - return TOKEN_NULL; - } - } - - return TOKEN_NONE; - } - } +/* +Copyright (C) 2008 Patrick van Bergen + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace Greenshot.Base.Core +{ + /// + /// This parses a JSON response, a modified version of the code found at: + /// See: http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html + /// + /// This file is under the MIT License, which is GPL Compatible and according to: http://en.wikipedia.org/wiki/MIT_License + /// can be used under the GPL "umbrella". + /// + /// TODO: code should be replaced when upgrading to .NET 3.5 or higher!! + /// + public class JSONHelper + { + public const int TOKEN_NONE = 0; + public const int TOKEN_CURLY_OPEN = 1; + public const int TOKEN_CURLY_CLOSE = 2; + public const int TOKEN_SQUARED_OPEN = 3; + public const int TOKEN_SQUARED_CLOSE = 4; + public const int TOKEN_COLON = 5; + public const int TOKEN_COMMA = 6; + public const int TOKEN_STRING = 7; + public const int TOKEN_NUMBER = 8; + public const int TOKEN_TRUE = 9; + public const int TOKEN_FALSE = 10; + public const int TOKEN_NULL = 11; + + private const int BUILDER_CAPACITY = 2000; + + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An ArrayList, a Hashtable, a double, a string, null, true, or false + public static IDictionary JsonDecode(string json) + { + bool success = true; + + return JsonDecode(json, ref success); + } + + /// + /// Parses the string json into a value; and fills 'success' with the successfullness of the parse. + /// + /// A JSON string. + /// Successful parse? + /// An ArrayList, a Hashtable, a double, a string, null, true, or false + public static IDictionary JsonDecode(string json, ref bool success) + { + success = true; + if (json != null) + { + char[] charArray = json.ToCharArray(); + int index = 0; + IDictionary value = ParseValue(charArray, ref index, ref success) as IDictionary; + return value; + } + + return null; + } + + protected static IDictionary ParseObject(char[] json, ref int index, ref bool success) + { + IDictionary table = new Dictionary(); + int token; + + // { + NextToken(json, ref index); + + bool done = false; + while (!done) + { + token = LookAhead(json, index); + if (token == TOKEN_NONE) + { + success = false; + return null; + } + else if (token == TOKEN_COMMA) + { + NextToken(json, ref index); + } + else if (token == TOKEN_CURLY_CLOSE) + { + NextToken(json, ref index); + return table; + } + else + { + // name + string name = ParseString(json, ref index, ref success); + if (!success) + { + success = false; + return null; + } + + // : + token = NextToken(json, ref index); + if (token != TOKEN_COLON) + { + success = false; + return null; + } + + // value + object value = ParseValue(json, ref index, ref success); + if (!success) + { + success = false; + return null; + } + + table.Add(name, value); + } + } + + return table; + } + + protected static IList ParseArray(char[] json, ref int index, ref bool success) + { + IList array = new List(); + + // [ + NextToken(json, ref index); + + bool done = false; + while (!done) + { + int token = LookAhead(json, index); + if (token == TOKEN_NONE) + { + success = false; + return null; + } + else if (token == TOKEN_COMMA) + { + NextToken(json, ref index); + } + else if (token == TOKEN_SQUARED_CLOSE) + { + NextToken(json, ref index); + break; + } + else + { + object value = ParseValue(json, ref index, ref success); + if (!success) + { + return null; + } + + array.Add(value); + } + } + + return array; + } + + protected static object ParseValue(char[] json, ref int index, ref bool success) + { + switch (LookAhead(json, index)) + { + case TOKEN_STRING: + return ParseString(json, ref index, ref success); + case TOKEN_NUMBER: + return ParseNumber(json, ref index, ref success); + case TOKEN_CURLY_OPEN: + return ParseObject(json, ref index, ref success); + case TOKEN_SQUARED_OPEN: + return ParseArray(json, ref index, ref success); + case TOKEN_TRUE: + NextToken(json, ref index); + return true; + case TOKEN_FALSE: + NextToken(json, ref index); + return false; + case TOKEN_NULL: + NextToken(json, ref index); + return null; + case TOKEN_NONE: + break; + } + + success = false; + return null; + } + + protected static string ParseString(char[] json, ref int index, ref bool success) + { + StringBuilder s = new StringBuilder(BUILDER_CAPACITY); + + EatWhitespace(json, ref index); + + // " + var c = json[index++]; + + bool complete = false; + while (!complete) + { + if (index == json.Length) + { + break; + } + + c = json[index++]; + if (c == '"') + { + complete = true; + break; + } + else if (c == '\\') + { + if (index == json.Length) + { + break; + } + + c = json[index++]; + if (c == '"') + { + s.Append('"'); + } + else if (c == '\\') + { + s.Append('\\'); + } + else if (c == '/') + { + s.Append('/'); + } + else if (c == 'b') + { + s.Append('\b'); + } + else if (c == 'f') + { + s.Append('\f'); + } + else if (c == 'n') + { + s.Append('\n'); + } + else if (c == 'r') + { + s.Append('\r'); + } + else if (c == 't') + { + s.Append('\t'); + } + else if (c == 'u') + { + int remainingLength = json.Length - index; + if (remainingLength >= 4) + { + // parse the 32 bit hex into an integer codepoint + if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var codePoint))) + { + return string.Empty; + } + + // convert the integer codepoint to a unicode char and add to string + s.Append(char.ConvertFromUtf32((int) codePoint)); + // skip 4 chars + index += 4; + } + else + { + break; + } + } + } + else + { + s.Append(c); + } + } + + if (!complete) + { + success = false; + return null; + } + + return s.ToString(); + } + + protected static double ParseNumber(char[] json, ref int index, ref bool success) + { + EatWhitespace(json, ref index); + + int lastIndex = GetLastIndexOfNumber(json, index); + int charLength = (lastIndex - index) + 1; + + success = double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out var number); + + index = lastIndex + 1; + return number; + } + + protected static int GetLastIndexOfNumber(char[] json, int index) + { + int lastIndex; + + for (lastIndex = index; lastIndex < json.Length; lastIndex++) + { + if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) + { + break; + } + } + + return lastIndex - 1; + } + + protected static void EatWhitespace(char[] json, ref int index) + { + for (; index < json.Length; index++) + { + if (" \t\n\r".IndexOf(json[index]) == -1) + { + break; + } + } + } + + protected static int LookAhead(char[] json, int index) + { + int saveIndex = index; + return NextToken(json, ref saveIndex); + } + + protected static int NextToken(char[] json, ref int index) + { + EatWhitespace(json, ref index); + + if (index == json.Length) + { + return TOKEN_NONE; + } + + char c = json[index]; + index++; + switch (c) + { + case '{': + return TOKEN_CURLY_OPEN; + case '}': + return TOKEN_CURLY_CLOSE; + case '[': + return TOKEN_SQUARED_OPEN; + case ']': + return TOKEN_SQUARED_CLOSE; + case ',': + return TOKEN_COMMA; + case '"': + return TOKEN_STRING; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + return TOKEN_NUMBER; + case ':': + return TOKEN_COLON; + } + + index--; + + int remainingLength = json.Length - index; + + // false + if (remainingLength >= 5) + { + if (json[index] == 'f' && + json[index + 1] == 'a' && + json[index + 2] == 'l' && + json[index + 3] == 's' && + json[index + 4] == 'e') + { + index += 5; + return TOKEN_FALSE; + } + } + + // true + if (remainingLength >= 4) + { + if (json[index] == 't' && + json[index + 1] == 'r' && + json[index + 2] == 'u' && + json[index + 3] == 'e') + { + index += 4; + return TOKEN_TRUE; + } + } + + // null + if (remainingLength >= 4) + { + if (json[index] == 'n' && + json[index + 1] == 'u' && + json[index + 2] == 'l' && + json[index + 3] == 'l') + { + index += 4; + return TOKEN_NULL; + } + } + + return TOKEN_NONE; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/Language.cs b/src/Greenshot.Base/Core/Language.cs similarity index 97% rename from src/GreenshotPlugin/Core/Language.cs rename to src/Greenshot.Base/Core/Language.cs index ae0b4ed0f..74ba1b457 100644 --- a/src/GreenshotPlugin/Core/Language.cs +++ b/src/Greenshot.Base/Core/Language.cs @@ -1,807 +1,807 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Xml; -using GreenshotPlugin.IniFile; -using log4net; -using Microsoft.Win32; - -namespace GreenshotPlugin.Core -{ - /// - /// This class supplies the GUI with translations, based upon keys. - /// The language resources are loaded from the language files found on fixed or supplied paths - /// - public class Language - { - private static readonly ILog Log = LogManager.GetLogger(typeof(Language)); - private static readonly List LanguagePaths = new List(); - private static readonly Dictionary> LanguageFiles = new Dictionary>(); - private static readonly Dictionary HelpFiles = new Dictionary(); - private const string DefaultLanguage = "en-US"; - private const string HelpFilenamePattern = @"help-*.html"; - private const string LanguageFilenamePattern = @"language*.xml"; - private static readonly Regex PrefixRegexp = new Regex(@"language_([a-zA-Z0-9]+).*"); - private static readonly Regex IetfCleanRegexp = new Regex(@"[^a-zA-Z]+"); - private static readonly Regex IetfRegexp = new Regex(@"^.*([a-zA-Z]{2,3}-[a-zA-Z]{1,2})\.xml$"); - private const string LanguageGroupsKey = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups"; - private static readonly List UnsupportedLanguageGroups = new List(); - private static readonly Dictionary Resources = new Dictionary(); - private static string _currentLanguage; - - public static event LanguageChangedHandler LanguageChanged; - - /// - /// Static initializer for the language code - /// - static Language() - { - if (!IniConfig.IsInitialized) - { - Log.Warn("IniConfig hasn't been initialized yet! (Design mode?)"); - IniConfig.Init("greenshot", "greenshot"); - } - - if (!LogHelper.IsInitialized) - { - Log.Warn("Log4net hasn't been initialized yet! (Design mode?)"); - LogHelper.InitializeLog4Net(); - } - - try - { - string applicationFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - // PAF Path - if (applicationFolder != null) - { - AddPath(Path.Combine(applicationFolder, @"App\Greenshot\Languages")); - } - - // Application data path - string applicationDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - AddPath(Path.Combine(applicationDataFolder, @"Greenshot\Languages\")); - - // Startup path - if (applicationFolder != null) - { - AddPath(Path.Combine(applicationFolder, @"Languages")); - } - } - catch (Exception pathException) - { - Log.Error(pathException); - } - - try - { - using RegistryKey languageGroupsKey = Registry.LocalMachine.OpenSubKey(LanguageGroupsKey, false); - if (languageGroupsKey != null) - { - string[] groups = languageGroupsKey.GetValueNames(); - foreach (string group in groups) - { - string groupValue = (string) languageGroupsKey.GetValue(group); - bool isGroupNotInstalled = "0".Equals(groupValue); - if (isGroupNotInstalled) - { - UnsupportedLanguageGroups.Add(group.ToLower()); - } - } - } - } - catch (Exception e) - { - Log.Warn("Couldn't read the installed language groups.", e); - } - - var coreConfig = IniConfig.GetIniSection(); - ScanFiles(); - if (!string.IsNullOrEmpty(coreConfig.Language)) - { - CurrentLanguage = coreConfig.Language; - if (CurrentLanguage != null && CurrentLanguage != coreConfig.Language) - { - coreConfig.Language = CurrentLanguage; - } - } - - if (CurrentLanguage == null) - { - Log.Warn("Couldn't set language from configuration, changing to default. Installation problem?"); - CurrentLanguage = DefaultLanguage; - if (CurrentLanguage != null) - { - coreConfig.Language = CurrentLanguage; - } - } - - if (CurrentLanguage == null) - { - Log.Error("Couldn't set language, installation problem?"); - } - } - - /// - /// Internal method to add a path to the paths that will be scanned for language files! - /// - /// - /// true if the path exists and is added - private static bool AddPath(string path) - { - if (!LanguagePaths.Contains(path)) - { - if (Directory.Exists(path)) - { - Log.DebugFormat("Adding language path {0}", path); - LanguagePaths.Add(path); - return true; - } - - Log.InfoFormat("Not adding non existing language path {0}", path); - } - - return false; - } - - /// - /// Add a new path to the paths that will be scanned for language files! - /// - /// - /// true if the path exists and is added - public static bool AddLanguageFilePath(string path) - { - if (!LanguagePaths.Contains(path)) - { - Log.DebugFormat("New language path {0}", path); - if (AddPath(path)) - { - ScanFiles(); - Reload(); - } - else - { - return false; - } - } - - return true; - } - - /// - /// Load the files for the specified ietf - /// - /// - private static void LoadFiles(string ietf) - { - ietf = ReformatIetf(ietf); - if (!LanguageFiles.ContainsKey(ietf)) - { - Log.ErrorFormat("No language {0} available.", ietf); - return; - } - - List filesToLoad = LanguageFiles[ietf]; - foreach (LanguageFile fileToLoad in filesToLoad) - { - LoadResources(fileToLoad); - } - } - - /// - /// Load the language resources from the scanned files - /// - private static void Reload() - { - Resources.Clear(); - LoadFiles(DefaultLanguage); - if (_currentLanguage != null && !_currentLanguage.Equals(DefaultLanguage)) - { - LoadFiles(_currentLanguage); - } - } - - /// - /// Get or set the current language - /// - public static string CurrentLanguage - { - get => _currentLanguage; - set - { - string ietf = FindBestIetfMatch(value); - if (!LanguageFiles.ContainsKey(ietf)) - { - Log.WarnFormat("No match for language {0} found!", ietf); - } - else - { - if (_currentLanguage == null || !_currentLanguage.Equals(ietf)) - { - _currentLanguage = ietf; - Reload(); - if (LanguageChanged == null) - { - return; - } - - try - { - LanguageChanged(null, null); - } - catch - { - // ignored - } - - return; - } - } - - Log.Debug("CurrentLanguage not changed!"); - } - } - - /// - /// Try to find the best match for the supplied IETF - /// - /// string - /// IETF - private static string FindBestIetfMatch(string inputIetf) - { - string returnIetf = inputIetf; - if (string.IsNullOrEmpty(returnIetf)) - { - returnIetf = DefaultLanguage; - } - - returnIetf = ReformatIetf(returnIetf); - if (!LanguageFiles.ContainsKey(returnIetf)) - { - Log.WarnFormat("Unknown language {0}, trying best match!", returnIetf); - if (returnIetf.Length == 5) - { - returnIetf = returnIetf.Substring(0, 2); - } - - foreach (string availableIetf in LanguageFiles.Keys) - { - if (!availableIetf.StartsWith(returnIetf)) continue; - - Log.InfoFormat("Found language {0}, best match for {1}!", availableIetf, returnIetf); - returnIetf = availableIetf; - break; - } - } - - return returnIetf; - } - - /// - /// This helper method clears all non alpha characters from the IETF, and does a reformatting. - /// This prevents problems with multiple formats or typos. - /// - /// - /// - private static string ReformatIetf(string inputIetf) - { - string returnIetf = null; - if (!string.IsNullOrEmpty(inputIetf)) - { - returnIetf = inputIetf.ToLower(); - returnIetf = IetfCleanRegexp.Replace(returnIetf, string.Empty); - if (returnIetf.Length == 4) - { - returnIetf = returnIetf.Substring(0, 2) + "-" + returnIetf.Substring(2, 2).ToUpper(); - } - } - - return returnIetf; - } - - /// - /// Return a list of all the supported languages - /// - public static IList SupportedLanguages - { - get - { - IList languages = new List(); - // Loop over all languages with all the files in there - foreach (List langs in LanguageFiles.Values) - { - // Loop over all the files for a language - foreach (LanguageFile langFile in langs) - { - // Only take the ones without prefix, these are the "base" language files - if (langFile.Prefix != null) continue; - languages.Add(langFile); - break; - } - } - - return languages; - } - } - - /// - /// Return the path to the help-file - /// - public static string HelpFilePath - { - get - { - if (HelpFiles.ContainsKey(_currentLanguage)) - { - return HelpFiles[_currentLanguage]; - } - - return HelpFiles[DefaultLanguage]; - } - } - - /// - /// Load the resources from the language file - /// - /// File to load from - private static void LoadResources(LanguageFile languageFile) - { - Log.InfoFormat("Loading language file {0}", languageFile.Filepath); - try - { - XmlDocument xmlDocument = new XmlDocument(); - xmlDocument.Load(languageFile.Filepath); - XmlNodeList resourceNodes = xmlDocument.GetElementsByTagName("resource"); - foreach (XmlNode resourceNode in resourceNodes) - { - string key = resourceNode.Attributes["name"].Value; - if (!string.IsNullOrEmpty(languageFile.Prefix)) - { - key = languageFile.Prefix + "." + key; - } - - string text = resourceNode.InnerText; - if (!string.IsNullOrEmpty(text)) - { - text = text.Trim(); - } - - if (!Resources.ContainsKey(key)) - { - Resources.Add(key, text); - } - else - { - Resources[key] = text; - } - } - } - catch (Exception e) - { - Log.Error("Could not load language file " + languageFile.Filepath, e); - } - } - - /// - /// Load the language file information - /// - /// - /// - private static LanguageFile LoadFileInfo(string languageFilePath) - { - try - { - XmlDocument xmlDocument = new XmlDocument(); - xmlDocument.Load(languageFilePath); - XmlNodeList nodes = xmlDocument.GetElementsByTagName("language"); - if (nodes.Count > 0) - { - LanguageFile languageFile = new LanguageFile - { - Filepath = languageFilePath - }; - XmlNode node = nodes.Item(0); - if (node?.Attributes != null) - { - languageFile.Description = node.Attributes["description"].Value; - if (node.Attributes["ietf"] != null) - { - languageFile.Ietf = ReformatIetf(node.Attributes["ietf"].Value); - } - - if (node.Attributes["version"] != null) - { - languageFile.Version = new Version(node.Attributes["version"].Value); - } - - if (node.Attributes["prefix"] != null) - { - languageFile.Prefix = node.Attributes["prefix"].Value.ToLower(); - } - - if (node.Attributes["languagegroup"] != null) - { - string languageGroup = node.Attributes["languagegroup"].Value; - languageFile.LanguageGroup = languageGroup.ToLower(); - } - } - - return languageFile; - } - - throw new XmlException("Root element is missing"); - } - catch (Exception e) - { - Log.Error("Could not load language file " + languageFilePath, e); - } - - return null; - } - - /// - /// Scan the files in all directories - /// - private static void ScanFiles() - { - LanguageFiles.Clear(); - HelpFiles.Clear(); - foreach (string languagePath in LanguagePaths) - { - if (!Directory.Exists(languagePath)) - { - Log.InfoFormat("Skipping non existing language path {0}", languagePath); - continue; - } - - Log.InfoFormat("Searching language directory '{0}' for language files with pattern '{1}'", languagePath, LanguageFilenamePattern); - try - { - foreach (string languageFilepath in Directory.GetFiles(languagePath, LanguageFilenamePattern, SearchOption.AllDirectories)) - { - //LOG.DebugFormat("Found language file: {0}", languageFilepath); - LanguageFile languageFile = LoadFileInfo(languageFilepath); - if (languageFile == null) - { - continue; - } - - if (string.IsNullOrEmpty(languageFile.Ietf)) - { - Log.WarnFormat("Fixing missing ietf in language-file {0}", languageFilepath); - string languageFilename = Path.GetFileName(languageFilepath); - if (IetfRegexp.IsMatch(languageFilename)) - { - string replacementIetf = IetfRegexp.Replace(languageFilename, "$1"); - languageFile.Ietf = ReformatIetf(replacementIetf); - Log.InfoFormat("Fixed IETF to {0}", languageFile.Ietf); - } - else - { - Log.ErrorFormat("Missing ietf , no recover possible... skipping language-file {0}!", languageFilepath); - continue; - } - } - - // Check if we can display the file - if (!string.IsNullOrEmpty(languageFile.LanguageGroup) && UnsupportedLanguageGroups.Contains(languageFile.LanguageGroup)) - { - Log.InfoFormat("Skipping unsuported (not able to display) language {0} from file {1}", languageFile.Description, languageFilepath); - continue; - } - - // build prefix, based on the filename, but only if it's not set in the file itself. - if (string.IsNullOrEmpty(languageFile.Prefix)) - { - string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath); - if (PrefixRegexp.IsMatch(languageFilename)) - { - languageFile.Prefix = PrefixRegexp.Replace(languageFilename, "$1"); - if (!string.IsNullOrEmpty(languageFile.Prefix)) - { - languageFile.Prefix = languageFile.Prefix.Replace("plugin", string.Empty).ToLower(); - } - } - } - - List currentFiles; - if (LanguageFiles.ContainsKey(languageFile.Ietf)) - { - currentFiles = LanguageFiles[languageFile.Ietf]; - bool needToAdd = true; - List deleteList = new List(); - foreach (LanguageFile compareWithLangfile in currentFiles) - { - if ((languageFile.Prefix != null || compareWithLangfile.Prefix != null) && - (languageFile.Prefix == null || - !languageFile.Prefix.Equals(compareWithLangfile.Prefix))) continue; - - if (compareWithLangfile.Version > languageFile.Version) - { - Log.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, - compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); - needToAdd = false; - break; - } - - Log.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, - compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); - deleteList.Add(compareWithLangfile); - } - - if (needToAdd) - { - foreach (LanguageFile deleteFile in deleteList) - { - currentFiles.Remove(deleteFile); - } - - Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); - currentFiles.Add(languageFile); - } - } - else - { - currentFiles = new List - { - languageFile - }; - LanguageFiles.Add(languageFile.Ietf, currentFiles); - Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); - } - } - } - catch (DirectoryNotFoundException) - { - Log.InfoFormat("Non existing language directory: {0}", languagePath); - } - catch (Exception e) - { - Log.Error("Error trying for read directory " + languagePath, e); - } - - // Now find the help files - Log.InfoFormat("Searching language directory '{0}' for help files with pattern '{1}'", languagePath, HelpFilenamePattern); - try - { - foreach (string helpFilepath in Directory.GetFiles(languagePath, HelpFilenamePattern, SearchOption.AllDirectories)) - { - Log.DebugFormat("Found help file: {0}", helpFilepath); - string helpFilename = Path.GetFileName(helpFilepath); - string ietf = ReformatIetf(helpFilename.Replace(".html", string.Empty).Replace("help-", "")); - if (!HelpFiles.ContainsKey(ietf)) - { - HelpFiles.Add(ietf, helpFilepath); - } - else - { - Log.WarnFormat("skipping help file {0}, already a file with the same IETF {1} found!", helpFilepath, ietf); - } - } - } - catch (DirectoryNotFoundException) - { - Log.InfoFormat("Non existing language directory: {0}", languagePath); - } - catch (Exception e) - { - Log.Error("Error trying for read directory " + languagePath, e); - } - } - } - - /// - /// Check if a resource with prefix.key exists - /// - /// - /// - /// true if available - public static bool HasKey(string prefix, string key) - { - return HasKey(prefix + "." + key); - } - - /// - /// Check if a resource with key exists - /// - /// - /// true if available - public static bool HasKey(string key) - { - if (key == null) - { - return false; - } - - return Resources.ContainsKey(key); - } - - /// - /// TryGet method which combines HasKey & GetString - /// - /// - /// out string - /// - public static bool TryGetString(string key, out string languageString) - { - return Resources.TryGetValue(key, out languageString); - } - - /// - /// TryGet method which combines HasKey & GetString - /// - /// string with prefix - /// string with key - /// out string - /// - public static bool TryGetString(string prefix, string key, out string languageString) - { - return Resources.TryGetValue(prefix + "." + key, out languageString); - } - - /// - /// TryGet method which combines HasKey & GetString - /// - /// string with prefix - /// Enum with key - /// out string - /// - public static bool TryGetString(string prefix, Enum key, out string languageString) - { - return Resources.TryGetValue(prefix + "." + key, out languageString); - } - - /// - /// Translate - /// - /// object - /// string - public static string Translate(object key) - { - string typename = key.GetType().Name; - string enumKey = typename + "." + key; - if (HasKey(enumKey)) - { - return GetString(enumKey); - } - - return key.ToString(); - } - - /// - /// Get the resource for key - /// - /// Enum - /// resource or a "string ###key### not found" - public static string GetString(Enum key) - { - if (key == null) - { - return null; - } - - return GetString(key.ToString()); - } - - /// - /// Get the resource for prefix.key - /// - /// string - /// Enum - /// resource or a "string ###prefix.key### not found" - public static string GetString(string prefix, Enum key) - { - if (key == null) - { - return null; - } - - return GetString(prefix + "." + key); - } - - /// - /// Get the resource for prefix.key - /// - /// string - /// string - /// resource or a "string ###prefix.key### not found" - public static string GetString(string prefix, string key) - { - return GetString(prefix + "." + key); - } - - /// - /// Get the resource for key - /// - /// string - /// resource or a "string ###key### not found" - public static string GetString(string key) - { - if (key == null) - { - return null; - } - - if (!Resources.TryGetValue(key, out var returnValue)) - { - return "string ###" + key + "### not found"; - } - - return returnValue; - } - - /// - /// Get the resource for key, format with with string.format an supply the parameters - /// - /// Enum - /// object - /// formatted resource or a "string ###key### not found" - public static string GetFormattedString(Enum key, object param) - { - return GetFormattedString(key.ToString(), param); - } - - /// - /// Get the resource for prefix.key, format with with string.format an supply the parameters - /// - /// string - /// Enum - /// object - /// formatted resource or a "string ###prefix.key### not found" - public static string GetFormattedString(string prefix, Enum key, object param) - { - return GetFormattedString(prefix, key.ToString(), param); - } - - /// - /// Get the resource for prefix.key, format with with string.format an supply the parameters - /// - /// string - /// string - /// object - /// formatted resource or a "string ###prefix.key### not found" - public static string GetFormattedString(string prefix, string key, object param) - { - return GetFormattedString(prefix + "." + key, param); - } - - /// - /// Get the resource for key, format with with string.format an supply the parameters - /// - /// string - /// object - /// formatted resource or a "string ###key### not found" - public static string GetFormattedString(string key, object param) - { - if (!Resources.TryGetValue(key, out var returnValue)) - { - return "string ###" + key + "### not found"; - } - - return string.Format(returnValue, param); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Xml; +using Greenshot.Base.IniFile; +using log4net; +using Microsoft.Win32; + +namespace Greenshot.Base.Core +{ + /// + /// This class supplies the GUI with translations, based upon keys. + /// The language resources are loaded from the language files found on fixed or supplied paths + /// + public class Language + { + private static readonly ILog Log = LogManager.GetLogger(typeof(Language)); + private static readonly List LanguagePaths = new List(); + private static readonly Dictionary> LanguageFiles = new Dictionary>(); + private static readonly Dictionary HelpFiles = new Dictionary(); + private const string DefaultLanguage = "en-US"; + private const string HelpFilenamePattern = @"help-*.html"; + private const string LanguageFilenamePattern = @"language*.xml"; + private static readonly Regex PrefixRegexp = new Regex(@"language_([a-zA-Z0-9]+).*"); + private static readonly Regex IetfCleanRegexp = new Regex(@"[^a-zA-Z]+"); + private static readonly Regex IetfRegexp = new Regex(@"^.*([a-zA-Z]{2,3}-[a-zA-Z]{1,2})\.xml$"); + private const string LanguageGroupsKey = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups"; + private static readonly List UnsupportedLanguageGroups = new List(); + private static readonly Dictionary Resources = new Dictionary(); + private static string _currentLanguage; + + public static event LanguageChangedHandler LanguageChanged; + + /// + /// Static initializer for the language code + /// + static Language() + { + if (!IniConfig.IsInitialized) + { + Log.Warn("IniConfig hasn't been initialized yet! (Design mode?)"); + IniConfig.Init("greenshot", "greenshot"); + } + + if (!LogHelper.IsInitialized) + { + Log.Warn("Log4net hasn't been initialized yet! (Design mode?)"); + LogHelper.InitializeLog4Net(); + } + + try + { + string applicationFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + // PAF Path + if (applicationFolder != null) + { + AddPath(Path.Combine(applicationFolder, @"App\Greenshot\Languages")); + } + + // Application data path + string applicationDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + AddPath(Path.Combine(applicationDataFolder, @"Greenshot\Languages\")); + + // Startup path + if (applicationFolder != null) + { + AddPath(Path.Combine(applicationFolder, @"Languages")); + } + } + catch (Exception pathException) + { + Log.Error(pathException); + } + + try + { + using RegistryKey languageGroupsKey = Registry.LocalMachine.OpenSubKey(LanguageGroupsKey, false); + if (languageGroupsKey != null) + { + string[] groups = languageGroupsKey.GetValueNames(); + foreach (string group in groups) + { + string groupValue = (string) languageGroupsKey.GetValue(group); + bool isGroupNotInstalled = "0".Equals(groupValue); + if (isGroupNotInstalled) + { + UnsupportedLanguageGroups.Add(group.ToLower()); + } + } + } + } + catch (Exception e) + { + Log.Warn("Couldn't read the installed language groups.", e); + } + + var coreConfig = IniConfig.GetIniSection(); + ScanFiles(); + if (!string.IsNullOrEmpty(coreConfig.Language)) + { + CurrentLanguage = coreConfig.Language; + if (CurrentLanguage != null && CurrentLanguage != coreConfig.Language) + { + coreConfig.Language = CurrentLanguage; + } + } + + if (CurrentLanguage == null) + { + Log.Warn("Couldn't set language from configuration, changing to default. Installation problem?"); + CurrentLanguage = DefaultLanguage; + if (CurrentLanguage != null) + { + coreConfig.Language = CurrentLanguage; + } + } + + if (CurrentLanguage == null) + { + Log.Error("Couldn't set language, installation problem?"); + } + } + + /// + /// Internal method to add a path to the paths that will be scanned for language files! + /// + /// + /// true if the path exists and is added + private static bool AddPath(string path) + { + if (!LanguagePaths.Contains(path)) + { + if (Directory.Exists(path)) + { + Log.DebugFormat("Adding language path {0}", path); + LanguagePaths.Add(path); + return true; + } + + Log.InfoFormat("Not adding non existing language path {0}", path); + } + + return false; + } + + /// + /// Add a new path to the paths that will be scanned for language files! + /// + /// + /// true if the path exists and is added + public static bool AddLanguageFilePath(string path) + { + if (!LanguagePaths.Contains(path)) + { + Log.DebugFormat("New language path {0}", path); + if (AddPath(path)) + { + ScanFiles(); + Reload(); + } + else + { + return false; + } + } + + return true; + } + + /// + /// Load the files for the specified ietf + /// + /// + private static void LoadFiles(string ietf) + { + ietf = ReformatIetf(ietf); + if (!LanguageFiles.ContainsKey(ietf)) + { + Log.ErrorFormat("No language {0} available.", ietf); + return; + } + + List filesToLoad = LanguageFiles[ietf]; + foreach (LanguageFile fileToLoad in filesToLoad) + { + LoadResources(fileToLoad); + } + } + + /// + /// Load the language resources from the scanned files + /// + private static void Reload() + { + Resources.Clear(); + LoadFiles(DefaultLanguage); + if (_currentLanguage != null && !_currentLanguage.Equals(DefaultLanguage)) + { + LoadFiles(_currentLanguage); + } + } + + /// + /// Get or set the current language + /// + public static string CurrentLanguage + { + get => _currentLanguage; + set + { + string ietf = FindBestIetfMatch(value); + if (!LanguageFiles.ContainsKey(ietf)) + { + Log.WarnFormat("No match for language {0} found!", ietf); + } + else + { + if (_currentLanguage == null || !_currentLanguage.Equals(ietf)) + { + _currentLanguage = ietf; + Reload(); + if (LanguageChanged == null) + { + return; + } + + try + { + LanguageChanged(null, null); + } + catch + { + // ignored + } + + return; + } + } + + Log.Debug("CurrentLanguage not changed!"); + } + } + + /// + /// Try to find the best match for the supplied IETF + /// + /// string + /// IETF + private static string FindBestIetfMatch(string inputIetf) + { + string returnIetf = inputIetf; + if (string.IsNullOrEmpty(returnIetf)) + { + returnIetf = DefaultLanguage; + } + + returnIetf = ReformatIetf(returnIetf); + if (!LanguageFiles.ContainsKey(returnIetf)) + { + Log.WarnFormat("Unknown language {0}, trying best match!", returnIetf); + if (returnIetf.Length == 5) + { + returnIetf = returnIetf.Substring(0, 2); + } + + foreach (string availableIetf in LanguageFiles.Keys) + { + if (!availableIetf.StartsWith(returnIetf)) continue; + + Log.InfoFormat("Found language {0}, best match for {1}!", availableIetf, returnIetf); + returnIetf = availableIetf; + break; + } + } + + return returnIetf; + } + + /// + /// This helper method clears all non alpha characters from the IETF, and does a reformatting. + /// This prevents problems with multiple formats or typos. + /// + /// + /// + private static string ReformatIetf(string inputIetf) + { + string returnIetf = null; + if (!string.IsNullOrEmpty(inputIetf)) + { + returnIetf = inputIetf.ToLower(); + returnIetf = IetfCleanRegexp.Replace(returnIetf, string.Empty); + if (returnIetf.Length == 4) + { + returnIetf = returnIetf.Substring(0, 2) + "-" + returnIetf.Substring(2, 2).ToUpper(); + } + } + + return returnIetf; + } + + /// + /// Return a list of all the supported languages + /// + public static IList SupportedLanguages + { + get + { + IList languages = new List(); + // Loop over all languages with all the files in there + foreach (List langs in LanguageFiles.Values) + { + // Loop over all the files for a language + foreach (LanguageFile langFile in langs) + { + // Only take the ones without prefix, these are the "base" language files + if (langFile.Prefix != null) continue; + languages.Add(langFile); + break; + } + } + + return languages; + } + } + + /// + /// Return the path to the help-file + /// + public static string HelpFilePath + { + get + { + if (HelpFiles.ContainsKey(_currentLanguage)) + { + return HelpFiles[_currentLanguage]; + } + + return HelpFiles[DefaultLanguage]; + } + } + + /// + /// Load the resources from the language file + /// + /// File to load from + private static void LoadResources(LanguageFile languageFile) + { + Log.InfoFormat("Loading language file {0}", languageFile.Filepath); + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(languageFile.Filepath); + XmlNodeList resourceNodes = xmlDocument.GetElementsByTagName("resource"); + foreach (XmlNode resourceNode in resourceNodes) + { + string key = resourceNode.Attributes["name"].Value; + if (!string.IsNullOrEmpty(languageFile.Prefix)) + { + key = languageFile.Prefix + "." + key; + } + + string text = resourceNode.InnerText; + if (!string.IsNullOrEmpty(text)) + { + text = text.Trim(); + } + + if (!Resources.ContainsKey(key)) + { + Resources.Add(key, text); + } + else + { + Resources[key] = text; + } + } + } + catch (Exception e) + { + Log.Error("Could not load language file " + languageFile.Filepath, e); + } + } + + /// + /// Load the language file information + /// + /// + /// + private static LanguageFile LoadFileInfo(string languageFilePath) + { + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(languageFilePath); + XmlNodeList nodes = xmlDocument.GetElementsByTagName("language"); + if (nodes.Count > 0) + { + LanguageFile languageFile = new LanguageFile + { + Filepath = languageFilePath + }; + XmlNode node = nodes.Item(0); + if (node?.Attributes != null) + { + languageFile.Description = node.Attributes["description"].Value; + if (node.Attributes["ietf"] != null) + { + languageFile.Ietf = ReformatIetf(node.Attributes["ietf"].Value); + } + + if (node.Attributes["version"] != null) + { + languageFile.Version = new Version(node.Attributes["version"].Value); + } + + if (node.Attributes["prefix"] != null) + { + languageFile.Prefix = node.Attributes["prefix"].Value.ToLower(); + } + + if (node.Attributes["languagegroup"] != null) + { + string languageGroup = node.Attributes["languagegroup"].Value; + languageFile.LanguageGroup = languageGroup.ToLower(); + } + } + + return languageFile; + } + + throw new XmlException("Root element is missing"); + } + catch (Exception e) + { + Log.Error("Could not load language file " + languageFilePath, e); + } + + return null; + } + + /// + /// Scan the files in all directories + /// + private static void ScanFiles() + { + LanguageFiles.Clear(); + HelpFiles.Clear(); + foreach (string languagePath in LanguagePaths) + { + if (!Directory.Exists(languagePath)) + { + Log.InfoFormat("Skipping non existing language path {0}", languagePath); + continue; + } + + Log.InfoFormat("Searching language directory '{0}' for language files with pattern '{1}'", languagePath, LanguageFilenamePattern); + try + { + foreach (string languageFilepath in Directory.GetFiles(languagePath, LanguageFilenamePattern, SearchOption.AllDirectories)) + { + //LOG.DebugFormat("Found language file: {0}", languageFilepath); + LanguageFile languageFile = LoadFileInfo(languageFilepath); + if (languageFile == null) + { + continue; + } + + if (string.IsNullOrEmpty(languageFile.Ietf)) + { + Log.WarnFormat("Fixing missing ietf in language-file {0}", languageFilepath); + string languageFilename = Path.GetFileName(languageFilepath); + if (IetfRegexp.IsMatch(languageFilename)) + { + string replacementIetf = IetfRegexp.Replace(languageFilename, "$1"); + languageFile.Ietf = ReformatIetf(replacementIetf); + Log.InfoFormat("Fixed IETF to {0}", languageFile.Ietf); + } + else + { + Log.ErrorFormat("Missing ietf , no recover possible... skipping language-file {0}!", languageFilepath); + continue; + } + } + + // Check if we can display the file + if (!string.IsNullOrEmpty(languageFile.LanguageGroup) && UnsupportedLanguageGroups.Contains(languageFile.LanguageGroup)) + { + Log.InfoFormat("Skipping unsuported (not able to display) language {0} from file {1}", languageFile.Description, languageFilepath); + continue; + } + + // build prefix, based on the filename, but only if it's not set in the file itself. + if (string.IsNullOrEmpty(languageFile.Prefix)) + { + string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath); + if (PrefixRegexp.IsMatch(languageFilename)) + { + languageFile.Prefix = PrefixRegexp.Replace(languageFilename, "$1"); + if (!string.IsNullOrEmpty(languageFile.Prefix)) + { + languageFile.Prefix = languageFile.Prefix.Replace("plugin", string.Empty).ToLower(); + } + } + } + + List currentFiles; + if (LanguageFiles.ContainsKey(languageFile.Ietf)) + { + currentFiles = LanguageFiles[languageFile.Ietf]; + bool needToAdd = true; + List deleteList = new List(); + foreach (LanguageFile compareWithLangfile in currentFiles) + { + if ((languageFile.Prefix != null || compareWithLangfile.Prefix != null) && + (languageFile.Prefix == null || + !languageFile.Prefix.Equals(compareWithLangfile.Prefix))) continue; + + if (compareWithLangfile.Version > languageFile.Version) + { + Log.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, + compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); + needToAdd = false; + break; + } + + Log.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, + compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version); + deleteList.Add(compareWithLangfile); + } + + if (needToAdd) + { + foreach (LanguageFile deleteFile in deleteList) + { + currentFiles.Remove(deleteFile); + } + + Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); + currentFiles.Add(languageFile); + } + } + else + { + currentFiles = new List + { + languageFile + }; + LanguageFiles.Add(languageFile.Ietf, currentFiles); + Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); + } + } + } + catch (DirectoryNotFoundException) + { + Log.InfoFormat("Non existing language directory: {0}", languagePath); + } + catch (Exception e) + { + Log.Error("Error trying for read directory " + languagePath, e); + } + + // Now find the help files + Log.InfoFormat("Searching language directory '{0}' for help files with pattern '{1}'", languagePath, HelpFilenamePattern); + try + { + foreach (string helpFilepath in Directory.GetFiles(languagePath, HelpFilenamePattern, SearchOption.AllDirectories)) + { + Log.DebugFormat("Found help file: {0}", helpFilepath); + string helpFilename = Path.GetFileName(helpFilepath); + string ietf = ReformatIetf(helpFilename.Replace(".html", string.Empty).Replace("help-", "")); + if (!HelpFiles.ContainsKey(ietf)) + { + HelpFiles.Add(ietf, helpFilepath); + } + else + { + Log.WarnFormat("skipping help file {0}, already a file with the same IETF {1} found!", helpFilepath, ietf); + } + } + } + catch (DirectoryNotFoundException) + { + Log.InfoFormat("Non existing language directory: {0}", languagePath); + } + catch (Exception e) + { + Log.Error("Error trying for read directory " + languagePath, e); + } + } + } + + /// + /// Check if a resource with prefix.key exists + /// + /// + /// + /// true if available + public static bool HasKey(string prefix, string key) + { + return HasKey(prefix + "." + key); + } + + /// + /// Check if a resource with key exists + /// + /// + /// true if available + public static bool HasKey(string key) + { + if (key == null) + { + return false; + } + + return Resources.ContainsKey(key); + } + + /// + /// TryGet method which combines HasKey & GetString + /// + /// + /// out string + /// + public static bool TryGetString(string key, out string languageString) + { + return Resources.TryGetValue(key, out languageString); + } + + /// + /// TryGet method which combines HasKey & GetString + /// + /// string with prefix + /// string with key + /// out string + /// + public static bool TryGetString(string prefix, string key, out string languageString) + { + return Resources.TryGetValue(prefix + "." + key, out languageString); + } + + /// + /// TryGet method which combines HasKey & GetString + /// + /// string with prefix + /// Enum with key + /// out string + /// + public static bool TryGetString(string prefix, Enum key, out string languageString) + { + return Resources.TryGetValue(prefix + "." + key, out languageString); + } + + /// + /// Translate + /// + /// object + /// string + public static string Translate(object key) + { + string typename = key.GetType().Name; + string enumKey = typename + "." + key; + if (HasKey(enumKey)) + { + return GetString(enumKey); + } + + return key.ToString(); + } + + /// + /// Get the resource for key + /// + /// Enum + /// resource or a "string ###key### not found" + public static string GetString(Enum key) + { + if (key == null) + { + return null; + } + + return GetString(key.ToString()); + } + + /// + /// Get the resource for prefix.key + /// + /// string + /// Enum + /// resource or a "string ###prefix.key### not found" + public static string GetString(string prefix, Enum key) + { + if (key == null) + { + return null; + } + + return GetString(prefix + "." + key); + } + + /// + /// Get the resource for prefix.key + /// + /// string + /// string + /// resource or a "string ###prefix.key### not found" + public static string GetString(string prefix, string key) + { + return GetString(prefix + "." + key); + } + + /// + /// Get the resource for key + /// + /// string + /// resource or a "string ###key### not found" + public static string GetString(string key) + { + if (key == null) + { + return null; + } + + if (!Resources.TryGetValue(key, out var returnValue)) + { + return "string ###" + key + "### not found"; + } + + return returnValue; + } + + /// + /// Get the resource for key, format with with string.format an supply the parameters + /// + /// Enum + /// object + /// formatted resource or a "string ###key### not found" + public static string GetFormattedString(Enum key, object param) + { + return GetFormattedString(key.ToString(), param); + } + + /// + /// Get the resource for prefix.key, format with with string.format an supply the parameters + /// + /// string + /// Enum + /// object + /// formatted resource or a "string ###prefix.key### not found" + public static string GetFormattedString(string prefix, Enum key, object param) + { + return GetFormattedString(prefix, key.ToString(), param); + } + + /// + /// Get the resource for prefix.key, format with with string.format an supply the parameters + /// + /// string + /// string + /// object + /// formatted resource or a "string ###prefix.key### not found" + public static string GetFormattedString(string prefix, string key, object param) + { + return GetFormattedString(prefix + "." + key, param); + } + + /// + /// Get the resource for key, format with with string.format an supply the parameters + /// + /// string + /// object + /// formatted resource or a "string ###key### not found" + public static string GetFormattedString(string key, object param) + { + if (!Resources.TryGetValue(key, out var returnValue)) + { + return "string ###" + key + "### not found"; + } + + return string.Format(returnValue, param); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/LanguageChangedHandler.cs b/src/Greenshot.Base/Core/LanguageChangedHandler.cs similarity index 73% rename from src/GreenshotPlugin/Core/LanguageChangedHandler.cs rename to src/Greenshot.Base/Core/LanguageChangedHandler.cs index ab68cb6d4..c9b71532e 100644 --- a/src/GreenshotPlugin/Core/LanguageChangedHandler.cs +++ b/src/Greenshot.Base/Core/LanguageChangedHandler.cs @@ -1,6 +1,6 @@ -using System; - -namespace GreenshotPlugin.Core -{ - public delegate void LanguageChangedHandler(object sender, EventArgs e); +using System; + +namespace Greenshot.Base.Core +{ + public delegate void LanguageChangedHandler(object sender, EventArgs e); } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/LanguageFile.cs b/src/Greenshot.Base/Core/LanguageFile.cs similarity index 94% rename from src/GreenshotPlugin/Core/LanguageFile.cs rename to src/Greenshot.Base/Core/LanguageFile.cs index 3d6552a3c..b9f8a57c4 100644 --- a/src/GreenshotPlugin/Core/LanguageFile.cs +++ b/src/Greenshot.Base/Core/LanguageFile.cs @@ -1,80 +1,80 @@ -using System; - -namespace GreenshotPlugin.Core -{ - /// - /// This class contains the information about a language file - /// - public class LanguageFile : IEquatable - { - public string Description { get; set; } - - public string Ietf { get; set; } - - public Version Version { get; set; } - - public string LanguageGroup { get; set; } - - public string Filepath { get; set; } - - public string Prefix { get; set; } - - /// - /// Overload equals so we can delete a entry from a collection - /// - /// - /// - public bool Equals(LanguageFile other) - { - if (Prefix != null) - { - if (other != null && !Prefix.Equals(other.Prefix)) - { - return false; - } - } - else if (other?.Prefix != null) - { - return false; - } - - if (Ietf != null) - { - if (other != null && !Ietf.Equals(other.Ietf)) - { - return false; - } - } - else if (other?.Ietf != null) - { - return false; - } - - if (Version != null) - { - if (other != null && !Version.Equals(other.Version)) - { - return false; - } - } - else if (other != null && other.Version != null) - { - return false; - } - - if (Filepath != null) - { - if (other != null && !Filepath.Equals(other.Filepath)) - { - return false; - } - } - else if (other?.Filepath != null) - { - return false; - } - - return true; - } - } +using System; + +namespace Greenshot.Base.Core +{ + /// + /// This class contains the information about a language file + /// + public class LanguageFile : IEquatable + { + public string Description { get; set; } + + public string Ietf { get; set; } + + public Version Version { get; set; } + + public string LanguageGroup { get; set; } + + public string Filepath { get; set; } + + public string Prefix { get; set; } + + /// + /// Overload equals so we can delete a entry from a collection + /// + /// + /// + public bool Equals(LanguageFile other) + { + if (Prefix != null) + { + if (other != null && !Prefix.Equals(other.Prefix)) + { + return false; + } + } + else if (other?.Prefix != null) + { + return false; + } + + if (Ietf != null) + { + if (other != null && !Ietf.Equals(other.Ietf)) + { + return false; + } + } + else if (other?.Ietf != null) + { + return false; + } + + if (Version != null) + { + if (other != null && !Version.Equals(other.Version)) + { + return false; + } + } + else if (other != null && other.Version != null) + { + return false; + } + + if (Filepath != null) + { + if (other != null && !Filepath.Equals(other.Filepath)) + { + return false; + } + } + else if (other?.Filepath != null) + { + return false; + } + + return true; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/LogHelper.cs b/src/Greenshot.Base/Core/LogHelper.cs similarity index 95% rename from src/GreenshotPlugin/Core/LogHelper.cs rename to src/Greenshot.Base/Core/LogHelper.cs index 45cd9df0e..eb02423f8 100644 --- a/src/GreenshotPlugin/Core/LogHelper.cs +++ b/src/Greenshot.Base/Core/LogHelper.cs @@ -1,124 +1,124 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.IO; -using System.Reflection; -using System.Windows.Forms; -using log4net; -using log4net.Appender; -using log4net.Config; -using log4net.Repository.Hierarchy; -using System; -using GreenshotPlugin.IniFile; -using log4net.Util; - -namespace GreenshotPlugin.Core -{ - /// - /// Initialize the logger - /// - public class LogHelper - { - private static bool _isLog4NetConfigured; - private const string InitMessage = "Greenshot initialization of log system failed"; - - public static bool IsInitialized => _isLog4NetConfigured; - - // Initialize Log4J - public static string InitializeLog4Net() - { - // Setup log4j, currently the file is called log4net.xml - foreach (var logName in new[] - { - "log4net.xml", @"App\Greenshot\log4net-portable.xml" - }) - { - string log4NetFilename = Path.Combine(Application.StartupPath, logName); - if (File.Exists(log4NetFilename)) - { - try - { - XmlConfigurator.Configure(new FileInfo(log4NetFilename)); - _isLog4NetConfigured = true; - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } - } - - // Fallback - if (!_isLog4NetConfigured) - { - try - { - Assembly assembly = typeof(LogHelper).Assembly; - using Stream stream = assembly.GetManifestResourceStream("GreenshotPlugin.log4net-embedded.xml"); - XmlConfigurator.Configure(stream); - _isLog4NetConfigured = true; - IniConfig.ForceIniInStartupPath(); - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - } - - if (_isLog4NetConfigured) - { - // Get the logfile name - try - { - if (((Hierarchy) LogManager.GetRepository()).Root.Appenders.Count > 0) - { - foreach (IAppender appender in ((Hierarchy) LogManager.GetRepository()).Root.Appenders) - { - var fileAppender = appender as FileAppender; - if (fileAppender != null) - { - return fileAppender.File; - } - } - } - } - catch - { - // ignored - } - } - - return null; - } - } - - /// - /// A simple helper class to support the logging to the AppData location - /// - public class SpecialFolderPatternConverter : PatternConverter - { - protected override void Convert(TextWriter writer, object state) - { - Environment.SpecialFolder specialFolder = (Environment.SpecialFolder) Enum.Parse(typeof(Environment.SpecialFolder), Option, true); - writer.Write(Environment.GetFolderPath(specialFolder)); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.IO; +using System.Reflection; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using log4net; +using log4net.Appender; +using log4net.Config; +using log4net.Repository.Hierarchy; +using log4net.Util; + +namespace Greenshot.Base.Core +{ + /// + /// Initialize the logger + /// + public class LogHelper + { + private static bool _isLog4NetConfigured; + private const string InitMessage = "Greenshot initialization of log system failed"; + + public static bool IsInitialized => _isLog4NetConfigured; + + // Initialize Log4J + public static string InitializeLog4Net() + { + // Setup log4j, currently the file is called log4net.xml + foreach (var logName in new[] + { + "log4net.xml", @"App\Greenshot\log4net-portable.xml" + }) + { + string log4NetFilename = Path.Combine(Application.StartupPath, logName); + if (File.Exists(log4NetFilename)) + { + try + { + XmlConfigurator.Configure(new FileInfo(log4NetFilename)); + _isLog4NetConfigured = true; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + } + + // Fallback + if (!_isLog4NetConfigured) + { + try + { + Assembly assembly = typeof(LogHelper).Assembly; + using Stream stream = assembly.GetManifestResourceStream("GreenshotPlugin.log4net-embedded.xml"); + XmlConfigurator.Configure(stream); + _isLog4NetConfigured = true; + IniConfig.ForceIniInStartupPath(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, InitMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + if (_isLog4NetConfigured) + { + // Get the logfile name + try + { + if (((Hierarchy) LogManager.GetRepository()).Root.Appenders.Count > 0) + { + foreach (IAppender appender in ((Hierarchy) LogManager.GetRepository()).Root.Appenders) + { + var fileAppender = appender as FileAppender; + if (fileAppender != null) + { + return fileAppender.File; + } + } + } + } + catch + { + // ignored + } + } + + return null; + } + } + + /// + /// A simple helper class to support the logging to the AppData location + /// + public class SpecialFolderPatternConverter : PatternConverter + { + protected override void Convert(TextWriter writer, object state) + { + Environment.SpecialFolder specialFolder = (Environment.SpecialFolder) Enum.Parse(typeof(Environment.SpecialFolder), Option, true); + writer.Write(Environment.GetFolderPath(specialFolder)); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/NetworkHelper.cs b/src/Greenshot.Base/Core/NetworkHelper.cs similarity index 96% rename from src/GreenshotPlugin/Core/NetworkHelper.cs rename to src/Greenshot.Base/Core/NetworkHelper.cs index 463a9bd19..21899e701 100644 --- a/src/GreenshotPlugin/Core/NetworkHelper.cs +++ b/src/Greenshot.Base/Core/NetworkHelper.cs @@ -1,728 +1,728 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using log4net; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Globalization; -using System.IO; -using System.Net; -using System.Text; -using System.Text.RegularExpressions; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; - -namespace GreenshotPlugin.Core -{ - /// - /// HTTP Method to make sure we have the correct method - /// - public enum HTTPMethod - { - GET, - POST, - PUT, - DELETE - }; - - /// - /// Description of NetworkHelper. - /// - public static class NetworkHelper - { - private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper)); - private static readonly CoreConfiguration Config = IniConfig.GetIniSection(); - - static NetworkHelper() - { - try - { - // Disable certificate checking - ServicePointManager.ServerCertificateValidationCallback += delegate { return true; }; - } - catch (Exception ex) - { - Log.Warn("An error has occurred while allowing self-signed certificates:", ex); - } - } - - /// - /// Download the uri into a memory stream, without catching exceptions - /// - /// Of an image - /// MemoryStream which is already seek-ed to 0 - public static MemoryStream GetAsMemoryStream(string url) - { - var request = CreateWebRequest(url); - using var response = (HttpWebResponse) request.GetResponse(); - var memoryStream = new MemoryStream(); - using (var responseStream = response.GetResponseStream()) - { - responseStream?.CopyTo(memoryStream); - // Make sure it can be used directly - memoryStream.Seek(0, SeekOrigin.Begin); - } - - return memoryStream; - } - - /// - /// Download the uri to Bitmap - /// - /// Of an image - /// Bitmap - public static Image DownloadImage(string url) - { - var extensions = new StringBuilder(); - foreach (var extension in ImageHelper.StreamConverters.Keys) - { - if (string.IsNullOrEmpty(extension)) - { - continue; - } - - extensions.AppendFormat(@"\.{0}|", extension); - } - - extensions.Length--; - - var imageUrlRegex = new Regex($@"(http|https)://.*(?{extensions})"); - var match = imageUrlRegex.Match(url); - try - { - using var memoryStream = GetAsMemoryStream(url); - try - { - return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null); - } - catch (Exception) - { - // If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead. - string content; - using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) - { - content = streamReader.ReadLine(); - } - - if (string.IsNullOrEmpty(content)) - { - throw; - } - - match = imageUrlRegex.Match(content); - if (!match.Success) - { - throw; - } - - using var memoryStream2 = GetAsMemoryStream(match.Value); - return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value); - } - } - catch (Exception e) - { - Log.Error("Problem downloading the image from: " + url, e); - } - - return null; - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri) - { - return CreateWebRequest(new Uri(uri)); - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) - { - return CreateWebRequest(new Uri(uri), method); - } - - /// - /// Helper method to create a web request with a lot of default settings - /// - /// Uri with uri to connect to - /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) - { - var webRequest = CreateWebRequest(uri); - webRequest.Method = method.ToString(); - return webRequest; - } - - /// - /// Helper method to create a web request, eventually with proxy - /// - /// Uri with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri) - { - var webRequest = (HttpWebRequest) WebRequest.Create(uri); - webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null; - // Make sure the default credentials are available - webRequest.Credentials = CredentialCache.DefaultCredentials; - - // Allow redirect, this is usually needed so that we don't get a problem when a service moves - webRequest.AllowAutoRedirect = true; - // Set default timeouts - webRequest.Timeout = Config.WebRequestTimeout * 1000; - webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000; - return webRequest; - } - - /// - /// Create a IWebProxy Object which can be used to access the Internet - /// This method will check the configuration if the proxy is allowed to be used. - /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins - /// - /// - /// IWebProxy filled with all the proxy details or null if none is set/wanted - public static IWebProxy CreateProxy(Uri uri) - { - IWebProxy proxyToUse = null; - if (!Config.UseProxy) - { - return proxyToUse; - } - - proxyToUse = WebRequest.DefaultWebProxy; - if (proxyToUse != null) - { - proxyToUse.Credentials = CredentialCache.DefaultCredentials; - if (!Log.IsDebugEnabled) - { - return proxyToUse; - } - - // check the proxy for the Uri - if (!proxyToUse.IsBypassed(uri)) - { - var proxyUri = proxyToUse.GetProxy(uri); - if (proxyUri != null) - { - Log.Debug("Using proxy: " + proxyUri + " for " + uri); - } - else - { - Log.Debug("No proxy found!"); - } - } - else - { - Log.Debug("Proxy bypass for: " + uri); - } - } - else - { - Log.Debug("No proxy found!"); - } - - return proxyToUse; - } - - /// - /// UrlEncodes a string without the requirement for System.Web - /// - /// - /// - // [Obsolete("Use System.Uri.EscapeDataString instead")] - public static string UrlEncode(string text) - { - if (!string.IsNullOrEmpty(text)) - { - // System.Uri provides reliable parsing, but doesn't encode spaces. - return Uri.EscapeDataString(text).Replace("%20", "+"); - } - - return null; - } - - /// - /// A wrapper around the EscapeDataString, as the limit is 32766 characters - /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx - /// - /// - /// escaped data string - public static string EscapeDataString(string text) - { - if (!string.IsNullOrEmpty(text)) - { - var result = new StringBuilder(); - int currentLocation = 0; - while (currentLocation < text.Length) - { - string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation)); - result.Append(Uri.EscapeDataString(process)); - currentLocation += 16384; - } - - return result.ToString(); - } - - return null; - } - - /// - /// UrlDecodes a string without requiring System.Web - /// - /// String to decode. - /// decoded string - public static string UrlDecode(string text) - { - // pre-process for + sign space formatting since System.Uri doesn't handle it - // plus literals are encoded as %2b normally so this should be safe - text = text.Replace("+", " "); - return Uri.UnescapeDataString(text); - } - - /// - /// ParseQueryString without the requirement for System.Web - /// - /// - /// IDictionary string, string - public static IDictionary ParseQueryString(string queryString) - { - IDictionary parameters = new SortedDictionary(); - // remove anything other than query string from uri - if (queryString.Contains("?")) - { - queryString = queryString.Substring(queryString.IndexOf('?') + 1); - } - - foreach (string vp in Regex.Split(queryString, "&")) - { - if (string.IsNullOrEmpty(vp)) - { - continue; - } - - string[] singlePair = Regex.Split(vp, "="); - if (parameters.ContainsKey(singlePair[0])) - { - parameters.Remove(singlePair[0]); - } - - parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty); - } - - return parameters; - } - - /// - /// Generate the query parameters - /// - /// the list of query parameters - /// a string with the query parameters - public static string GenerateQueryParameters(IDictionary queryParameters) - { - if (queryParameters == null || queryParameters.Count == 0) - { - return string.Empty; - } - - queryParameters = new SortedDictionary(queryParameters); - - var sb = new StringBuilder(); - foreach (string key in queryParameters.Keys) - { - sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}")); - } - - sb.Remove(sb.Length - 1, 1); - - return sb.ToString(); - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest - /// - /// HttpWebRequest to write the multipart form data to - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) - { - string boundary = $"----------{Guid.NewGuid():N}"; - webRequest.ContentType = "multipart/form-data; boundary=" + boundary; - using Stream formDataStream = webRequest.GetRequestStream(); - WriteMultipartFormData(formDataStream, boundary, postParameters); - } - - /// - /// Write Multipart Form Data to a Stream, content-type should be set before this! - /// - /// Stream to write the multipart form data to - /// String boundary for the multipart/form-data - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) - { - bool needsClrf = false; - foreach (var param in postParameters) - { - // Add a CRLF to allow multiple parameters to be added. - // Skip it on the first parameter, add it to subsequent parameters. - if (needsClrf) - { - formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); - } - - needsClrf = true; - - if (param.Value is IBinaryContainer binaryContainer) - { - binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream); - } - else - { - string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}"; - formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); - } - } - - // Add the end of the request. Start with a newline - string footer = "\r\n--" + boundary + "--\r\n"; - formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); - } - - /// - /// Post content HttpWebRequest - /// - /// HttpWebRequest to write the multipart form data to - /// IDictionary with the headers - /// IBinaryContainer - public static void Post(HttpWebRequest webRequest, IDictionary headers, IBinaryContainer binaryContainer = null) - { - foreach (var header in headers) - { - switch (header.Key) - { - case "Content-Type": - webRequest.ContentType = header.Value as string; - break; - case "Accept": - webRequest.Accept = header.Value as string; - break; - default: - webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); - break; - } - } - - if (!headers.ContainsKey("Content-Type")) - { - webRequest.ContentType = "application/octet-stream"; - } - - if (binaryContainer != null) - { - using var requestStream = webRequest.GetRequestStream(); - binaryContainer.WriteToStream(requestStream); - } - } - - /// - /// Post content HttpWebRequest - /// - /// HttpWebRequest to write the multipart form data to - /// IDictionary with the headers - /// string - public static void Post(HttpWebRequest webRequest, IDictionary headers, string jsonString) - { - if (headers != null) - { - foreach (var header in headers) - { - switch (header.Key) - { - case "Content-Type": - webRequest.ContentType = header.Value as string; - break; - case "Accept": - webRequest.Accept = header.Value as string; - break; - default: - webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); - break; - } - } - - if (!headers.ContainsKey("Content-Type")) - { - webRequest.ContentType = "application/json"; - } - } - else - { - webRequest.ContentType = "application/json"; - } - - if (jsonString != null) - { - using var requestStream = webRequest.GetRequestStream(); - using var streamWriter = new StreamWriter(requestStream); - streamWriter.Write(jsonString); - } - } - - /// - /// Post the parameters "x-www-form-urlencoded" - /// - /// - /// - public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) - { - webRequest.ContentType = "application/x-www-form-urlencoded"; - string urlEncoded = GenerateQueryParameters(parameters); - - byte[] data = Encoding.UTF8.GetBytes(urlEncoded); - using var requestStream = webRequest.GetRequestStream(); - requestStream.Write(data, 0, data.Length); - } - - /// - /// Log the headers of the WebResponse, if IsDebugEnabled - /// - /// WebResponse - private static void DebugHeaders(WebResponse response) - { - if (!Log.IsDebugEnabled) - { - return; - } - - Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri); - foreach (string key in response.Headers.AllKeys) - { - Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]); - } - } - - /// - /// Process the web response. - /// - /// The request object. - /// The response data. - /// TODO: This method should handle the StatusCode better! - public static string GetResponseAsString(HttpWebRequest webRequest) - { - return GetResponseAsString(webRequest, false); - } - - /// - /// Read the response as string - /// - /// - /// string or null - private static string GetResponseAsString(HttpWebResponse response) - { - string responseData = null; - if (response == null) - { - return null; - } - - using (response) - { - Stream responseStream = response.GetResponseStream(); - if (responseStream != null) - { - using StreamReader reader = new StreamReader(responseStream, true); - responseData = reader.ReadToEnd(); - } - } - - return responseData; - } - - /// - /// - /// - /// - /// - /// - public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) - { - string responseData = null; - HttpWebResponse response = null; - bool isHttpError = false; - try - { - response = (HttpWebResponse) webRequest.GetResponse(); - Log.InfoFormat("Response status: {0}", response.StatusCode); - isHttpError = (int) response.StatusCode >= 300; - if (isHttpError) - { - Log.ErrorFormat("HTTP error {0}", response.StatusCode); - } - - DebugHeaders(response); - responseData = GetResponseAsString(response); - if (isHttpError) - { - Log.ErrorFormat("HTTP response {0}", responseData); - } - } - catch (WebException e) - { - response = (HttpWebResponse) e.Response; - HttpStatusCode statusCode = HttpStatusCode.Unused; - if (response != null) - { - statusCode = response.StatusCode; - Log.ErrorFormat("HTTP error {0}", statusCode); - string errorContent = GetResponseAsString(response); - if (alsoReturnContentOnError) - { - return errorContent; - } - - Log.ErrorFormat("Content: {0}", errorContent); - } - - Log.Error("WebException: ", e); - if (statusCode == HttpStatusCode.Unauthorized) - { - throw new UnauthorizedAccessException(e.Message); - } - - throw; - } - finally - { - if (response != null) - { - if (isHttpError) - { - Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); - } - - response.Close(); - } - } - - return responseData; - } - } - - /// - /// This interface can be used to pass binary information around, like byte[] or Image - /// - public interface IBinaryContainer - { - void WriteFormDataToStream(string boundary, string name, Stream formDataStream); - void WriteToStream(Stream formDataStream); - string ToBase64String(Base64FormattingOptions formattingOptions); - byte[] ToByteArray(); - void Upload(HttpWebRequest webRequest); - - string ContentType { get; } - string Filename { get; set; } - } - - /// A container to supply surfaces to a Multi-part form data upload - /// - public class SurfaceContainer : IBinaryContainer - { - private readonly ISurface _surface; - private readonly SurfaceOutputSettings _outputSettings; - - public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) - { - _surface = surface; - _outputSettings = outputSettings; - Filename = filename; - } - - /// - /// Create a Base64String from the Surface by saving it to a memory stream and converting it. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) - { - using MemoryStream stream = new MemoryStream(); - ImageOutput.SaveToStream(_surface, stream, _outputSettings); - return Convert.ToBase64String(stream.GetBuffer(), 0, (int) stream.Length, formattingOptions); - } - - /// - /// Create a byte[] from the image by saving it to a memory stream. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// byte[] - public byte[] ToByteArray() - { - using MemoryStream stream = new MemoryStream(); - ImageOutput.SaveToStream(_surface, stream, _outputSettings); - return stream.ToArray(); - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Multipart separator - /// Name of the thing - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) - { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n"; - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings); - } - - /// - /// A plain "write data to stream" - /// - /// - public void WriteToStream(Stream dataStream) - { - // Write the file data directly to the Stream, rather than serializing it to a string. - ImageOutput.SaveToStream(_surface, dataStream, _outputSettings); - } - - /// - /// Upload the Surface as image to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) - { - webRequest.ContentType = ContentType; - using var requestStream = webRequest.GetRequestStream(); - WriteToStream(requestStream); - } - - public string ContentType => "image/" + _outputSettings.Format; - public string Filename { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// HTTP Method to make sure we have the correct method + /// + public enum HTTPMethod + { + GET, + POST, + PUT, + DELETE + }; + + /// + /// Description of NetworkHelper. + /// + public static class NetworkHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper)); + private static readonly CoreConfiguration Config = IniConfig.GetIniSection(); + + static NetworkHelper() + { + try + { + // Disable certificate checking + ServicePointManager.ServerCertificateValidationCallback += delegate { return true; }; + } + catch (Exception ex) + { + Log.Warn("An error has occurred while allowing self-signed certificates:", ex); + } + } + + /// + /// Download the uri into a memory stream, without catching exceptions + /// + /// Of an image + /// MemoryStream which is already seek-ed to 0 + public static MemoryStream GetAsMemoryStream(string url) + { + var request = CreateWebRequest(url); + using var response = (HttpWebResponse) request.GetResponse(); + var memoryStream = new MemoryStream(); + using (var responseStream = response.GetResponseStream()) + { + responseStream?.CopyTo(memoryStream); + // Make sure it can be used directly + memoryStream.Seek(0, SeekOrigin.Begin); + } + + return memoryStream; + } + + /// + /// Download the uri to Bitmap + /// + /// Of an image + /// Bitmap + public static Image DownloadImage(string url) + { + var extensions = new StringBuilder(); + foreach (var extension in ImageHelper.StreamConverters.Keys) + { + if (string.IsNullOrEmpty(extension)) + { + continue; + } + + extensions.AppendFormat(@"\.{0}|", extension); + } + + extensions.Length--; + + var imageUrlRegex = new Regex($@"(http|https)://.*(?{extensions})"); + var match = imageUrlRegex.Match(url); + try + { + using var memoryStream = GetAsMemoryStream(url); + try + { + return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null); + } + catch (Exception) + { + // If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead. + string content; + using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) + { + content = streamReader.ReadLine(); + } + + if (string.IsNullOrEmpty(content)) + { + throw; + } + + match = imageUrlRegex.Match(content); + if (!match.Success) + { + throw; + } + + using var memoryStream2 = GetAsMemoryStream(match.Value); + return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value); + } + } + catch (Exception e) + { + Log.Error("Problem downloading the image from: " + url, e); + } + + return null; + } + + /// + /// Helper method to create a web request with a lot of default settings + /// + /// string with uri to connect to + /// WebRequest + public static HttpWebRequest CreateWebRequest(string uri) + { + return CreateWebRequest(new Uri(uri)); + } + + /// + /// Helper method to create a web request with a lot of default settings + /// + /// string with uri to connect to + /// /// Method to use + /// WebRequest + public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) + { + return CreateWebRequest(new Uri(uri), method); + } + + /// + /// Helper method to create a web request with a lot of default settings + /// + /// Uri with uri to connect to + /// Method to use + /// WebRequest + public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) + { + var webRequest = CreateWebRequest(uri); + webRequest.Method = method.ToString(); + return webRequest; + } + + /// + /// Helper method to create a web request, eventually with proxy + /// + /// Uri with uri to connect to + /// WebRequest + public static HttpWebRequest CreateWebRequest(Uri uri) + { + var webRequest = (HttpWebRequest) WebRequest.Create(uri); + webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null; + // Make sure the default credentials are available + webRequest.Credentials = CredentialCache.DefaultCredentials; + + // Allow redirect, this is usually needed so that we don't get a problem when a service moves + webRequest.AllowAutoRedirect = true; + // Set default timeouts + webRequest.Timeout = Config.WebRequestTimeout * 1000; + webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000; + return webRequest; + } + + /// + /// Create a IWebProxy Object which can be used to access the Internet + /// This method will check the configuration if the proxy is allowed to be used. + /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins + /// + /// + /// IWebProxy filled with all the proxy details or null if none is set/wanted + public static IWebProxy CreateProxy(Uri uri) + { + IWebProxy proxyToUse = null; + if (!Config.UseProxy) + { + return proxyToUse; + } + + proxyToUse = WebRequest.DefaultWebProxy; + if (proxyToUse != null) + { + proxyToUse.Credentials = CredentialCache.DefaultCredentials; + if (!Log.IsDebugEnabled) + { + return proxyToUse; + } + + // check the proxy for the Uri + if (!proxyToUse.IsBypassed(uri)) + { + var proxyUri = proxyToUse.GetProxy(uri); + if (proxyUri != null) + { + Log.Debug("Using proxy: " + proxyUri + " for " + uri); + } + else + { + Log.Debug("No proxy found!"); + } + } + else + { + Log.Debug("Proxy bypass for: " + uri); + } + } + else + { + Log.Debug("No proxy found!"); + } + + return proxyToUse; + } + + /// + /// UrlEncodes a string without the requirement for System.Web + /// + /// + /// + // [Obsolete("Use System.Uri.EscapeDataString instead")] + public static string UrlEncode(string text) + { + if (!string.IsNullOrEmpty(text)) + { + // System.Uri provides reliable parsing, but doesn't encode spaces. + return Uri.EscapeDataString(text).Replace("%20", "+"); + } + + return null; + } + + /// + /// A wrapper around the EscapeDataString, as the limit is 32766 characters + /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx + /// + /// + /// escaped data string + public static string EscapeDataString(string text) + { + if (!string.IsNullOrEmpty(text)) + { + var result = new StringBuilder(); + int currentLocation = 0; + while (currentLocation < text.Length) + { + string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation)); + result.Append(Uri.EscapeDataString(process)); + currentLocation += 16384; + } + + return result.ToString(); + } + + return null; + } + + /// + /// UrlDecodes a string without requiring System.Web + /// + /// String to decode. + /// decoded string + public static string UrlDecode(string text) + { + // pre-process for + sign space formatting since System.Uri doesn't handle it + // plus literals are encoded as %2b normally so this should be safe + text = text.Replace("+", " "); + return Uri.UnescapeDataString(text); + } + + /// + /// ParseQueryString without the requirement for System.Web + /// + /// + /// IDictionary string, string + public static IDictionary ParseQueryString(string queryString) + { + IDictionary parameters = new SortedDictionary(); + // remove anything other than query string from uri + if (queryString.Contains("?")) + { + queryString = queryString.Substring(queryString.IndexOf('?') + 1); + } + + foreach (string vp in Regex.Split(queryString, "&")) + { + if (string.IsNullOrEmpty(vp)) + { + continue; + } + + string[] singlePair = Regex.Split(vp, "="); + if (parameters.ContainsKey(singlePair[0])) + { + parameters.Remove(singlePair[0]); + } + + parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty); + } + + return parameters; + } + + /// + /// Generate the query parameters + /// + /// the list of query parameters + /// a string with the query parameters + public static string GenerateQueryParameters(IDictionary queryParameters) + { + if (queryParameters == null || queryParameters.Count == 0) + { + return string.Empty; + } + + queryParameters = new SortedDictionary(queryParameters); + + var sb = new StringBuilder(); + foreach (string key in queryParameters.Keys) + { + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}")); + } + + sb.Remove(sb.Length - 1, 1); + + return sb.ToString(); + } + + /// + /// Write Multipart Form Data directly to the HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) + { + string boundary = $"----------{Guid.NewGuid():N}"; + webRequest.ContentType = "multipart/form-data; boundary=" + boundary; + using Stream formDataStream = webRequest.GetRequestStream(); + WriteMultipartFormData(formDataStream, boundary, postParameters); + } + + /// + /// Write Multipart Form Data to a Stream, content-type should be set before this! + /// + /// Stream to write the multipart form data to + /// String boundary for the multipart/form-data + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) + { + bool needsClrf = false; + foreach (var param in postParameters) + { + // Add a CRLF to allow multiple parameters to be added. + // Skip it on the first parameter, add it to subsequent parameters. + if (needsClrf) + { + formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); + } + + needsClrf = true; + + if (param.Value is IBinaryContainer binaryContainer) + { + binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream); + } + else + { + string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}"; + formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); + } + } + + // Add the end of the request. Start with a newline + string footer = "\r\n--" + boundary + "--\r\n"; + formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); + } + + /// + /// Post content HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// IDictionary with the headers + /// IBinaryContainer + public static void Post(HttpWebRequest webRequest, IDictionary headers, IBinaryContainer binaryContainer = null) + { + foreach (var header in headers) + { + switch (header.Key) + { + case "Content-Type": + webRequest.ContentType = header.Value as string; + break; + case "Accept": + webRequest.Accept = header.Value as string; + break; + default: + webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); + break; + } + } + + if (!headers.ContainsKey("Content-Type")) + { + webRequest.ContentType = "application/octet-stream"; + } + + if (binaryContainer != null) + { + using var requestStream = webRequest.GetRequestStream(); + binaryContainer.WriteToStream(requestStream); + } + } + + /// + /// Post content HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// IDictionary with the headers + /// string + public static void Post(HttpWebRequest webRequest, IDictionary headers, string jsonString) + { + if (headers != null) + { + foreach (var header in headers) + { + switch (header.Key) + { + case "Content-Type": + webRequest.ContentType = header.Value as string; + break; + case "Accept": + webRequest.Accept = header.Value as string; + break; + default: + webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); + break; + } + } + + if (!headers.ContainsKey("Content-Type")) + { + webRequest.ContentType = "application/json"; + } + } + else + { + webRequest.ContentType = "application/json"; + } + + if (jsonString != null) + { + using var requestStream = webRequest.GetRequestStream(); + using var streamWriter = new StreamWriter(requestStream); + streamWriter.Write(jsonString); + } + } + + /// + /// Post the parameters "x-www-form-urlencoded" + /// + /// + /// + public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) + { + webRequest.ContentType = "application/x-www-form-urlencoded"; + string urlEncoded = GenerateQueryParameters(parameters); + + byte[] data = Encoding.UTF8.GetBytes(urlEncoded); + using var requestStream = webRequest.GetRequestStream(); + requestStream.Write(data, 0, data.Length); + } + + /// + /// Log the headers of the WebResponse, if IsDebugEnabled + /// + /// WebResponse + private static void DebugHeaders(WebResponse response) + { + if (!Log.IsDebugEnabled) + { + return; + } + + Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri); + foreach (string key in response.Headers.AllKeys) + { + Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]); + } + } + + /// + /// Process the web response. + /// + /// The request object. + /// The response data. + /// TODO: This method should handle the StatusCode better! + public static string GetResponseAsString(HttpWebRequest webRequest) + { + return GetResponseAsString(webRequest, false); + } + + /// + /// Read the response as string + /// + /// + /// string or null + private static string GetResponseAsString(HttpWebResponse response) + { + string responseData = null; + if (response == null) + { + return null; + } + + using (response) + { + Stream responseStream = response.GetResponseStream(); + if (responseStream != null) + { + using StreamReader reader = new StreamReader(responseStream, true); + responseData = reader.ReadToEnd(); + } + } + + return responseData; + } + + /// + /// + /// + /// + /// + /// + public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) + { + string responseData = null; + HttpWebResponse response = null; + bool isHttpError = false; + try + { + response = (HttpWebResponse) webRequest.GetResponse(); + Log.InfoFormat("Response status: {0}", response.StatusCode); + isHttpError = (int) response.StatusCode >= 300; + if (isHttpError) + { + Log.ErrorFormat("HTTP error {0}", response.StatusCode); + } + + DebugHeaders(response); + responseData = GetResponseAsString(response); + if (isHttpError) + { + Log.ErrorFormat("HTTP response {0}", responseData); + } + } + catch (WebException e) + { + response = (HttpWebResponse) e.Response; + HttpStatusCode statusCode = HttpStatusCode.Unused; + if (response != null) + { + statusCode = response.StatusCode; + Log.ErrorFormat("HTTP error {0}", statusCode); + string errorContent = GetResponseAsString(response); + if (alsoReturnContentOnError) + { + return errorContent; + } + + Log.ErrorFormat("Content: {0}", errorContent); + } + + Log.Error("WebException: ", e); + if (statusCode == HttpStatusCode.Unauthorized) + { + throw new UnauthorizedAccessException(e.Message); + } + + throw; + } + finally + { + if (response != null) + { + if (isHttpError) + { + Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); + } + + response.Close(); + } + } + + return responseData; + } + } + + /// + /// This interface can be used to pass binary information around, like byte[] or Image + /// + public interface IBinaryContainer + { + void WriteFormDataToStream(string boundary, string name, Stream formDataStream); + void WriteToStream(Stream formDataStream); + string ToBase64String(Base64FormattingOptions formattingOptions); + byte[] ToByteArray(); + void Upload(HttpWebRequest webRequest); + + string ContentType { get; } + string Filename { get; set; } + } + + /// A container to supply surfaces to a Multi-part form data upload + /// + public class SurfaceContainer : IBinaryContainer + { + private readonly ISurface _surface; + private readonly SurfaceOutputSettings _outputSettings; + + public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) + { + _surface = surface; + _outputSettings = outputSettings; + Filename = filename; + } + + /// + /// Create a Base64String from the Surface by saving it to a memory stream and converting it. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// string + public string ToBase64String(Base64FormattingOptions formattingOptions) + { + using MemoryStream stream = new MemoryStream(); + ImageOutput.SaveToStream(_surface, stream, _outputSettings); + return Convert.ToBase64String(stream.GetBuffer(), 0, (int) stream.Length, formattingOptions); + } + + /// + /// Create a byte[] from the image by saving it to a memory stream. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// byte[] + public byte[] ToByteArray() + { + using MemoryStream stream = new MemoryStream(); + ImageOutput.SaveToStream(_surface, stream, _outputSettings); + return stream.ToArray(); + } + + /// + /// Write Multipart Form Data directly to the HttpWebRequest response stream + /// + /// Multipart separator + /// Name of the thing + /// Stream to write to + public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) + { + // Add just the first part of this param, since we will write the file data directly to the Stream + string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n"; + + formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); + ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings); + } + + /// + /// A plain "write data to stream" + /// + /// + public void WriteToStream(Stream dataStream) + { + // Write the file data directly to the Stream, rather than serializing it to a string. + ImageOutput.SaveToStream(_surface, dataStream, _outputSettings); + } + + /// + /// Upload the Surface as image to the webrequest + /// + /// + public void Upload(HttpWebRequest webRequest) + { + webRequest.ContentType = ContentType; + using var requestStream = webRequest.GetRequestStream(); + WriteToStream(requestStream); + } + + public string ContentType => "image/" + _outputSettings.Format; + public string Filename { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs b/src/Greenshot.Base/Core/OAuth/LocalJsonReceiver.cs similarity index 99% rename from src/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs rename to src/Greenshot.Base/Core/OAuth/LocalJsonReceiver.cs index d837e85c0..c99221d09 100644 --- a/src/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs +++ b/src/Greenshot.Base/Core/OAuth/LocalJsonReceiver.cs @@ -30,7 +30,7 @@ using System.Threading; using log4net; using Newtonsoft.Json; -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// OAuth 2.0 verification code receiver that runs a local server on a free port diff --git a/src/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs b/src/Greenshot.Base/Core/OAuth/LocalServerCodeReceiver.cs similarity index 99% rename from src/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs rename to src/Greenshot.Base/Core/OAuth/LocalServerCodeReceiver.cs index 1bc9670c7..702e3f7fe 100644 --- a/src/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs +++ b/src/Greenshot.Base/Core/OAuth/LocalServerCodeReceiver.cs @@ -29,7 +29,7 @@ using System.Text; using System.Threading; using log4net; -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// OAuth 2.0 verification code receiver that runs a local server on a free port diff --git a/src/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs b/src/Greenshot.Base/Core/OAuth/OAuth2AuthorizeMode.cs similarity index 97% rename from src/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs rename to src/Greenshot.Base/Core/OAuth/OAuth2AuthorizeMode.cs index ed391d9a8..1d761fc96 100644 --- a/src/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs +++ b/src/Greenshot.Base/Core/OAuth/OAuth2AuthorizeMode.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// Specify the authorize mode that is used to get the token from the cloud service. diff --git a/src/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs b/src/Greenshot.Base/Core/OAuth/OAuth2Helper.cs similarity index 99% rename from src/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs rename to src/Greenshot.Base/Core/OAuth/OAuth2Helper.cs index 36704a055..e5d009b96 100644 --- a/src/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs +++ b/src/Greenshot.Base/Core/OAuth/OAuth2Helper.cs @@ -23,9 +23,9 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Net; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// Code to simplify OAuth 2 diff --git a/src/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs b/src/Greenshot.Base/Core/OAuth/OAuth2Settings.cs similarity index 99% rename from src/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs rename to src/Greenshot.Base/Core/OAuth/OAuth2Settings.cs index d008c6b5b..c4fb6d2e2 100644 --- a/src/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs +++ b/src/Greenshot.Base/Core/OAuth/OAuth2Settings.cs @@ -23,7 +23,7 @@ using System; using System.Collections.Generic; using System.Drawing; -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// Settings for the OAuth 2 protocol diff --git a/src/GreenshotPlugin/Core/OAuth/OAuthSession.cs b/src/Greenshot.Base/Core/OAuth/OAuthSession.cs similarity index 99% rename from src/GreenshotPlugin/Core/OAuth/OAuthSession.cs rename to src/Greenshot.Base/Core/OAuth/OAuthSession.cs index aedff7fe2..f8364df8e 100644 --- a/src/GreenshotPlugin/Core/OAuth/OAuthSession.cs +++ b/src/Greenshot.Base/Core/OAuth/OAuthSession.cs @@ -27,10 +27,10 @@ using System.Net; using System.Security.Cryptography; using System.Text; using System.Threading; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; using log4net; -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// An OAuth 1 session object diff --git a/src/GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs b/src/Greenshot.Base/Core/OAuth/OAuthSignatureTypes.cs similarity index 96% rename from src/GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs rename to src/Greenshot.Base/Core/OAuth/OAuthSignatureTypes.cs index 6b07f2de2..eeca8decd 100644 --- a/src/GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs +++ b/src/Greenshot.Base/Core/OAuth/OAuthSignatureTypes.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Core.OAuth +namespace Greenshot.Base.Core.OAuth { /// /// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol diff --git a/src/GreenshotPlugin/Core/ObjectExtensions.cs b/src/Greenshot.Base/Core/ObjectExtensions.cs similarity index 96% rename from src/GreenshotPlugin/Core/ObjectExtensions.cs rename to src/Greenshot.Base/Core/ObjectExtensions.cs index 5a47a3d08..297015824 100644 --- a/src/GreenshotPlugin/Core/ObjectExtensions.cs +++ b/src/Greenshot.Base/Core/ObjectExtensions.cs @@ -1,118 +1,118 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; - -namespace GreenshotPlugin.Core -{ - /// - /// Extension methods which work for objects - /// - public static class ObjectExtensions - { - /// - /// Perform a deep Copy of the object. - /// - /// The type of object being copied. - /// The object instance to copy. - /// The copied object. - public static T Clone(this T source) - { - var typeparam = typeof(T); - if (!typeparam.IsInterface && !typeparam.IsSerializable) - { - throw new ArgumentException("The type must be serializable.", nameof(source)); - } - - // Don't serialize a null object, simply return the default for that object - if (source == null) - { - return default; - } - - IFormatter formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, source); - stream.Seek(0, SeekOrigin.Begin); - return (T) formatter.Deserialize(stream); - } - - /// - /// Clone the content from source to destination - /// - /// Type to clone - /// Instance to copy from - /// Instance to copy to - public static void CloneTo(this T source, T destination) - { - var type = typeof(T); - var myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - - foreach (var fieldInfo in myObjectFields) - { - fieldInfo.SetValue(destination, fieldInfo.GetValue(source)); - } - - var myObjectProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - - foreach (var propertyInfo in myObjectProperties) - { - if (propertyInfo.CanWrite) - { - propertyInfo.SetValue(destination, propertyInfo.GetValue(source, null), null); - } - } - } - - /// - /// Compare two lists - /// - /// - /// IList - /// IList - /// true if they are the same - public static bool CompareLists(IList l1, IList l2) - { - if (l1.Count != l2.Count) - { - return false; - } - - int matched = 0; - foreach (T item in l1) - { - if (!l2.Contains(item)) - { - return false; - } - - matched++; - } - - return matched == l1.Count; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Greenshot.Base.Core +{ + /// + /// Extension methods which work for objects + /// + public static class ObjectExtensions + { + /// + /// Perform a deep Copy of the object. + /// + /// The type of object being copied. + /// The object instance to copy. + /// The copied object. + public static T Clone(this T source) + { + var typeparam = typeof(T); + if (!typeparam.IsInterface && !typeparam.IsSerializable) + { + throw new ArgumentException("The type must be serializable.", nameof(source)); + } + + // Don't serialize a null object, simply return the default for that object + if (source == null) + { + return default; + } + + IFormatter formatter = new BinaryFormatter(); + using var stream = new MemoryStream(); + formatter.Serialize(stream, source); + stream.Seek(0, SeekOrigin.Begin); + return (T) formatter.Deserialize(stream); + } + + /// + /// Clone the content from source to destination + /// + /// Type to clone + /// Instance to copy from + /// Instance to copy to + public static void CloneTo(this T source, T destination) + { + var type = typeof(T); + var myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + + foreach (var fieldInfo in myObjectFields) + { + fieldInfo.SetValue(destination, fieldInfo.GetValue(source)); + } + + var myObjectProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + + foreach (var propertyInfo in myObjectProperties) + { + if (propertyInfo.CanWrite) + { + propertyInfo.SetValue(destination, propertyInfo.GetValue(source, null), null); + } + } + } + + /// + /// Compare two lists + /// + /// + /// IList + /// IList + /// true if they are the same + public static bool CompareLists(IList l1, IList l2) + { + if (l1.Count != l2.Count) + { + return false; + } + + int matched = 0; + foreach (T item in l1) + { + if (!l2.Contains(item)) + { + return false; + } + + matched++; + } + + return matched == l1.Count; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/PluginUtils.cs b/src/Greenshot.Base/Core/PluginUtils.cs similarity index 96% rename from src/GreenshotPlugin/Core/PluginUtils.cs rename to src/Greenshot.Base/Core/PluginUtils.cs index 870e2cca7..34fcba5d9 100644 --- a/src/GreenshotPlugin/Core/PluginUtils.cs +++ b/src/Greenshot.Base/Core/PluginUtils.cs @@ -1,228 +1,228 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using GreenshotPlugin.UnmanagedHelpers; -using log4net; -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; - -namespace GreenshotPlugin.Core -{ - /// - /// Description of PluginUtils. - /// - public static class PluginUtils - { - 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 readonly IDictionary ExeIconCache = new Dictionary(); - - static PluginUtils() - { - CoreConfig.PropertyChanged += OnIconSizeChanged; - } - - /// - /// Clear icon cache - /// - /// - /// - private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName != "IconSize") return; - var cachedImages = new List(); - lock (ExeIconCache) - { - foreach (string key in ExeIconCache.Keys) - { - cachedImages.Add(ExeIconCache[key]); - } - - ExeIconCache.Clear(); - } - - foreach (Image cachedImage in cachedImages) - { - cachedImage?.Dispose(); - } - } - - /// - /// Get the path of an executable - /// - /// e.g. cmd.exe - /// Path to file - public static string GetExePath(string exeName) - { - using (var key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) - { - if (key != null) - { - // "" is the default key, which should point to the requested location - return (string) key.GetValue(string.Empty); - } - } - - foreach (string pathEntry in (Environment.GetEnvironmentVariable("PATH") ?? string.Empty).Split(';')) - { - try - { - string path = pathEntry.Trim(); - if (!string.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exeName))) - { - return Path.GetFullPath(path); - } - } - catch (Exception) - { - Log.WarnFormat("Problem with path entry '{0}'.", pathEntry); - } - } - - return null; - } - - /// - /// Get icon from resource files, from the cache. - /// Examples can be found here: https://diymediahome.org/windows-icons-reference-list-with-details-locations-images/ - /// - /// path to the exe or dll - /// index of the icon - /// Bitmap with the icon or null if something happended - public static Image GetCachedExeIcon(string path, int index) - { - string cacheKey = $"{path}:{index}"; - Image returnValue; - lock (ExeIconCache) - { - if (ExeIconCache.TryGetValue(cacheKey, out returnValue)) - { - return returnValue; - } - - lock (ExeIconCache) - { - if (ExeIconCache.TryGetValue(cacheKey, out returnValue)) - { - return returnValue; - } - - returnValue = GetExeIcon(path, index); - if (returnValue != null) - { - ExeIconCache.Add(cacheKey, returnValue); - } - } - } - - return returnValue; - } - - /// - /// Get icon for executable - /// - /// path to the exe or dll - /// index of the icon - /// Bitmap with the icon or null if something happended - private static Bitmap GetExeIcon(string path, int index) - { - if (!File.Exists(path)) - { - return null; - } - - try - { - using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, CoreConfig.UseLargeIcons)) - { - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - - using (Icon appIcon = Shell32.GetFileIcon(path, CoreConfig.UseLargeIcons ? Shell32.IconSize.Large : Shell32.IconSize.Small, false)) - { - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - } - catch (Exception exIcon) - { - Log.Error("error retrieving icon: ", exIcon); - } - - return null; - } - - /// - /// Helper method to add a plugin MenuItem to the Greenshot context menu - /// - /// ToolStripMenuItem - public static void AddToContextMenu(ToolStripMenuItem item) - { - // Here we can hang ourselves to the main context menu! - var contextMenu = SimpleServiceProvider.Current.GetInstance(); - bool addedItem = false; - - // Try to find a separator, so we insert ourselves after it - for (int i = 0; i < contextMenu.Items.Count; i++) - { - if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator)) - { - // Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore" - if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag)) - { - var separator = new ToolStripSeparator - { - Tag = "PluginsAreAddedAfter", - Size = new Size(305, 6) - }; - contextMenu.Items.Insert(i, separator); - } - else if (!"PluginsAreAddedAfter".Equals(contextMenu.Items[i].Tag)) - { - continue; - } - - contextMenu.Items.Insert(i + 1, item); - addedItem = true; - break; - } - } - - // If we didn't insert the item, we just add it... - if (!addedItem) - { - contextMenu.Items.Add(item); - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.UnmanagedHelpers; +using log4net; +using Microsoft.Win32; + +namespace Greenshot.Base.Core +{ + /// + /// Description of PluginUtils. + /// + public static class PluginUtils + { + 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 readonly IDictionary ExeIconCache = new Dictionary(); + + static PluginUtils() + { + CoreConfig.PropertyChanged += OnIconSizeChanged; + } + + /// + /// Clear icon cache + /// + /// + /// + private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != "IconSize") return; + var cachedImages = new List(); + lock (ExeIconCache) + { + foreach (string key in ExeIconCache.Keys) + { + cachedImages.Add(ExeIconCache[key]); + } + + ExeIconCache.Clear(); + } + + foreach (Image cachedImage in cachedImages) + { + cachedImage?.Dispose(); + } + } + + /// + /// Get the path of an executable + /// + /// e.g. cmd.exe + /// Path to file + public static string GetExePath(string exeName) + { + using (var key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) + { + if (key != null) + { + // "" is the default key, which should point to the requested location + return (string) key.GetValue(string.Empty); + } + } + + foreach (string pathEntry in (Environment.GetEnvironmentVariable("PATH") ?? string.Empty).Split(';')) + { + try + { + string path = pathEntry.Trim(); + if (!string.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exeName))) + { + return Path.GetFullPath(path); + } + } + catch (Exception) + { + Log.WarnFormat("Problem with path entry '{0}'.", pathEntry); + } + } + + return null; + } + + /// + /// Get icon from resource files, from the cache. + /// Examples can be found here: https://diymediahome.org/windows-icons-reference-list-with-details-locations-images/ + /// + /// path to the exe or dll + /// index of the icon + /// Bitmap with the icon or null if something happended + public static Image GetCachedExeIcon(string path, int index) + { + string cacheKey = $"{path}:{index}"; + Image returnValue; + lock (ExeIconCache) + { + if (ExeIconCache.TryGetValue(cacheKey, out returnValue)) + { + return returnValue; + } + + lock (ExeIconCache) + { + if (ExeIconCache.TryGetValue(cacheKey, out returnValue)) + { + return returnValue; + } + + returnValue = GetExeIcon(path, index); + if (returnValue != null) + { + ExeIconCache.Add(cacheKey, returnValue); + } + } + } + + return returnValue; + } + + /// + /// Get icon for executable + /// + /// path to the exe or dll + /// index of the icon + /// Bitmap with the icon or null if something happended + private static Bitmap GetExeIcon(string path, int index) + { + if (!File.Exists(path)) + { + return null; + } + + try + { + using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, CoreConfig.UseLargeIcons)) + { + if (appIcon != null) + { + return appIcon.ToBitmap(); + } + } + + using (Icon appIcon = Shell32.GetFileIcon(path, CoreConfig.UseLargeIcons ? Shell32.IconSize.Large : Shell32.IconSize.Small, false)) + { + if (appIcon != null) + { + return appIcon.ToBitmap(); + } + } + } + catch (Exception exIcon) + { + Log.Error("error retrieving icon: ", exIcon); + } + + return null; + } + + /// + /// Helper method to add a plugin MenuItem to the Greenshot context menu + /// + /// ToolStripMenuItem + public static void AddToContextMenu(ToolStripMenuItem item) + { + // Here we can hang ourselves to the main context menu! + var contextMenu = SimpleServiceProvider.Current.GetInstance(); + bool addedItem = false; + + // Try to find a separator, so we insert ourselves after it + for (int i = 0; i < contextMenu.Items.Count; i++) + { + if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator)) + { + // Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore" + if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag)) + { + var separator = new ToolStripSeparator + { + Tag = "PluginsAreAddedAfter", + Size = new Size(305, 6) + }; + contextMenu.Items.Insert(i, separator); + } + else if (!"PluginsAreAddedAfter".Equals(contextMenu.Items[i].Tag)) + { + continue; + } + + contextMenu.Items.Insert(i + 1, item); + addedItem = true; + break; + } + } + + // If we didn't insert the item, we just add it... + if (!addedItem) + { + contextMenu.Items.Add(item); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/QuantizerHelper.cs b/src/Greenshot.Base/Core/QuantizerHelper.cs similarity index 97% rename from src/GreenshotPlugin/Core/QuantizerHelper.cs rename to src/Greenshot.Base/Core/QuantizerHelper.cs index 91296005d..9ae5211a1 100644 --- a/src/GreenshotPlugin/Core/QuantizerHelper.cs +++ b/src/Greenshot.Base/Core/QuantizerHelper.cs @@ -1,771 +1,771 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using log4net; - -namespace GreenshotPlugin.Core -{ - internal class WuColorCube - { - /// - /// Gets or sets the red minimum. - /// - /// The red minimum. - public int RedMinimum { get; set; } - - /// - /// Gets or sets the red maximum. - /// - /// The red maximum. - public int RedMaximum { get; set; } - - /// - /// Gets or sets the green minimum. - /// - /// The green minimum. - public int GreenMinimum { get; set; } - - /// - /// Gets or sets the green maximum. - /// - /// The green maximum. - public int GreenMaximum { get; set; } - - /// - /// Gets or sets the blue minimum. - /// - /// The blue minimum. - public int BlueMinimum { get; set; } - - /// - /// Gets or sets the blue maximum. - /// - /// The blue maximum. - public int BlueMaximum { get; set; } - - /// - /// Gets or sets the cube volume. - /// - /// The volume. - public int Volume { get; set; } - } - - public class WuQuantizer : IDisposable - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(WuQuantizer)); - - private const int MAXCOLOR = 512; - private const int RED = 2; - private const int GREEN = 1; - private const int BLUE = 0; - private const int SIDESIZE = 33; - private const int MAXSIDEINDEX = 32; - private const int MAXVOLUME = SIDESIZE * SIDESIZE * SIDESIZE; - - // To count the colors - private readonly int colorCount; - - private int[] reds; - private int[] greens; - private int[] blues; - private int[] sums; - - private readonly long[,,] weights; - private readonly long[,,] momentsRed; - private readonly long[,,] momentsGreen; - private readonly long[,,] momentsBlue; - private readonly float[,,] moments; - - private byte[] tag; - - private readonly WuColorCube[] cubes; - private readonly Bitmap sourceBitmap; - private Bitmap resultBitmap; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - if (resultBitmap != null) - { - resultBitmap.Dispose(); - resultBitmap = null; - } - } - } - - /// - /// See for more details. - /// - public WuQuantizer(Bitmap sourceBitmap) - { - this.sourceBitmap = sourceBitmap; - // Make sure the color count variables are reset - BitArray bitArray = new BitArray((int) Math.Pow(2, 24)); - colorCount = 0; - - // creates all the cubes - cubes = new WuColorCube[MAXCOLOR]; - - // initializes all the cubes - for (int cubeIndex = 0; cubeIndex < MAXCOLOR; cubeIndex++) - { - cubes[cubeIndex] = new WuColorCube(); - } - - // resets the reference minimums - cubes[0].RedMinimum = 0; - cubes[0].GreenMinimum = 0; - cubes[0].BlueMinimum = 0; - - // resets the reference maximums - cubes[0].RedMaximum = MAXSIDEINDEX; - cubes[0].GreenMaximum = MAXSIDEINDEX; - cubes[0].BlueMaximum = MAXSIDEINDEX; - - weights = new long[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsRed = new long[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsGreen = new long[SIDESIZE, SIDESIZE, SIDESIZE]; - momentsBlue = new long[SIDESIZE, SIDESIZE, SIDESIZE]; - moments = new float[SIDESIZE, SIDESIZE, SIDESIZE]; - - int[] table = new int[256]; - - for (int tableIndex = 0; tableIndex < 256; ++tableIndex) - { - table[tableIndex] = tableIndex * tableIndex; - } - - // Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage - using IFastBitmap sourceFastBitmap = FastBitmap.Create(sourceBitmap); - IFastBitmapWithBlend sourceFastBitmapWithBlend = sourceFastBitmap as IFastBitmapWithBlend; - sourceFastBitmap.Lock(); - using FastChunkyBitmap destinationFastBitmap = FastBitmap.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap; - destinationFastBitmap.Lock(); - for (int y = 0; y < sourceFastBitmap.Height; y++) - { - for (int x = 0; x < sourceFastBitmap.Width; x++) - { - Color color; - if (sourceFastBitmapWithBlend == null) - { - color = sourceFastBitmap.GetColorAt(x, y); - } - else - { - color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y); - } - - // To count the colors - int index = color.ToArgb() & 0x00ffffff; - // Check if we already have this color - if (!bitArray.Get(index)) - { - // If not, add 1 to the single colors - colorCount++; - bitArray.Set(index, true); - } - - int indexRed = (color.R >> 3) + 1; - int indexGreen = (color.G >> 3) + 1; - int indexBlue = (color.B >> 3) + 1; - - weights[indexRed, indexGreen, indexBlue]++; - momentsRed[indexRed, indexGreen, indexBlue] += color.R; - momentsGreen[indexRed, indexGreen, indexBlue] += color.G; - momentsBlue[indexRed, indexGreen, indexBlue] += color.B; - moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B]; - - // Store the initial "match" - int paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue; - destinationFastBitmap.SetColorIndexAt(x, y, (byte) (paletteIndex & 0xff)); - } - } - - resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap(); - } - - /// - /// See for more details. - /// - public int GetColorCount() - { - return colorCount; - } - - /// - /// Reindex the 24/32 BPP (A)RGB image to a 8BPP - /// - /// Bitmap - public Bitmap SimpleReindex() - { - List colors = new List(); - Dictionary lookup = new Dictionary(); - using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) - { - bbbDest.Lock(); - using IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap); - IFastBitmapWithBlend bbbSrcBlend = bbbSrc as IFastBitmapWithBlend; - - bbbSrc.Lock(); - byte index; - for (int y = 0; y < bbbSrc.Height; y++) - { - for (int x = 0; x < bbbSrc.Width; x++) - { - Color color; - if (bbbSrcBlend != null) - { - color = bbbSrcBlend.GetBlendedColorAt(x, y); - } - else - { - color = bbbSrc.GetColorAt(x, y); - } - - if (lookup.ContainsKey(color)) - { - index = lookup[color]; - } - else - { - colors.Add(color); - index = (byte) (colors.Count - 1); - lookup.Add(color, index); - } - - bbbDest.SetColorIndexAt(x, y, index); - } - } - } - - // generates palette - ColorPalette imagePalette = resultBitmap.Palette; - Color[] entries = imagePalette.Entries; - for (int paletteIndex = 0; paletteIndex < 256; paletteIndex++) - { - if (paletteIndex < colorCount) - { - entries[paletteIndex] = colors[paletteIndex]; - } - else - { - entries[paletteIndex] = Color.Black; - } - } - - resultBitmap.Palette = imagePalette; - - // Make sure the bitmap is not disposed, as we return it. - Bitmap tmpBitmap = resultBitmap; - resultBitmap = null; - return tmpBitmap; - } - - /// - /// Get the image - /// - public Bitmap GetQuantizedImage(int allowedColorCount) - { - if (allowedColorCount > 256) - { - throw new ArgumentOutOfRangeException(nameof(allowedColorCount), "Quantizing muss be done to get less than 256 colors"); - } - - if (colorCount < allowedColorCount) - { - // Simple logic to reduce to 8 bit - LOG.Info("Colors in the image are already less as whished for, using simple copy to indexed image, no quantizing needed!"); - return SimpleReindex(); - } - - // preprocess the colors - CalculateMoments(); - LOG.Info("Calculated the moments..."); - int next = 0; - float[] volumeVariance = new float[MAXCOLOR]; - - // processes the cubes - for (int cubeIndex = 1; cubeIndex < allowedColorCount; ++cubeIndex) - { - // if cut is possible; make it - if (Cut(cubes[next], cubes[cubeIndex])) - { - volumeVariance[next] = cubes[next].Volume > 1 ? CalculateVariance(cubes[next]) : 0.0f; - volumeVariance[cubeIndex] = cubes[cubeIndex].Volume > 1 ? CalculateVariance(cubes[cubeIndex]) : 0.0f; - } - else - { - // the cut was not possible, revert the index - volumeVariance[next] = 0.0f; - cubeIndex--; - } - - next = 0; - float temp = volumeVariance[0]; - - for (int index = 1; index <= cubeIndex; ++index) - { - if (volumeVariance[index] > temp) - { - temp = volumeVariance[index]; - next = index; - } - } - - if (temp <= 0.0) - { - allowedColorCount = cubeIndex + 1; - break; - } - } - - int[] lookupRed = new int[MAXCOLOR]; - int[] lookupGreen = new int[MAXCOLOR]; - int[] lookupBlue = new int[MAXCOLOR]; - - tag = new byte[MAXVOLUME]; - - // precalculates lookup tables - for (int k = 0; k < allowedColorCount; ++k) - { - Mark(cubes[k], k, tag); - - long weight = Volume(cubes[k], weights); - - if (weight > 0) - { - lookupRed[k] = (int) (Volume(cubes[k], momentsRed) / weight); - lookupGreen[k] = (int) (Volume(cubes[k], momentsGreen) / weight); - lookupBlue[k] = (int) (Volume(cubes[k], momentsBlue) / weight); - } - else - { - lookupRed[k] = 0; - lookupGreen[k] = 0; - lookupBlue[k] = 0; - } - } - - reds = new int[allowedColorCount + 1]; - greens = new int[allowedColorCount + 1]; - blues = new int[allowedColorCount + 1]; - sums = new int[allowedColorCount + 1]; - - LOG.Info("Starting bitmap reconstruction..."); - - using (FastChunkyBitmap dest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) - { - using IFastBitmap src = FastBitmap.Create(sourceBitmap); - IFastBitmapWithBlend srcBlend = src as IFastBitmapWithBlend; - Dictionary lookup = new Dictionary(); - for (int y = 0; y < src.Height; y++) - { - for (int x = 0; x < src.Width; x++) - { - Color color; - if (srcBlend != null) - { - // WithoutAlpha, this makes it possible to ignore the alpha - color = srcBlend.GetBlendedColorAt(x, y); - } - else - { - color = src.GetColorAt(x, y); - } - - // Check if we already matched the color - byte bestMatch; - if (!lookup.ContainsKey(color)) - { - // If not we need to find the best match - - // First get initial match - bestMatch = dest.GetColorIndexAt(x, y); - bestMatch = tag[bestMatch]; - - int bestDistance = 100000000; - for (int lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++) - { - int foundRed = lookupRed[lookupIndex]; - int foundGreen = lookupGreen[lookupIndex]; - int foundBlue = lookupBlue[lookupIndex]; - int deltaRed = color.R - foundRed; - int deltaGreen = color.G - foundGreen; - int deltaBlue = color.B - foundBlue; - - int distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; - - if (distance < bestDistance) - { - bestDistance = distance; - bestMatch = (byte) lookupIndex; - } - } - - lookup.Add(color, bestMatch); - } - else - { - // Already matched, so we just use the lookup - bestMatch = lookup[color]; - } - - reds[bestMatch] += color.R; - greens[bestMatch] += color.G; - blues[bestMatch] += color.B; - sums[bestMatch]++; - - dest.SetColorIndexAt(x, y, bestMatch); - } - } - } - - - // generates palette - ColorPalette imagePalette = resultBitmap.Palette; - Color[] entries = imagePalette.Entries; - for (int paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++) - { - if (sums[paletteIndex] > 0) - { - reds[paletteIndex] /= sums[paletteIndex]; - greens[paletteIndex] /= sums[paletteIndex]; - blues[paletteIndex] /= sums[paletteIndex]; - } - - entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]); - } - - resultBitmap.Palette = imagePalette; - - // Make sure the bitmap is not disposed, as we return it. - Bitmap tmpBitmap = resultBitmap; - resultBitmap = null; - return tmpBitmap; - } - - /// - /// Converts the histogram to a series of moments. - /// - private void CalculateMoments() - { - long[] area = new long[SIDESIZE]; - long[] areaRed = new long[SIDESIZE]; - long[] areaGreen = new long[SIDESIZE]; - long[] areaBlue = new long[SIDESIZE]; - float[] area2 = new float[SIDESIZE]; - - for (int redIndex = 1; redIndex <= MAXSIDEINDEX; ++redIndex) - { - for (int index = 0; index <= MAXSIDEINDEX; ++index) - { - area[index] = 0; - areaRed[index] = 0; - areaGreen[index] = 0; - areaBlue[index] = 0; - area2[index] = 0; - } - - for (int greenIndex = 1; greenIndex <= MAXSIDEINDEX; ++greenIndex) - { - long line = 0; - long lineRed = 0; - long lineGreen = 0; - long lineBlue = 0; - float line2 = 0.0f; - - for (int blueIndex = 1; blueIndex <= MAXSIDEINDEX; ++blueIndex) - { - line += weights[redIndex, greenIndex, blueIndex]; - lineRed += momentsRed[redIndex, greenIndex, blueIndex]; - lineGreen += momentsGreen[redIndex, greenIndex, blueIndex]; - lineBlue += momentsBlue[redIndex, greenIndex, blueIndex]; - line2 += moments[redIndex, greenIndex, blueIndex]; - - area[blueIndex] += line; - areaRed[blueIndex] += lineRed; - areaGreen[blueIndex] += lineGreen; - areaBlue[blueIndex] += lineBlue; - area2[blueIndex] += line2; - - weights[redIndex, greenIndex, blueIndex] = weights[redIndex - 1, greenIndex, blueIndex] + area[blueIndex]; - momentsRed[redIndex, greenIndex, blueIndex] = momentsRed[redIndex - 1, greenIndex, blueIndex] + areaRed[blueIndex]; - momentsGreen[redIndex, greenIndex, blueIndex] = momentsGreen[redIndex - 1, greenIndex, blueIndex] + areaGreen[blueIndex]; - momentsBlue[redIndex, greenIndex, blueIndex] = momentsBlue[redIndex - 1, greenIndex, blueIndex] + areaBlue[blueIndex]; - moments[redIndex, greenIndex, blueIndex] = moments[redIndex - 1, greenIndex, blueIndex] + area2[blueIndex]; - } - } - } - } - - /// - /// Computes the volume of the cube in a specific moment. - /// - private static long Volume(WuColorCube cube, long[,,] moment) - { - return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - - moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; - } - - /// - /// Computes the volume of the cube in a specific moment. For the floating-point values. - /// - private static float VolumeFloat(WuColorCube cube, float[,,] moment) - { - return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - - moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; - } - - /// - /// Splits the cube in given position, and color direction. - /// - private static long Top(WuColorCube cube, int direction, int position, long[,,] moment) - { - return direction switch - { - RED => (moment[position, cube.GreenMaximum, cube.BlueMaximum] - - moment[position, cube.GreenMaximum, cube.BlueMinimum] - - moment[position, cube.GreenMinimum, cube.BlueMaximum] + - moment[position, cube.GreenMinimum, cube.BlueMinimum]), - GREEN => (moment[cube.RedMaximum, position, cube.BlueMaximum] - - moment[cube.RedMaximum, position, cube.BlueMinimum] - - moment[cube.RedMinimum, position, cube.BlueMaximum] + - moment[cube.RedMinimum, position, cube.BlueMinimum]), - BLUE => (moment[cube.RedMaximum, cube.GreenMaximum, position] - - moment[cube.RedMaximum, cube.GreenMinimum, position] - - moment[cube.RedMinimum, cube.GreenMaximum, position] + - moment[cube.RedMinimum, cube.GreenMinimum, position]), - _ => 0, - }; - } - - /// - /// Splits the cube in a given color direction at its minimum. - /// - private static long Bottom(WuColorCube cube, int direction, long[,,] moment) - { - return direction switch - { - RED => (-moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), - GREEN => (-moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), - BLUE => (-moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] + - moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + - moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] - - moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), - _ => 0 - }; - } - - /// - /// Calculates statistical variance for a given cube. - /// - private float CalculateVariance(WuColorCube cube) - { - float volumeRed = Volume(cube, momentsRed); - float volumeGreen = Volume(cube, momentsGreen); - float volumeBlue = Volume(cube, momentsBlue); - float volumeMoment = VolumeFloat(cube, moments); - float volumeWeight = Volume(cube, weights); - - float distance = volumeRed * volumeRed + volumeGreen * volumeGreen + volumeBlue * volumeBlue; - - return volumeMoment - (distance / volumeWeight); - } - - /// - /// Finds the optimal (maximal) position for the cut. - /// - private float Maximize(WuColorCube cube, int direction, int first, int last, int[] cut, long wholeRed, long wholeGreen, long wholeBlue, long wholeWeight) - { - long bottomRed = Bottom(cube, direction, momentsRed); - long bottomGreen = Bottom(cube, direction, momentsGreen); - long bottomBlue = Bottom(cube, direction, momentsBlue); - long bottomWeight = Bottom(cube, direction, weights); - - float result = 0.0f; - cut[0] = -1; - - for (int position = first; position < last; ++position) - { - // determines the cube cut at a certain position - long halfRed = bottomRed + Top(cube, direction, position, momentsRed); - long halfGreen = bottomGreen + Top(cube, direction, position, momentsGreen); - long halfBlue = bottomBlue + Top(cube, direction, position, momentsBlue); - long halfWeight = bottomWeight + Top(cube, direction, position, weights); - - // the cube cannot be cut at bottom (this would lead to empty cube) - if (halfWeight != 0) - { - float halfDistance = (float) halfRed * halfRed + (float) halfGreen * halfGreen + (float) halfBlue * halfBlue; - float temp = halfDistance / halfWeight; - - halfRed = wholeRed - halfRed; - halfGreen = wholeGreen - halfGreen; - halfBlue = wholeBlue - halfBlue; - halfWeight = wholeWeight - halfWeight; - - if (halfWeight != 0) - { - halfDistance = (float) halfRed * halfRed + (float) halfGreen * halfGreen + (float) halfBlue * halfBlue; - temp += halfDistance / halfWeight; - - if (temp > result) - { - result = temp; - cut[0] = position; - } - } - } - } - - return result; - } - - /// - /// Cuts a cube with another one. - /// - private bool Cut(WuColorCube first, WuColorCube second) - { - int direction; - - int[] cutRed = - { - 0 - }; - int[] cutGreen = - { - 0 - }; - int[] cutBlue = - { - 0 - }; - - long wholeRed = Volume(first, momentsRed); - long wholeGreen = Volume(first, momentsGreen); - long wholeBlue = Volume(first, momentsBlue); - long wholeWeight = Volume(first, weights); - - float maxRed = Maximize(first, RED, first.RedMinimum + 1, first.RedMaximum, cutRed, wholeRed, wholeGreen, wholeBlue, wholeWeight); - float maxGreen = Maximize(first, GREEN, first.GreenMinimum + 1, first.GreenMaximum, cutGreen, wholeRed, wholeGreen, wholeBlue, wholeWeight); - float maxBlue = Maximize(first, BLUE, first.BlueMinimum + 1, first.BlueMaximum, cutBlue, wholeRed, wholeGreen, wholeBlue, wholeWeight); - - if ((maxRed >= maxGreen) && (maxRed >= maxBlue)) - { - direction = RED; - - // cannot split empty cube - if (cutRed[0] < 0) return false; - } - else - { - if ((maxGreen >= maxRed) && (maxGreen >= maxBlue)) - { - direction = GREEN; - } - else - { - direction = BLUE; - } - } - - second.RedMaximum = first.RedMaximum; - second.GreenMaximum = first.GreenMaximum; - second.BlueMaximum = first.BlueMaximum; - - // cuts in a certain direction - switch (direction) - { - case RED: - second.RedMinimum = first.RedMaximum = cutRed[0]; - second.GreenMinimum = first.GreenMinimum; - second.BlueMinimum = first.BlueMinimum; - break; - - case GREEN: - second.GreenMinimum = first.GreenMaximum = cutGreen[0]; - second.RedMinimum = first.RedMinimum; - second.BlueMinimum = first.BlueMinimum; - break; - - case BLUE: - second.BlueMinimum = first.BlueMaximum = cutBlue[0]; - second.RedMinimum = first.RedMinimum; - second.GreenMinimum = first.GreenMinimum; - break; - } - - // determines the volumes after cut - first.Volume = (first.RedMaximum - first.RedMinimum) * (first.GreenMaximum - first.GreenMinimum) * (first.BlueMaximum - first.BlueMinimum); - second.Volume = (second.RedMaximum - second.RedMinimum) * (second.GreenMaximum - second.GreenMinimum) * (second.BlueMaximum - second.BlueMinimum); - - // the cut was successfull - return true; - } - - /// - /// Marks all the tags with a given label. - /// - private void Mark(WuColorCube cube, int label, byte[] tag) - { - for (int redIndex = cube.RedMinimum + 1; redIndex <= cube.RedMaximum; ++redIndex) - { - for (int greenIndex = cube.GreenMinimum + 1; greenIndex <= cube.GreenMaximum; ++greenIndex) - { - for (int blueIndex = cube.BlueMinimum + 1; blueIndex <= cube.BlueMaximum; ++blueIndex) - { - tag[(redIndex << 10) + (redIndex << 6) + redIndex + (greenIndex << 5) + greenIndex + blueIndex] = (byte) label; - } - } - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using log4net; + +namespace Greenshot.Base.Core +{ + internal class WuColorCube + { + /// + /// Gets or sets the red minimum. + /// + /// The red minimum. + public int RedMinimum { get; set; } + + /// + /// Gets or sets the red maximum. + /// + /// The red maximum. + public int RedMaximum { get; set; } + + /// + /// Gets or sets the green minimum. + /// + /// The green minimum. + public int GreenMinimum { get; set; } + + /// + /// Gets or sets the green maximum. + /// + /// The green maximum. + public int GreenMaximum { get; set; } + + /// + /// Gets or sets the blue minimum. + /// + /// The blue minimum. + public int BlueMinimum { get; set; } + + /// + /// Gets or sets the blue maximum. + /// + /// The blue maximum. + public int BlueMaximum { get; set; } + + /// + /// Gets or sets the cube volume. + /// + /// The volume. + public int Volume { get; set; } + } + + public class WuQuantizer : IDisposable + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(WuQuantizer)); + + private const int MAXCOLOR = 512; + private const int RED = 2; + private const int GREEN = 1; + private const int BLUE = 0; + private const int SIDESIZE = 33; + private const int MAXSIDEINDEX = 32; + private const int MAXVOLUME = SIDESIZE * SIDESIZE * SIDESIZE; + + // To count the colors + private readonly int colorCount; + + private int[] reds; + private int[] greens; + private int[] blues; + private int[] sums; + + private readonly long[,,] weights; + private readonly long[,,] momentsRed; + private readonly long[,,] momentsGreen; + private readonly long[,,] momentsBlue; + private readonly float[,,] moments; + + private byte[] tag; + + private readonly WuColorCube[] cubes; + private readonly Bitmap sourceBitmap; + private Bitmap resultBitmap; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (resultBitmap != null) + { + resultBitmap.Dispose(); + resultBitmap = null; + } + } + } + + /// + /// See for more details. + /// + public WuQuantizer(Bitmap sourceBitmap) + { + this.sourceBitmap = sourceBitmap; + // Make sure the color count variables are reset + BitArray bitArray = new BitArray((int) Math.Pow(2, 24)); + colorCount = 0; + + // creates all the cubes + cubes = new WuColorCube[MAXCOLOR]; + + // initializes all the cubes + for (int cubeIndex = 0; cubeIndex < MAXCOLOR; cubeIndex++) + { + cubes[cubeIndex] = new WuColorCube(); + } + + // resets the reference minimums + cubes[0].RedMinimum = 0; + cubes[0].GreenMinimum = 0; + cubes[0].BlueMinimum = 0; + + // resets the reference maximums + cubes[0].RedMaximum = MAXSIDEINDEX; + cubes[0].GreenMaximum = MAXSIDEINDEX; + cubes[0].BlueMaximum = MAXSIDEINDEX; + + weights = new long[SIDESIZE, SIDESIZE, SIDESIZE]; + momentsRed = new long[SIDESIZE, SIDESIZE, SIDESIZE]; + momentsGreen = new long[SIDESIZE, SIDESIZE, SIDESIZE]; + momentsBlue = new long[SIDESIZE, SIDESIZE, SIDESIZE]; + moments = new float[SIDESIZE, SIDESIZE, SIDESIZE]; + + int[] table = new int[256]; + + for (int tableIndex = 0; tableIndex < 256; ++tableIndex) + { + table[tableIndex] = tableIndex * tableIndex; + } + + // Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage + using IFastBitmap sourceFastBitmap = FastBitmap.Create(sourceBitmap); + IFastBitmapWithBlend sourceFastBitmapWithBlend = sourceFastBitmap as IFastBitmapWithBlend; + sourceFastBitmap.Lock(); + using FastChunkyBitmap destinationFastBitmap = FastBitmap.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap; + destinationFastBitmap.Lock(); + for (int y = 0; y < sourceFastBitmap.Height; y++) + { + for (int x = 0; x < sourceFastBitmap.Width; x++) + { + Color color; + if (sourceFastBitmapWithBlend == null) + { + color = sourceFastBitmap.GetColorAt(x, y); + } + else + { + color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y); + } + + // To count the colors + int index = color.ToArgb() & 0x00ffffff; + // Check if we already have this color + if (!bitArray.Get(index)) + { + // If not, add 1 to the single colors + colorCount++; + bitArray.Set(index, true); + } + + int indexRed = (color.R >> 3) + 1; + int indexGreen = (color.G >> 3) + 1; + int indexBlue = (color.B >> 3) + 1; + + weights[indexRed, indexGreen, indexBlue]++; + momentsRed[indexRed, indexGreen, indexBlue] += color.R; + momentsGreen[indexRed, indexGreen, indexBlue] += color.G; + momentsBlue[indexRed, indexGreen, indexBlue] += color.B; + moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B]; + + // Store the initial "match" + int paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue; + destinationFastBitmap.SetColorIndexAt(x, y, (byte) (paletteIndex & 0xff)); + } + } + + resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap(); + } + + /// + /// See for more details. + /// + public int GetColorCount() + { + return colorCount; + } + + /// + /// Reindex the 24/32 BPP (A)RGB image to a 8BPP + /// + /// Bitmap + public Bitmap SimpleReindex() + { + List colors = new List(); + Dictionary lookup = new Dictionary(); + using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) + { + bbbDest.Lock(); + using IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap); + IFastBitmapWithBlend bbbSrcBlend = bbbSrc as IFastBitmapWithBlend; + + bbbSrc.Lock(); + byte index; + for (int y = 0; y < bbbSrc.Height; y++) + { + for (int x = 0; x < bbbSrc.Width; x++) + { + Color color; + if (bbbSrcBlend != null) + { + color = bbbSrcBlend.GetBlendedColorAt(x, y); + } + else + { + color = bbbSrc.GetColorAt(x, y); + } + + if (lookup.ContainsKey(color)) + { + index = lookup[color]; + } + else + { + colors.Add(color); + index = (byte) (colors.Count - 1); + lookup.Add(color, index); + } + + bbbDest.SetColorIndexAt(x, y, index); + } + } + } + + // generates palette + ColorPalette imagePalette = resultBitmap.Palette; + Color[] entries = imagePalette.Entries; + for (int paletteIndex = 0; paletteIndex < 256; paletteIndex++) + { + if (paletteIndex < colorCount) + { + entries[paletteIndex] = colors[paletteIndex]; + } + else + { + entries[paletteIndex] = Color.Black; + } + } + + resultBitmap.Palette = imagePalette; + + // Make sure the bitmap is not disposed, as we return it. + Bitmap tmpBitmap = resultBitmap; + resultBitmap = null; + return tmpBitmap; + } + + /// + /// Get the image + /// + public Bitmap GetQuantizedImage(int allowedColorCount) + { + if (allowedColorCount > 256) + { + throw new ArgumentOutOfRangeException(nameof(allowedColorCount), "Quantizing muss be done to get less than 256 colors"); + } + + if (colorCount < allowedColorCount) + { + // Simple logic to reduce to 8 bit + LOG.Info("Colors in the image are already less as whished for, using simple copy to indexed image, no quantizing needed!"); + return SimpleReindex(); + } + + // preprocess the colors + CalculateMoments(); + LOG.Info("Calculated the moments..."); + int next = 0; + float[] volumeVariance = new float[MAXCOLOR]; + + // processes the cubes + for (int cubeIndex = 1; cubeIndex < allowedColorCount; ++cubeIndex) + { + // if cut is possible; make it + if (Cut(cubes[next], cubes[cubeIndex])) + { + volumeVariance[next] = cubes[next].Volume > 1 ? CalculateVariance(cubes[next]) : 0.0f; + volumeVariance[cubeIndex] = cubes[cubeIndex].Volume > 1 ? CalculateVariance(cubes[cubeIndex]) : 0.0f; + } + else + { + // the cut was not possible, revert the index + volumeVariance[next] = 0.0f; + cubeIndex--; + } + + next = 0; + float temp = volumeVariance[0]; + + for (int index = 1; index <= cubeIndex; ++index) + { + if (volumeVariance[index] > temp) + { + temp = volumeVariance[index]; + next = index; + } + } + + if (temp <= 0.0) + { + allowedColorCount = cubeIndex + 1; + break; + } + } + + int[] lookupRed = new int[MAXCOLOR]; + int[] lookupGreen = new int[MAXCOLOR]; + int[] lookupBlue = new int[MAXCOLOR]; + + tag = new byte[MAXVOLUME]; + + // precalculates lookup tables + for (int k = 0; k < allowedColorCount; ++k) + { + Mark(cubes[k], k, tag); + + long weight = Volume(cubes[k], weights); + + if (weight > 0) + { + lookupRed[k] = (int) (Volume(cubes[k], momentsRed) / weight); + lookupGreen[k] = (int) (Volume(cubes[k], momentsGreen) / weight); + lookupBlue[k] = (int) (Volume(cubes[k], momentsBlue) / weight); + } + else + { + lookupRed[k] = 0; + lookupGreen[k] = 0; + lookupBlue[k] = 0; + } + } + + reds = new int[allowedColorCount + 1]; + greens = new int[allowedColorCount + 1]; + blues = new int[allowedColorCount + 1]; + sums = new int[allowedColorCount + 1]; + + LOG.Info("Starting bitmap reconstruction..."); + + using (FastChunkyBitmap dest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) + { + using IFastBitmap src = FastBitmap.Create(sourceBitmap); + IFastBitmapWithBlend srcBlend = src as IFastBitmapWithBlend; + Dictionary lookup = new Dictionary(); + for (int y = 0; y < src.Height; y++) + { + for (int x = 0; x < src.Width; x++) + { + Color color; + if (srcBlend != null) + { + // WithoutAlpha, this makes it possible to ignore the alpha + color = srcBlend.GetBlendedColorAt(x, y); + } + else + { + color = src.GetColorAt(x, y); + } + + // Check if we already matched the color + byte bestMatch; + if (!lookup.ContainsKey(color)) + { + // If not we need to find the best match + + // First get initial match + bestMatch = dest.GetColorIndexAt(x, y); + bestMatch = tag[bestMatch]; + + int bestDistance = 100000000; + for (int lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++) + { + int foundRed = lookupRed[lookupIndex]; + int foundGreen = lookupGreen[lookupIndex]; + int foundBlue = lookupBlue[lookupIndex]; + int deltaRed = color.R - foundRed; + int deltaGreen = color.G - foundGreen; + int deltaBlue = color.B - foundBlue; + + int distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; + + if (distance < bestDistance) + { + bestDistance = distance; + bestMatch = (byte) lookupIndex; + } + } + + lookup.Add(color, bestMatch); + } + else + { + // Already matched, so we just use the lookup + bestMatch = lookup[color]; + } + + reds[bestMatch] += color.R; + greens[bestMatch] += color.G; + blues[bestMatch] += color.B; + sums[bestMatch]++; + + dest.SetColorIndexAt(x, y, bestMatch); + } + } + } + + + // generates palette + ColorPalette imagePalette = resultBitmap.Palette; + Color[] entries = imagePalette.Entries; + for (int paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++) + { + if (sums[paletteIndex] > 0) + { + reds[paletteIndex] /= sums[paletteIndex]; + greens[paletteIndex] /= sums[paletteIndex]; + blues[paletteIndex] /= sums[paletteIndex]; + } + + entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]); + } + + resultBitmap.Palette = imagePalette; + + // Make sure the bitmap is not disposed, as we return it. + Bitmap tmpBitmap = resultBitmap; + resultBitmap = null; + return tmpBitmap; + } + + /// + /// Converts the histogram to a series of moments. + /// + private void CalculateMoments() + { + long[] area = new long[SIDESIZE]; + long[] areaRed = new long[SIDESIZE]; + long[] areaGreen = new long[SIDESIZE]; + long[] areaBlue = new long[SIDESIZE]; + float[] area2 = new float[SIDESIZE]; + + for (int redIndex = 1; redIndex <= MAXSIDEINDEX; ++redIndex) + { + for (int index = 0; index <= MAXSIDEINDEX; ++index) + { + area[index] = 0; + areaRed[index] = 0; + areaGreen[index] = 0; + areaBlue[index] = 0; + area2[index] = 0; + } + + for (int greenIndex = 1; greenIndex <= MAXSIDEINDEX; ++greenIndex) + { + long line = 0; + long lineRed = 0; + long lineGreen = 0; + long lineBlue = 0; + float line2 = 0.0f; + + for (int blueIndex = 1; blueIndex <= MAXSIDEINDEX; ++blueIndex) + { + line += weights[redIndex, greenIndex, blueIndex]; + lineRed += momentsRed[redIndex, greenIndex, blueIndex]; + lineGreen += momentsGreen[redIndex, greenIndex, blueIndex]; + lineBlue += momentsBlue[redIndex, greenIndex, blueIndex]; + line2 += moments[redIndex, greenIndex, blueIndex]; + + area[blueIndex] += line; + areaRed[blueIndex] += lineRed; + areaGreen[blueIndex] += lineGreen; + areaBlue[blueIndex] += lineBlue; + area2[blueIndex] += line2; + + weights[redIndex, greenIndex, blueIndex] = weights[redIndex - 1, greenIndex, blueIndex] + area[blueIndex]; + momentsRed[redIndex, greenIndex, blueIndex] = momentsRed[redIndex - 1, greenIndex, blueIndex] + areaRed[blueIndex]; + momentsGreen[redIndex, greenIndex, blueIndex] = momentsGreen[redIndex - 1, greenIndex, blueIndex] + areaGreen[blueIndex]; + momentsBlue[redIndex, greenIndex, blueIndex] = momentsBlue[redIndex - 1, greenIndex, blueIndex] + areaBlue[blueIndex]; + moments[redIndex, greenIndex, blueIndex] = moments[redIndex - 1, greenIndex, blueIndex] + area2[blueIndex]; + } + } + } + } + + /// + /// Computes the volume of the cube in a specific moment. + /// + private static long Volume(WuColorCube cube, long[,,] moment) + { + return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - + moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; + } + + /// + /// Computes the volume of the cube in a specific moment. For the floating-point values. + /// + private static float VolumeFloat(WuColorCube cube, float[,,] moment) + { + return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] - + moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] - + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] - + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]; + } + + /// + /// Splits the cube in given position, and color direction. + /// + private static long Top(WuColorCube cube, int direction, int position, long[,,] moment) + { + return direction switch + { + RED => (moment[position, cube.GreenMaximum, cube.BlueMaximum] - + moment[position, cube.GreenMaximum, cube.BlueMinimum] - + moment[position, cube.GreenMinimum, cube.BlueMaximum] + + moment[position, cube.GreenMinimum, cube.BlueMinimum]), + GREEN => (moment[cube.RedMaximum, position, cube.BlueMaximum] - + moment[cube.RedMaximum, position, cube.BlueMinimum] - + moment[cube.RedMinimum, position, cube.BlueMaximum] + + moment[cube.RedMinimum, position, cube.BlueMinimum]), + BLUE => (moment[cube.RedMaximum, cube.GreenMaximum, position] - + moment[cube.RedMaximum, cube.GreenMinimum, position] - + moment[cube.RedMinimum, cube.GreenMaximum, position] + + moment[cube.RedMinimum, cube.GreenMinimum, position]), + _ => 0, + }; + } + + /// + /// Splits the cube in a given color direction at its minimum. + /// + private static long Bottom(WuColorCube cube, int direction, long[,,] moment) + { + return direction switch + { + RED => (-moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] + + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] + + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), + GREEN => (-moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] + + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] - + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), + BLUE => (-moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] + + moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] + + moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] - + moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]), + _ => 0 + }; + } + + /// + /// Calculates statistical variance for a given cube. + /// + private float CalculateVariance(WuColorCube cube) + { + float volumeRed = Volume(cube, momentsRed); + float volumeGreen = Volume(cube, momentsGreen); + float volumeBlue = Volume(cube, momentsBlue); + float volumeMoment = VolumeFloat(cube, moments); + float volumeWeight = Volume(cube, weights); + + float distance = volumeRed * volumeRed + volumeGreen * volumeGreen + volumeBlue * volumeBlue; + + return volumeMoment - (distance / volumeWeight); + } + + /// + /// Finds the optimal (maximal) position for the cut. + /// + private float Maximize(WuColorCube cube, int direction, int first, int last, int[] cut, long wholeRed, long wholeGreen, long wholeBlue, long wholeWeight) + { + long bottomRed = Bottom(cube, direction, momentsRed); + long bottomGreen = Bottom(cube, direction, momentsGreen); + long bottomBlue = Bottom(cube, direction, momentsBlue); + long bottomWeight = Bottom(cube, direction, weights); + + float result = 0.0f; + cut[0] = -1; + + for (int position = first; position < last; ++position) + { + // determines the cube cut at a certain position + long halfRed = bottomRed + Top(cube, direction, position, momentsRed); + long halfGreen = bottomGreen + Top(cube, direction, position, momentsGreen); + long halfBlue = bottomBlue + Top(cube, direction, position, momentsBlue); + long halfWeight = bottomWeight + Top(cube, direction, position, weights); + + // the cube cannot be cut at bottom (this would lead to empty cube) + if (halfWeight != 0) + { + float halfDistance = (float) halfRed * halfRed + (float) halfGreen * halfGreen + (float) halfBlue * halfBlue; + float temp = halfDistance / halfWeight; + + halfRed = wholeRed - halfRed; + halfGreen = wholeGreen - halfGreen; + halfBlue = wholeBlue - halfBlue; + halfWeight = wholeWeight - halfWeight; + + if (halfWeight != 0) + { + halfDistance = (float) halfRed * halfRed + (float) halfGreen * halfGreen + (float) halfBlue * halfBlue; + temp += halfDistance / halfWeight; + + if (temp > result) + { + result = temp; + cut[0] = position; + } + } + } + } + + return result; + } + + /// + /// Cuts a cube with another one. + /// + private bool Cut(WuColorCube first, WuColorCube second) + { + int direction; + + int[] cutRed = + { + 0 + }; + int[] cutGreen = + { + 0 + }; + int[] cutBlue = + { + 0 + }; + + long wholeRed = Volume(first, momentsRed); + long wholeGreen = Volume(first, momentsGreen); + long wholeBlue = Volume(first, momentsBlue); + long wholeWeight = Volume(first, weights); + + float maxRed = Maximize(first, RED, first.RedMinimum + 1, first.RedMaximum, cutRed, wholeRed, wholeGreen, wholeBlue, wholeWeight); + float maxGreen = Maximize(first, GREEN, first.GreenMinimum + 1, first.GreenMaximum, cutGreen, wholeRed, wholeGreen, wholeBlue, wholeWeight); + float maxBlue = Maximize(first, BLUE, first.BlueMinimum + 1, first.BlueMaximum, cutBlue, wholeRed, wholeGreen, wholeBlue, wholeWeight); + + if ((maxRed >= maxGreen) && (maxRed >= maxBlue)) + { + direction = RED; + + // cannot split empty cube + if (cutRed[0] < 0) return false; + } + else + { + if ((maxGreen >= maxRed) && (maxGreen >= maxBlue)) + { + direction = GREEN; + } + else + { + direction = BLUE; + } + } + + second.RedMaximum = first.RedMaximum; + second.GreenMaximum = first.GreenMaximum; + second.BlueMaximum = first.BlueMaximum; + + // cuts in a certain direction + switch (direction) + { + case RED: + second.RedMinimum = first.RedMaximum = cutRed[0]; + second.GreenMinimum = first.GreenMinimum; + second.BlueMinimum = first.BlueMinimum; + break; + + case GREEN: + second.GreenMinimum = first.GreenMaximum = cutGreen[0]; + second.RedMinimum = first.RedMinimum; + second.BlueMinimum = first.BlueMinimum; + break; + + case BLUE: + second.BlueMinimum = first.BlueMaximum = cutBlue[0]; + second.RedMinimum = first.RedMinimum; + second.GreenMinimum = first.GreenMinimum; + break; + } + + // determines the volumes after cut + first.Volume = (first.RedMaximum - first.RedMinimum) * (first.GreenMaximum - first.GreenMinimum) * (first.BlueMaximum - first.BlueMinimum); + second.Volume = (second.RedMaximum - second.RedMinimum) * (second.GreenMaximum - second.GreenMinimum) * (second.BlueMaximum - second.BlueMinimum); + + // the cut was successfull + return true; + } + + /// + /// Marks all the tags with a given label. + /// + private void Mark(WuColorCube cube, int label, byte[] tag) + { + for (int redIndex = cube.RedMinimum + 1; redIndex <= cube.RedMaximum; ++redIndex) + { + for (int greenIndex = cube.GreenMinimum + 1; greenIndex <= cube.GreenMaximum; ++greenIndex) + { + for (int blueIndex = cube.BlueMinimum + 1; blueIndex <= cube.BlueMaximum; ++blueIndex) + { + tag[(redIndex << 10) + (redIndex << 6) + redIndex + (greenIndex << 5) + greenIndex + blueIndex] = (byte) label; + } + } + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/RegistryKeyExtensions.cs b/src/Greenshot.Base/Core/RegistryKeyExtensions.cs similarity index 99% rename from src/GreenshotPlugin/Core/RegistryKeyExtensions.cs rename to src/Greenshot.Base/Core/RegistryKeyExtensions.cs index 383c55e67..a1abcea98 100644 --- a/src/GreenshotPlugin/Core/RegistryKeyExtensions.cs +++ b/src/Greenshot.Base/Core/RegistryKeyExtensions.cs @@ -22,7 +22,7 @@ using System; using Microsoft.Win32; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// A helper class for accessing the registry diff --git a/src/GreenshotPlugin/Core/SimpleServiceProvider.cs b/src/Greenshot.Base/Core/SimpleServiceProvider.cs similarity index 92% rename from src/GreenshotPlugin/Core/SimpleServiceProvider.cs rename to src/Greenshot.Base/Core/SimpleServiceProvider.cs index fc197367d..bff814540 100644 --- a/src/GreenshotPlugin/Core/SimpleServiceProvider.cs +++ b/src/Greenshot.Base/Core/SimpleServiceProvider.cs @@ -1,61 +1,61 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPlugin.Core -{ - /// - /// A really cheap and simple DI system - /// - public class SimpleServiceProvider : IServiceLocator - { - private readonly Dictionary> _services = new Dictionary>(); - - public static IServiceLocator Current { get; } = new SimpleServiceProvider(); - - public IEnumerable GetAllInstances() - { - var typeOfService = typeof(TService); - if (!_services.TryGetValue(typeOfService, out var results)) - { - yield break; - } - - foreach (TService result in results) - { - yield return result; - } - } - - public TService GetInstance() - { - return GetAllInstances().SingleOrDefault(); - } - - public void AddService(IEnumerable services) - { - var serviceType = typeof(TService); - if (!_services.TryGetValue(serviceType, out var currentServices)) - { - currentServices = new List(); - _services.Add(serviceType, currentServices); - } - - foreach (var service in services) - { - if (service == null) - { - continue; - } - - currentServices.Add(service); - } - } - - public void AddService(params TService[] services) - { - AddService(services.AsEnumerable()); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using Greenshot.Base.Interfaces; + +namespace Greenshot.Base.Core +{ + /// + /// A really cheap and simple DI system + /// + public class SimpleServiceProvider : IServiceLocator + { + private readonly Dictionary> _services = new Dictionary>(); + + public static IServiceLocator Current { get; } = new SimpleServiceProvider(); + + public IEnumerable GetAllInstances() + { + var typeOfService = typeof(TService); + if (!_services.TryGetValue(typeOfService, out var results)) + { + yield break; + } + + foreach (TService result in results) + { + yield return result; + } + } + + public TService GetInstance() + { + return GetAllInstances().SingleOrDefault(); + } + + public void AddService(IEnumerable services) + { + var serviceType = typeof(TService); + if (!_services.TryGetValue(serviceType, out var currentServices)) + { + currentServices = new List(); + _services.Add(serviceType, currentServices); + } + + foreach (var service in services) + { + if (service == null) + { + continue; + } + + currentServices.Add(service); + } + } + + public void AddService(params TService[] services) + { + AddService(services.AsEnumerable()); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/StringExtensions.cs b/src/Greenshot.Base/Core/StringExtensions.cs similarity index 99% rename from src/GreenshotPlugin/Core/StringExtensions.cs rename to src/Greenshot.Base/Core/StringExtensions.cs index d82f51e14..1265e3616 100644 --- a/src/GreenshotPlugin/Core/StringExtensions.cs +++ b/src/Greenshot.Base/Core/StringExtensions.cs @@ -20,14 +20,14 @@ */ using System; +using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; -using log4net; using System.Text.RegularExpressions; -using System.Collections.Generic; +using log4net; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { public static class StringExtensions { diff --git a/src/GreenshotPlugin/Core/SvgImage.cs b/src/Greenshot.Base/Core/SvgImage.cs similarity index 99% rename from src/GreenshotPlugin/Core/SvgImage.cs rename to src/Greenshot.Base/Core/SvgImage.cs index 7924c3480..f04e8c0df 100644 --- a/src/GreenshotPlugin/Core/SvgImage.cs +++ b/src/Greenshot.Base/Core/SvgImage.cs @@ -24,7 +24,7 @@ using System.Drawing.Imaging; using System.IO; using Svg; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// Create an image look like of the SVG diff --git a/src/GreenshotPlugin/Core/WindowCapture.cs b/src/Greenshot.Base/Core/WindowCapture.cs similarity index 96% rename from src/GreenshotPlugin/Core/WindowCapture.cs rename to src/Greenshot.Base/Core/WindowCapture.cs index fafd88a18..7d5c751d9 100644 --- a/src/GreenshotPlugin/Core/WindowCapture.cs +++ b/src/Greenshot.Base/Core/WindowCapture.cs @@ -1,444 +1,444 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using GreenshotPlugin.UnmanagedHelpers; -using log4net; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.UnmanagedHelpers.Structs; - -namespace GreenshotPlugin.Core -{ - /// - /// The Window Capture code - /// - public static class WindowCapture - { - private static readonly ILog Log = LogManager.GetLogger(typeof(WindowCapture)); - private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection(); - - /// - /// Used to cleanup the unmanaged resource in the iconInfo for the CaptureCursor method - /// - /// - /// - [DllImport("gdi32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeleteObject(IntPtr hObject); - - /// - /// Get the bounds of all screens combined. - /// - /// A Rectangle of the bounds of the entire display area. - public static Rectangle GetScreenBounds() - { - int left = 0, top = 0, bottom = 0, right = 0; - foreach (Screen screen in Screen.AllScreens) - { - left = Math.Min(left, screen.Bounds.X); - top = Math.Min(top, screen.Bounds.Y); - int screenAbsRight = screen.Bounds.X + screen.Bounds.Width; - int screenAbsBottom = screen.Bounds.Y + screen.Bounds.Height; - right = Math.Max(right, screenAbsRight); - bottom = Math.Max(bottom, screenAbsBottom); - } - - return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top))); - } - - /// - /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation - /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. - /// - /// - /// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen) - /// - public static Point GetCursorLocationRelativeToScreenBounds() - { - return GetLocationRelativeToScreenBounds(User32.GetCursorLocation()); - } - - /// - /// Converts locationRelativeToScreenOrigin to be relative to top left corner of all screen bounds, which might - /// be different in multi-screen setups. This implementation - /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. - /// - /// - /// Point - public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin) - { - Point ret = locationRelativeToScreenOrigin; - Rectangle bounds = GetScreenBounds(); - ret.Offset(-bounds.X, -bounds.Y); - return ret; - } - - /// - /// This method will capture the current Cursor by using User32 Code - /// - /// A Capture Object with the Mouse Cursor information in it. - public static ICapture CaptureCursor(ICapture capture) - { - Log.Debug("Capturing the mouse cursor."); - if (capture == null) - { - capture = new Capture(); - } - - var cursorInfo = new CursorInfo(); - cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); - if (!User32.GetCursorInfo(out cursorInfo)) return capture; - if (cursorInfo.flags != User32.CURSOR_SHOWING) return capture; - - using SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor); - if (!User32.GetIconInfo(safeIcon, out var iconInfo)) return capture; - - Point cursorLocation = User32.GetCursorLocation(); - // Align cursor location to Bitmap coordinates (instead of Screen coordinates) - var x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X; - var y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y; - // Set the location - capture.CursorLocation = new Point(x, y); - - using (Icon icon = Icon.FromHandle(safeIcon.DangerousGetHandle())) - { - capture.Cursor = icon; - } - - if (iconInfo.hbmMask != IntPtr.Zero) - { - DeleteObject(iconInfo.hbmMask); - } - - if (iconInfo.hbmColor != IntPtr.Zero) - { - DeleteObject(iconInfo.hbmColor); - } - - return capture; - } - - /// - /// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen. - /// - /// A Capture Object with the Screen as an Image - public static ICapture CaptureScreen(ICapture capture) - { - if (capture == null) - { - capture = new Capture(); - } - - return CaptureRectangle(capture, capture.ScreenBounds); - } - - /// - /// Helper method to create an exception that might explain what is wrong while capturing - /// - /// string with current method - /// Rectangle of what we want to capture - /// - private static Exception CreateCaptureException(string method, Rectangle captureBounds) - { - Exception exceptionToThrow = User32.CreateWin32Exception(method); - if (!captureBounds.IsEmpty) - { - exceptionToThrow.Data.Add("Height", captureBounds.Height); - exceptionToThrow.Data.Add("Width", captureBounds.Width); - } - - return exceptionToThrow; - } - - /// - /// Helper method to check if it is allowed to capture the process using DWM - /// - /// Process owning the window - /// true if it's allowed - public static bool IsDwmAllowed(Process process) - { - if (process == null) return true; - if (Configuration.NoDWMCaptureForProduct == null || - Configuration.NoDWMCaptureForProduct.Count <= 0) return true; - - try - { - string productName = process.MainModule?.FileVersionInfo.ProductName; - if (productName != null && Configuration.NoDWMCaptureForProduct.Contains(productName.ToLower())) - { - return false; - } - } - catch (Exception ex) - { - Log.Warn(ex.Message); - } - - return true; - } - - /// - /// Helper method to check if it is allowed to capture the process using GDI - /// - /// Process owning the window - /// true if it's allowed - public static bool IsGdiAllowed(Process process) - { - if (process == null) return true; - if (Configuration.NoGDICaptureForProduct == null || - Configuration.NoGDICaptureForProduct.Count <= 0) return true; - - try - { - string productName = process.MainModule?.FileVersionInfo.ProductName; - if (productName != null && Configuration.NoGDICaptureForProduct.Contains(productName.ToLower())) - { - return false; - } - } - catch (Exception ex) - { - Log.Warn(ex.Message); - } - - return true; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// ICapture where the captured Bitmap will be stored - /// Rectangle with the bounds to capture - /// A Capture Object with a part of the Screen as an Image - public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds) - { - if (capture == null) - { - capture = new Capture(); - } - - Image capturedImage = null; - // If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here - if (CaptureHandler.CaptureScreenRectangle != null) - { - try - { - capturedImage = CaptureHandler.CaptureScreenRectangle(captureBounds); - } - catch - { - // ignored - } - } - - // If no capture, use the normal screen capture - if (capturedImage == null) - { - capturedImage = CaptureRectangle(captureBounds); - } - - capture.Image = capturedImage; - capture.Location = captureBounds.Location; - return capture.Image == null ? null : capture; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// ICapture where the captured Bitmap will be stored - /// Rectangle with the bounds to capture - /// A Capture Object with a part of the Screen as an Image - public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds) - { - if (capture == null) - { - capture = new Capture(); - } - - capture.Image = CaptureRectangle(captureBounds); - capture.Location = captureBounds.Location; - return capture.Image == null ? null : capture; - } - - /// - /// This method will use User32 code to capture the specified captureBounds from the screen - /// - /// Rectangle with the bounds to capture - /// Bitmap which is captured from the screen at the location specified by the captureBounds - public static Bitmap CaptureRectangle(Rectangle captureBounds) - { - Bitmap returnBitmap = null; - if (captureBounds.Height <= 0 || captureBounds.Width <= 0) - { - Log.Warn("Nothing to capture, ignoring!"); - return null; - } - - Log.Debug("CaptureRectangle Called!"); - - // .NET GDI+ Solution, according to some post this has a GDI+ leak... - // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen - // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height); - // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) { - // graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt); - // } - // capture.Image = capturedBitmap; - // capture.Location = captureBounds.Location; - - using (var desktopDcHandle = SafeWindowDcHandle.FromDesktop()) - { - if (desktopDcHandle.IsInvalid) - { - // Get Exception before the error is lost - Exception exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds); - // throw exception - throw exceptionToThrow; - } - - // create a device context we can copy to - using SafeCompatibleDCHandle safeCompatibleDcHandle = GDI32.CreateCompatibleDC(desktopDcHandle); - // Check if the device context is there, if not throw an error with as much info as possible! - if (safeCompatibleDcHandle.IsInvalid) - { - // Get Exception before the error is lost - Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds); - // throw exception - throw exceptionToThrow; - } - - // Create BITMAPINFOHEADER for CreateDIBSection - BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24); - - // Make sure the last error is set to 0 - Win32.SetLastError(0); - - // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height - using SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDcHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out _, IntPtr.Zero, 0); - if (safeDibSectionHandle.IsInvalid) - { - // Get Exception before the error is lost - var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds); - exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32()); - exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32()); - - // Throw so people can report the problem - throw exceptionToThrow; - } - - // select the bitmap object and store the old handle - using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle)) - { - // bitblt over (make copy) - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - GDI32.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y, - CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); - } - - // get a .NET image object for it - // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0�80004005 error is to re-try... - bool success = false; - ExternalException exception = null; - for (int i = 0; i < 3; i++) - { - try - { - // Collect all screens inside this capture - List screensInsideCapture = new List(); - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.IntersectsWith(captureBounds)) - { - screensInsideCapture.Add(screen); - } - } - - // Check all all screens are of an equal size - bool offscreenContent; - using (Region captureRegion = new Region(captureBounds)) - { - // Exclude every visible part - foreach (Screen screen in screensInsideCapture) - { - captureRegion.Exclude(screen.Bounds); - } - - // If the region is not empty, we have "offscreenContent" - using Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow()); - offscreenContent = !captureRegion.IsEmpty(screenGraphics); - } - - // Check if we need to have a transparent background, needed for offscreen content - if (offscreenContent) - { - using Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); - // Create a new bitmap which has a transparent background - returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, - tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution); - // Content will be copied here - using Graphics graphics = Graphics.FromImage(returnBitmap); - // For all screens copy the content to the new bitmap - foreach (Screen screen in Screen.AllScreens) - { - Rectangle screenBounds = screen.Bounds; - // Make sure the bounds are offsetted to the capture bounds - screenBounds.Offset(-captureBounds.X, -captureBounds.Y); - graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel); - } - } - else - { - // All screens, which are inside the capture, are of equal size - // assign image to Capture, the image will be disposed there.. - returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); - } - - // We got through the capture without exception - success = true; - break; - } - catch (ExternalException ee) - { - Log.Warn("Problem getting bitmap at try " + i + " : ", ee); - exception = ee; - } - } - - if (!success) - { - Log.Error("Still couldn't create Bitmap!"); - if (exception != null) - { - throw exception; - } - } - } - - return returnBitmap; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Structs; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// The Window Capture code + /// + public static class WindowCapture + { + private static readonly ILog Log = LogManager.GetLogger(typeof(WindowCapture)); + private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection(); + + /// + /// Used to cleanup the unmanaged resource in the iconInfo for the CaptureCursor method + /// + /// + /// + [DllImport("gdi32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DeleteObject(IntPtr hObject); + + /// + /// Get the bounds of all screens combined. + /// + /// A Rectangle of the bounds of the entire display area. + public static Rectangle GetScreenBounds() + { + int left = 0, top = 0, bottom = 0, right = 0; + foreach (Screen screen in Screen.AllScreens) + { + left = Math.Min(left, screen.Bounds.X); + top = Math.Min(top, screen.Bounds.Y); + int screenAbsRight = screen.Bounds.X + screen.Bounds.Width; + int screenAbsBottom = screen.Bounds.Y + screen.Bounds.Height; + right = Math.Max(right, screenAbsRight); + bottom = Math.Max(bottom, screenAbsBottom); + } + + return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top))); + } + + /// + /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation + /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. + /// + /// + /// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen) + /// + public static Point GetCursorLocationRelativeToScreenBounds() + { + return GetLocationRelativeToScreenBounds(User32.GetCursorLocation()); + } + + /// + /// Converts locationRelativeToScreenOrigin to be relative to top left corner of all screen bounds, which might + /// be different in multi-screen setups. This implementation + /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. + /// + /// + /// Point + public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin) + { + Point ret = locationRelativeToScreenOrigin; + Rectangle bounds = GetScreenBounds(); + ret.Offset(-bounds.X, -bounds.Y); + return ret; + } + + /// + /// This method will capture the current Cursor by using User32 Code + /// + /// A Capture Object with the Mouse Cursor information in it. + public static ICapture CaptureCursor(ICapture capture) + { + Log.Debug("Capturing the mouse cursor."); + if (capture == null) + { + capture = new Capture(); + } + + var cursorInfo = new CursorInfo(); + cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); + if (!User32.GetCursorInfo(out cursorInfo)) return capture; + if (cursorInfo.flags != User32.CURSOR_SHOWING) return capture; + + using SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor); + if (!User32.GetIconInfo(safeIcon, out var iconInfo)) return capture; + + Point cursorLocation = User32.GetCursorLocation(); + // Align cursor location to Bitmap coordinates (instead of Screen coordinates) + var x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X; + var y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y; + // Set the location + capture.CursorLocation = new Point(x, y); + + using (Icon icon = Icon.FromHandle(safeIcon.DangerousGetHandle())) + { + capture.Cursor = icon; + } + + if (iconInfo.hbmMask != IntPtr.Zero) + { + DeleteObject(iconInfo.hbmMask); + } + + if (iconInfo.hbmColor != IntPtr.Zero) + { + DeleteObject(iconInfo.hbmColor); + } + + return capture; + } + + /// + /// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen. + /// + /// A Capture Object with the Screen as an Image + public static ICapture CaptureScreen(ICapture capture) + { + if (capture == null) + { + capture = new Capture(); + } + + return CaptureRectangle(capture, capture.ScreenBounds); + } + + /// + /// Helper method to create an exception that might explain what is wrong while capturing + /// + /// string with current method + /// Rectangle of what we want to capture + /// + private static Exception CreateCaptureException(string method, Rectangle captureBounds) + { + Exception exceptionToThrow = User32.CreateWin32Exception(method); + if (!captureBounds.IsEmpty) + { + exceptionToThrow.Data.Add("Height", captureBounds.Height); + exceptionToThrow.Data.Add("Width", captureBounds.Width); + } + + return exceptionToThrow; + } + + /// + /// Helper method to check if it is allowed to capture the process using DWM + /// + /// Process owning the window + /// true if it's allowed + public static bool IsDwmAllowed(Process process) + { + if (process == null) return true; + if (Configuration.NoDWMCaptureForProduct == null || + Configuration.NoDWMCaptureForProduct.Count <= 0) return true; + + try + { + string productName = process.MainModule?.FileVersionInfo.ProductName; + if (productName != null && Configuration.NoDWMCaptureForProduct.Contains(productName.ToLower())) + { + return false; + } + } + catch (Exception ex) + { + Log.Warn(ex.Message); + } + + return true; + } + + /// + /// Helper method to check if it is allowed to capture the process using GDI + /// + /// Process owning the window + /// true if it's allowed + public static bool IsGdiAllowed(Process process) + { + if (process == null) return true; + if (Configuration.NoGDICaptureForProduct == null || + Configuration.NoGDICaptureForProduct.Count <= 0) return true; + + try + { + string productName = process.MainModule?.FileVersionInfo.ProductName; + if (productName != null && Configuration.NoGDICaptureForProduct.Contains(productName.ToLower())) + { + return false; + } + } + catch (Exception ex) + { + Log.Warn(ex.Message); + } + + return true; + } + + /// + /// This method will use User32 code to capture the specified captureBounds from the screen + /// + /// ICapture where the captured Bitmap will be stored + /// Rectangle with the bounds to capture + /// A Capture Object with a part of the Screen as an Image + public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds) + { + if (capture == null) + { + capture = new Capture(); + } + + Image capturedImage = null; + // If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here + if (CaptureHandler.CaptureScreenRectangle != null) + { + try + { + capturedImage = CaptureHandler.CaptureScreenRectangle(captureBounds); + } + catch + { + // ignored + } + } + + // If no capture, use the normal screen capture + if (capturedImage == null) + { + capturedImage = CaptureRectangle(captureBounds); + } + + capture.Image = capturedImage; + capture.Location = captureBounds.Location; + return capture.Image == null ? null : capture; + } + + /// + /// This method will use User32 code to capture the specified captureBounds from the screen + /// + /// ICapture where the captured Bitmap will be stored + /// Rectangle with the bounds to capture + /// A Capture Object with a part of the Screen as an Image + public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds) + { + if (capture == null) + { + capture = new Capture(); + } + + capture.Image = CaptureRectangle(captureBounds); + capture.Location = captureBounds.Location; + return capture.Image == null ? null : capture; + } + + /// + /// This method will use User32 code to capture the specified captureBounds from the screen + /// + /// Rectangle with the bounds to capture + /// Bitmap which is captured from the screen at the location specified by the captureBounds + public static Bitmap CaptureRectangle(Rectangle captureBounds) + { + Bitmap returnBitmap = null; + if (captureBounds.Height <= 0 || captureBounds.Width <= 0) + { + Log.Warn("Nothing to capture, ignoring!"); + return null; + } + + Log.Debug("CaptureRectangle Called!"); + + // .NET GDI+ Solution, according to some post this has a GDI+ leak... + // See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen + // Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height); + // using (Graphics graphics = Graphics.FromImage(capturedBitmap)) { + // graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt); + // } + // capture.Image = capturedBitmap; + // capture.Location = captureBounds.Location; + + using (var desktopDcHandle = SafeWindowDcHandle.FromDesktop()) + { + if (desktopDcHandle.IsInvalid) + { + // Get Exception before the error is lost + Exception exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds); + // throw exception + throw exceptionToThrow; + } + + // create a device context we can copy to + using SafeCompatibleDCHandle safeCompatibleDcHandle = GDI32.CreateCompatibleDC(desktopDcHandle); + // Check if the device context is there, if not throw an error with as much info as possible! + if (safeCompatibleDcHandle.IsInvalid) + { + // Get Exception before the error is lost + Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds); + // throw exception + throw exceptionToThrow; + } + + // Create BITMAPINFOHEADER for CreateDIBSection + BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24); + + // Make sure the last error is set to 0 + Win32.SetLastError(0); + + // create a bitmap we can copy it to, using GetDeviceCaps to get the width/height + using SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDcHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out _, IntPtr.Zero, 0); + if (safeDibSectionHandle.IsInvalid) + { + // Get Exception before the error is lost + var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds); + exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32()); + exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32()); + + // Throw so people can report the problem + throw exceptionToThrow; + } + + // select the bitmap object and store the old handle + using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle)) + { + // bitblt over (make copy) + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + GDI32.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y, + CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); + } + + // get a .NET image object for it + // A suggestion for the "A generic error occurred in GDI+." E_FAIL/0�80004005 error is to re-try... + bool success = false; + ExternalException exception = null; + for (int i = 0; i < 3; i++) + { + try + { + // Collect all screens inside this capture + List screensInsideCapture = new List(); + foreach (Screen screen in Screen.AllScreens) + { + if (screen.Bounds.IntersectsWith(captureBounds)) + { + screensInsideCapture.Add(screen); + } + } + + // Check all all screens are of an equal size + bool offscreenContent; + using (Region captureRegion = new Region(captureBounds)) + { + // Exclude every visible part + foreach (Screen screen in screensInsideCapture) + { + captureRegion.Exclude(screen.Bounds); + } + + // If the region is not empty, we have "offscreenContent" + using Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow()); + offscreenContent = !captureRegion.IsEmpty(screenGraphics); + } + + // Check if we need to have a transparent background, needed for offscreen content + if (offscreenContent) + { + using Bitmap tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); + // Create a new bitmap which has a transparent background + returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, + tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution); + // Content will be copied here + using Graphics graphics = Graphics.FromImage(returnBitmap); + // For all screens copy the content to the new bitmap + foreach (Screen screen in Screen.AllScreens) + { + Rectangle screenBounds = screen.Bounds; + // Make sure the bounds are offsetted to the capture bounds + screenBounds.Offset(-captureBounds.X, -captureBounds.Y); + graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel); + } + } + else + { + // All screens, which are inside the capture, are of equal size + // assign image to Capture, the image will be disposed there.. + returnBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()); + } + + // We got through the capture without exception + success = true; + break; + } + catch (ExternalException ee) + { + Log.Warn("Problem getting bitmap at try " + i + " : ", ee); + exception = ee; + } + } + + if (!success) + { + Log.Error("Still couldn't create Bitmap!"); + if (exception != null) + { + throw exception; + } + } + } + + return returnBitmap; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/WindowDetails.cs b/src/Greenshot.Base/Core/WindowDetails.cs similarity index 96% rename from src/GreenshotPlugin/Core/WindowDetails.cs rename to src/Greenshot.Base/Core/WindowDetails.cs index 641c0db20..c656e586c 100644 --- a/src/GreenshotPlugin/Core/WindowDetails.cs +++ b/src/Greenshot.Base/Core/WindowDetails.cs @@ -1,1876 +1,1874 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interop; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; -using log4net; - -namespace GreenshotPlugin.Core -{ - /// - /// Code for handling with "windows" - /// Main code is taken from vbAccelerator, location: - /// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp - /// but a LOT of changes/enhancements were made to adapt it for Greenshot. - /// - /// Provides details about a Window returned by the enumeration - /// - public class WindowDetails : IEquatable - { - 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[] - { - "Progman", "Button", "Dwm" - }); //"MS-SDIa" - - private static readonly ILog Log = LogManager.GetLogger(typeof(WindowDetails)); - private static readonly CoreConfiguration Conf = IniConfig.GetIniSection(); - private static readonly IList IgnoreHandles = new List(); - private static readonly IList ExcludeProcessesFromFreeze = new List(); - private static readonly IAppVisibility AppVisibility; - - static WindowDetails() - { - try - { - // Only try to instantiate when Windows 8 or later. - if (WindowsVersion.IsWindows8OrLater) - { - AppVisibility = COMWrapper.CreateInstance(); - } - } - catch (Exception ex) - { - Log.WarnFormat("Couldn't create instance of IAppVisibility: {0}", ex.Message); - } - } - - public static void AddProcessToExcludeFromFreeze(string processName) - { - if (!ExcludeProcessesFromFreeze.Contains(processName)) - { - ExcludeProcessesFromFreeze.Add(processName); - } - } - - internal static bool IsIgnoreHandle(IntPtr handle) - { - return IgnoreHandles.Contains(handle); - } - - private IList _childWindows; - 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" - /// - public bool IsWin10App => AppFrameWindowClass.Equals(ClassName); - - /// - /// Check if this window belongs to a background app - /// - 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 - /// is set to the Window handle, so two EnumWindowsItem - /// objects for the same Window will be equal. - /// - /// The Window Handle for this window - public override int GetHashCode() - { - return Handle.ToInt32(); - } - - public override bool Equals(object right) - { - return Equals(right as WindowDetails); - } - - /// - /// Compare two windows details - /// - /// - /// - public bool Equals(WindowDetails other) - { - if (other is null) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - if (GetType() != other.GetType()) - { - return false; - } - - return other.Handle == Handle; - } - - /// - /// Check if the window has children - /// - public bool HasChildren => (_childWindows != null) && (_childWindows.Count > 0); - - /// - /// Freeze information updates - /// - public void FreezeDetails() - { - _frozen = true; - } - - /// - /// Make the information update again. - /// - public void UnfreezeDetails() - { - _frozen = false; - } - - /// - /// Get the file path to the exe for the process which owns this window - /// - public string ProcessPath - { - get - { - if (Handle == IntPtr.Zero) - { - // not a valid window handle - return string.Empty; - } - - // Get the process id - User32.GetWindowThreadProcessId(Handle, out var processId); - return Kernel32.GetProcessPath(processId); - } - } - - - /// - /// Get the icon belonging to the process - /// - public Image DisplayIcon - { - get - { - try - { - using var appIcon = GetAppIcon(Handle); - if (appIcon != null) - { - return appIcon.ToBitmap(); - } - } - catch (Exception ex) - { - Log.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); - Log.Warn(ex); - } - - if (IsMetroApp) - { - // No method yet to get the metro icon - return null; - } - - try - { - return PluginUtils.GetCachedExeIcon(ProcessPath, 0); - } - catch (Exception ex) - { - Log.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); - Log.Warn(ex); - } - - return null; - } - } - - /// - /// Get the icon for a hWnd - /// - /// - /// - private static Icon GetAppIcon(IntPtr hWnd) - { - IntPtr iconSmall = IntPtr.Zero; - IntPtr iconBig = new IntPtr(1); - IntPtr iconSmall2 = new IntPtr(2); - - IntPtr iconHandle; - if (Conf.UseLargeIcons) - { - iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconBig, IntPtr.Zero); - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICON); - } - } - else - { - iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconSmall2, IntPtr.Zero); - } - - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconSmall, IntPtr.Zero); - } - - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICONSM); - } - - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconBig, IntPtr.Zero); - } - - if (iconHandle == IntPtr.Zero) - { - iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICON); - } - - if (iconHandle == IntPtr.Zero) - { - return null; - } - - Icon icon = Icon.FromHandle(iconHandle); - - return icon; - } - - /// - /// Use this to make remove internal windows, like the mainform and the captureforms, invisible - /// - /// - public static void RegisterIgnoreHandle(IntPtr ignoreHandle) - { - IgnoreHandles.Add(ignoreHandle); - } - - /// - /// Use this to remove the with RegisterIgnoreHandle registered handle - /// - /// - public static void UnregisterIgnoreHandle(IntPtr ignoreHandle) - { - IgnoreHandles.Remove(ignoreHandle); - } - - public IList Children - { - get - { - if (_childWindows == null) - { - GetChildren(); - } - - return _childWindows; - } - } - - /// - /// Retrieve the child with matching classname - /// - public WindowDetails GetChild(string childClassname) - { - foreach (var child in Children) - { - if (childClassname.Equals(child.ClassName)) - { - return child; - } - } - - return null; - } - - public IntPtr ParentHandle - { - get - { - if (_parentHandle == IntPtr.Zero) - { - _parentHandle = User32.GetParent(Handle); - _parent = null; - } - - return _parentHandle; - } - set - { - if (_parentHandle != value) - { - _parentHandle = value; - _parent = null; - } - } - } - - /// - /// Get the parent of the current window - /// - /// WindowDetails of the parent, or null if none - public WindowDetails GetParent() - { - if (_parent == null) - { - if (_parentHandle == IntPtr.Zero) - { - _parentHandle = User32.GetParent(Handle); - } - - if (_parentHandle != IntPtr.Zero) - { - _parent = new WindowDetails(_parentHandle); - } - } - - return _parent; - } - - /// - /// Retrieve all the children, this only stores the children internally. - /// One should normally use the getter "Children" - /// - public IList GetChildren() - { - if (_childWindows == null) - { - return GetChildren(0); - } - - return _childWindows; - } - - /// - /// Retrieve all the children, this only stores the children internally, use the "Children" property for the value - /// - /// Specify how many levels we go in - public IList GetChildren(int levelsToGo) - { - if (_childWindows != null) - { - return _childWindows; - } - - _childWindows = new WindowsEnumerator().GetWindows(Handle, null).Items; - foreach (var childWindow in _childWindows) - { - if (levelsToGo > 0) - { - childWindow.GetChildren(levelsToGo - 1); - } - } - - return _childWindows; - } - - /// - /// Gets the window's handle - /// - public IntPtr Handle { get; } - - private string _text; - - /// - /// Gets the window's title (caption) - /// - public string Text - { - set => _text = value; - get - { - if (_text == null) - { - var title = new StringBuilder(260, 260); - User32.GetWindowText(Handle, title, title.Capacity); - _text = title.ToString(); - } - - return _text; - } - } - - private string _className; - - /// - /// Gets the window's class name. - /// - public string ClassName => _className ??= GetClassName(Handle); - - /// - /// Gets/Sets whether the window is iconic (minimized) or not. - /// - public bool Iconic - { - get - { - if (IsMetroApp) - { - return !Visible; - } - - return User32.IsIconic(Handle) || Location.X <= -32000; - } - set - { - if (value) - { - User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MINIMIZE, IntPtr.Zero); - } - else - { - User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_RESTORE, IntPtr.Zero); - } - } - } - - /// - /// Gets/Sets whether the window is maximized or not. - /// - public bool Maximised - { - get - { - if (IsApp) - { - if (Visible) - { - Rectangle windowRectangle = WindowRectangle; - foreach (var screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(windowRectangle)) - { - if (windowRectangle.Equals(screen.Bounds)) - { - return true; - } - } - } - } - - return false; - } - - return User32.IsZoomed(Handle); - } - set - { - if (value) - { - User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MAXIMIZE, IntPtr.Zero); - } - else - { - User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MINIMIZE, IntPtr.Zero); - } - } - } - - /// - /// Returns if this window is cloaked - /// - public bool IsCloaked - { - get => DWM.IsWindowCloaked(Handle); - } - - /// - /// Gets whether the window is visible. - /// - public bool Visible - { - get - { - // Tip from Raymond Chen https://devblogs.microsoft.com/oldnewthing/20200302-00/?p=103507 - if (IsCloaked) - { - return false; - } - - if (IsApp) - { - Rectangle windowRectangle = WindowRectangle; - foreach (Screen screen in Screen.AllScreens) - { - if (screen.Bounds.Contains(windowRectangle)) - { - if (windowRectangle.Equals(screen.Bounds)) - { - // Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes - // Although it might be the other App, this is not "very" important - RECT rect = new RECT(screen.Bounds); - IntPtr monitor = User32.MonitorFromRect(ref rect, User32.MONITOR_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 User32.IsWindowVisible(Handle); - } - } - - public bool HasParent - { - get - { - GetParent(); - return _parentHandle != IntPtr.Zero; - } - } - - public int ProcessId - { - get - { - User32.GetWindowThreadProcessId(Handle, out var processId); - return processId; - } - } - - public Process Process - { - get - { - try - { - User32.GetWindowThreadProcessId(Handle, out var processId); - return Process.GetProcessById(processId); - } - catch (Exception ex) - { - Log.Warn(ex); - } - - return null; - } - } - - private Rectangle _previousWindowRectangle = Rectangle.Empty; - private long _lastWindowRectangleRetrieveTime; - private const long CacheTime = TimeSpan.TicksPerSecond * 2; - - /// - /// Gets the bounding rectangle of the window - /// - public Rectangle WindowRectangle - { - get - { - // Try to return a cached value - long now = DateTime.Now.Ticks; - if (_previousWindowRectangle.IsEmpty || !_frozen) - { - if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime) - { - return _previousWindowRectangle; - } - - Rectangle windowRect = Rectangle.Empty; - if (DWM.IsDwmEnabled) - { - bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); - if (IsApp) - { - // Pre-Cache for maximized call, this is only on Windows 8 apps (full screen) - if (gotFrameBounds) - { - _previousWindowRectangle = windowRect; - _lastWindowRectangleRetrieveTime = now; - } - } - - if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised) - { - // Somehow DWM doesn't calculate it corectly, 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.Inflate(Conf.Win10BorderCrop); - _previousWindowRectangle = windowRect; - _lastWindowRectangleRetrieveTime = now; - return windowRect; - } - } - - if (windowRect.IsEmpty) - { - if (!GetWindowRect(out windowRect)) - { - Win32Error error = Win32.GetLastErrorCode(); - Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); - } - } - - // Correction for maximized windows, only if it's not an app - if (!HasParent && !IsApp && Maximised) - { - // Only if the border size can be retrieved - if (GetBorderSize(out var size)) - { - windowRect = new Rectangle(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 Rectangle anymore - if (windowRect.IsEmpty) - { - return _previousWindowRectangle; - } - - _previousWindowRectangle = windowRect; - return windowRect; - } - - return _previousWindowRectangle; - } - } - - /// - /// Gets the location of the window relative to the screen. - /// - public Point Location - { - get - { - Rectangle tmpRectangle = WindowRectangle; - return new Point(tmpRectangle.Left, tmpRectangle.Top); - } - } - - /// - /// Gets the size of the window. - /// - public Size Size - { - get - { - Rectangle tmpRectangle = WindowRectangle; - return new Size(tmpRectangle.Right - tmpRectangle.Left, tmpRectangle.Bottom - tmpRectangle.Top); - } - } - - /// - /// Get the client rectangle, this is the part of the window inside the borders (drawable area) - /// - public Rectangle ClientRectangle - { - get - { - if (!GetClientRect(out var clientRect)) - { - Win32Error error = Win32.GetLastErrorCode(); - Log.WarnFormat("Couldn't retrieve the client rectangle for {0}, error: {1}", Text, Win32.GetMessage(error)); - } - - return clientRect; - } - } - - /// - /// Check if the supplied point lies in the window - /// - /// Point with the coordinates to check - /// true if the point lies within - public bool Contains(Point p) - { - return WindowRectangle.Contains(p); - } - - /// - /// Restores and Brings the window to the front, - /// assuming it is a visible application window. - /// - public void Restore() - { - if (Iconic) - { - User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_RESTORE, IntPtr.Zero); - } - - User32.BringWindowToTop(Handle); - User32.SetForegroundWindow(Handle); - // Make sure windows has time to perform the action - // TODO: this is BAD practice! - while (Iconic) - { - Application.DoEvents(); - } - } - - /// - /// Get / Set the WindowStyle - /// - public WindowStyleFlags WindowStyle - { - get => (WindowStyleFlags) User32.GetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE); - set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE, new IntPtr((long) value)); - } - - /// - /// Get/Set the WindowPlacement - /// - public WindowPlacement WindowPlacement - { - get - { - var placement = WindowPlacement.Default; - User32.GetWindowPlacement(Handle, ref placement); - return placement; - } - set { User32.SetWindowPlacement(Handle, ref value); } - } - - /// - /// Get/Set the Extended WindowStyle - /// - public ExtendedWindowStyleFlags ExtendedWindowStyle - { - get => (ExtendedWindowStyleFlags) User32.GetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_EXSTYLE); - set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint) value)); - } - - /// - /// Capture Window with GDI+ - /// - /// The capture to fill - /// ICapture - public ICapture CaptureGdiWindow(ICapture capture) - { - Image capturedImage = PrintWindow(); - if (capturedImage != null) - { - capture.Image = capturedImage; - capture.Location = Location; - return capture; - } - - return null; - } - - /// - /// Capture DWM Window - /// - /// Capture to fill - /// Wanted WindowCaptureMode - /// True if auto mode is used - /// ICapture with the capture - public ICapture CaptureDwmWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) - { - IntPtr thumbnailHandle = IntPtr.Zero; - Form tempForm = null; - bool tempFormShown = false; - try - { - tempForm = new Form - { - ShowInTaskbar = false, - FormBorderStyle = FormBorderStyle.None, - TopMost = true - }; - - // Register the Thumbnail - DWM.DwmRegisterThumbnail(tempForm.Handle, Handle, out thumbnailHandle); - - // Get the original size - DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out var sourceSize); - - if (sourceSize.Width <= 0 || sourceSize.Height <= 0) - { - return null; - } - - // Calculate the location of the temp form - Rectangle windowRectangle = WindowRectangle; - Point formLocation = windowRectangle.Location; - Size borderSize = new Size(); - bool doesCaptureFit = false; - if (!Maximised) - { - // Assume using it's own location - formLocation = windowRectangle.Location; - // TODO: Use Rectangle.Union! - using Region workingArea = new Region(Screen.PrimaryScreen.Bounds); - // Find the screen where the window is and check if it fits - foreach (Screen screen in Screen.AllScreens) - { - if (!Equals(screen, Screen.PrimaryScreen)) - { - workingArea.Union(screen.Bounds); - } - } - - // If the formLocation is not inside the visible area - if (!workingArea.AreRectangleCornersVisisble(windowRectangle)) - { - // If none found we find the biggest screen - foreach (Screen screen in Screen.AllScreens) - { - Rectangle newWindowRectangle = new Rectangle(screen.WorkingArea.Location, windowRectangle.Size); - if (workingArea.AreRectangleCornersVisisble(newWindowRectangle)) - { - formLocation = screen.Bounds.Location; - doesCaptureFit = true; - break; - } - } - } - else - { - doesCaptureFit = true; - } - } - else if (!WindowsVersion.IsWindows8OrLater) - { - //GetClientRect(out windowRectangle); - GetBorderSize(out borderSize); - formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height); - } - - tempForm.Location = formLocation; - tempForm.Size = sourceSize.ToSize(); - - // Prepare rectangle to capture from the screen. - Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height); - if (Maximised) - { - // Correct capture size for maximized window by offsetting the X,Y with the border size - // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) - captureRectangle.Inflate(borderSize.Width, borderSize.Height); - } - else - { - // TODO: Also 8.x? - if (WindowsVersion.IsWindows10OrLater) - { - captureRectangle.Inflate(Conf.Win10BorderCrop); - } - - if (autoMode) - { - // check if the capture fits - if (!doesCaptureFit) - { - // 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)) - { - // we return null which causes the capturing code to try another method. - return null; - } - } - } - } - - // Prepare the displaying of the Thumbnail - DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES - { - Opacity = 255, - Visible = true, - Destination = new RECT(0, 0, sourceSize.Width, sourceSize.Height) - }; - DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); - tempForm.Show(); - tempFormShown = true; - - // Intersect with screen - captureRectangle.Intersect(capture.ScreenBounds); - - // Destination bitmap for the capture - Bitmap capturedBitmap = null; - bool frozen = false; - try - { - // Check if we make a transparent capture - if (windowCaptureMode == WindowCaptureMode.AeroTransparent) - { - frozen = FreezeWindow(); - // Use white, later black to capture transparent - tempForm.BackColor = Color.White; - // Make sure everything is visible - tempForm.Refresh(); - Application.DoEvents(); - - try - { - using Bitmap whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle); - // Apply a white color - 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 all changes are processed and visible - Application.DoEvents(); - using Bitmap blackBitmap = WindowCapture.CaptureRectangle(captureRectangle); - capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap); - } - catch (Exception e) - { - Log.Debug("Exception: ", e); - // Some problem occurred, cleanup and make a normal capture - if (capturedBitmap != null) - { - capturedBitmap.Dispose(); - capturedBitmap = null; - } - } - } - - // If no capture up till now, create a normal capture. - if (capturedBitmap == null) - { - // Remove transparency, this will break the capturing - if (!autoMode) - { - tempForm.BackColor = Color.FromArgb(255, Conf.DWMBackgroundColor.R, Conf.DWMBackgroundColor.G, Conf.DWMBackgroundColor.B); - } - else - { - Color colorizationColor = DWM.ColorizationColor; - // Modify by losing the transparency and increasing the intensity (as if the background color is white) - colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); - tempForm.BackColor = colorizationColor; - } - - // 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 all changes are processed and visible - Application.DoEvents(); - // Capture from the screen - capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle); - } - - if (capturedBitmap != null) - { - // Not needed for Windows 8 - if (!WindowsVersion.IsWindows8OrLater) - { - // Only if the Inivalue is set, not maximized and it's not a tool window. - if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) - { - // Remove corners - if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) - { - Log.Debug("Changing pixelformat to Alpha for the RemoveCorners"); - Bitmap tmpBitmap = ImageHelper.Clone(capturedBitmap, PixelFormat.Format32bppArgb); - capturedBitmap.Dispose(); - capturedBitmap = tmpBitmap; - } - - RemoveCorners(capturedBitmap); - } - } - } - } - finally - { - // Make sure to ALWAYS unfreeze!! - if (frozen) - { - UnfreezeWindow(); - } - } - - capture.Image = capturedBitmap; - // Make sure the capture location is the location of the window, not the copy - capture.Location = Location; - } - finally - { - if (thumbnailHandle != IntPtr.Zero) - { - // Unregister (cleanup), as we are finished we don't need the form or the thumbnail anymore - DWM.DwmUnregisterThumbnail(thumbnailHandle); - } - - if (tempForm != null) - { - if (tempFormShown) - { - tempForm.Close(); - } - - tempForm.Dispose(); - tempForm = null; - } - } - - return capture; - } - - /// - /// Helper method to remove the corners from a DMW capture - /// - /// The bitmap to remove the corners from. - private void RemoveCorners(Bitmap image) - { - using IFastBitmap fastBitmap = FastBitmap.Create(image); - for (int y = 0; y < Conf.WindowCornerCutShape.Count; y++) - { - for (int x = 0; x < Conf.WindowCornerCutShape[y]; x++) - { - fastBitmap.SetColorAt(x, y, Color.Transparent); - fastBitmap.SetColorAt(image.Width - 1 - x, y, Color.Transparent); - fastBitmap.SetColorAt(image.Width - 1 - x, image.Height - 1 - y, Color.Transparent); - fastBitmap.SetColorAt(x, image.Height - 1 - y, Color.Transparent); - } - } - } - - /// - /// Apply transparency by comparing a transparent capture with a black and white background - /// A "Math.min" makes sure there is no overflow, but this could cause the picture to have shifted colors. - /// The pictures should have been taken without differency, except for the colors. - /// - /// Bitmap with the black image - /// Bitmap with the black image - /// Bitmap with transparency - private Bitmap ApplyTransparency(Bitmap blackBitmap, Bitmap whiteBitmap) - { - using IFastBitmap targetBuffer = FastBitmap.CreateEmpty(blackBitmap.Size, PixelFormat.Format32bppArgb, Color.Transparent); - targetBuffer.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution); - using (IFastBitmap blackBuffer = FastBitmap.Create(blackBitmap)) - { - using IFastBitmap whiteBuffer = FastBitmap.Create(whiteBitmap); - for (int y = 0; y < blackBuffer.Height; y++) - { - for (int x = 0; x < blackBuffer.Width; x++) - { - Color c0 = blackBuffer.GetColorAt(x, y); - Color c1 = whiteBuffer.GetColorAt(x, y); - // Calculate alpha as double in range 0-1 - int alpha = c0.R - c1.R + 255; - if (alpha == 255) - { - // Alpha == 255 means no change! - targetBuffer.SetColorAt(x, y, c0); - } - else if (alpha == 0) - { - // Complete transparency, use transparent pixel - targetBuffer.SetColorAt(x, y, Color.Transparent); - } - else - { - // Calculate original color - byte originalAlpha = (byte) Math.Min(255, alpha); - var alphaFactor = alpha / 255d; - //LOG.DebugFormat("Alpha {0} & c0 {1} & c1 {2}", alpha, c0, c1); - byte originalRed = (byte) Math.Min(255, c0.R / alphaFactor); - byte originalGreen = (byte) Math.Min(255, c0.G / alphaFactor); - byte originalBlue = (byte) Math.Min(255, c0.B / alphaFactor); - Color originalColor = Color.FromArgb(originalAlpha, originalRed, originalGreen, originalBlue); - //Color originalColor = Color.FromArgb(originalAlpha, originalRed, c0.G, c0.B); - targetBuffer.SetColorAt(x, y, originalColor); - } - } - } - } - - return targetBuffer.UnlockAndReturnBitmap(); - } - - /// - /// Helper method to get the window size for DWM Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetExtendedFrameBounds(out Rectangle rectangle) - { - int result = DWM.DwmGetWindowAttribute(Handle, DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out RECT rect, Marshal.SizeOf(typeof(RECT))); - if (result >= 0) - { - rectangle = rect.ToRectangle(); - return true; - } - - rectangle = Rectangle.Empty; - return false; - } - - /// - /// Helper method to get the window size for GDI Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetClientRect(out Rectangle rectangle) - { - var windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - rectangle = result ? windowInfo.rcClient.ToRectangle() : Rectangle.Empty; - return result; - } - - /// - /// Helper method to get the window size for GDI Windows - /// - /// out Rectangle - /// bool true if it worked - private bool GetWindowRect(out Rectangle rectangle) - { - var windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - rectangle = result ? windowInfo.rcWindow.ToRectangle() : Rectangle.Empty; - return result; - } - - /// - /// Helper method to get the Border size for GDI Windows - /// - /// out Size - /// bool true if it worked - private bool GetBorderSize(out Size size) - { - var windowInfo = new WindowInfo(); - // Get the Window Info for this window - bool result = User32.GetWindowInfo(Handle, ref windowInfo); - size = result ? new Size((int) windowInfo.cxWindowBorders, (int) windowInfo.cyWindowBorders) : Size.Empty; - return result; - } - - /// - /// Set the window as foreground window - /// - /// hWnd of the window to bring to the foreground - public static void ToForeground(IntPtr hWnd) - { - var foregroundWindow = User32.GetForegroundWindow(); - if (hWnd == foregroundWindow) - { - return; - } - - var window = new WindowDetails(hWnd); - // Nothing we can do if it's not visible! - if (!window.Visible) - { - return; - } - - var threadId1 = User32.GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero); - var threadId2 = User32.GetWindowThreadProcessId(hWnd, IntPtr.Zero); - - // Show window in foreground. - if (threadId1 != threadId2) - { - User32.AttachThreadInput(threadId1, threadId2, 1); - User32.SetForegroundWindow(hWnd); - User32.AttachThreadInput(threadId1, threadId2, 0); - } - else - { - User32.SetForegroundWindow(hWnd); - } - - User32.BringWindowToTop(hWnd); - - if (window.Iconic) - { - window.Iconic = false; - } - } - - /// - /// Set the window as foreground window - /// - public void ToForeground() - { - ToForeground(Handle); - } - - /// - /// Get the region for a window - /// - private Region GetRegion() - { - using (SafeRegionHandle region = GDI32.CreateRectRgn(0, 0, 0, 0)) - { - if (!region.IsInvalid) - { - RegionResult result = User32.GetWindowRgn(Handle, region); - if (result != RegionResult.REGION_ERROR && result != RegionResult.REGION_NULLREGION) - { - return Region.FromHrgn(region.DangerousGetHandle()); - } - } - } - - return null; - } - - private bool CanFreezeOrUnfreeze(string titleOrProcessname) - { - if (string.IsNullOrEmpty(titleOrProcessname)) - { - return false; - } - - if (titleOrProcessname.ToLower().Contains("greenshot")) - { - return false; - } - - foreach (string excludeProcess in ExcludeProcessesFromFreeze) - { - if (titleOrProcessname.ToLower().Contains(excludeProcess)) - { - return false; - } - } - - return true; - } - - /// - /// Freezes the process belonging to the window - /// Warning: Use only if no other way!! - /// - private bool FreezeWindow() - { - bool frozen = false; - using (Process proc = Process.GetProcessById(ProcessId)) - { - string processName = proc.ProcessName; - if (!CanFreezeOrUnfreeze(processName)) - { - Log.DebugFormat("Not freezing {0}", processName); - return false; - } - - if (!CanFreezeOrUnfreeze(Text)) - { - Log.DebugFormat("Not freezing {0}", processName); - return false; - } - - Log.DebugFormat("Freezing process: {0}", processName); - - - foreach (ProcessThread pT in proc.Threads) - { - IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint) pT.Id); - - if (pOpenThread == IntPtr.Zero) - { - break; - } - - frozen = true; - Kernel32.SuspendThread(pOpenThread); - pT.Dispose(); - } - } - - return frozen; - } - - /// - /// Unfreeze the process belonging to the window - /// - public void UnfreezeWindow() - { - using Process proc = Process.GetProcessById(ProcessId); - string processName = proc.ProcessName; - if (!CanFreezeOrUnfreeze(processName)) - { - Log.DebugFormat("Not unfreezing {0}", processName); - return; - } - - if (!CanFreezeOrUnfreeze(Text)) - { - Log.DebugFormat("Not unfreezing {0}", processName); - return; - } - - Log.DebugFormat("Unfreezing process: {0}", processName); - - foreach (ProcessThread pT in proc.Threads) - { - IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint) pT.Id); - - if (pOpenThread == IntPtr.Zero) - { - break; - } - - Kernel32.ResumeThread(pOpenThread); - } - } - - /// - /// Return an Image representing the Window! - /// As GDI+ draws it, it will be without Aero borders! - /// - public Image PrintWindow() - { - Rectangle windowRect = WindowRectangle; - // Start the capture - Exception exceptionOccured = null; - Image returnImage; - using (Region region = GetRegion()) - { - PixelFormat pixelFormat = PixelFormat.Format24bppRgb; - // Only use 32 bpp ARGB when the window has a region - if (region != null) - { - pixelFormat = PixelFormat.Format32bppArgb; - } - - returnImage = new Bitmap(windowRect.Width, windowRect.Height, pixelFormat); - using Graphics graphics = Graphics.FromImage(returnImage); - using (SafeDeviceContextHandle graphicsDc = graphics.GetSafeDeviceContext()) - { - bool printSucceeded = User32.PrintWindow(Handle, graphicsDc.DangerousGetHandle(), 0x0); - if (!printSucceeded) - { - // something went wrong, most likely a "0x80004005" (Acess Denied) when using UAC - exceptionOccured = User32.CreateWin32Exception("PrintWindow"); - } - } - - // Apply the region "transparency" - if (region != null && !region.IsEmpty(graphics)) - { - graphics.ExcludeClip(region); - graphics.Clear(Color.Transparent); - } - - graphics.Flush(); - } - - // Return null if error - if (exceptionOccured != null) - { - Log.ErrorFormat("Error calling print window: {0}", exceptionOccured.Message); - returnImage.Dispose(); - return null; - } - - if (!HasParent && Maximised) - { - Log.Debug("Correcting for maximalization"); - GetBorderSize(out var borderSize); - Rectangle borderRectangle = new Rectangle(borderSize.Width, borderSize.Height, windowRect.Width - (2 * borderSize.Width), - windowRect.Height - (2 * borderSize.Height)); - ImageHelper.Crop(ref returnImage, ref borderRectangle); - } - - return returnImage; - } - - /// - /// Constructs a new instance of this class for - /// the specified Window Handle. - /// - /// The Window Handle - public WindowDetails(IntPtr hWnd) - { - Handle = hWnd; - } - - /// - /// Gets an instance of the current active foreground window - /// - /// WindowDetails of the current window - public static WindowDetails GetActiveWindow() - { - IntPtr hWnd = User32.GetForegroundWindow(); - if (hWnd != IntPtr.Zero) - { - if (IgnoreHandles.Contains(hWnd)) - { - return GetDesktopWindow(); - } - - WindowDetails activeWindow = new WindowDetails(hWnd); - // Invisible Windows should not be active - if (!activeWindow.Visible) - { - return GetDesktopWindow(); - } - - return activeWindow; - } - - return null; - } - - /// - /// Gets the Desktop window - /// - /// WindowDetails for the desktop window - public static WindowDetails GetDesktopWindow() - { - return new WindowDetails(User32.GetDesktopWindow()); - } - - /// - /// Get all the top level windows - /// - /// List of WindowDetails with all the top level windows - public static IList GetAllWindows() - { - return GetAllWindows(null); - } - - /// - /// Get all the top level windows, with matching classname - /// - /// List WindowDetails with all the top level windows - public static IList GetAllWindows(string classname) - { - return new WindowsEnumerator().GetWindows(IntPtr.Zero, classname).Items; - } - - /// - /// Recursive "find children which" - /// - /// point to check for - /// - public WindowDetails FindChildUnderPoint(Point point) - { - if (!Contains(point)) - { - return null; - } - - var rect = WindowRectangle; - // If the mouse it at the edge, take the whole window - if (rect.X == point.X || rect.Y == point.Y || rect.Right == point.X || rect.Bottom == point.Y) - { - return this; - } - - // Look into the child windows - foreach (var childWindow in Children) - { - if (childWindow.Contains(point)) - { - return childWindow.FindChildUnderPoint(point); - } - } - - return this; - } - - /// - /// Retrieves the classname for a hWnd - /// - /// IntPtr with the windows handle - /// String with ClassName - public static string GetClassName(IntPtr hWnd) - { - var classNameBuilder = new StringBuilder(260, 260); - User32.GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity); - return classNameBuilder.ToString(); - } - - /// - /// Helper method to decide if a top level window is visible - /// - /// - /// - /// - private static bool IsVisible(WindowDetails window, Rectangle screenBounds) - { - // Ignore invisible - if (!window.Visible) - { - return false; - } - - // Ignore minimized - if (window.Iconic) - { - return false; - } - - if (IgnoreClasses.Contains(window.ClassName)) - { - return false; - } - - // On windows which are visible on the screen - var windowRect = window.WindowRectangle; - windowRect.Intersect(screenBounds); - if (windowRect.IsEmpty) - { - return false; - } - - // 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) - { - return false; - } - - return true; - } - - /// - /// Get all the visible top level windows - /// - /// List WindowDetails with all the visible top level windows - public static IEnumerable GetVisibleWindows() - { - Rectangle screenBounds = WindowCapture.GetScreenBounds(); - foreach (var window in GetAppWindows()) - { - if (IsVisible(window, screenBounds)) - { - yield return window; - } - } - - foreach (var window in GetAllWindows()) - { - if (IsVisible(window, screenBounds)) - { - yield return window; - } - } - } - - /// - /// 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 = User32.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 = User32.FindWindow(GutterClass, null); - if (gutterHandle != IntPtr.Zero) - { - yield return new WindowDetails(gutterHandle); - } - } - - nextHandle = User32.FindWindowEx(IntPtr.Zero, nextHandle, AppWindowClass, null); - } - } - - /// - /// Check if the window is a top level - /// - /// WindowDetails - /// bool - private static bool IsTopLevel(WindowDetails window) - { - if (window.IsCloaked) - { - return false; - } - - // Windows without size - if (window.WindowRectangle.Size.Width * window.WindowRectangle.Size.Height == 0) - { - return false; - } - - if (window.HasParent) - { - return false; - } - - var exWindowStyle = window.ExtendedWindowStyle; - if ((exWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) != 0) - { - return false; - } - - // Skip everything which is not rendered "normally", trying to fix BUG-2017 - if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) - { - return false; - } - - // Skip preview windows, like the one from Firefox - if ((window.WindowStyle & WindowStyleFlags.WS_VISIBLE) == 0) - { - return false; - } - - // Ignore windows without title - if (window.Text.Length == 0) - { - return false; - } - - if (IgnoreClasses.Contains(window.ClassName)) - { - return false; - } - - if (!(window.Visible || window.Iconic)) - { - return false; - } - - return !window.IsBackgroundWin10App; - } - - /// - /// Get all the top level windows - /// - /// 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)) - { - yield return possibleTopLevel; - } - } - } - - /// - /// Find a window belonging to the same process as the supplied window. - /// - /// - /// - public static WindowDetails GetLinkedWindow(WindowDetails windowToLinkTo) - { - int processIdSelectedWindow = windowToLinkTo.ProcessId; - foreach (var window in GetAllWindows()) - { - // Ignore windows without title - if (window.Text.Length == 0) - { - continue; - } - - // Ignore invisible - if (!window.Visible) - { - continue; - } - - if (window.Handle == windowToLinkTo.Handle) - { - continue; - } - - if (window.Iconic) - { - continue; - } - - // Windows without size - Size windowSize = window.WindowRectangle.Size; - if (windowSize.Width == 0 || windowSize.Height == 0) - { - continue; - } - - if (window.ProcessId == processIdSelectedWindow) - { - Log.InfoFormat("Found window {0} belonging to same process as the window {1}", window.Text, windowToLinkTo.Text); - return window; - } - } - - return null; - } - - /// - /// Helper method to "active" all windows that are not in the supplied list. - /// One should preferably call "GetVisibleWindows" for the oldWindows. - /// - /// List WindowDetails with old windows - public static void ActiveNewerWindows(IEnumerable oldWindows) - { - var oldWindowsList = new List(oldWindows); - foreach (var window in GetVisibleWindows()) - { - if (!oldWindowsList.Contains(window)) - { - window.ToForeground(); - } - } - } - - /// - /// Get the AppLauncher - /// - /// - public static WindowDetails GetAppLauncher() - { - // Only if Windows 8 (or higher) - if (AppVisibility == null) - { - return null; - } - - IntPtr appLauncher = User32.FindWindow(ApplauncherClass, null); - if (appLauncher != IntPtr.Zero) - { - return new WindowDetails(appLauncher); - } - - return null; - } - - /// - /// Return true if the metro-app-launcher is visible - /// - /// - public static bool IsAppLauncherVisible - { - get - { - if (AppVisibility != null) - { - return AppVisibility.IsLauncherVisible; - } - - return false; - } - } - - /// - /// Make a string representation of the window details - /// - /// string - public override string ToString() - { - var result = new StringBuilder(); - result.AppendLine($"Text: {Text}"); - result.AppendLine($"ClassName: {ClassName}"); - result.AppendLine($"ExtendedWindowStyle: {ExtendedWindowStyle}"); - result.AppendLine($"WindowStyle: {WindowStyle}"); - result.AppendLine($"Size: {WindowRectangle.Size}"); - result.AppendLine($"HasParent: {HasParent}"); - result.AppendLine($"IsWin10App: {IsWin10App}"); - result.AppendLine($"IsApp: {IsApp}"); - result.AppendLine($"Visible: {Visible}"); - result.AppendLine($"IsWindowVisible: {User32.IsWindowVisible(Handle)}"); - result.AppendLine($"IsCloaked: {IsCloaked}"); - result.AppendLine($"Iconic: {Iconic}"); - result.AppendLine($"IsBackgroundWin10App: {IsBackgroundWin10App}"); - if (HasChildren) - { - result.AppendLine($"Children classes: {string.Join(",", Children.Select(c => c.ClassName))}"); - } - - return result.ToString(); - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interop; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// Code for handling with "windows" + /// Main code is taken from vbAccelerator, location: + /// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp + /// but a LOT of changes/enhancements were made to adapt it for Greenshot. + /// + /// Provides details about a Window returned by the enumeration + /// + public class WindowDetails : IEquatable + { + 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[] + { + "Progman", "Button", "Dwm" + }); //"MS-SDIa" + + private static readonly ILog Log = LogManager.GetLogger(typeof(WindowDetails)); + private static readonly CoreConfiguration Conf = IniConfig.GetIniSection(); + private static readonly IList IgnoreHandles = new List(); + private static readonly IList ExcludeProcessesFromFreeze = new List(); + private static readonly IAppVisibility AppVisibility; + + static WindowDetails() + { + try + { + // Only try to instantiate when Windows 8 or later. + if (WindowsVersion.IsWindows8OrLater) + { + AppVisibility = COMWrapper.CreateInstance(); + } + } + catch (Exception ex) + { + Log.WarnFormat("Couldn't create instance of IAppVisibility: {0}", ex.Message); + } + } + + public static void AddProcessToExcludeFromFreeze(string processName) + { + if (!ExcludeProcessesFromFreeze.Contains(processName)) + { + ExcludeProcessesFromFreeze.Add(processName); + } + } + + internal static bool IsIgnoreHandle(IntPtr handle) + { + return IgnoreHandles.Contains(handle); + } + + private IList _childWindows; + 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" + /// + public bool IsWin10App => AppFrameWindowClass.Equals(ClassName); + + /// + /// Check if this window belongs to a background app + /// + 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 + /// is set to the Window handle, so two EnumWindowsItem + /// objects for the same Window will be equal. + /// + /// The Window Handle for this window + public override int GetHashCode() + { + return Handle.ToInt32(); + } + + public override bool Equals(object right) + { + return Equals(right as WindowDetails); + } + + /// + /// Compare two windows details + /// + /// + /// + public bool Equals(WindowDetails other) + { + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (GetType() != other.GetType()) + { + return false; + } + + return other.Handle == Handle; + } + + /// + /// Check if the window has children + /// + public bool HasChildren => (_childWindows != null) && (_childWindows.Count > 0); + + /// + /// Freeze information updates + /// + public void FreezeDetails() + { + _frozen = true; + } + + /// + /// Make the information update again. + /// + public void UnfreezeDetails() + { + _frozen = false; + } + + /// + /// Get the file path to the exe for the process which owns this window + /// + public string ProcessPath + { + get + { + if (Handle == IntPtr.Zero) + { + // not a valid window handle + return string.Empty; + } + + // Get the process id + User32.GetWindowThreadProcessId(Handle, out var processId); + return Kernel32.GetProcessPath(processId); + } + } + + + /// + /// Get the icon belonging to the process + /// + public Image DisplayIcon + { + get + { + try + { + using var appIcon = GetAppIcon(Handle); + if (appIcon != null) + { + return appIcon.ToBitmap(); + } + } + catch (Exception ex) + { + Log.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); + Log.Warn(ex); + } + + if (IsMetroApp) + { + // No method yet to get the metro icon + return null; + } + + try + { + return PluginUtils.GetCachedExeIcon(ProcessPath, 0); + } + catch (Exception ex) + { + Log.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message); + Log.Warn(ex); + } + + return null; + } + } + + /// + /// Get the icon for a hWnd + /// + /// + /// + private static Icon GetAppIcon(IntPtr hWnd) + { + IntPtr iconSmall = IntPtr.Zero; + IntPtr iconBig = new IntPtr(1); + IntPtr iconSmall2 = new IntPtr(2); + + IntPtr iconHandle; + if (Conf.UseLargeIcons) + { + iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconBig, IntPtr.Zero); + if (iconHandle == IntPtr.Zero) + { + iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICON); + } + } + else + { + iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconSmall2, IntPtr.Zero); + } + + if (iconHandle == IntPtr.Zero) + { + iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconSmall, IntPtr.Zero); + } + + if (iconHandle == IntPtr.Zero) + { + iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICONSM); + } + + if (iconHandle == IntPtr.Zero) + { + iconHandle = User32.SendMessage(hWnd, (int) WindowsMessages.WM_GETICON, iconBig, IntPtr.Zero); + } + + if (iconHandle == IntPtr.Zero) + { + iconHandle = User32.GetClassLongWrapper(hWnd, (int) ClassLongIndex.GCL_HICON); + } + + if (iconHandle == IntPtr.Zero) + { + return null; + } + + Icon icon = Icon.FromHandle(iconHandle); + + return icon; + } + + /// + /// Use this to make remove internal windows, like the mainform and the captureforms, invisible + /// + /// + public static void RegisterIgnoreHandle(IntPtr ignoreHandle) + { + IgnoreHandles.Add(ignoreHandle); + } + + /// + /// Use this to remove the with RegisterIgnoreHandle registered handle + /// + /// + public static void UnregisterIgnoreHandle(IntPtr ignoreHandle) + { + IgnoreHandles.Remove(ignoreHandle); + } + + public IList Children + { + get + { + if (_childWindows == null) + { + GetChildren(); + } + + return _childWindows; + } + } + + /// + /// Retrieve the child with matching classname + /// + public WindowDetails GetChild(string childClassname) + { + foreach (var child in Children) + { + if (childClassname.Equals(child.ClassName)) + { + return child; + } + } + + return null; + } + + public IntPtr ParentHandle + { + get + { + if (_parentHandle == IntPtr.Zero) + { + _parentHandle = User32.GetParent(Handle); + _parent = null; + } + + return _parentHandle; + } + set + { + if (_parentHandle != value) + { + _parentHandle = value; + _parent = null; + } + } + } + + /// + /// Get the parent of the current window + /// + /// WindowDetails of the parent, or null if none + public WindowDetails GetParent() + { + if (_parent == null) + { + if (_parentHandle == IntPtr.Zero) + { + _parentHandle = User32.GetParent(Handle); + } + + if (_parentHandle != IntPtr.Zero) + { + _parent = new WindowDetails(_parentHandle); + } + } + + return _parent; + } + + /// + /// Retrieve all the children, this only stores the children internally. + /// One should normally use the getter "Children" + /// + public IList GetChildren() + { + if (_childWindows == null) + { + return GetChildren(0); + } + + return _childWindows; + } + + /// + /// Retrieve all the children, this only stores the children internally, use the "Children" property for the value + /// + /// Specify how many levels we go in + public IList GetChildren(int levelsToGo) + { + if (_childWindows != null) + { + return _childWindows; + } + + _childWindows = new WindowsEnumerator().GetWindows(Handle, null).Items; + foreach (var childWindow in _childWindows) + { + if (levelsToGo > 0) + { + childWindow.GetChildren(levelsToGo - 1); + } + } + + return _childWindows; + } + + /// + /// Gets the window's handle + /// + public IntPtr Handle { get; } + + private string _text; + + /// + /// Gets the window's title (caption) + /// + public string Text + { + set => _text = value; + get + { + if (_text == null) + { + var title = new StringBuilder(260, 260); + User32.GetWindowText(Handle, title, title.Capacity); + _text = title.ToString(); + } + + return _text; + } + } + + private string _className; + + /// + /// Gets the window's class name. + /// + public string ClassName => _className ??= GetClassName(Handle); + + /// + /// Gets/Sets whether the window is iconic (minimized) or not. + /// + public bool Iconic + { + get + { + if (IsMetroApp) + { + return !Visible; + } + + return User32.IsIconic(Handle) || Location.X <= -32000; + } + set + { + if (value) + { + User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MINIMIZE, IntPtr.Zero); + } + else + { + User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_RESTORE, IntPtr.Zero); + } + } + } + + /// + /// Gets/Sets whether the window is maximized or not. + /// + public bool Maximised + { + get + { + if (IsApp) + { + if (Visible) + { + Rectangle windowRectangle = WindowRectangle; + foreach (var screen in Screen.AllScreens) + { + if (screen.Bounds.Contains(windowRectangle)) + { + if (windowRectangle.Equals(screen.Bounds)) + { + return true; + } + } + } + } + + return false; + } + + return User32.IsZoomed(Handle); + } + set + { + if (value) + { + User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MAXIMIZE, IntPtr.Zero); + } + else + { + User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_MINIMIZE, IntPtr.Zero); + } + } + } + + /// + /// Returns if this window is cloaked + /// + public bool IsCloaked + { + get => DWM.IsWindowCloaked(Handle); + } + + /// + /// Gets whether the window is visible. + /// + public bool Visible + { + get + { + // Tip from Raymond Chen https://devblogs.microsoft.com/oldnewthing/20200302-00/?p=103507 + if (IsCloaked) + { + return false; + } + + if (IsApp) + { + Rectangle windowRectangle = WindowRectangle; + foreach (Screen screen in Screen.AllScreens) + { + if (screen.Bounds.Contains(windowRectangle)) + { + if (windowRectangle.Equals(screen.Bounds)) + { + // Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes + // Although it might be the other App, this is not "very" important + RECT rect = new RECT(screen.Bounds); + IntPtr monitor = User32.MonitorFromRect(ref rect, User32.MONITOR_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 User32.IsWindowVisible(Handle); + } + } + + public bool HasParent + { + get + { + GetParent(); + return _parentHandle != IntPtr.Zero; + } + } + + public int ProcessId + { + get + { + User32.GetWindowThreadProcessId(Handle, out var processId); + return processId; + } + } + + public Process Process + { + get + { + try + { + User32.GetWindowThreadProcessId(Handle, out var processId); + return Process.GetProcessById(processId); + } + catch (Exception ex) + { + Log.Warn(ex); + } + + return null; + } + } + + private Rectangle _previousWindowRectangle = Rectangle.Empty; + private long _lastWindowRectangleRetrieveTime; + private const long CacheTime = TimeSpan.TicksPerSecond * 2; + + /// + /// Gets the bounding rectangle of the window + /// + public Rectangle WindowRectangle + { + get + { + // Try to return a cached value + long now = DateTime.Now.Ticks; + if (_previousWindowRectangle.IsEmpty || !_frozen) + { + if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime) + { + return _previousWindowRectangle; + } + + Rectangle windowRect = Rectangle.Empty; + if (DWM.IsDwmEnabled) + { + bool gotFrameBounds = GetExtendedFrameBounds(out windowRect); + if (IsApp) + { + // Pre-Cache for maximized call, this is only on Windows 8 apps (full screen) + if (gotFrameBounds) + { + _previousWindowRectangle = windowRect; + _lastWindowRectangleRetrieveTime = now; + } + } + + if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised) + { + // Somehow DWM doesn't calculate it corectly, 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.Inflate(Conf.Win10BorderCrop); + _previousWindowRectangle = windowRect; + _lastWindowRectangleRetrieveTime = now; + return windowRect; + } + } + + if (windowRect.IsEmpty) + { + if (!GetWindowRect(out windowRect)) + { + Win32Error error = Win32.GetLastErrorCode(); + Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); + } + } + + // Correction for maximized windows, only if it's not an app + if (!HasParent && !IsApp && Maximised) + { + // Only if the border size can be retrieved + if (GetBorderSize(out var size)) + { + windowRect = new Rectangle(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 Rectangle anymore + if (windowRect.IsEmpty) + { + return _previousWindowRectangle; + } + + _previousWindowRectangle = windowRect; + return windowRect; + } + + return _previousWindowRectangle; + } + } + + /// + /// Gets the location of the window relative to the screen. + /// + public Point Location + { + get + { + Rectangle tmpRectangle = WindowRectangle; + return new Point(tmpRectangle.Left, tmpRectangle.Top); + } + } + + /// + /// Gets the size of the window. + /// + public Size Size + { + get + { + Rectangle tmpRectangle = WindowRectangle; + return new Size(tmpRectangle.Right - tmpRectangle.Left, tmpRectangle.Bottom - tmpRectangle.Top); + } + } + + /// + /// Get the client rectangle, this is the part of the window inside the borders (drawable area) + /// + public Rectangle ClientRectangle + { + get + { + if (!GetClientRect(out var clientRect)) + { + Win32Error error = Win32.GetLastErrorCode(); + Log.WarnFormat("Couldn't retrieve the client rectangle for {0}, error: {1}", Text, Win32.GetMessage(error)); + } + + return clientRect; + } + } + + /// + /// Check if the supplied point lies in the window + /// + /// Point with the coordinates to check + /// true if the point lies within + public bool Contains(Point p) + { + return WindowRectangle.Contains(p); + } + + /// + /// Restores and Brings the window to the front, + /// assuming it is a visible application window. + /// + public void Restore() + { + if (Iconic) + { + User32.SendMessage(Handle, (int) WindowsMessages.WM_SYSCOMMAND, (IntPtr) User32.SC_RESTORE, IntPtr.Zero); + } + + User32.BringWindowToTop(Handle); + User32.SetForegroundWindow(Handle); + // Make sure windows has time to perform the action + // TODO: this is BAD practice! + while (Iconic) + { + Application.DoEvents(); + } + } + + /// + /// Get / Set the WindowStyle + /// + public WindowStyleFlags WindowStyle + { + get => (WindowStyleFlags) User32.GetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE); + set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_STYLE, new IntPtr((long) value)); + } + + /// + /// Get/Set the WindowPlacement + /// + public WindowPlacement WindowPlacement + { + get + { + var placement = WindowPlacement.Default; + User32.GetWindowPlacement(Handle, ref placement); + return placement; + } + set { User32.SetWindowPlacement(Handle, ref value); } + } + + /// + /// Get/Set the Extended WindowStyle + /// + public ExtendedWindowStyleFlags ExtendedWindowStyle + { + get => (ExtendedWindowStyleFlags) User32.GetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_EXSTYLE); + set => User32.SetWindowLongWrapper(Handle, (int) WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint) value)); + } + + /// + /// Capture Window with GDI+ + /// + /// The capture to fill + /// ICapture + public ICapture CaptureGdiWindow(ICapture capture) + { + Image capturedImage = PrintWindow(); + if (capturedImage != null) + { + capture.Image = capturedImage; + capture.Location = Location; + return capture; + } + + return null; + } + + /// + /// Capture DWM Window + /// + /// Capture to fill + /// Wanted WindowCaptureMode + /// True if auto mode is used + /// ICapture with the capture + public ICapture CaptureDwmWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) + { + IntPtr thumbnailHandle = IntPtr.Zero; + Form tempForm = null; + bool tempFormShown = false; + try + { + tempForm = new Form + { + ShowInTaskbar = false, + FormBorderStyle = FormBorderStyle.None, + TopMost = true + }; + + // Register the Thumbnail + DWM.DwmRegisterThumbnail(tempForm.Handle, Handle, out thumbnailHandle); + + // Get the original size + DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out var sourceSize); + + if (sourceSize.Width <= 0 || sourceSize.Height <= 0) + { + return null; + } + + // Calculate the location of the temp form + Rectangle windowRectangle = WindowRectangle; + Point formLocation = windowRectangle.Location; + Size borderSize = new Size(); + bool doesCaptureFit = false; + if (!Maximised) + { + // Assume using it's own location + formLocation = windowRectangle.Location; + // TODO: Use Rectangle.Union! + using Region workingArea = new Region(Screen.PrimaryScreen.Bounds); + // Find the screen where the window is and check if it fits + foreach (Screen screen in Screen.AllScreens) + { + if (!Equals(screen, Screen.PrimaryScreen)) + { + workingArea.Union(screen.Bounds); + } + } + + // If the formLocation is not inside the visible area + if (!workingArea.AreRectangleCornersVisisble(windowRectangle)) + { + // If none found we find the biggest screen + foreach (Screen screen in Screen.AllScreens) + { + Rectangle newWindowRectangle = new Rectangle(screen.WorkingArea.Location, windowRectangle.Size); + if (workingArea.AreRectangleCornersVisisble(newWindowRectangle)) + { + formLocation = screen.Bounds.Location; + doesCaptureFit = true; + break; + } + } + } + else + { + doesCaptureFit = true; + } + } + else if (!WindowsVersion.IsWindows8OrLater) + { + //GetClientRect(out windowRectangle); + GetBorderSize(out borderSize); + formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height); + } + + tempForm.Location = formLocation; + tempForm.Size = sourceSize.ToSize(); + + // Prepare rectangle to capture from the screen. + Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height); + if (Maximised) + { + // Correct capture size for maximized window by offsetting the X,Y with the border size + // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) + captureRectangle.Inflate(borderSize.Width, borderSize.Height); + } + else + { + // TODO: Also 8.x? + if (WindowsVersion.IsWindows10OrLater) + { + captureRectangle.Inflate(Conf.Win10BorderCrop); + } + + if (autoMode) + { + // check if the capture fits + if (!doesCaptureFit) + { + // 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)) + { + // we return null which causes the capturing code to try another method. + return null; + } + } + } + } + + // Prepare the displaying of the Thumbnail + DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES + { + Opacity = 255, + Visible = true, + Destination = new RECT(0, 0, sourceSize.Width, sourceSize.Height) + }; + DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); + tempForm.Show(); + tempFormShown = true; + + // Intersect with screen + captureRectangle.Intersect(capture.ScreenBounds); + + // Destination bitmap for the capture + Bitmap capturedBitmap = null; + bool frozen = false; + try + { + // Check if we make a transparent capture + if (windowCaptureMode == WindowCaptureMode.AeroTransparent) + { + frozen = FreezeWindow(); + // Use white, later black to capture transparent + tempForm.BackColor = Color.White; + // Make sure everything is visible + tempForm.Refresh(); + Application.DoEvents(); + + try + { + using Bitmap whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle); + // Apply a white color + 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 all changes are processed and visible + Application.DoEvents(); + using Bitmap blackBitmap = WindowCapture.CaptureRectangle(captureRectangle); + capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap); + } + catch (Exception e) + { + Log.Debug("Exception: ", e); + // Some problem occurred, cleanup and make a normal capture + if (capturedBitmap != null) + { + capturedBitmap.Dispose(); + capturedBitmap = null; + } + } + } + + // If no capture up till now, create a normal capture. + if (capturedBitmap == null) + { + // Remove transparency, this will break the capturing + if (!autoMode) + { + tempForm.BackColor = Color.FromArgb(255, Conf.DWMBackgroundColor.R, Conf.DWMBackgroundColor.G, Conf.DWMBackgroundColor.B); + } + else + { + Color colorizationColor = DWM.ColorizationColor; + // Modify by losing the transparency and increasing the intensity (as if the background color is white) + colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); + tempForm.BackColor = colorizationColor; + } + + // 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 all changes are processed and visible + Application.DoEvents(); + // Capture from the screen + capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle); + } + + if (capturedBitmap != null) + { + // Not needed for Windows 8 + if (!WindowsVersion.IsWindows8OrLater) + { + // Only if the Inivalue is set, not maximized and it's not a tool window. + if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) + { + // Remove corners + if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) + { + Log.Debug("Changing pixelformat to Alpha for the RemoveCorners"); + Bitmap tmpBitmap = ImageHelper.Clone(capturedBitmap, PixelFormat.Format32bppArgb); + capturedBitmap.Dispose(); + capturedBitmap = tmpBitmap; + } + + RemoveCorners(capturedBitmap); + } + } + } + } + finally + { + // Make sure to ALWAYS unfreeze!! + if (frozen) + { + UnfreezeWindow(); + } + } + + capture.Image = capturedBitmap; + // Make sure the capture location is the location of the window, not the copy + capture.Location = Location; + } + finally + { + if (thumbnailHandle != IntPtr.Zero) + { + // Unregister (cleanup), as we are finished we don't need the form or the thumbnail anymore + DWM.DwmUnregisterThumbnail(thumbnailHandle); + } + + if (tempForm != null) + { + if (tempFormShown) + { + tempForm.Close(); + } + + tempForm.Dispose(); + tempForm = null; + } + } + + return capture; + } + + /// + /// Helper method to remove the corners from a DMW capture + /// + /// The bitmap to remove the corners from. + private void RemoveCorners(Bitmap image) + { + using IFastBitmap fastBitmap = FastBitmap.Create(image); + for (int y = 0; y < Conf.WindowCornerCutShape.Count; y++) + { + for (int x = 0; x < Conf.WindowCornerCutShape[y]; x++) + { + fastBitmap.SetColorAt(x, y, Color.Transparent); + fastBitmap.SetColorAt(image.Width - 1 - x, y, Color.Transparent); + fastBitmap.SetColorAt(image.Width - 1 - x, image.Height - 1 - y, Color.Transparent); + fastBitmap.SetColorAt(x, image.Height - 1 - y, Color.Transparent); + } + } + } + + /// + /// Apply transparency by comparing a transparent capture with a black and white background + /// A "Math.min" makes sure there is no overflow, but this could cause the picture to have shifted colors. + /// The pictures should have been taken without differency, except for the colors. + /// + /// Bitmap with the black image + /// Bitmap with the black image + /// Bitmap with transparency + private Bitmap ApplyTransparency(Bitmap blackBitmap, Bitmap whiteBitmap) + { + using IFastBitmap targetBuffer = FastBitmap.CreateEmpty(blackBitmap.Size, PixelFormat.Format32bppArgb, Color.Transparent); + targetBuffer.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution); + using (IFastBitmap blackBuffer = FastBitmap.Create(blackBitmap)) + { + using IFastBitmap whiteBuffer = FastBitmap.Create(whiteBitmap); + for (int y = 0; y < blackBuffer.Height; y++) + { + for (int x = 0; x < blackBuffer.Width; x++) + { + Color c0 = blackBuffer.GetColorAt(x, y); + Color c1 = whiteBuffer.GetColorAt(x, y); + // Calculate alpha as double in range 0-1 + int alpha = c0.R - c1.R + 255; + if (alpha == 255) + { + // Alpha == 255 means no change! + targetBuffer.SetColorAt(x, y, c0); + } + else if (alpha == 0) + { + // Complete transparency, use transparent pixel + targetBuffer.SetColorAt(x, y, Color.Transparent); + } + else + { + // Calculate original color + byte originalAlpha = (byte) Math.Min(255, alpha); + var alphaFactor = alpha / 255d; + //LOG.DebugFormat("Alpha {0} & c0 {1} & c1 {2}", alpha, c0, c1); + byte originalRed = (byte) Math.Min(255, c0.R / alphaFactor); + byte originalGreen = (byte) Math.Min(255, c0.G / alphaFactor); + byte originalBlue = (byte) Math.Min(255, c0.B / alphaFactor); + Color originalColor = Color.FromArgb(originalAlpha, originalRed, originalGreen, originalBlue); + //Color originalColor = Color.FromArgb(originalAlpha, originalRed, c0.G, c0.B); + targetBuffer.SetColorAt(x, y, originalColor); + } + } + } + } + + return targetBuffer.UnlockAndReturnBitmap(); + } + + /// + /// Helper method to get the window size for DWM Windows + /// + /// out Rectangle + /// bool true if it worked + private bool GetExtendedFrameBounds(out Rectangle rectangle) + { + int result = DWM.DwmGetWindowAttribute(Handle, DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out RECT rect, Marshal.SizeOf(typeof(RECT))); + if (result >= 0) + { + rectangle = rect.ToRectangle(); + return true; + } + + rectangle = Rectangle.Empty; + return false; + } + + /// + /// Helper method to get the window size for GDI Windows + /// + /// out Rectangle + /// bool true if it worked + private bool GetClientRect(out Rectangle rectangle) + { + var windowInfo = new WindowInfo(); + // Get the Window Info for this window + bool result = User32.GetWindowInfo(Handle, ref windowInfo); + rectangle = result ? windowInfo.rcClient.ToRectangle() : Rectangle.Empty; + return result; + } + + /// + /// Helper method to get the window size for GDI Windows + /// + /// out Rectangle + /// bool true if it worked + private bool GetWindowRect(out Rectangle rectangle) + { + var windowInfo = new WindowInfo(); + // Get the Window Info for this window + bool result = User32.GetWindowInfo(Handle, ref windowInfo); + rectangle = result ? windowInfo.rcWindow.ToRectangle() : Rectangle.Empty; + return result; + } + + /// + /// Helper method to get the Border size for GDI Windows + /// + /// out Size + /// bool true if it worked + private bool GetBorderSize(out Size size) + { + var windowInfo = new WindowInfo(); + // Get the Window Info for this window + bool result = User32.GetWindowInfo(Handle, ref windowInfo); + size = result ? new Size((int) windowInfo.cxWindowBorders, (int) windowInfo.cyWindowBorders) : Size.Empty; + return result; + } + + /// + /// Set the window as foreground window + /// + /// hWnd of the window to bring to the foreground + public static void ToForeground(IntPtr hWnd) + { + var foregroundWindow = User32.GetForegroundWindow(); + if (hWnd == foregroundWindow) + { + return; + } + + var window = new WindowDetails(hWnd); + // Nothing we can do if it's not visible! + if (!window.Visible) + { + return; + } + + var threadId1 = User32.GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero); + var threadId2 = User32.GetWindowThreadProcessId(hWnd, IntPtr.Zero); + + // Show window in foreground. + if (threadId1 != threadId2) + { + User32.AttachThreadInput(threadId1, threadId2, 1); + User32.SetForegroundWindow(hWnd); + User32.AttachThreadInput(threadId1, threadId2, 0); + } + else + { + User32.SetForegroundWindow(hWnd); + } + + User32.BringWindowToTop(hWnd); + + if (window.Iconic) + { + window.Iconic = false; + } + } + + /// + /// Set the window as foreground window + /// + public void ToForeground() + { + ToForeground(Handle); + } + + /// + /// Get the region for a window + /// + private Region GetRegion() + { + using (SafeRegionHandle region = GDI32.CreateRectRgn(0, 0, 0, 0)) + { + if (!region.IsInvalid) + { + RegionResult result = User32.GetWindowRgn(Handle, region); + if (result != RegionResult.REGION_ERROR && result != RegionResult.REGION_NULLREGION) + { + return Region.FromHrgn(region.DangerousGetHandle()); + } + } + } + + return null; + } + + private bool CanFreezeOrUnfreeze(string titleOrProcessname) + { + if (string.IsNullOrEmpty(titleOrProcessname)) + { + return false; + } + + if (titleOrProcessname.ToLower().Contains("greenshot")) + { + return false; + } + + foreach (string excludeProcess in ExcludeProcessesFromFreeze) + { + if (titleOrProcessname.ToLower().Contains(excludeProcess)) + { + return false; + } + } + + return true; + } + + /// + /// Freezes the process belonging to the window + /// Warning: Use only if no other way!! + /// + private bool FreezeWindow() + { + bool frozen = false; + using (Process proc = Process.GetProcessById(ProcessId)) + { + string processName = proc.ProcessName; + if (!CanFreezeOrUnfreeze(processName)) + { + Log.DebugFormat("Not freezing {0}", processName); + return false; + } + + if (!CanFreezeOrUnfreeze(Text)) + { + Log.DebugFormat("Not freezing {0}", processName); + return false; + } + + Log.DebugFormat("Freezing process: {0}", processName); + + + foreach (ProcessThread pT in proc.Threads) + { + IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint) pT.Id); + + if (pOpenThread == IntPtr.Zero) + { + break; + } + + frozen = true; + Kernel32.SuspendThread(pOpenThread); + pT.Dispose(); + } + } + + return frozen; + } + + /// + /// Unfreeze the process belonging to the window + /// + public void UnfreezeWindow() + { + using Process proc = Process.GetProcessById(ProcessId); + string processName = proc.ProcessName; + if (!CanFreezeOrUnfreeze(processName)) + { + Log.DebugFormat("Not unfreezing {0}", processName); + return; + } + + if (!CanFreezeOrUnfreeze(Text)) + { + Log.DebugFormat("Not unfreezing {0}", processName); + return; + } + + Log.DebugFormat("Unfreezing process: {0}", processName); + + foreach (ProcessThread pT in proc.Threads) + { + IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint) pT.Id); + + if (pOpenThread == IntPtr.Zero) + { + break; + } + + Kernel32.ResumeThread(pOpenThread); + } + } + + /// + /// Return an Image representing the Window! + /// As GDI+ draws it, it will be without Aero borders! + /// + public Image PrintWindow() + { + Rectangle windowRect = WindowRectangle; + // Start the capture + Exception exceptionOccured = null; + Image returnImage; + using (Region region = GetRegion()) + { + PixelFormat pixelFormat = PixelFormat.Format24bppRgb; + // Only use 32 bpp ARGB when the window has a region + if (region != null) + { + pixelFormat = PixelFormat.Format32bppArgb; + } + + returnImage = new Bitmap(windowRect.Width, windowRect.Height, pixelFormat); + using Graphics graphics = Graphics.FromImage(returnImage); + using (SafeDeviceContextHandle graphicsDc = graphics.GetSafeDeviceContext()) + { + bool printSucceeded = User32.PrintWindow(Handle, graphicsDc.DangerousGetHandle(), 0x0); + if (!printSucceeded) + { + // something went wrong, most likely a "0x80004005" (Acess Denied) when using UAC + exceptionOccured = User32.CreateWin32Exception("PrintWindow"); + } + } + + // Apply the region "transparency" + if (region != null && !region.IsEmpty(graphics)) + { + graphics.ExcludeClip(region); + graphics.Clear(Color.Transparent); + } + + graphics.Flush(); + } + + // Return null if error + if (exceptionOccured != null) + { + Log.ErrorFormat("Error calling print window: {0}", exceptionOccured.Message); + returnImage.Dispose(); + return null; + } + + if (!HasParent && Maximised) + { + Log.Debug("Correcting for maximalization"); + GetBorderSize(out var borderSize); + Rectangle borderRectangle = new Rectangle(borderSize.Width, borderSize.Height, windowRect.Width - (2 * borderSize.Width), + windowRect.Height - (2 * borderSize.Height)); + ImageHelper.Crop(ref returnImage, ref borderRectangle); + } + + return returnImage; + } + + /// + /// Constructs a new instance of this class for + /// the specified Window Handle. + /// + /// The Window Handle + public WindowDetails(IntPtr hWnd) + { + Handle = hWnd; + } + + /// + /// Gets an instance of the current active foreground window + /// + /// WindowDetails of the current window + public static WindowDetails GetActiveWindow() + { + IntPtr hWnd = User32.GetForegroundWindow(); + if (hWnd != IntPtr.Zero) + { + if (IgnoreHandles.Contains(hWnd)) + { + return GetDesktopWindow(); + } + + WindowDetails activeWindow = new WindowDetails(hWnd); + // Invisible Windows should not be active + if (!activeWindow.Visible) + { + return GetDesktopWindow(); + } + + return activeWindow; + } + + return null; + } + + /// + /// Gets the Desktop window + /// + /// WindowDetails for the desktop window + public static WindowDetails GetDesktopWindow() + { + return new WindowDetails(User32.GetDesktopWindow()); + } + + /// + /// Get all the top level windows + /// + /// List of WindowDetails with all the top level windows + public static IList GetAllWindows() + { + return GetAllWindows(null); + } + + /// + /// Get all the top level windows, with matching classname + /// + /// List WindowDetails with all the top level windows + public static IList GetAllWindows(string classname) + { + return new WindowsEnumerator().GetWindows(IntPtr.Zero, classname).Items; + } + + /// + /// Recursive "find children which" + /// + /// point to check for + /// + public WindowDetails FindChildUnderPoint(Point point) + { + if (!Contains(point)) + { + return null; + } + + var rect = WindowRectangle; + // If the mouse it at the edge, take the whole window + if (rect.X == point.X || rect.Y == point.Y || rect.Right == point.X || rect.Bottom == point.Y) + { + return this; + } + + // Look into the child windows + foreach (var childWindow in Children) + { + if (childWindow.Contains(point)) + { + return childWindow.FindChildUnderPoint(point); + } + } + + return this; + } + + /// + /// Retrieves the classname for a hWnd + /// + /// IntPtr with the windows handle + /// String with ClassName + public static string GetClassName(IntPtr hWnd) + { + var classNameBuilder = new StringBuilder(260, 260); + User32.GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity); + return classNameBuilder.ToString(); + } + + /// + /// Helper method to decide if a top level window is visible + /// + /// + /// + /// + private static bool IsVisible(WindowDetails window, Rectangle screenBounds) + { + // Ignore invisible + if (!window.Visible) + { + return false; + } + + // Ignore minimized + if (window.Iconic) + { + return false; + } + + if (IgnoreClasses.Contains(window.ClassName)) + { + return false; + } + + // On windows which are visible on the screen + var windowRect = window.WindowRectangle; + windowRect.Intersect(screenBounds); + if (windowRect.IsEmpty) + { + return false; + } + + // 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) + { + return false; + } + + return true; + } + + /// + /// Get all the visible top level windows + /// + /// List WindowDetails with all the visible top level windows + public static IEnumerable GetVisibleWindows() + { + Rectangle screenBounds = WindowCapture.GetScreenBounds(); + foreach (var window in GetAppWindows()) + { + if (IsVisible(window, screenBounds)) + { + yield return window; + } + } + + foreach (var window in GetAllWindows()) + { + if (IsVisible(window, screenBounds)) + { + yield return window; + } + } + } + + /// + /// 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 = User32.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 = User32.FindWindow(GutterClass, null); + if (gutterHandle != IntPtr.Zero) + { + yield return new WindowDetails(gutterHandle); + } + } + + nextHandle = User32.FindWindowEx(IntPtr.Zero, nextHandle, AppWindowClass, null); + } + } + + /// + /// Check if the window is a top level + /// + /// WindowDetails + /// bool + private static bool IsTopLevel(WindowDetails window) + { + if (window.IsCloaked) + { + return false; + } + + // Windows without size + if (window.WindowRectangle.Size.Width * window.WindowRectangle.Size.Height == 0) + { + return false; + } + + if (window.HasParent) + { + return false; + } + + var exWindowStyle = window.ExtendedWindowStyle; + if ((exWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) != 0) + { + return false; + } + + // Skip everything which is not rendered "normally", trying to fix BUG-2017 + if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) + { + return false; + } + + // Skip preview windows, like the one from Firefox + if ((window.WindowStyle & WindowStyleFlags.WS_VISIBLE) == 0) + { + return false; + } + + // Ignore windows without title + if (window.Text.Length == 0) + { + return false; + } + + if (IgnoreClasses.Contains(window.ClassName)) + { + return false; + } + + if (!(window.Visible || window.Iconic)) + { + return false; + } + + return !window.IsBackgroundWin10App; + } + + /// + /// Get all the top level windows + /// + /// 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)) + { + yield return possibleTopLevel; + } + } + } + + /// + /// Find a window belonging to the same process as the supplied window. + /// + /// + /// + public static WindowDetails GetLinkedWindow(WindowDetails windowToLinkTo) + { + int processIdSelectedWindow = windowToLinkTo.ProcessId; + foreach (var window in GetAllWindows()) + { + // Ignore windows without title + if (window.Text.Length == 0) + { + continue; + } + + // Ignore invisible + if (!window.Visible) + { + continue; + } + + if (window.Handle == windowToLinkTo.Handle) + { + continue; + } + + if (window.Iconic) + { + continue; + } + + // Windows without size + Size windowSize = window.WindowRectangle.Size; + if (windowSize.Width == 0 || windowSize.Height == 0) + { + continue; + } + + if (window.ProcessId == processIdSelectedWindow) + { + Log.InfoFormat("Found window {0} belonging to same process as the window {1}", window.Text, windowToLinkTo.Text); + return window; + } + } + + return null; + } + + /// + /// Helper method to "active" all windows that are not in the supplied list. + /// One should preferably call "GetVisibleWindows" for the oldWindows. + /// + /// List WindowDetails with old windows + public static void ActiveNewerWindows(IEnumerable oldWindows) + { + var oldWindowsList = new List(oldWindows); + foreach (var window in GetVisibleWindows()) + { + if (!oldWindowsList.Contains(window)) + { + window.ToForeground(); + } + } + } + + /// + /// Get the AppLauncher + /// + /// + public static WindowDetails GetAppLauncher() + { + // Only if Windows 8 (or higher) + if (AppVisibility == null) + { + return null; + } + + IntPtr appLauncher = User32.FindWindow(ApplauncherClass, null); + if (appLauncher != IntPtr.Zero) + { + return new WindowDetails(appLauncher); + } + + return null; + } + + /// + /// Return true if the metro-app-launcher is visible + /// + /// + public static bool IsAppLauncherVisible + { + get + { + if (AppVisibility != null) + { + return AppVisibility.IsLauncherVisible; + } + + return false; + } + } + + /// + /// Make a string representation of the window details + /// + /// string + public override string ToString() + { + var result = new StringBuilder(); + result.AppendLine($"Text: {Text}"); + result.AppendLine($"ClassName: {ClassName}"); + result.AppendLine($"ExtendedWindowStyle: {ExtendedWindowStyle}"); + result.AppendLine($"WindowStyle: {WindowStyle}"); + result.AppendLine($"Size: {WindowRectangle.Size}"); + result.AppendLine($"HasParent: {HasParent}"); + result.AppendLine($"IsWin10App: {IsWin10App}"); + result.AppendLine($"IsApp: {IsApp}"); + result.AppendLine($"Visible: {Visible}"); + result.AppendLine($"IsWindowVisible: {User32.IsWindowVisible(Handle)}"); + result.AppendLine($"IsCloaked: {IsCloaked}"); + result.AppendLine($"Iconic: {Iconic}"); + result.AppendLine($"IsBackgroundWin10App: {IsBackgroundWin10App}"); + if (HasChildren) + { + result.AppendLine($"Children classes: {string.Join(",", Children.Select(c => c.ClassName))}"); + } + + return result.ToString(); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/WindowsEnumerator.cs b/src/Greenshot.Base/Core/WindowsEnumerator.cs similarity index 95% rename from src/GreenshotPlugin/Core/WindowsEnumerator.cs rename to src/Greenshot.Base/Core/WindowsEnumerator.cs index 09eece85f..7278a3131 100644 --- a/src/GreenshotPlugin/Core/WindowsEnumerator.cs +++ b/src/Greenshot.Base/Core/WindowsEnumerator.cs @@ -1,108 +1,108 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using GreenshotPlugin.UnmanagedHelpers; -using System; -using System.Collections.Generic; -using System.Text; - -namespace GreenshotPlugin.Core -{ - /// - /// EnumWindows wrapper for .NET - /// - public class WindowsEnumerator - { - /// - /// Returns the collection of windows returned by GetWindows - /// - public IList Items { get; private set; } - - /// - /// Gets all child windows of the specified window - /// - /// Window Handle to get children for - /// Window Classname to copy, use null to copy all - public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname) - { - Items = new List(); - User32.EnumChildWindows(hWndParent, WindowEnum, IntPtr.Zero); - - bool hasParent = !IntPtr.Zero.Equals(hWndParent); - string parentText = null; - if (hasParent) - { - var title = new StringBuilder(260, 260); - User32.GetWindowText(hWndParent, title, title.Capacity); - parentText = title.ToString(); - } - - var windows = new List(); - foreach (var window in Items) - { - if (hasParent) - { - window.Text = parentText; - window.ParentHandle = hWndParent; - } - - if (classname == null || window.ClassName.Equals(classname)) - { - windows.Add(window); - } - } - - Items = windows; - return this; - } - - /// - /// The enum Windows callback. - /// - /// Window Handle - /// Application defined value - /// 1 to continue enumeration, 0 to stop - private int WindowEnum(IntPtr hWnd, int lParam) - { - return OnWindowEnum(hWnd) ? 1 : 0; - } - - /// - /// Called whenever a new window is about to be added - /// by the Window enumeration called from GetWindows. - /// If overriding this function, return true to continue - /// enumeration or false to stop. If you do not call - /// the base implementation the Items collection will - /// be empty. - /// - /// Window handle to add - /// True to continue enumeration, False to stop - private bool OnWindowEnum(IntPtr hWnd) - { - if (!WindowDetails.IsIgnoreHandle(hWnd)) - { - Items.Add(new WindowDetails(hWnd)); - } - - return true; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Text; +using Greenshot.Base.UnmanagedHelpers; + +namespace Greenshot.Base.Core +{ + /// + /// EnumWindows wrapper for .NET + /// + public class WindowsEnumerator + { + /// + /// Returns the collection of windows returned by GetWindows + /// + public IList Items { get; private set; } + + /// + /// Gets all child windows of the specified window + /// + /// Window Handle to get children for + /// Window Classname to copy, use null to copy all + public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname) + { + Items = new List(); + User32.EnumChildWindows(hWndParent, WindowEnum, IntPtr.Zero); + + bool hasParent = !IntPtr.Zero.Equals(hWndParent); + string parentText = null; + if (hasParent) + { + var title = new StringBuilder(260, 260); + User32.GetWindowText(hWndParent, title, title.Capacity); + parentText = title.ToString(); + } + + var windows = new List(); + foreach (var window in Items) + { + if (hasParent) + { + window.Text = parentText; + window.ParentHandle = hWndParent; + } + + if (classname == null || window.ClassName.Equals(classname)) + { + windows.Add(window); + } + } + + Items = windows; + return this; + } + + /// + /// The enum Windows callback. + /// + /// Window Handle + /// Application defined value + /// 1 to continue enumeration, 0 to stop + private int WindowEnum(IntPtr hWnd, int lParam) + { + return OnWindowEnum(hWnd) ? 1 : 0; + } + + /// + /// Called whenever a new window is about to be added + /// by the Window enumeration called from GetWindows. + /// If overriding this function, return true to continue + /// enumeration or false to stop. If you do not call + /// the base implementation the Items collection will + /// be empty. + /// + /// Window handle to add + /// True to continue enumeration, False to stop + private bool OnWindowEnum(IntPtr hWnd) + { + if (!WindowDetails.IsIgnoreHandle(hWnd)) + { + Items.Add(new WindowDetails(hWnd)); + } + + return true; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Core/WindowsVersion.cs b/src/Greenshot.Base/Core/WindowsVersion.cs similarity index 98% rename from src/GreenshotPlugin/Core/WindowsVersion.cs rename to src/Greenshot.Base/Core/WindowsVersion.cs index 703fcd206..bf3af14ce 100644 --- a/src/GreenshotPlugin/Core/WindowsVersion.cs +++ b/src/Greenshot.Base/Core/WindowsVersion.cs @@ -3,7 +3,7 @@ using System; -namespace GreenshotPlugin.Core +namespace Greenshot.Base.Core { /// /// Extension methods to test the windows version diff --git a/src/GreenshotPlugin/Core/WmInputLangChangeRequestFilter.cs b/src/Greenshot.Base/Core/WmInputLangChangeRequestFilter.cs similarity index 94% rename from src/GreenshotPlugin/Core/WmInputLangChangeRequestFilter.cs rename to src/Greenshot.Base/Core/WmInputLangChangeRequestFilter.cs index fba055f7f..3d59bcb28 100644 --- a/src/GreenshotPlugin/Core/WmInputLangChangeRequestFilter.cs +++ b/src/Greenshot.Base/Core/WmInputLangChangeRequestFilter.cs @@ -1,66 +1,66 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Windows.Forms; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using log4net; - -namespace GreenshotPlugin.Core -{ - /// - /// This IMessageFilter filters out all WM_INPUTLANGCHANGEREQUEST messages which go to a handle which is >32 bits. - /// The need for this is documented here: http://stackoverflow.com/a/32021586 - /// - public class WmInputLangChangeRequestFilter : IMessageFilter - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(WmInputLangChangeRequestFilter)); - - /// - /// This will do some filtering - /// - /// Message - /// true if the message should be filtered - public bool PreFilterMessage(ref Message m) - { - return PreFilterMessageExternal(ref m); - } - - /// - /// Also used in the MainForm WndProc - /// - /// Message - /// true if the message should be filtered - public static bool PreFilterMessageExternal(ref Message m) - { - WindowsMessages message = (WindowsMessages) m.Msg; - if (message == WindowsMessages.WM_INPUTLANGCHANGEREQUEST || message == WindowsMessages.WM_INPUTLANGCHANGE) - { - LOG.WarnFormat("Filtering: {0}, {1:X} - {2:X} - {3:X}", message, m.LParam.ToInt64(), m.WParam.ToInt64(), m.HWnd.ToInt64()); - // For now we always return true - return true; - // But it could look something like this: - //return (m.LParam.ToInt64() | 0x7FFFFFFF) != 0; - } - - return false; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Windows.Forms; +using Greenshot.Base.UnmanagedHelpers.Enums; +using log4net; + +namespace Greenshot.Base.Core +{ + /// + /// This IMessageFilter filters out all WM_INPUTLANGCHANGEREQUEST messages which go to a handle which is >32 bits. + /// The need for this is documented here: http://stackoverflow.com/a/32021586 + /// + public class WmInputLangChangeRequestFilter : IMessageFilter + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(WmInputLangChangeRequestFilter)); + + /// + /// This will do some filtering + /// + /// Message + /// true if the message should be filtered + public bool PreFilterMessage(ref Message m) + { + return PreFilterMessageExternal(ref m); + } + + /// + /// Also used in the MainForm WndProc + /// + /// Message + /// true if the message should be filtered + public static bool PreFilterMessageExternal(ref Message m) + { + WindowsMessages message = (WindowsMessages) m.Msg; + if (message == WindowsMessages.WM_INPUTLANGCHANGEREQUEST || message == WindowsMessages.WM_INPUTLANGCHANGE) + { + LOG.WarnFormat("Filtering: {0}, {1:X} - {2:X} - {3:X}", message, m.LParam.ToInt64(), m.WParam.ToInt64(), m.HWnd.ToInt64()); + // For now we always return true + return true; + // But it could look something like this: + //return (m.LParam.ToInt64() | 0x7FFFFFFF) != 0; + } + + return false; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/AdjustEffect.cs b/src/Greenshot.Base/Effects/AdjustEffect.cs similarity index 93% rename from src/GreenshotPlugin/Effects/AdjustEffect.cs rename to src/Greenshot.Base/Effects/AdjustEffect.cs index f2f472805..8445c09a8 100644 --- a/src/GreenshotPlugin/Effects/AdjustEffect.cs +++ b/src/Greenshot.Base/Effects/AdjustEffect.cs @@ -1,54 +1,54 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// AdjustEffect - /// - public class AdjustEffect : IEffect - { - public AdjustEffect() - { - Reset(); - } - - public float Contrast { get; set; } - public float Brightness { get; set; } - public float Gamma { get; set; } - - public void Reset() - { - Contrast = 1f; - Brightness = 1f; - Gamma = 1f; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// AdjustEffect + /// + public class AdjustEffect : IEffect + { + public AdjustEffect() + { + Reset(); + } + + public float Contrast { get; set; } + public float Brightness { get; set; } + public float Gamma { get; set; } + + public void Reset() + { + Contrast = 1f; + Brightness = 1f; + Gamma = 1f; + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/BorderEffect.cs b/src/Greenshot.Base/Effects/BorderEffect.cs similarity index 93% rename from src/GreenshotPlugin/Effects/BorderEffect.cs rename to src/Greenshot.Base/Effects/BorderEffect.cs index 650f63fe5..b297dcad8 100644 --- a/src/GreenshotPlugin/Effects/BorderEffect.cs +++ b/src/Greenshot.Base/Effects/BorderEffect.cs @@ -1,52 +1,52 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// BorderEffect - /// - public class BorderEffect : IEffect - { - public BorderEffect() - { - Reset(); - } - - public Color Color { get; set; } - public int Width { get; set; } - - public void Reset() - { - Width = 2; - Color = Color.Black; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, matrix); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// BorderEffect + /// + public class BorderEffect : IEffect + { + public BorderEffect() + { + Reset(); + } + + public Color Color { get; set; } + public int Width { get; set; } + + public void Reset() + { + Width = 2; + Color = Color.Black; + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, matrix); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/DropShadowEffect.cs b/src/Greenshot.Base/Effects/DropShadowEffect.cs similarity index 93% rename from src/GreenshotPlugin/Effects/DropShadowEffect.cs rename to src/Greenshot.Base/Effects/DropShadowEffect.cs index dd262aa07..2ca91aabf 100644 --- a/src/GreenshotPlugin/Effects/DropShadowEffect.cs +++ b/src/Greenshot.Base/Effects/DropShadowEffect.cs @@ -1,59 +1,59 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// DropShadowEffect - /// - [TypeConverter(typeof(EffectConverter))] - public class DropShadowEffect : IEffect - { - public DropShadowEffect() - { - Reset(); - } - - public float Darkness { get; set; } - - public int ShadowSize { get; set; } - - public Point ShadowOffset { get; set; } - - public virtual void Reset() - { - Darkness = 0.6f; - ShadowSize = 7; - ShadowOffset = new Point(-1, -1); - } - - public virtual Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// DropShadowEffect + /// + [TypeConverter(typeof(EffectConverter))] + public class DropShadowEffect : IEffect + { + public DropShadowEffect() + { + Reset(); + } + + public float Darkness { get; set; } + + public int ShadowSize { get; set; } + + public Point ShadowOffset { get; set; } + + public virtual void Reset() + { + Darkness = 0.6f; + ShadowSize = 7; + ShadowOffset = new Point(-1, -1); + } + + public virtual Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/GrayscaleEffect.cs b/src/Greenshot.Base/Effects/GrayscaleEffect.cs similarity index 92% rename from src/GreenshotPlugin/Effects/GrayscaleEffect.cs rename to src/Greenshot.Base/Effects/GrayscaleEffect.cs index 11e0f14a9..b557dbd7d 100644 --- a/src/GreenshotPlugin/Effects/GrayscaleEffect.cs +++ b/src/Greenshot.Base/Effects/GrayscaleEffect.cs @@ -1,43 +1,43 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// GrayscaleEffect - /// - public class GrayscaleEffect : IEffect - { - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateGrayscale(sourceImage); - } - - public void Reset() - { - // No settings to reset - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// GrayscaleEffect + /// + public class GrayscaleEffect : IEffect + { + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.CreateGrayscale(sourceImage); + } + + public void Reset() + { + // No settings to reset + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/IEffect.cs b/src/Greenshot.Base/Effects/IEffect.cs similarity index 95% rename from src/GreenshotPlugin/Effects/IEffect.cs rename to src/Greenshot.Base/Effects/IEffect.cs index 26c2d1240..e0a8fb6a0 100644 --- a/src/GreenshotPlugin/Effects/IEffect.cs +++ b/src/Greenshot.Base/Effects/IEffect.cs @@ -1,46 +1,46 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace GreenshotPlugin.Effects -{ - /// - /// Interface to describe an effect - /// - public interface IEffect - { - /// - /// Apply this IEffect to the supplied sourceImage. - /// In the process of applying the supplied matrix will be modified to represent the changes. - /// - /// Image to apply the effect to - /// Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas - /// new image with applied effect - Image Apply(Image sourceImage, Matrix matrix); - - /// - /// Reset all values to their defaults - /// - void Reset(); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace Greenshot.Base.Effects +{ + /// + /// Interface to describe an effect + /// + public interface IEffect + { + /// + /// Apply this IEffect to the supplied sourceImage. + /// In the process of applying the supplied matrix will be modified to represent the changes. + /// + /// Image to apply the effect to + /// Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas + /// new image with applied effect + Image Apply(Image sourceImage, Matrix matrix); + + /// + /// Reset all values to their defaults + /// + void Reset(); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/InvertEffect.cs b/src/Greenshot.Base/Effects/InvertEffect.cs similarity index 92% rename from src/GreenshotPlugin/Effects/InvertEffect.cs rename to src/Greenshot.Base/Effects/InvertEffect.cs index fc5d09178..4d5ce8dc7 100644 --- a/src/GreenshotPlugin/Effects/InvertEffect.cs +++ b/src/Greenshot.Base/Effects/InvertEffect.cs @@ -1,43 +1,43 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// InvertEffect - /// - public class InvertEffect : IEffect - { - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateNegative(sourceImage); - } - - public void Reset() - { - // No settings to reset - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// InvertEffect + /// + public class InvertEffect : IEffect + { + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.CreateNegative(sourceImage); + } + + public void Reset() + { + // No settings to reset + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/MonochromeEffect.cs b/src/Greenshot.Base/Effects/MonochromeEffect.cs similarity index 93% rename from src/GreenshotPlugin/Effects/MonochromeEffect.cs rename to src/Greenshot.Base/Effects/MonochromeEffect.cs index 7d3bcec87..5a9be096b 100644 --- a/src/GreenshotPlugin/Effects/MonochromeEffect.cs +++ b/src/Greenshot.Base/Effects/MonochromeEffect.cs @@ -1,51 +1,51 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// MonochromeEffect - /// - public class MonochromeEffect : IEffect - { - private readonly byte _threshold; - - /// Threshold for monochrome filter (0 - 255), lower value means less black - public MonochromeEffect(byte threshold) - { - _threshold = threshold; - } - - public void Reset() - { - // TODO: Modify the threshold to have a default, which is reset here - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.CreateMonochrome(sourceImage, _threshold); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// MonochromeEffect + /// + public class MonochromeEffect : IEffect + { + private readonly byte _threshold; + + /// Threshold for monochrome filter (0 - 255), lower value means less black + public MonochromeEffect(byte threshold) + { + _threshold = threshold; + } + + public void Reset() + { + // TODO: Modify the threshold to have a default, which is reset here + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.CreateMonochrome(sourceImage, _threshold); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/ReduceColorsEffect.cs b/src/Greenshot.Base/Effects/ReduceColorsEffect.cs similarity index 94% rename from src/GreenshotPlugin/Effects/ReduceColorsEffect.cs rename to src/Greenshot.Base/Effects/ReduceColorsEffect.cs index be8aad54d..cd119544f 100644 --- a/src/GreenshotPlugin/Effects/ReduceColorsEffect.cs +++ b/src/Greenshot.Base/Effects/ReduceColorsEffect.cs @@ -1,70 +1,70 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; -using log4net; - -namespace GreenshotPlugin.Effects -{ - /// - /// ReduceColorsEffect - /// - public class ReduceColorsEffect : IEffect - { - private static readonly ILog Log = LogManager.GetLogger(typeof(ReduceColorsEffect)); - - public ReduceColorsEffect() - { - Reset(); - } - - public int Colors { get; set; } - - public void Reset() - { - Colors = 256; - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - using (WuQuantizer quantizer = new WuQuantizer((Bitmap) sourceImage)) - { - int colorCount = quantizer.GetColorCount(); - if (colorCount > Colors) - { - try - { - return quantizer.GetQuantizedImage(Colors); - } - catch (Exception e) - { - Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); - } - } - } - - return null; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; +using log4net; + +namespace Greenshot.Base.Effects +{ + /// + /// ReduceColorsEffect + /// + public class ReduceColorsEffect : IEffect + { + private static readonly ILog Log = LogManager.GetLogger(typeof(ReduceColorsEffect)); + + public ReduceColorsEffect() + { + Reset(); + } + + public int Colors { get; set; } + + public void Reset() + { + Colors = 256; + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + using (WuQuantizer quantizer = new WuQuantizer((Bitmap) sourceImage)) + { + int colorCount = quantizer.GetColorCount(); + if (colorCount > Colors) + { + try + { + return quantizer.GetQuantizedImage(Colors); + } + catch (Exception e) + { + Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); + } + } + } + + return null; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/ResizeCanvasEffect.cs b/src/Greenshot.Base/Effects/ResizeCanvasEffect.cs similarity index 94% rename from src/GreenshotPlugin/Effects/ResizeCanvasEffect.cs rename to src/Greenshot.Base/Effects/ResizeCanvasEffect.cs index 5b990f2d4..5a8742f3d 100644 --- a/src/GreenshotPlugin/Effects/ResizeCanvasEffect.cs +++ b/src/Greenshot.Base/Effects/ResizeCanvasEffect.cs @@ -1,58 +1,58 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// ResizeCanvasEffect - /// - public class ResizeCanvasEffect : IEffect - { - public ResizeCanvasEffect(int left, int right, int top, int bottom) - { - Left = left; - Right = right; - Top = top; - Bottom = bottom; - BackgroundColor = Color.Empty; // Uses the default background color depending on the format - } - - public int Left { get; set; } - public int Right { get; set; } - public int Top { get; set; } - public int Bottom { get; set; } - public Color BackgroundColor { get; set; } - - public void Reset() - { - // values don't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom, matrix); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// ResizeCanvasEffect + /// + public class ResizeCanvasEffect : IEffect + { + public ResizeCanvasEffect(int left, int right, int top, int bottom) + { + Left = left; + Right = right; + Top = top; + Bottom = bottom; + BackgroundColor = Color.Empty; // Uses the default background color depending on the format + } + + public int Left { get; set; } + public int Right { get; set; } + public int Top { get; set; } + public int Bottom { get; set; } + public Color BackgroundColor { get; set; } + + public void Reset() + { + // values don't have a default value + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom, matrix); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/ResizeEffect.cs b/src/Greenshot.Base/Effects/ResizeEffect.cs similarity index 93% rename from src/GreenshotPlugin/Effects/ResizeEffect.cs rename to src/Greenshot.Base/Effects/ResizeEffect.cs index cfcae71cd..b756cbaff 100644 --- a/src/GreenshotPlugin/Effects/ResizeEffect.cs +++ b/src/Greenshot.Base/Effects/ResizeEffect.cs @@ -1,54 +1,54 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// ResizeEffect - /// - public class ResizeEffect : IEffect - { - public ResizeEffect(int width, int height, bool maintainAspectRatio) - { - Width = width; - Height = height; - MaintainAspectRatio = maintainAspectRatio; - } - - public int Width { get; set; } - public int Height { get; set; } - public bool MaintainAspectRatio { get; set; } - - public void Reset() - { - // values don't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height, matrix); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// ResizeEffect + /// + public class ResizeEffect : IEffect + { + public ResizeEffect(int width, int height, bool maintainAspectRatio) + { + Width = width; + Height = height; + MaintainAspectRatio = maintainAspectRatio; + } + + public int Width { get; set; } + public int Height { get; set; } + public bool MaintainAspectRatio { get; set; } + + public void Reset() + { + // values don't have a default value + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height, matrix); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/RotateEffect.cs b/src/Greenshot.Base/Effects/RotateEffect.cs similarity index 94% rename from src/GreenshotPlugin/Effects/RotateEffect.cs rename to src/Greenshot.Base/Effects/RotateEffect.cs index 8eb7a6978..09c00d35b 100644 --- a/src/GreenshotPlugin/Effects/RotateEffect.cs +++ b/src/Greenshot.Base/Effects/RotateEffect.cs @@ -1,69 +1,69 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// RotateEffect - /// - public class RotateEffect : IEffect - { - public RotateEffect(int angle) - { - Angle = angle; - } - - public int Angle { get; set; } - - public void Reset() - { - // Angle doesn't have a default value - } - - public Image Apply(Image sourceImage, Matrix matrix) - { - RotateFlipType flipType; - if (Angle == 90) - { - matrix.Rotate(90, MatrixOrder.Append); - matrix.Translate(sourceImage.Height, 0, MatrixOrder.Append); - flipType = RotateFlipType.Rotate90FlipNone; - } - else if (Angle == -90 || Angle == 270) - { - flipType = RotateFlipType.Rotate270FlipNone; - matrix.Rotate(-90, MatrixOrder.Append); - matrix.Translate(0, sourceImage.Width, MatrixOrder.Append); - } - else - { - throw new NotSupportedException("Currently only an angle of 90 or -90 (270) is supported."); - } - - return ImageHelper.RotateFlip(sourceImage, flipType); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// RotateEffect + /// + public class RotateEffect : IEffect + { + public RotateEffect(int angle) + { + Angle = angle; + } + + public int Angle { get; set; } + + public void Reset() + { + // Angle doesn't have a default value + } + + public Image Apply(Image sourceImage, Matrix matrix) + { + RotateFlipType flipType; + if (Angle == 90) + { + matrix.Rotate(90, MatrixOrder.Append); + matrix.Translate(sourceImage.Height, 0, MatrixOrder.Append); + flipType = RotateFlipType.Rotate90FlipNone; + } + else if (Angle == -90 || Angle == 270) + { + flipType = RotateFlipType.Rotate270FlipNone; + matrix.Rotate(-90, MatrixOrder.Append); + matrix.Translate(0, sourceImage.Width, MatrixOrder.Append); + } + else + { + throw new NotSupportedException("Currently only an angle of 90 or -90 (270) is supported."); + } + + return ImageHelper.RotateFlip(sourceImage, flipType); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Effects/TornEdgeEffect.cs b/src/Greenshot.Base/Effects/TornEdgeEffect.cs similarity index 94% rename from src/GreenshotPlugin/Effects/TornEdgeEffect.cs rename to src/Greenshot.Base/Effects/TornEdgeEffect.cs index 70d671287..e283593fc 100644 --- a/src/GreenshotPlugin/Effects/TornEdgeEffect.cs +++ b/src/Greenshot.Base/Effects/TornEdgeEffect.cs @@ -1,75 +1,75 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using GreenshotPlugin.Core; - -namespace GreenshotPlugin.Effects -{ - /// - /// TornEdgeEffect extends on DropShadowEffect - /// - [TypeConverter(typeof(EffectConverter))] - public sealed class TornEdgeEffect : DropShadowEffect - { - public TornEdgeEffect() - { - Reset(); - } - - public int ToothHeight { get; set; } - public int HorizontalToothRange { get; set; } - public int VerticalToothRange { get; set; } - public bool[] Edges { get; set; } - public bool GenerateShadow { get; set; } - - public override void Reset() - { - base.Reset(); - ShadowSize = 7; - ToothHeight = 12; - HorizontalToothRange = 20; - VerticalToothRange = 20; - Edges = new[] - { - true, true, true, true - }; - GenerateShadow = true; - } - - public override Image Apply(Image sourceImage, Matrix matrix) - { - Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange, Edges); - if (GenerateShadow) - { - using (tmpTornImage) - { - return ImageHelper.CreateShadow(tmpTornImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); - } - } - - return tmpTornImage; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using Greenshot.Base.Core; + +namespace Greenshot.Base.Effects +{ + /// + /// TornEdgeEffect extends on DropShadowEffect + /// + [TypeConverter(typeof(EffectConverter))] + public sealed class TornEdgeEffect : DropShadowEffect + { + public TornEdgeEffect() + { + Reset(); + } + + public int ToothHeight { get; set; } + public int HorizontalToothRange { get; set; } + public int VerticalToothRange { get; set; } + public bool[] Edges { get; set; } + public bool GenerateShadow { get; set; } + + public override void Reset() + { + base.Reset(); + ShadowSize = 7; + ToothHeight = 12; + HorizontalToothRange = 20; + VerticalToothRange = 20; + Edges = new[] + { + true, true, true, true + }; + GenerateShadow = true; + } + + public override Image Apply(Image sourceImage, Matrix matrix) + { + Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange, Edges); + if (GenerateShadow) + { + using (tmpTornImage) + { + return ImageHelper.CreateShadow(tmpTornImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb); + } + } + + return tmpTornImage; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/FileDescriptorReader.cs b/src/Greenshot.Base/FileDescriptorReader.cs similarity index 98% rename from src/GreenshotPlugin/FileDescriptorReader.cs rename to src/Greenshot.Base/FileDescriptorReader.cs index 3acfcf7a3..90cc3f99a 100644 --- a/src/GreenshotPlugin/FileDescriptorReader.cs +++ b/src/Greenshot.Base/FileDescriptorReader.cs @@ -25,9 +25,9 @@ using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Text; -using GreenshotPlugin.UnmanagedHelpers.Structs; +using Greenshot.Base.UnmanagedHelpers.Structs; -namespace GreenshotPlugin +namespace Greenshot.Base { /// /// Specifies which fields are valid in a FileDescriptor Structure diff --git a/src/GreenshotPlugin/GlobalSuppressions.cs b/src/Greenshot.Base/GlobalSuppressions.cs similarity index 100% rename from src/GreenshotPlugin/GlobalSuppressions.cs rename to src/Greenshot.Base/GlobalSuppressions.cs diff --git a/src/GreenshotPlugin/GreenshotPlugin.csproj b/src/Greenshot.Base/Greenshot.Base.csproj similarity index 68% rename from src/GreenshotPlugin/GreenshotPlugin.csproj rename to src/Greenshot.Base/Greenshot.Base.csproj index db8b82b57..2f74649f6 100644 --- a/src/GreenshotPlugin/GreenshotPlugin.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -1,26 +1,18 @@ - - - - GreenshotPlugin - GreenshotPlugin - true - - - - - PreserveNewest - - - - - - - - - - - - - - - + + + + true + + + + + + + + + + + + + + diff --git a/src/GreenshotPlugin/Hooking/WindowsEventHook.cs b/src/Greenshot.Base/Hooking/WindowsEventHook.cs similarity index 98% rename from src/GreenshotPlugin/Hooking/WindowsEventHook.cs rename to src/Greenshot.Base/Hooking/WindowsEventHook.cs index 06ae3a83c..474b15fef 100644 --- a/src/GreenshotPlugin/Hooking/WindowsEventHook.cs +++ b/src/Greenshot.Base/Hooking/WindowsEventHook.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Enums; -namespace GreenshotPlugin.Hooking +namespace Greenshot.Base.Hooking { /// /// The WinEventHook can register handlers to become important windows events diff --git a/src/GreenshotPlugin/Hooking/WindowsOpenCloseMonitor.cs b/src/Greenshot.Base/Hooking/WindowsOpenCloseMonitor.cs similarity index 98% rename from src/GreenshotPlugin/Hooking/WindowsOpenCloseMonitor.cs rename to src/Greenshot.Base/Hooking/WindowsOpenCloseMonitor.cs index 626e3424f..2ab54e5de 100644 --- a/src/GreenshotPlugin/Hooking/WindowsOpenCloseMonitor.cs +++ b/src/Greenshot.Base/Hooking/WindowsOpenCloseMonitor.cs @@ -20,10 +20,10 @@ */ using System; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.UnmanagedHelpers.Enums; -namespace GreenshotPlugin.Hooking +namespace Greenshot.Base.Hooking { /// /// Event arguments for the WindowOpenCloseEvent diff --git a/src/GreenshotPlugin/Hooking/WindowsTitleMonitor.cs b/src/Greenshot.Base/Hooking/WindowsTitleMonitor.cs similarity index 97% rename from src/GreenshotPlugin/Hooking/WindowsTitleMonitor.cs rename to src/Greenshot.Base/Hooking/WindowsTitleMonitor.cs index 081b1f28f..194ec4fc3 100644 --- a/src/GreenshotPlugin/Hooking/WindowsTitleMonitor.cs +++ b/src/Greenshot.Base/Hooking/WindowsTitleMonitor.cs @@ -20,10 +20,10 @@ */ using System; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.UnmanagedHelpers.Enums; -namespace GreenshotPlugin.Hooking +namespace Greenshot.Base.Hooking { /// /// Event arguments for the TitleChangeEvent diff --git a/src/GreenshotPlugin/IEInterop/IHTMLBodyElement.cs b/src/Greenshot.Base/IEInterop/IHTMLBodyElement.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLBodyElement.cs rename to src/Greenshot.Base/IEInterop/IHTMLBodyElement.cs index 234a1ec29..4b79bcc3e 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLBodyElement.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLBodyElement.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F1D8-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLBodyElement - { - string scroll - { - set; - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F1D8-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLBodyElement + { + string scroll + { + set; + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLCurrentStyle.cs b/src/Greenshot.Base/IEInterop/IHTMLCurrentStyle.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLCurrentStyle.cs rename to src/Greenshot.Base/IEInterop/IHTMLCurrentStyle.cs index 95539a5f7..09ba37f79 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLCurrentStyle.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLCurrentStyle.cs @@ -1,81 +1,81 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050f3db-98b5-11cf-bb82-00aa00bdce0b"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLCurrentStyle - { - /// styleFloat property of IHTMLStyle interface. - string styleFloat - { - [DispId(-2147413042)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string left - { - [DispId(-2147418112 + 3)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string top - { - [DispId(-2147418112 + 4)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string width - { - [DispId(-2147418112 + 5)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string height - { - [DispId(-2147418112 + 6)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string right - { - [DispId(-2147418112 + 0x4d)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string bottom - { - [DispId(-2147418112 + 0x4e)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050f3db-98b5-11cf-bb82-00aa00bdce0b"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLCurrentStyle + { + /// styleFloat property of IHTMLStyle interface. + string styleFloat + { + [DispId(-2147413042)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string left + { + [DispId(-2147418112 + 3)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string top + { + [DispId(-2147418112 + 4)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string width + { + [DispId(-2147418112 + 5)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string height + { + [DispId(-2147418112 + 6)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string right + { + [DispId(-2147418112 + 0x4d)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string bottom + { + [DispId(-2147418112 + 0x4e)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLDocument.cs b/src/Greenshot.Base/IEInterop/IHTMLDocument.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLDocument.cs rename to src/Greenshot.Base/IEInterop/IHTMLDocument.cs index 3ef5be8a7..affc1530e 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLDocument.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLDocument.cs @@ -1,39 +1,39 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - /// IHTMLDocument interface. - [Guid("626FC520-A41E-11CF-A731-00A0C9082637")] - [ComImport] - [TypeLibType(TypeLibTypeFlags.FDual)] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLDocument - { - object Script - { - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + /// IHTMLDocument interface. + [Guid("626FC520-A41E-11CF-A731-00A0C9082637")] + [ComImport] + [TypeLibType(TypeLibTypeFlags.FDual)] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLDocument + { + object Script + { + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLDocument2.cs b/src/Greenshot.Base/IEInterop/IHTMLDocument2.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLDocument2.cs rename to src/Greenshot.Base/IEInterop/IHTMLDocument2.cs index 1ee72c537..635aea6dd 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLDocument2.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLDocument2.cs @@ -1,85 +1,85 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - /// IHTMLDocument2 interface. - [Guid("332C4425-26CB-11D0-B483-00C04FD90119")] - [ComImport] - [TypeLibType(TypeLibTypeFlags.FDual)] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLDocument2 - { - IHTMLElement body - { - [DispId(1004)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - string title - { - [DispId(1012)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - object frames - { - [DispId(1019)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - string url - { - [DispId(1025)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - IHTMLWindow2 parentWindow - { - [DispId(1034)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - object bgColor { [DispId(-501)] get; } - - IHTMLSelectionObject selection - { - [DispId(1017)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - string designMode - { - [DispId(1014)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - [DispId(1014)] set; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + /// IHTMLDocument2 interface. + [Guid("332C4425-26CB-11D0-B483-00C04FD90119")] + [ComImport] + [TypeLibType(TypeLibTypeFlags.FDual)] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLDocument2 + { + IHTMLElement body + { + [DispId(1004)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + string title + { + [DispId(1012)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + object frames + { + [DispId(1019)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + string url + { + [DispId(1025)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + IHTMLWindow2 parentWindow + { + [DispId(1034)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + object bgColor { [DispId(-501)] get; } + + IHTMLSelectionObject selection + { + [DispId(1017)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + string designMode + { + [DispId(1014)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1014)] set; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLDocument3.cs b/src/Greenshot.Base/IEInterop/IHTMLDocument3.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLDocument3.cs rename to src/Greenshot.Base/IEInterop/IHTMLDocument3.cs index 21d73b54a..adcf26e0c 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLDocument3.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLDocument3.cs @@ -1,50 +1,50 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - /// IHTMLDocument3 interface. - [Guid("3050F485-98B5-11CF-BB82-00AA00BDCE0B")] - [ComImport] - [TypeLibType(TypeLibTypeFlags.FDual)] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLDocument3 - { - IHTMLElement documentElement - { - [DispId(1075)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(1086)] - [return: MarshalAs(UnmanagedType.IDispatch)] - IHTMLElementCollection getElementsByName([MarshalAs(UnmanagedType.BStr)] string v); - - [DispId(1088)] - IHTMLElement getElementById([MarshalAs(UnmanagedType.BStr)] string v); - - [DispId(1087)] - IHTMLElementCollection getElementsByTagName([MarshalAs(UnmanagedType.BStr)] string v); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + /// IHTMLDocument3 interface. + [Guid("3050F485-98B5-11CF-BB82-00AA00BDCE0B")] + [ComImport] + [TypeLibType(TypeLibTypeFlags.FDual)] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLDocument3 + { + IHTMLElement documentElement + { + [DispId(1075)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(1086)] + [return: MarshalAs(UnmanagedType.IDispatch)] + IHTMLElementCollection getElementsByName([MarshalAs(UnmanagedType.BStr)] string v); + + [DispId(1088)] + IHTMLElement getElementById([MarshalAs(UnmanagedType.BStr)] string v); + + [DispId(1087)] + IHTMLElementCollection getElementsByTagName([MarshalAs(UnmanagedType.BStr)] string v); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLDocument4.cs b/src/Greenshot.Base/IEInterop/IHTMLDocument4.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLDocument4.cs rename to src/Greenshot.Base/IEInterop/IHTMLDocument4.cs index 09f8d7a02..1b543991a 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLDocument4.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLDocument4.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComVisible(true), Guid("3050f69a-98b5-11cf-bb82-00aa00bdce0b"), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch), - TypeLibType(TypeLibTypeFlags.FDual)] - public interface IHTMLDocument4 - { - [DispId(1090)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool hasFocus(); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComVisible(true), Guid("3050f69a-98b5-11cf-bb82-00aa00bdce0b"), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch), + TypeLibType(TypeLibTypeFlags.FDual)] + public interface IHTMLDocument4 + { + [DispId(1090)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool hasFocus(); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLDocument5.cs b/src/Greenshot.Base/IEInterop/IHTMLDocument5.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLDocument5.cs rename to src/Greenshot.Base/IEInterop/IHTMLDocument5.cs index 628652a37..020249783 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLDocument5.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLDocument5.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, ComVisible(true), Guid("3050f80c-98b5-11cf-bb82-00aa00bdce0b"), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch), - TypeLibType(TypeLibTypeFlags.FDual)] - public interface IHTMLDocument5 - { - [DispId(1102)] - string compatMode - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, ComVisible(true), Guid("3050f80c-98b5-11cf-bb82-00aa00bdce0b"), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch), + TypeLibType(TypeLibTypeFlags.FDual)] + public interface IHTMLDocument5 + { + [DispId(1102)] + string compatMode + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLElement.cs b/src/Greenshot.Base/IEInterop/IHTMLElement.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLElement.cs rename to src/Greenshot.Base/IEInterop/IHTMLElement.cs index df1c5d9f4..9e37d98c6 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLElement.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLElement.cs @@ -1,113 +1,113 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F1FF-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLElement - { - [DispId(-2147417611)] - void setAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, object AttributeValue, int lFlags); - - [DispId(-2147417610)] - object getAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); - - long offsetLeft { [DispId(-2147417104)] get; } - - long offsetTop { [DispId(-2147417103)] get; } - - long offsetWidth { [DispId(-2147417102)] get; } - - long offsetHeight { [DispId(-2147417101)] get; } - - IHTMLElement offsetParent { [DispId(-2147417100)] get; } - - string className - { - [DispId(-2147417111)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - IHTMLDocument2 document - { - [DispId(-2147417094)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - string id - { - [DispId(-2147417110)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string innerHTML - { - [DispId(-2147417086)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string innerText - { - [DispId(-2147417085)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - IHTMLStyle style - { - [DispId(-2147418038)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - string tagName - { - [DispId(-2147417108)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string title - { - [DispId(-2147418043)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - [DispId(-2147417093)] - void scrollIntoView(bool varargStart); - - IHTMLElementCollection children - { - [DispId(-2147417075)] - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F1FF-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLElement + { + [DispId(-2147417611)] + void setAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, object AttributeValue, int lFlags); + + [DispId(-2147417610)] + object getAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); + + long offsetLeft { [DispId(-2147417104)] get; } + + long offsetTop { [DispId(-2147417103)] get; } + + long offsetWidth { [DispId(-2147417102)] get; } + + long offsetHeight { [DispId(-2147417101)] get; } + + IHTMLElement offsetParent { [DispId(-2147417100)] get; } + + string className + { + [DispId(-2147417111)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + IHTMLDocument2 document + { + [DispId(-2147417094)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + string id + { + [DispId(-2147417110)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string innerHTML + { + [DispId(-2147417086)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string innerText + { + [DispId(-2147417085)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + IHTMLStyle style + { + [DispId(-2147418038)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + string tagName + { + [DispId(-2147417108)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string title + { + [DispId(-2147418043)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + [DispId(-2147417093)] + void scrollIntoView(bool varargStart); + + IHTMLElementCollection children + { + [DispId(-2147417075)] + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLElement2.cs b/src/Greenshot.Base/IEInterop/IHTMLElement2.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLElement2.cs rename to src/Greenshot.Base/IEInterop/IHTMLElement2.cs index df5a5d9d4..d6b5e794f 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLElement2.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLElement2.cs @@ -1,42 +1,42 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F434-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLElement2 - { - [DispId(-2147417067)] - [return: MarshalAs(UnmanagedType.IDispatch)] - IHTMLRect getBoundingClientRect(); - - IHTMLCurrentStyle currentStyle - { - [DispId(-2147417105)] - [return: MarshalAs(UnmanagedType.Interface)] //IHTMLCurrentStyle - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F434-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLElement2 + { + [DispId(-2147417067)] + [return: MarshalAs(UnmanagedType.IDispatch)] + IHTMLRect getBoundingClientRect(); + + IHTMLCurrentStyle currentStyle + { + [DispId(-2147417105)] + [return: MarshalAs(UnmanagedType.Interface)] //IHTMLCurrentStyle + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLElementCollection.cs b/src/Greenshot.Base/IEInterop/IHTMLElementCollection.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLElementCollection.cs rename to src/Greenshot.Base/IEInterop/IHTMLElementCollection.cs index d8ac07646..f0735cc6d 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLElementCollection.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLElementCollection.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Collections; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport(), ComVisible(true), - Guid("3050F21F-98B5-11CF-BB82-00AA00BDCE0B"), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch), - TypeLibType(TypeLibTypeFlags.FDispatchable)] - public interface IHTMLElementCollection : IEnumerable - { - new IEnumerator GetEnumerator(); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Collections; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport(), ComVisible(true), + Guid("3050F21F-98B5-11CF-BB82-00AA00BDCE0B"), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch), + TypeLibType(TypeLibTypeFlags.FDispatchable)] + public interface IHTMLElementCollection : IEnumerable + { + new IEnumerator GetEnumerator(); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLFrameBase.cs b/src/Greenshot.Base/IEInterop/IHTMLFrameBase.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLFrameBase.cs rename to src/Greenshot.Base/IEInterop/IHTMLFrameBase.cs index db68866d2..c35da0240 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLFrameBase.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLFrameBase.cs @@ -1,108 +1,108 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComVisible(true), ComImport(), Guid("3050f311-98b5-11cf-bb82-00aa00bdce0b"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLFrameBase - { -//dispinterface IHTMLFrameBase { -// properties: -// methods: -// [id(0x80010bb8), propput] -// void src([in] BSTR rhs); -// [id(0x80010bb8), propget] -// BSTR src(); -// [id(0x80010000), propput] -// void name([in] BSTR rhs); -// [id(0x80010000), propget] -// BSTR name(); -// [id(0x80010bba), propput] -// void border([in] VARIANT rhs); -// [id(0x80010bba), propget] -// VARIANT border(); -// [id(0x80010bbb), propput] -// void frameBorder([in] BSTR rhs); -// [id(0x80010bbb), propget] -// BSTR frameBorder(); -// [id(0x80010bbc), propput] -// void frameSpacing([in] VARIANT rhs); -// [id(0x80010bbc), propget] -// VARIANT frameSpacing(); -// [id(0x80010bbd), propput] -// void marginWidth([in] VARIANT rhs); -// [id(0x80010bbd), propget] -// VARIANT marginWidth(); -// [id(0x80010bbe), propput] -// void marginHeight([in] VARIANT rhs); -// [id(0x80010bbe), propget] -// VARIANT marginHeight(); -// [id(0x80010bbf), propput] -// void noResize([in] VARIANT_BOOL rhs); -// [id(0x80010bbf), propget] -// VARIANT_BOOL noResize(); -// [id(0x80010bc0), propput] -// void scrolling([in] BSTR rhs); -// [id(0x80010bc0), propget] -// BSTR scrolling(); -//}; -// [DispId(HTMLDispIDs.DISPID_IHTMLFRAMEBASE_SRC)] - string src - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string name - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - object border { get; } - - string frameBorder - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - object frameSpacing { get; } - object marginWidth { get; } - object marginHeight { get; } - - bool noResize - { - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - string scrolling - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComVisible(true), ComImport(), Guid("3050f311-98b5-11cf-bb82-00aa00bdce0b"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLFrameBase + { +//dispinterface IHTMLFrameBase { +// properties: +// methods: +// [id(0x80010bb8), propput] +// void src([in] BSTR rhs); +// [id(0x80010bb8), propget] +// BSTR src(); +// [id(0x80010000), propput] +// void name([in] BSTR rhs); +// [id(0x80010000), propget] +// BSTR name(); +// [id(0x80010bba), propput] +// void border([in] VARIANT rhs); +// [id(0x80010bba), propget] +// VARIANT border(); +// [id(0x80010bbb), propput] +// void frameBorder([in] BSTR rhs); +// [id(0x80010bbb), propget] +// BSTR frameBorder(); +// [id(0x80010bbc), propput] +// void frameSpacing([in] VARIANT rhs); +// [id(0x80010bbc), propget] +// VARIANT frameSpacing(); +// [id(0x80010bbd), propput] +// void marginWidth([in] VARIANT rhs); +// [id(0x80010bbd), propget] +// VARIANT marginWidth(); +// [id(0x80010bbe), propput] +// void marginHeight([in] VARIANT rhs); +// [id(0x80010bbe), propget] +// VARIANT marginHeight(); +// [id(0x80010bbf), propput] +// void noResize([in] VARIANT_BOOL rhs); +// [id(0x80010bbf), propget] +// VARIANT_BOOL noResize(); +// [id(0x80010bc0), propput] +// void scrolling([in] BSTR rhs); +// [id(0x80010bc0), propget] +// BSTR scrolling(); +//}; +// [DispId(HTMLDispIDs.DISPID_IHTMLFRAMEBASE_SRC)] + string src + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string name + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + object border { get; } + + string frameBorder + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + object frameSpacing { get; } + object marginWidth { get; } + object marginHeight { get; } + + bool noResize + { + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + string scrolling + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLFramesCollection2.cs b/src/Greenshot.Base/IEInterop/IHTMLFramesCollection2.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLFramesCollection2.cs rename to src/Greenshot.Base/IEInterop/IHTMLFramesCollection2.cs index 41b759aef..3a68b485d 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLFramesCollection2.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLFramesCollection2.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport(), ComVisible(true), - Guid("332C4426-26CB-11D0-B483-00C04FD90119"), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch), - TypeLibType(TypeLibTypeFlags.FDispatchable)] - public interface IHTMLFramesCollection2 - { - [DispId(0)] - [return: MarshalAs(UnmanagedType.IDispatch)] - IHTMLWindow2 item(int pvarIndex); - - long length { [DispId(1001)] get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport(), ComVisible(true), + Guid("332C4426-26CB-11D0-B483-00C04FD90119"), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch), + TypeLibType(TypeLibTypeFlags.FDispatchable)] + public interface IHTMLFramesCollection2 + { + [DispId(0)] + [return: MarshalAs(UnmanagedType.IDispatch)] + IHTMLWindow2 item(int pvarIndex); + + long length { [DispId(1001)] get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLRect.cs b/src/Greenshot.Base/IEInterop/IHTMLRect.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLRect.cs rename to src/Greenshot.Base/IEInterop/IHTMLRect.cs index 1b2f8363c..01a3e886d 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLRect.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLRect.cs @@ -1,39 +1,39 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F4A3-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLRect - { - int bottom { [DispId(1004)] get; } - - int left { [DispId(1001)] get; } - - int right { [DispId(1003)] get; } - - int top { [DispId(1002)] get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F4A3-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLRect + { + int bottom { [DispId(1004)] get; } + + int left { [DispId(1001)] get; } + + int right { [DispId(1003)] get; } + + int top { [DispId(1002)] get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLScreen.cs b/src/Greenshot.Base/IEInterop/IHTMLScreen.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLScreen.cs rename to src/Greenshot.Base/IEInterop/IHTMLScreen.cs index 082935187..2eab0d041 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLScreen.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLScreen.cs @@ -1,34 +1,34 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F35C-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLScreen - { - [DispId(1003)] int width { get; } - [DispId(1004)] int height { get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F35C-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLScreen + { + [DispId(1003)] int width { get; } + [DispId(1004)] int height { get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLScreen2.cs b/src/Greenshot.Base/IEInterop/IHTMLScreen2.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLScreen2.cs rename to src/Greenshot.Base/IEInterop/IHTMLScreen2.cs index 9870f889e..3e7d379cc 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLScreen2.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLScreen2.cs @@ -1,39 +1,39 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F84A-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLScreen2 - { - int logicalXDPI { [DispId(1009)] get; } - - int logicalYDPI { [DispId(1010)] get; } - - int deviceXDPI { [DispId(1011)] get; } - - int deviceYDPI { [DispId(1012)] get; } - }; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F84A-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLScreen2 + { + int logicalXDPI { [DispId(1009)] get; } + + int logicalYDPI { [DispId(1010)] get; } + + int deviceXDPI { [DispId(1011)] get; } + + int deviceYDPI { [DispId(1012)] get; } + }; } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLSelectionObject.cs b/src/Greenshot.Base/IEInterop/IHTMLSelectionObject.cs similarity index 95% rename from src/GreenshotPlugin/IEInterop/IHTMLSelectionObject.cs rename to src/Greenshot.Base/IEInterop/IHTMLSelectionObject.cs index 32982a281..2fa199ab5 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLSelectionObject.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLSelectionObject.cs @@ -1,49 +1,49 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - // See: http://msdn.microsoft.com/en-us/library/aa768849%28v=vs.85%29.aspx - [ComImport, Guid("3050f25A-98b5-11cf-bb82-00aa00bdce0b"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLSelectionObject - { - [return: MarshalAs(UnmanagedType.IDispatch)] - [DispId(1001)] - IHTMLTxtRange createRange(); - - [DispId(1002)] - void empty(); - - [DispId(1003)] - void clear(); - - [DispId(1004)] - string EventType - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + // See: http://msdn.microsoft.com/en-us/library/aa768849%28v=vs.85%29.aspx + [ComImport, Guid("3050f25A-98b5-11cf-bb82-00aa00bdce0b"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLSelectionObject + { + [return: MarshalAs(UnmanagedType.IDispatch)] + [DispId(1001)] + IHTMLTxtRange createRange(); + + [DispId(1002)] + void empty(); + + [DispId(1003)] + void clear(); + + [DispId(1004)] + string EventType + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLStyle.cs b/src/Greenshot.Base/IEInterop/IHTMLStyle.cs similarity index 97% rename from src/GreenshotPlugin/IEInterop/IHTMLStyle.cs rename to src/Greenshot.Base/IEInterop/IHTMLStyle.cs index d5cd7f5be..3be39344a 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLStyle.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLStyle.cs @@ -1,1103 +1,1103 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComImport, Guid("3050F25E-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLStyle - { - /// setAttribute method of IHTMLStyle interface. - /// An original IDL definition of setAttribute method was the following: HRESULT setAttribute (BSTR strAttributeName, VARIANT AttributeValue, [optional, defaultvalue(1)] long lFlags); - // IDL: HRESULT setAttribute (BSTR strAttributeName, VARIANT AttributeValue, [optional, defaultvalue(1)] long lFlags); - // VB6: Sub setAttribute (ByVal strAttributeName As String, ByVal AttributeValue As Any, [ByVal lFlags As Long = 1]) - [DispId(-2147417611)] - void setAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, object AttributeValue, int lFlags); - - /// getAttribute method of IHTMLStyle interface. - /// An original IDL definition of getAttribute method was the following: HRESULT getAttribute (BSTR strAttributeName, [optional, defaultvalue(0)] long lFlags, [out, retval] VARIANT* ReturnValue); - // IDL: HRESULT getAttribute (BSTR strAttributeName, [optional, defaultvalue(0)] long lFlags, [out, retval] VARIANT* ReturnValue); - // VB6: Function getAttribute (ByVal strAttributeName As String, [ByVal lFlags As Long = 0]) As Any - [DispId(-2147417610)] - object getAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); - - /// removeAttribute method of IHTMLStyle interface. - /// An original IDL definition of removeAttribute method was the following: HRESULT removeAttribute (BSTR strAttributeName, [optional, defaultvalue(1)] long lFlags, [out, retval] VARIANT_BOOL* ReturnValue); - // IDL: HRESULT removeAttribute (BSTR strAttributeName, [optional, defaultvalue(1)] long lFlags, [out, retval] VARIANT_BOOL* ReturnValue); - // VB6: Function removeAttribute (ByVal strAttributeName As String, [ByVal lFlags As Long = 1]) As Boolean - [DispId(-2147417609)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool removeAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); - - /// toString method of IHTMLStyle interface. - /// An original IDL definition of toString method was the following: HRESULT toString ([out, retval] BSTR* ReturnValue); - // IDL: HRESULT toString ([out, retval] BSTR* ReturnValue); - // VB6: Function toString As String - [DispId(-2147414104)] - [return: MarshalAs(UnmanagedType.BStr)] - string toString(); - - /// background property of IHTMLStyle interface. - /// An original IDL definition of background property was the following: BSTR background; - // IDL: BSTR background; - // VB6: background As String - string background - { - // IDL: HRESULT background ([out, retval] BSTR* ReturnValue); - // VB6: Function background As String - [DispId(-2147413080)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT background (BSTR value); - // VB6: Sub background (ByVal value As String) - [DispId(-2147413080)] set; - } - - /// backgroundAttachment property of IHTMLStyle interface. - /// An original IDL definition of backgroundAttachment property was the following: BSTR backgroundAttachment; - // IDL: BSTR backgroundAttachment; - // VB6: backgroundAttachment As String - string backgroundAttachment - { - // IDL: HRESULT backgroundAttachment ([out, retval] BSTR* ReturnValue); - // VB6: Function backgroundAttachment As String - [DispId(-2147413067)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT backgroundAttachment (BSTR value); - // VB6: Sub backgroundAttachment (ByVal value As String) - [DispId(-2147413067)] set; - } - - /// backgroundColor property of IHTMLStyle interface. - /// An original IDL definition of backgroundColor property was the following: VARIANT backgroundColor; - // IDL: VARIANT backgroundColor; - // VB6: backgroundColor As Any - object backgroundColor - { - // IDL: HRESULT backgroundColor ([out, retval] VARIANT* ReturnValue); - // VB6: Function backgroundColor As Any - [DispId(-501)] get; - // IDL: HRESULT backgroundColor (VARIANT value); - // VB6: Sub backgroundColor (ByVal value As Any) - [DispId(-501)] set; - } - - /// backgroundImage property of IHTMLStyle interface. - /// An original IDL definition of backgroundImage property was the following: BSTR backgroundImage; - // IDL: BSTR backgroundImage; - // VB6: backgroundImage As String - string backgroundImage - { - // IDL: HRESULT backgroundImage ([out, retval] BSTR* ReturnValue); - // VB6: Function backgroundImage As String - [DispId(-2147413111)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT backgroundImage (BSTR value); - // VB6: Sub backgroundImage (ByVal value As String) - [DispId(-2147413111)] set; - } - - /// backgroundPosition property of IHTMLStyle interface. - /// An original IDL definition of backgroundPosition property was the following: BSTR backgroundPosition; - // IDL: BSTR backgroundPosition; - // VB6: backgroundPosition As String - string backgroundPosition - { - // IDL: HRESULT backgroundPosition ([out, retval] BSTR* ReturnValue); - // VB6: Function backgroundPosition As String - [DispId(-2147413066)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT backgroundPosition (BSTR value); - // VB6: Sub backgroundPosition (ByVal value As String) - [DispId(-2147413066)] set; - } - - /// backgroundPositionX property of IHTMLStyle interface. - /// An original IDL definition of backgroundPositionX property was the following: VARIANT backgroundPositionX; - // IDL: VARIANT backgroundPositionX; - // VB6: backgroundPositionX As Any - object backgroundPositionX - { - // IDL: HRESULT backgroundPositionX ([out, retval] VARIANT* ReturnValue); - // VB6: Function backgroundPositionX As Any - [DispId(-2147413079)] get; - // IDL: HRESULT backgroundPositionX (VARIANT value); - // VB6: Sub backgroundPositionX (ByVal value As Any) - [DispId(-2147413079)] set; - } - - /// backgroundPositionY property of IHTMLStyle interface. - /// An original IDL definition of backgroundPositionY property was the following: VARIANT backgroundPositionY; - // IDL: VARIANT backgroundPositionY; - // VB6: backgroundPositionY As Any - object backgroundPositionY - { - // IDL: HRESULT backgroundPositionY ([out, retval] VARIANT* ReturnValue); - // VB6: Function backgroundPositionY As Any - [DispId(-2147413078)] get; - // IDL: HRESULT backgroundPositionY (VARIANT value); - // VB6: Sub backgroundPositionY (ByVal value As Any) - [DispId(-2147413078)] set; - } - - /// backgroundRepeat property of IHTMLStyle interface. - /// An original IDL definition of backgroundRepeat property was the following: BSTR backgroundRepeat; - // IDL: BSTR backgroundRepeat; - // VB6: backgroundRepeat As String - string backgroundRepeat - { - // IDL: HRESULT backgroundRepeat ([out, retval] BSTR* ReturnValue); - // VB6: Function backgroundRepeat As String - [DispId(-2147413068)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT backgroundRepeat (BSTR value); - // VB6: Sub backgroundRepeat (ByVal value As String) - [DispId(-2147413068)] set; - } - - /// border property of IHTMLStyle interface. - /// An original IDL definition of border property was the following: BSTR border; - // IDL: BSTR border; - // VB6: border As String - string border - { - // IDL: HRESULT border ([out, retval] BSTR* ReturnValue); - // VB6: Function border As String - [DispId(-2147413063)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT border (BSTR value); - // VB6: Sub border (ByVal value As String) - [DispId(-2147413063)] set; - } - - /// borderBottom property of IHTMLStyle interface. - /// An original IDL definition of borderBottom property was the following: BSTR borderBottom; - // IDL: BSTR borderBottom; - // VB6: borderBottom As String - string borderBottom - { - // IDL: HRESULT borderBottom ([out, retval] BSTR* ReturnValue); - // VB6: Function borderBottom As String - [DispId(-2147413060)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderBottom (BSTR value); - // VB6: Sub borderBottom (ByVal value As String) - [DispId(-2147413060)] set; - } - - /// borderBottomColor property of IHTMLStyle interface. - /// An original IDL definition of borderBottomColor property was the following: VARIANT borderBottomColor; - // IDL: VARIANT borderBottomColor; - // VB6: borderBottomColor As Any - object borderBottomColor - { - // IDL: HRESULT borderBottomColor ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderBottomColor As Any - [DispId(-2147413055)] get; - // IDL: HRESULT borderBottomColor (VARIANT value); - // VB6: Sub borderBottomColor (ByVal value As Any) - [DispId(-2147413055)] set; - } - - /// borderBottomStyle property of IHTMLStyle interface. - /// An original IDL definition of borderBottomStyle property was the following: BSTR borderBottomStyle; - // IDL: BSTR borderBottomStyle; - // VB6: borderBottomStyle As String - string borderBottomStyle - { - // IDL: HRESULT borderBottomStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function borderBottomStyle As String - [DispId(-2147413045)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderBottomStyle (BSTR value); - // VB6: Sub borderBottomStyle (ByVal value As String) - [DispId(-2147413045)] set; - } - - /// borderBottomWidth property of IHTMLStyle interface. - /// An original IDL definition of borderBottomWidth property was the following: VARIANT borderBottomWidth; - // IDL: VARIANT borderBottomWidth; - // VB6: borderBottomWidth As Any - object borderBottomWidth - { - // IDL: HRESULT borderBottomWidth ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderBottomWidth As Any - [DispId(-2147413050)] get; - // IDL: HRESULT borderBottomWidth (VARIANT value); - // VB6: Sub borderBottomWidth (ByVal value As Any) - [DispId(-2147413050)] set; - } - - /// borderColor property of IHTMLStyle interface. - /// An original IDL definition of borderColor property was the following: BSTR borderColor; - // IDL: BSTR borderColor; - // VB6: borderColor As String - string borderColor - { - // IDL: HRESULT borderColor ([out, retval] BSTR* ReturnValue); - // VB6: Function borderColor As String - [DispId(-2147413058)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderColor (BSTR value); - // VB6: Sub borderColor (ByVal value As String) - [DispId(-2147413058)] set; - } - - /// borderLeft property of IHTMLStyle interface. - /// An original IDL definition of borderLeft property was the following: BSTR borderLeft; - // IDL: BSTR borderLeft; - // VB6: borderLeft As String - string borderLeft - { - // IDL: HRESULT borderLeft ([out, retval] BSTR* ReturnValue); - // VB6: Function borderLeft As String - [DispId(-2147413059)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderLeft (BSTR value); - // VB6: Sub borderLeft (ByVal value As String) - [DispId(-2147413059)] set; - } - - /// borderLeftColor property of IHTMLStyle interface. - /// An original IDL definition of borderLeftColor property was the following: VARIANT borderLeftColor; - // IDL: VARIANT borderLeftColor; - // VB6: borderLeftColor As Any - object borderLeftColor - { - // IDL: HRESULT borderLeftColor ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderLeftColor As Any - [DispId(-2147413054)] get; - // IDL: HRESULT borderLeftColor (VARIANT value); - // VB6: Sub borderLeftColor (ByVal value As Any) - [DispId(-2147413054)] set; - } - - /// borderLeftStyle property of IHTMLStyle interface. - /// An original IDL definition of borderLeftStyle property was the following: BSTR borderLeftStyle; - // IDL: BSTR borderLeftStyle; - // VB6: borderLeftStyle As String - string borderLeftStyle - { - // IDL: HRESULT borderLeftStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function borderLeftStyle As String - [DispId(-2147413044)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderLeftStyle (BSTR value); - // VB6: Sub borderLeftStyle (ByVal value As String) - [DispId(-2147413044)] set; - } - - /// borderLeftWidth property of IHTMLStyle interface. - /// An original IDL definition of borderLeftWidth property was the following: VARIANT borderLeftWidth; - // IDL: VARIANT borderLeftWidth; - // VB6: borderLeftWidth As Any - object borderLeftWidth - { - // IDL: HRESULT borderLeftWidth ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderLeftWidth As Any - [DispId(-2147413049)] get; - // IDL: HRESULT borderLeftWidth (VARIANT value); - // VB6: Sub borderLeftWidth (ByVal value As Any) - [DispId(-2147413049)] set; - } - - /// borderRight property of IHTMLStyle interface. - /// An original IDL definition of borderRight property was the following: BSTR borderRight; - // IDL: BSTR borderRight; - // VB6: borderRight As String - string borderRight - { - // IDL: HRESULT borderRight ([out, retval] BSTR* ReturnValue); - // VB6: Function borderRight As String - [DispId(-2147413061)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderRight (BSTR value); - // VB6: Sub borderRight (ByVal value As String) - [DispId(-2147413061)] set; - } - - /// borderRightColor property of IHTMLStyle interface. - /// An original IDL definition of borderRightColor property was the following: VARIANT borderRightColor; - // IDL: VARIANT borderRightColor; - // VB6: borderRightColor As Any - object borderRightColor - { - // IDL: HRESULT borderRightColor ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderRightColor As Any - [DispId(-2147413056)] get; - // IDL: HRESULT borderRightColor (VARIANT value); - // VB6: Sub borderRightColor (ByVal value As Any) - [DispId(-2147413056)] set; - } - - /// borderRightStyle property of IHTMLStyle interface. - /// An original IDL definition of borderRightStyle property was the following: BSTR borderRightStyle; - // IDL: BSTR borderRightStyle; - // VB6: borderRightStyle As String - string borderRightStyle - { - // IDL: HRESULT borderRightStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function borderRightStyle As String - [DispId(-2147413046)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderRightStyle (BSTR value); - // VB6: Sub borderRightStyle (ByVal value As String) - [DispId(-2147413046)] set; - } - - /// borderRightWidth property of IHTMLStyle interface. - /// An original IDL definition of borderRightWidth property was the following: VARIANT borderRightWidth; - // IDL: VARIANT borderRightWidth; - // VB6: borderRightWidth As Any - object borderRightWidth - { - // IDL: HRESULT borderRightWidth ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderRightWidth As Any - [DispId(-2147413051)] get; - // IDL: HRESULT borderRightWidth (VARIANT value); - // VB6: Sub borderRightWidth (ByVal value As Any) - [DispId(-2147413051)] set; - } - - /// borderStyle property of IHTMLStyle interface. - /// An original IDL definition of borderStyle property was the following: BSTR borderStyle; - // IDL: BSTR borderStyle; - // VB6: borderStyle As String - string borderStyle - { - // IDL: HRESULT borderStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function borderStyle As String - [DispId(-2147413048)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderStyle (BSTR value); - // VB6: Sub borderStyle (ByVal value As String) - [DispId(-2147413048)] set; - } - - /// borderTop property of IHTMLStyle interface. - /// An original IDL definition of borderTop property was the following: BSTR borderTop; - // IDL: BSTR borderTop; - // VB6: borderTop As String - string borderTop - { - // IDL: HRESULT borderTop ([out, retval] BSTR* ReturnValue); - // VB6: Function borderTop As String - [DispId(-2147413062)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderTop (BSTR value); - // VB6: Sub borderTop (ByVal value As String) - [DispId(-2147413062)] set; - } - - /// borderTopColor property of IHTMLStyle interface. - /// An original IDL definition of borderTopColor property was the following: VARIANT borderTopColor; - // IDL: VARIANT borderTopColor; - // VB6: borderTopColor As Any - object borderTopColor - { - // IDL: HRESULT borderTopColor ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderTopColor As Any - [DispId(-2147413057)] get; - // IDL: HRESULT borderTopColor (VARIANT value); - // VB6: Sub borderTopColor (ByVal value As Any) - [DispId(-2147413057)] set; - } - - /// borderTopStyle property of IHTMLStyle interface. - /// An original IDL definition of borderTopStyle property was the following: BSTR borderTopStyle; - // IDL: BSTR borderTopStyle; - // VB6: borderTopStyle As String - string borderTopStyle - { - // IDL: HRESULT borderTopStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function borderTopStyle As String - [DispId(-2147413047)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderTopStyle (BSTR value); - // VB6: Sub borderTopStyle (ByVal value As String) - [DispId(-2147413047)] set; - } - - /// borderTopWidth property of IHTMLStyle interface. - /// An original IDL definition of borderTopWidth property was the following: VARIANT borderTopWidth; - // IDL: VARIANT borderTopWidth; - // VB6: borderTopWidth As Any - object borderTopWidth - { - // IDL: HRESULT borderTopWidth ([out, retval] VARIANT* ReturnValue); - // VB6: Function borderTopWidth As Any - [DispId(-2147413052)] get; - // IDL: HRESULT borderTopWidth (VARIANT value); - // VB6: Sub borderTopWidth (ByVal value As Any) - [DispId(-2147413052)] set; - } - - /// borderWidth property of IHTMLStyle interface. - /// An original IDL definition of borderWidth property was the following: BSTR borderWidth; - // IDL: BSTR borderWidth; - // VB6: borderWidth As String - string borderWidth - { - // IDL: HRESULT borderWidth ([out, retval] BSTR* ReturnValue); - // VB6: Function borderWidth As String - [DispId(-2147413053)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT borderWidth (BSTR value); - // VB6: Sub borderWidth (ByVal value As String) - [DispId(-2147413053)] set; - } - - /// clear property of IHTMLStyle interface. - /// An original IDL definition of clear property was the following: BSTR clear; - // IDL: BSTR clear; - // VB6: clear As String - string clear - { - // IDL: HRESULT clear ([out, retval] BSTR* ReturnValue); - // VB6: Function clear As String - [DispId(-2147413096)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT clear (BSTR value); - // VB6: Sub clear (ByVal value As String) - [DispId(-2147413096)] set; - } - - /// clip property of IHTMLStyle interface. - /// An original IDL definition of clip property was the following: BSTR clip; - // IDL: BSTR clip; - // VB6: clip As String - string clip - { - // IDL: HRESULT clip ([out, retval] BSTR* ReturnValue); - // VB6: Function clip As String - [DispId(-2147413020)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT clip (BSTR value); - // VB6: Sub clip (ByVal value As String) - [DispId(-2147413020)] set; - } - - /// color property of IHTMLStyle interface. - /// An original IDL definition of color property was the following: VARIANT color; - // IDL: VARIANT color; - // VB6: color As Any - object color - { - // IDL: HRESULT color ([out, retval] VARIANT* ReturnValue); - // VB6: Function color As Any - [DispId(-2147413110)] get; - // IDL: HRESULT color (VARIANT value); - // VB6: Sub color (ByVal value As Any) - [DispId(-2147413110)] set; - } - - /// cssText property of IHTMLStyle interface. - /// An original IDL definition of cssText property was the following: BSTR cssText; - // IDL: BSTR cssText; - // VB6: cssText As String - string cssText - { - // IDL: HRESULT cssText ([out, retval] BSTR* ReturnValue); - // VB6: Function cssText As String - [DispId(-2147413013)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT cssText (BSTR value); - // VB6: Sub cssText (ByVal value As String) - [DispId(-2147413013)] set; - } - - /// cursor property of IHTMLStyle interface. - /// An original IDL definition of cursor property was the following: BSTR cursor; - // IDL: BSTR cursor; - // VB6: cursor As String - string cursor - { - // IDL: HRESULT cursor ([out, retval] BSTR* ReturnValue); - // VB6: Function cursor As String - [DispId(-2147413010)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT cursor (BSTR value); - // VB6: Sub cursor (ByVal value As String) - [DispId(-2147413010)] set; - } - - /// display property of IHTMLStyle interface. - /// An original IDL definition of display property was the following: BSTR display; - // IDL: BSTR display; - // VB6: display As String - string display - { - // IDL: HRESULT display ([out, retval] BSTR* ReturnValue); - // VB6: Function display As String - [DispId(-2147413041)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT display (BSTR value); - // VB6: Sub display (ByVal value As String) - [DispId(-2147413041)] set; - } - - /// filter property of IHTMLStyle interface. - /// An original IDL definition of filter property was the following: BSTR filter; - // IDL: BSTR filter; - // VB6: filter As String - string filter - { - // IDL: HRESULT filter ([out, retval] BSTR* ReturnValue); - // VB6: Function filter As String - [DispId(-2147413030)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT filter (BSTR value); - // VB6: Sub filter (ByVal value As String) - [DispId(-2147413030)] set; - } - - /// font property of IHTMLStyle interface. - /// An original IDL definition of font property was the following: BSTR font; - // IDL: BSTR font; - // VB6: font As String - string font - { - // IDL: HRESULT font ([out, retval] BSTR* ReturnValue); - // VB6: Function font As String - [DispId(-2147413071)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT font (BSTR value); - // VB6: Sub font (ByVal value As String) - [DispId(-2147413071)] set; - } - - /// fontFamily property of IHTMLStyle interface. - /// An original IDL definition of fontFamily property was the following: BSTR fontFamily; - // IDL: BSTR fontFamily; - // VB6: fontFamily As String - string fontFamily - { - // IDL: HRESULT fontFamily ([out, retval] BSTR* ReturnValue); - // VB6: Function fontFamily As String - [DispId(-2147413094)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT fontFamily (BSTR value); - // VB6: Sub fontFamily (ByVal value As String) - [DispId(-2147413094)] set; - } - - /// fontSize property of IHTMLStyle interface. - /// An original IDL definition of fontSize property was the following: VARIANT fontSize; - // IDL: VARIANT fontSize; - // VB6: fontSize As Any - object fontSize - { - // IDL: HRESULT fontSize ([out, retval] VARIANT* ReturnValue); - // VB6: Function fontSize As Any - [DispId(-2147413093)] get; - // IDL: HRESULT fontSize (VARIANT value); - // VB6: Sub fontSize (ByVal value As Any) - [DispId(-2147413093)] set; - } - - /// fontStyle property of IHTMLStyle interface. - /// An original IDL definition of fontStyle property was the following: BSTR fontStyle; - // IDL: BSTR fontStyle; - // VB6: fontStyle As String - string fontStyle - { - // IDL: HRESULT fontStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function fontStyle As String - [DispId(-2147413088)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT fontStyle (BSTR value); - // VB6: Sub fontStyle (ByVal value As String) - [DispId(-2147413088)] set; - } - - /// fontVariant property of IHTMLStyle interface. - /// An original IDL definition of fontVariant property was the following: BSTR fontVariant; - // IDL: BSTR fontVariant; - // VB6: fontVariant As String - string fontVariant - { - // IDL: HRESULT fontVariant ([out, retval] BSTR* ReturnValue); - // VB6: Function fontVariant As String - [DispId(-2147413087)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT fontVariant (BSTR value); - // VB6: Sub fontVariant (ByVal value As String) - [DispId(-2147413087)] set; - } - - /// fontWeight property of IHTMLStyle interface. - /// An original IDL definition of fontWeight property was the following: BSTR fontWeight; - // IDL: BSTR fontWeight; - // VB6: fontWeight As String - string fontWeight - { - // IDL: HRESULT fontWeight ([out, retval] BSTR* ReturnValue); - // VB6: Function fontWeight As String - [DispId(-2147413085)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT fontWeight (BSTR value); - // VB6: Sub fontWeight (ByVal value As String) - [DispId(-2147413085)] set; - } - - /// height property of IHTMLStyle interface. - /// An original IDL definition of height property was the following: VARIANT height; - // IDL: VARIANT height; - // VB6: height As Any - object height - { - // IDL: HRESULT height ([out, retval] VARIANT* ReturnValue); - // VB6: Function height As Any - [DispId(-2147418106)] get; - // IDL: HRESULT height (VARIANT value); - // VB6: Sub height (ByVal value As Any) - [DispId(-2147418106)] set; - } - - /// left property of IHTMLStyle interface. - /// An original IDL definition of left property was the following: VARIANT left; - // IDL: VARIANT left; - // VB6: left As Any - object left - { - // IDL: HRESULT left ([out, retval] VARIANT* ReturnValue); - // VB6: Function left As Any - [DispId(-2147418109)] get; - // IDL: HRESULT left (VARIANT value); - // VB6: Sub left (ByVal value As Any) - [DispId(-2147418109)] set; - } - - /// letterSpacing property of IHTMLStyle interface. - /// An original IDL definition of letterSpacing property was the following: VARIANT letterSpacing; - // IDL: VARIANT letterSpacing; - // VB6: letterSpacing As Any - object letterSpacing - { - // IDL: HRESULT letterSpacing ([out, retval] VARIANT* ReturnValue); - // VB6: Function letterSpacing As Any - [DispId(-2147413104)] get; - // IDL: HRESULT letterSpacing (VARIANT value); - // VB6: Sub letterSpacing (ByVal value As Any) - [DispId(-2147413104)] set; - } - - /// lineHeight property of IHTMLStyle interface. - /// An original IDL definition of lineHeight property was the following: VARIANT lineHeight; - // IDL: VARIANT lineHeight; - // VB6: lineHeight As Any - object lineHeight - { - // IDL: HRESULT lineHeight ([out, retval] VARIANT* ReturnValue); - // VB6: Function lineHeight As Any - [DispId(-2147413106)] get; - // IDL: HRESULT lineHeight (VARIANT value); - // VB6: Sub lineHeight (ByVal value As Any) - [DispId(-2147413106)] set; - } - - /// listStyle property of IHTMLStyle interface. - /// An original IDL definition of listStyle property was the following: BSTR listStyle; - // IDL: BSTR listStyle; - // VB6: listStyle As String - string listStyle - { - // IDL: HRESULT listStyle ([out, retval] BSTR* ReturnValue); - // VB6: Function listStyle As String - [DispId(-2147413037)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT listStyle (BSTR value); - // VB6: Sub listStyle (ByVal value As String) - [DispId(-2147413037)] set; - } - - /// listStyleImage property of IHTMLStyle interface. - /// An original IDL definition of listStyleImage property was the following: BSTR listStyleImage; - // IDL: BSTR listStyleImage; - // VB6: listStyleImage As String - string listStyleImage - { - // IDL: HRESULT listStyleImage ([out, retval] BSTR* ReturnValue); - // VB6: Function listStyleImage As String - [DispId(-2147413038)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT listStyleImage (BSTR value); - // VB6: Sub listStyleImage (ByVal value As String) - [DispId(-2147413038)] set; - } - - /// listStylePosition property of IHTMLStyle interface. - /// An original IDL definition of listStylePosition property was the following: BSTR listStylePosition; - // IDL: BSTR listStylePosition; - // VB6: listStylePosition As String - string listStylePosition - { - // IDL: HRESULT listStylePosition ([out, retval] BSTR* ReturnValue); - // VB6: Function listStylePosition As String - [DispId(-2147413039)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT listStylePosition (BSTR value); - // VB6: Sub listStylePosition (ByVal value As String) - [DispId(-2147413039)] set; - } - - /// listStyleType property of IHTMLStyle interface. - /// An original IDL definition of listStyleType property was the following: BSTR listStyleType; - // IDL: BSTR listStyleType; - // VB6: listStyleType As String - string listStyleType - { - // IDL: HRESULT listStyleType ([out, retval] BSTR* ReturnValue); - // VB6: Function listStyleType As String - [DispId(-2147413040)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT listStyleType (BSTR value); - // VB6: Sub listStyleType (ByVal value As String) - [DispId(-2147413040)] set; - } - - /// margin property of IHTMLStyle interface. - /// An original IDL definition of margin property was the following: BSTR margin; - // IDL: BSTR margin; - // VB6: margin As String - string margin - { - // IDL: HRESULT margin ([out, retval] BSTR* ReturnValue); - // VB6: Function margin As String - [DispId(-2147413076)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT margin (BSTR value); - // VB6: Sub margin (ByVal value As String) - [DispId(-2147413076)] set; - } - - /// marginBottom property of IHTMLStyle interface. - /// An original IDL definition of marginBottom property was the following: VARIANT marginBottom; - // IDL: VARIANT marginBottom; - // VB6: marginBottom As Any - object marginBottom - { - // IDL: HRESULT marginBottom ([out, retval] VARIANT* ReturnValue); - // VB6: Function marginBottom As Any - [DispId(-2147413073)] get; - // IDL: HRESULT marginBottom (VARIANT value); - // VB6: Sub marginBottom (ByVal value As Any) - [DispId(-2147413073)] set; - } - - /// marginLeft property of IHTMLStyle interface. - /// An original IDL definition of marginLeft property was the following: VARIANT marginLeft; - // IDL: VARIANT marginLeft; - // VB6: marginLeft As Any - object marginLeft - { - // IDL: HRESULT marginLeft ([out, retval] VARIANT* ReturnValue); - // VB6: Function marginLeft As Any - [DispId(-2147413072)] get; - // IDL: HRESULT marginLeft (VARIANT value); - // VB6: Sub marginLeft (ByVal value As Any) - [DispId(-2147413072)] set; - } - - /// marginRight property of IHTMLStyle interface. - /// An original IDL definition of marginRight property was the following: VARIANT marginRight; - // IDL: VARIANT marginRight; - // VB6: marginRight As Any - object marginRight - { - // IDL: HRESULT marginRight ([out, retval] VARIANT* ReturnValue); - // VB6: Function marginRight As Any - [DispId(-2147413074)] get; - // IDL: HRESULT marginRight (VARIANT value); - // VB6: Sub marginRight (ByVal value As Any) - [DispId(-2147413074)] set; - } - - /// marginTop property of IHTMLStyle interface. - /// An original IDL definition of marginTop property was the following: VARIANT marginTop; - // IDL: VARIANT marginTop; - // VB6: marginTop As Any - object marginTop - { - // IDL: HRESULT marginTop ([out, retval] VARIANT* ReturnValue); - // VB6: Function marginTop As Any - [DispId(-2147413075)] get; - // IDL: HRESULT marginTop (VARIANT value); - // VB6: Sub marginTop (ByVal value As Any) - [DispId(-2147413075)] set; - } - - /// overflow property of IHTMLStyle interface. - /// An original IDL definition of overflow property was the following: BSTR overflow; - // IDL: BSTR overflow; - // VB6: overflow As String - string overflow - { - // IDL: HRESULT overflow ([out, retval] BSTR* ReturnValue); - // VB6: Function overflow As String - [DispId(-2147413102)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT overflow (BSTR value); - // VB6: Sub overflow (ByVal value As String) - [DispId(-2147413102)] set; - } - - /// padding property of IHTMLStyle interface. - /// An original IDL definition of padding property was the following: BSTR padding; - // IDL: BSTR padding; - // VB6: padding As String - string padding - { - // IDL: HRESULT padding ([out, retval] BSTR* ReturnValue); - // VB6: Function padding As String - [DispId(-2147413101)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - // IDL: HRESULT padding (BSTR value); - // VB6: Sub padding (ByVal value As String) - [DispId(-2147413101)] set; - } - - /// paddingBottom property of IHTMLStyle interface. - /// An original IDL definition of paddingBottom property was the following: VARIANT paddingBottom; - // IDL: VARIANT paddingBottom; - // VB6: paddingBottom As Any - object paddingBottom - { - // IDL: HRESULT paddingBottom ([out, retval] VARIANT* ReturnValue); - // VB6: Function paddingBottom As Any - [DispId(-2147413098)] get; - // IDL: HRESULT paddingBottom (VARIANT value); - // VB6: Sub paddingBottom (ByVal value As Any) - [DispId(-2147413098)] set; - } - - /// paddingLeft property of IHTMLStyle interface. - /// An original IDL definition of paddingLeft property was the following: VARIANT paddingLeft; - // IDL: VARIANT paddingLeft; - // VB6: paddingLeft As Any - object paddingLeft - { - // IDL: HRESULT paddingLeft ([out, retval] VARIANT* ReturnValue); - // VB6: Function paddingLeft As Any - [DispId(-2147413097)] get; - // IDL: HRESULT paddingLeft (VARIANT value); - // VB6: Sub paddingLeft (ByVal value As Any) - [DispId(-2147413097)] set; - } - - /// paddingRight property of IHTMLStyle interface. - object paddingRight { [DispId(-2147413099)] get; } - - /// paddingTop property of IHTMLStyle interface. - object paddingTop { [DispId(-2147413100)] get; } - - /// pageBreakAfter property of IHTMLStyle interface. - string pageBreakAfter - { - [DispId(-2147413034)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// pageBreakBefore property of IHTMLStyle interface. - string pageBreakBefore - { - [DispId(-2147413035)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// pixelHeight property of IHTMLStyle interface. - int pixelHeight { [DispId(-2147414109)] get; } - - /// pixelLeft property of IHTMLStyle interface. - int pixelLeft { [DispId(-2147414111)] get; } - - /// pixelTop property of IHTMLStyle interface. - int pixelTop { [DispId(-2147414112)] get; } - - /// pixelWidth property of IHTMLStyle interface. - int pixelWidth { [DispId(-2147414110)] get; } - - /// posHeight property of IHTMLStyle interface. - float posHeight { [DispId(-2147414105)] get; } - - /// position property of IHTMLStyle interface. - string position - { - [DispId(-2147413022)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// posLeft property of IHTMLStyle interface. - float posLeft { [DispId(-2147414107)] get; } - - /// posTop property of IHTMLStyle interface. - float posTop { [DispId(-2147414108)] get; } - - /// posWidth property of IHTMLStyle interface. - float posWidth { [DispId(-2147414106)] get; } - - /// styleFloat property of IHTMLStyle interface. - string styleFloat - { - [DispId(-2147413042)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// textAlign property of IHTMLStyle interface. - string textAlign - { - [DispId(-2147418040)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// textDecoration property of IHTMLStyle interface. - string textDecoration - { - [DispId(-2147413077)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// textDecorationBlink property of IHTMLStyle interface. - bool textDecorationBlink - { - [DispId(-2147413090)] - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - /// textDecorationLineThrough property of IHTMLStyle interface. - bool textDecorationLineThrough - { - [DispId(-2147413092)] - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - /// textDecorationNone property of IHTMLStyle interface. - bool textDecorationNone - { - [DispId(-2147413089)] - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - /// textDecorationOverline property of IHTMLStyle interface. - bool textDecorationOverline - { - [DispId(-2147413043)] - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - /// textDecorationUnderline property of IHTMLStyle interface. - bool textDecorationUnderline - { - [DispId(-2147413091)] - [return: MarshalAs(UnmanagedType.VariantBool)] - get; - } - - /// textIndent property of IHTMLStyle interface. - object textIndent { [DispId(-2147413105)] get; } - - /// textTransform property of IHTMLStyle interface. - string textTransform - { - [DispId(-2147413108)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// top property of IHTMLStyle interface. - object top { [DispId(-2147418108)] get; } - - /// verticalAlign property of IHTMLStyle interface. - object verticalAlign { [DispId(-2147413064)] get; } - - /// visibility property of IHTMLStyle interface. - string visibility - { - [DispId(-2147413032)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// whiteSpace property of IHTMLStyle interface. - string whiteSpace - { - [DispId(-2147413036)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - /// width property of IHTMLStyle interface. - object width { [DispId(-2147418107)] get; } - - /// wordSpacing property of IHTMLStyle interface. - object wordSpacing { [DispId(-2147413065)] get; } - - /// zIndex property of IHTMLStyle interface. - object zIndex { [DispId(-2147413021)] get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComImport, Guid("3050F25E-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLStyle + { + /// setAttribute method of IHTMLStyle interface. + /// An original IDL definition of setAttribute method was the following: HRESULT setAttribute (BSTR strAttributeName, VARIANT AttributeValue, [optional, defaultvalue(1)] long lFlags); + // IDL: HRESULT setAttribute (BSTR strAttributeName, VARIANT AttributeValue, [optional, defaultvalue(1)] long lFlags); + // VB6: Sub setAttribute (ByVal strAttributeName As String, ByVal AttributeValue As Any, [ByVal lFlags As Long = 1]) + [DispId(-2147417611)] + void setAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, object AttributeValue, int lFlags); + + /// getAttribute method of IHTMLStyle interface. + /// An original IDL definition of getAttribute method was the following: HRESULT getAttribute (BSTR strAttributeName, [optional, defaultvalue(0)] long lFlags, [out, retval] VARIANT* ReturnValue); + // IDL: HRESULT getAttribute (BSTR strAttributeName, [optional, defaultvalue(0)] long lFlags, [out, retval] VARIANT* ReturnValue); + // VB6: Function getAttribute (ByVal strAttributeName As String, [ByVal lFlags As Long = 0]) As Any + [DispId(-2147417610)] + object getAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); + + /// removeAttribute method of IHTMLStyle interface. + /// An original IDL definition of removeAttribute method was the following: HRESULT removeAttribute (BSTR strAttributeName, [optional, defaultvalue(1)] long lFlags, [out, retval] VARIANT_BOOL* ReturnValue); + // IDL: HRESULT removeAttribute (BSTR strAttributeName, [optional, defaultvalue(1)] long lFlags, [out, retval] VARIANT_BOOL* ReturnValue); + // VB6: Function removeAttribute (ByVal strAttributeName As String, [ByVal lFlags As Long = 1]) As Boolean + [DispId(-2147417609)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool removeAttribute([MarshalAs(UnmanagedType.BStr)] string strAttributeName, int lFlags); + + /// toString method of IHTMLStyle interface. + /// An original IDL definition of toString method was the following: HRESULT toString ([out, retval] BSTR* ReturnValue); + // IDL: HRESULT toString ([out, retval] BSTR* ReturnValue); + // VB6: Function toString As String + [DispId(-2147414104)] + [return: MarshalAs(UnmanagedType.BStr)] + string toString(); + + /// background property of IHTMLStyle interface. + /// An original IDL definition of background property was the following: BSTR background; + // IDL: BSTR background; + // VB6: background As String + string background + { + // IDL: HRESULT background ([out, retval] BSTR* ReturnValue); + // VB6: Function background As String + [DispId(-2147413080)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT background (BSTR value); + // VB6: Sub background (ByVal value As String) + [DispId(-2147413080)] set; + } + + /// backgroundAttachment property of IHTMLStyle interface. + /// An original IDL definition of backgroundAttachment property was the following: BSTR backgroundAttachment; + // IDL: BSTR backgroundAttachment; + // VB6: backgroundAttachment As String + string backgroundAttachment + { + // IDL: HRESULT backgroundAttachment ([out, retval] BSTR* ReturnValue); + // VB6: Function backgroundAttachment As String + [DispId(-2147413067)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT backgroundAttachment (BSTR value); + // VB6: Sub backgroundAttachment (ByVal value As String) + [DispId(-2147413067)] set; + } + + /// backgroundColor property of IHTMLStyle interface. + /// An original IDL definition of backgroundColor property was the following: VARIANT backgroundColor; + // IDL: VARIANT backgroundColor; + // VB6: backgroundColor As Any + object backgroundColor + { + // IDL: HRESULT backgroundColor ([out, retval] VARIANT* ReturnValue); + // VB6: Function backgroundColor As Any + [DispId(-501)] get; + // IDL: HRESULT backgroundColor (VARIANT value); + // VB6: Sub backgroundColor (ByVal value As Any) + [DispId(-501)] set; + } + + /// backgroundImage property of IHTMLStyle interface. + /// An original IDL definition of backgroundImage property was the following: BSTR backgroundImage; + // IDL: BSTR backgroundImage; + // VB6: backgroundImage As String + string backgroundImage + { + // IDL: HRESULT backgroundImage ([out, retval] BSTR* ReturnValue); + // VB6: Function backgroundImage As String + [DispId(-2147413111)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT backgroundImage (BSTR value); + // VB6: Sub backgroundImage (ByVal value As String) + [DispId(-2147413111)] set; + } + + /// backgroundPosition property of IHTMLStyle interface. + /// An original IDL definition of backgroundPosition property was the following: BSTR backgroundPosition; + // IDL: BSTR backgroundPosition; + // VB6: backgroundPosition As String + string backgroundPosition + { + // IDL: HRESULT backgroundPosition ([out, retval] BSTR* ReturnValue); + // VB6: Function backgroundPosition As String + [DispId(-2147413066)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT backgroundPosition (BSTR value); + // VB6: Sub backgroundPosition (ByVal value As String) + [DispId(-2147413066)] set; + } + + /// backgroundPositionX property of IHTMLStyle interface. + /// An original IDL definition of backgroundPositionX property was the following: VARIANT backgroundPositionX; + // IDL: VARIANT backgroundPositionX; + // VB6: backgroundPositionX As Any + object backgroundPositionX + { + // IDL: HRESULT backgroundPositionX ([out, retval] VARIANT* ReturnValue); + // VB6: Function backgroundPositionX As Any + [DispId(-2147413079)] get; + // IDL: HRESULT backgroundPositionX (VARIANT value); + // VB6: Sub backgroundPositionX (ByVal value As Any) + [DispId(-2147413079)] set; + } + + /// backgroundPositionY property of IHTMLStyle interface. + /// An original IDL definition of backgroundPositionY property was the following: VARIANT backgroundPositionY; + // IDL: VARIANT backgroundPositionY; + // VB6: backgroundPositionY As Any + object backgroundPositionY + { + // IDL: HRESULT backgroundPositionY ([out, retval] VARIANT* ReturnValue); + // VB6: Function backgroundPositionY As Any + [DispId(-2147413078)] get; + // IDL: HRESULT backgroundPositionY (VARIANT value); + // VB6: Sub backgroundPositionY (ByVal value As Any) + [DispId(-2147413078)] set; + } + + /// backgroundRepeat property of IHTMLStyle interface. + /// An original IDL definition of backgroundRepeat property was the following: BSTR backgroundRepeat; + // IDL: BSTR backgroundRepeat; + // VB6: backgroundRepeat As String + string backgroundRepeat + { + // IDL: HRESULT backgroundRepeat ([out, retval] BSTR* ReturnValue); + // VB6: Function backgroundRepeat As String + [DispId(-2147413068)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT backgroundRepeat (BSTR value); + // VB6: Sub backgroundRepeat (ByVal value As String) + [DispId(-2147413068)] set; + } + + /// border property of IHTMLStyle interface. + /// An original IDL definition of border property was the following: BSTR border; + // IDL: BSTR border; + // VB6: border As String + string border + { + // IDL: HRESULT border ([out, retval] BSTR* ReturnValue); + // VB6: Function border As String + [DispId(-2147413063)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT border (BSTR value); + // VB6: Sub border (ByVal value As String) + [DispId(-2147413063)] set; + } + + /// borderBottom property of IHTMLStyle interface. + /// An original IDL definition of borderBottom property was the following: BSTR borderBottom; + // IDL: BSTR borderBottom; + // VB6: borderBottom As String + string borderBottom + { + // IDL: HRESULT borderBottom ([out, retval] BSTR* ReturnValue); + // VB6: Function borderBottom As String + [DispId(-2147413060)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderBottom (BSTR value); + // VB6: Sub borderBottom (ByVal value As String) + [DispId(-2147413060)] set; + } + + /// borderBottomColor property of IHTMLStyle interface. + /// An original IDL definition of borderBottomColor property was the following: VARIANT borderBottomColor; + // IDL: VARIANT borderBottomColor; + // VB6: borderBottomColor As Any + object borderBottomColor + { + // IDL: HRESULT borderBottomColor ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderBottomColor As Any + [DispId(-2147413055)] get; + // IDL: HRESULT borderBottomColor (VARIANT value); + // VB6: Sub borderBottomColor (ByVal value As Any) + [DispId(-2147413055)] set; + } + + /// borderBottomStyle property of IHTMLStyle interface. + /// An original IDL definition of borderBottomStyle property was the following: BSTR borderBottomStyle; + // IDL: BSTR borderBottomStyle; + // VB6: borderBottomStyle As String + string borderBottomStyle + { + // IDL: HRESULT borderBottomStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function borderBottomStyle As String + [DispId(-2147413045)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderBottomStyle (BSTR value); + // VB6: Sub borderBottomStyle (ByVal value As String) + [DispId(-2147413045)] set; + } + + /// borderBottomWidth property of IHTMLStyle interface. + /// An original IDL definition of borderBottomWidth property was the following: VARIANT borderBottomWidth; + // IDL: VARIANT borderBottomWidth; + // VB6: borderBottomWidth As Any + object borderBottomWidth + { + // IDL: HRESULT borderBottomWidth ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderBottomWidth As Any + [DispId(-2147413050)] get; + // IDL: HRESULT borderBottomWidth (VARIANT value); + // VB6: Sub borderBottomWidth (ByVal value As Any) + [DispId(-2147413050)] set; + } + + /// borderColor property of IHTMLStyle interface. + /// An original IDL definition of borderColor property was the following: BSTR borderColor; + // IDL: BSTR borderColor; + // VB6: borderColor As String + string borderColor + { + // IDL: HRESULT borderColor ([out, retval] BSTR* ReturnValue); + // VB6: Function borderColor As String + [DispId(-2147413058)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderColor (BSTR value); + // VB6: Sub borderColor (ByVal value As String) + [DispId(-2147413058)] set; + } + + /// borderLeft property of IHTMLStyle interface. + /// An original IDL definition of borderLeft property was the following: BSTR borderLeft; + // IDL: BSTR borderLeft; + // VB6: borderLeft As String + string borderLeft + { + // IDL: HRESULT borderLeft ([out, retval] BSTR* ReturnValue); + // VB6: Function borderLeft As String + [DispId(-2147413059)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderLeft (BSTR value); + // VB6: Sub borderLeft (ByVal value As String) + [DispId(-2147413059)] set; + } + + /// borderLeftColor property of IHTMLStyle interface. + /// An original IDL definition of borderLeftColor property was the following: VARIANT borderLeftColor; + // IDL: VARIANT borderLeftColor; + // VB6: borderLeftColor As Any + object borderLeftColor + { + // IDL: HRESULT borderLeftColor ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderLeftColor As Any + [DispId(-2147413054)] get; + // IDL: HRESULT borderLeftColor (VARIANT value); + // VB6: Sub borderLeftColor (ByVal value As Any) + [DispId(-2147413054)] set; + } + + /// borderLeftStyle property of IHTMLStyle interface. + /// An original IDL definition of borderLeftStyle property was the following: BSTR borderLeftStyle; + // IDL: BSTR borderLeftStyle; + // VB6: borderLeftStyle As String + string borderLeftStyle + { + // IDL: HRESULT borderLeftStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function borderLeftStyle As String + [DispId(-2147413044)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderLeftStyle (BSTR value); + // VB6: Sub borderLeftStyle (ByVal value As String) + [DispId(-2147413044)] set; + } + + /// borderLeftWidth property of IHTMLStyle interface. + /// An original IDL definition of borderLeftWidth property was the following: VARIANT borderLeftWidth; + // IDL: VARIANT borderLeftWidth; + // VB6: borderLeftWidth As Any + object borderLeftWidth + { + // IDL: HRESULT borderLeftWidth ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderLeftWidth As Any + [DispId(-2147413049)] get; + // IDL: HRESULT borderLeftWidth (VARIANT value); + // VB6: Sub borderLeftWidth (ByVal value As Any) + [DispId(-2147413049)] set; + } + + /// borderRight property of IHTMLStyle interface. + /// An original IDL definition of borderRight property was the following: BSTR borderRight; + // IDL: BSTR borderRight; + // VB6: borderRight As String + string borderRight + { + // IDL: HRESULT borderRight ([out, retval] BSTR* ReturnValue); + // VB6: Function borderRight As String + [DispId(-2147413061)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderRight (BSTR value); + // VB6: Sub borderRight (ByVal value As String) + [DispId(-2147413061)] set; + } + + /// borderRightColor property of IHTMLStyle interface. + /// An original IDL definition of borderRightColor property was the following: VARIANT borderRightColor; + // IDL: VARIANT borderRightColor; + // VB6: borderRightColor As Any + object borderRightColor + { + // IDL: HRESULT borderRightColor ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderRightColor As Any + [DispId(-2147413056)] get; + // IDL: HRESULT borderRightColor (VARIANT value); + // VB6: Sub borderRightColor (ByVal value As Any) + [DispId(-2147413056)] set; + } + + /// borderRightStyle property of IHTMLStyle interface. + /// An original IDL definition of borderRightStyle property was the following: BSTR borderRightStyle; + // IDL: BSTR borderRightStyle; + // VB6: borderRightStyle As String + string borderRightStyle + { + // IDL: HRESULT borderRightStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function borderRightStyle As String + [DispId(-2147413046)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderRightStyle (BSTR value); + // VB6: Sub borderRightStyle (ByVal value As String) + [DispId(-2147413046)] set; + } + + /// borderRightWidth property of IHTMLStyle interface. + /// An original IDL definition of borderRightWidth property was the following: VARIANT borderRightWidth; + // IDL: VARIANT borderRightWidth; + // VB6: borderRightWidth As Any + object borderRightWidth + { + // IDL: HRESULT borderRightWidth ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderRightWidth As Any + [DispId(-2147413051)] get; + // IDL: HRESULT borderRightWidth (VARIANT value); + // VB6: Sub borderRightWidth (ByVal value As Any) + [DispId(-2147413051)] set; + } + + /// borderStyle property of IHTMLStyle interface. + /// An original IDL definition of borderStyle property was the following: BSTR borderStyle; + // IDL: BSTR borderStyle; + // VB6: borderStyle As String + string borderStyle + { + // IDL: HRESULT borderStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function borderStyle As String + [DispId(-2147413048)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderStyle (BSTR value); + // VB6: Sub borderStyle (ByVal value As String) + [DispId(-2147413048)] set; + } + + /// borderTop property of IHTMLStyle interface. + /// An original IDL definition of borderTop property was the following: BSTR borderTop; + // IDL: BSTR borderTop; + // VB6: borderTop As String + string borderTop + { + // IDL: HRESULT borderTop ([out, retval] BSTR* ReturnValue); + // VB6: Function borderTop As String + [DispId(-2147413062)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderTop (BSTR value); + // VB6: Sub borderTop (ByVal value As String) + [DispId(-2147413062)] set; + } + + /// borderTopColor property of IHTMLStyle interface. + /// An original IDL definition of borderTopColor property was the following: VARIANT borderTopColor; + // IDL: VARIANT borderTopColor; + // VB6: borderTopColor As Any + object borderTopColor + { + // IDL: HRESULT borderTopColor ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderTopColor As Any + [DispId(-2147413057)] get; + // IDL: HRESULT borderTopColor (VARIANT value); + // VB6: Sub borderTopColor (ByVal value As Any) + [DispId(-2147413057)] set; + } + + /// borderTopStyle property of IHTMLStyle interface. + /// An original IDL definition of borderTopStyle property was the following: BSTR borderTopStyle; + // IDL: BSTR borderTopStyle; + // VB6: borderTopStyle As String + string borderTopStyle + { + // IDL: HRESULT borderTopStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function borderTopStyle As String + [DispId(-2147413047)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderTopStyle (BSTR value); + // VB6: Sub borderTopStyle (ByVal value As String) + [DispId(-2147413047)] set; + } + + /// borderTopWidth property of IHTMLStyle interface. + /// An original IDL definition of borderTopWidth property was the following: VARIANT borderTopWidth; + // IDL: VARIANT borderTopWidth; + // VB6: borderTopWidth As Any + object borderTopWidth + { + // IDL: HRESULT borderTopWidth ([out, retval] VARIANT* ReturnValue); + // VB6: Function borderTopWidth As Any + [DispId(-2147413052)] get; + // IDL: HRESULT borderTopWidth (VARIANT value); + // VB6: Sub borderTopWidth (ByVal value As Any) + [DispId(-2147413052)] set; + } + + /// borderWidth property of IHTMLStyle interface. + /// An original IDL definition of borderWidth property was the following: BSTR borderWidth; + // IDL: BSTR borderWidth; + // VB6: borderWidth As String + string borderWidth + { + // IDL: HRESULT borderWidth ([out, retval] BSTR* ReturnValue); + // VB6: Function borderWidth As String + [DispId(-2147413053)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT borderWidth (BSTR value); + // VB6: Sub borderWidth (ByVal value As String) + [DispId(-2147413053)] set; + } + + /// clear property of IHTMLStyle interface. + /// An original IDL definition of clear property was the following: BSTR clear; + // IDL: BSTR clear; + // VB6: clear As String + string clear + { + // IDL: HRESULT clear ([out, retval] BSTR* ReturnValue); + // VB6: Function clear As String + [DispId(-2147413096)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT clear (BSTR value); + // VB6: Sub clear (ByVal value As String) + [DispId(-2147413096)] set; + } + + /// clip property of IHTMLStyle interface. + /// An original IDL definition of clip property was the following: BSTR clip; + // IDL: BSTR clip; + // VB6: clip As String + string clip + { + // IDL: HRESULT clip ([out, retval] BSTR* ReturnValue); + // VB6: Function clip As String + [DispId(-2147413020)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT clip (BSTR value); + // VB6: Sub clip (ByVal value As String) + [DispId(-2147413020)] set; + } + + /// color property of IHTMLStyle interface. + /// An original IDL definition of color property was the following: VARIANT color; + // IDL: VARIANT color; + // VB6: color As Any + object color + { + // IDL: HRESULT color ([out, retval] VARIANT* ReturnValue); + // VB6: Function color As Any + [DispId(-2147413110)] get; + // IDL: HRESULT color (VARIANT value); + // VB6: Sub color (ByVal value As Any) + [DispId(-2147413110)] set; + } + + /// cssText property of IHTMLStyle interface. + /// An original IDL definition of cssText property was the following: BSTR cssText; + // IDL: BSTR cssText; + // VB6: cssText As String + string cssText + { + // IDL: HRESULT cssText ([out, retval] BSTR* ReturnValue); + // VB6: Function cssText As String + [DispId(-2147413013)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT cssText (BSTR value); + // VB6: Sub cssText (ByVal value As String) + [DispId(-2147413013)] set; + } + + /// cursor property of IHTMLStyle interface. + /// An original IDL definition of cursor property was the following: BSTR cursor; + // IDL: BSTR cursor; + // VB6: cursor As String + string cursor + { + // IDL: HRESULT cursor ([out, retval] BSTR* ReturnValue); + // VB6: Function cursor As String + [DispId(-2147413010)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT cursor (BSTR value); + // VB6: Sub cursor (ByVal value As String) + [DispId(-2147413010)] set; + } + + /// display property of IHTMLStyle interface. + /// An original IDL definition of display property was the following: BSTR display; + // IDL: BSTR display; + // VB6: display As String + string display + { + // IDL: HRESULT display ([out, retval] BSTR* ReturnValue); + // VB6: Function display As String + [DispId(-2147413041)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT display (BSTR value); + // VB6: Sub display (ByVal value As String) + [DispId(-2147413041)] set; + } + + /// filter property of IHTMLStyle interface. + /// An original IDL definition of filter property was the following: BSTR filter; + // IDL: BSTR filter; + // VB6: filter As String + string filter + { + // IDL: HRESULT filter ([out, retval] BSTR* ReturnValue); + // VB6: Function filter As String + [DispId(-2147413030)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT filter (BSTR value); + // VB6: Sub filter (ByVal value As String) + [DispId(-2147413030)] set; + } + + /// font property of IHTMLStyle interface. + /// An original IDL definition of font property was the following: BSTR font; + // IDL: BSTR font; + // VB6: font As String + string font + { + // IDL: HRESULT font ([out, retval] BSTR* ReturnValue); + // VB6: Function font As String + [DispId(-2147413071)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT font (BSTR value); + // VB6: Sub font (ByVal value As String) + [DispId(-2147413071)] set; + } + + /// fontFamily property of IHTMLStyle interface. + /// An original IDL definition of fontFamily property was the following: BSTR fontFamily; + // IDL: BSTR fontFamily; + // VB6: fontFamily As String + string fontFamily + { + // IDL: HRESULT fontFamily ([out, retval] BSTR* ReturnValue); + // VB6: Function fontFamily As String + [DispId(-2147413094)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT fontFamily (BSTR value); + // VB6: Sub fontFamily (ByVal value As String) + [DispId(-2147413094)] set; + } + + /// fontSize property of IHTMLStyle interface. + /// An original IDL definition of fontSize property was the following: VARIANT fontSize; + // IDL: VARIANT fontSize; + // VB6: fontSize As Any + object fontSize + { + // IDL: HRESULT fontSize ([out, retval] VARIANT* ReturnValue); + // VB6: Function fontSize As Any + [DispId(-2147413093)] get; + // IDL: HRESULT fontSize (VARIANT value); + // VB6: Sub fontSize (ByVal value As Any) + [DispId(-2147413093)] set; + } + + /// fontStyle property of IHTMLStyle interface. + /// An original IDL definition of fontStyle property was the following: BSTR fontStyle; + // IDL: BSTR fontStyle; + // VB6: fontStyle As String + string fontStyle + { + // IDL: HRESULT fontStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function fontStyle As String + [DispId(-2147413088)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT fontStyle (BSTR value); + // VB6: Sub fontStyle (ByVal value As String) + [DispId(-2147413088)] set; + } + + /// fontVariant property of IHTMLStyle interface. + /// An original IDL definition of fontVariant property was the following: BSTR fontVariant; + // IDL: BSTR fontVariant; + // VB6: fontVariant As String + string fontVariant + { + // IDL: HRESULT fontVariant ([out, retval] BSTR* ReturnValue); + // VB6: Function fontVariant As String + [DispId(-2147413087)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT fontVariant (BSTR value); + // VB6: Sub fontVariant (ByVal value As String) + [DispId(-2147413087)] set; + } + + /// fontWeight property of IHTMLStyle interface. + /// An original IDL definition of fontWeight property was the following: BSTR fontWeight; + // IDL: BSTR fontWeight; + // VB6: fontWeight As String + string fontWeight + { + // IDL: HRESULT fontWeight ([out, retval] BSTR* ReturnValue); + // VB6: Function fontWeight As String + [DispId(-2147413085)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT fontWeight (BSTR value); + // VB6: Sub fontWeight (ByVal value As String) + [DispId(-2147413085)] set; + } + + /// height property of IHTMLStyle interface. + /// An original IDL definition of height property was the following: VARIANT height; + // IDL: VARIANT height; + // VB6: height As Any + object height + { + // IDL: HRESULT height ([out, retval] VARIANT* ReturnValue); + // VB6: Function height As Any + [DispId(-2147418106)] get; + // IDL: HRESULT height (VARIANT value); + // VB6: Sub height (ByVal value As Any) + [DispId(-2147418106)] set; + } + + /// left property of IHTMLStyle interface. + /// An original IDL definition of left property was the following: VARIANT left; + // IDL: VARIANT left; + // VB6: left As Any + object left + { + // IDL: HRESULT left ([out, retval] VARIANT* ReturnValue); + // VB6: Function left As Any + [DispId(-2147418109)] get; + // IDL: HRESULT left (VARIANT value); + // VB6: Sub left (ByVal value As Any) + [DispId(-2147418109)] set; + } + + /// letterSpacing property of IHTMLStyle interface. + /// An original IDL definition of letterSpacing property was the following: VARIANT letterSpacing; + // IDL: VARIANT letterSpacing; + // VB6: letterSpacing As Any + object letterSpacing + { + // IDL: HRESULT letterSpacing ([out, retval] VARIANT* ReturnValue); + // VB6: Function letterSpacing As Any + [DispId(-2147413104)] get; + // IDL: HRESULT letterSpacing (VARIANT value); + // VB6: Sub letterSpacing (ByVal value As Any) + [DispId(-2147413104)] set; + } + + /// lineHeight property of IHTMLStyle interface. + /// An original IDL definition of lineHeight property was the following: VARIANT lineHeight; + // IDL: VARIANT lineHeight; + // VB6: lineHeight As Any + object lineHeight + { + // IDL: HRESULT lineHeight ([out, retval] VARIANT* ReturnValue); + // VB6: Function lineHeight As Any + [DispId(-2147413106)] get; + // IDL: HRESULT lineHeight (VARIANT value); + // VB6: Sub lineHeight (ByVal value As Any) + [DispId(-2147413106)] set; + } + + /// listStyle property of IHTMLStyle interface. + /// An original IDL definition of listStyle property was the following: BSTR listStyle; + // IDL: BSTR listStyle; + // VB6: listStyle As String + string listStyle + { + // IDL: HRESULT listStyle ([out, retval] BSTR* ReturnValue); + // VB6: Function listStyle As String + [DispId(-2147413037)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT listStyle (BSTR value); + // VB6: Sub listStyle (ByVal value As String) + [DispId(-2147413037)] set; + } + + /// listStyleImage property of IHTMLStyle interface. + /// An original IDL definition of listStyleImage property was the following: BSTR listStyleImage; + // IDL: BSTR listStyleImage; + // VB6: listStyleImage As String + string listStyleImage + { + // IDL: HRESULT listStyleImage ([out, retval] BSTR* ReturnValue); + // VB6: Function listStyleImage As String + [DispId(-2147413038)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT listStyleImage (BSTR value); + // VB6: Sub listStyleImage (ByVal value As String) + [DispId(-2147413038)] set; + } + + /// listStylePosition property of IHTMLStyle interface. + /// An original IDL definition of listStylePosition property was the following: BSTR listStylePosition; + // IDL: BSTR listStylePosition; + // VB6: listStylePosition As String + string listStylePosition + { + // IDL: HRESULT listStylePosition ([out, retval] BSTR* ReturnValue); + // VB6: Function listStylePosition As String + [DispId(-2147413039)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT listStylePosition (BSTR value); + // VB6: Sub listStylePosition (ByVal value As String) + [DispId(-2147413039)] set; + } + + /// listStyleType property of IHTMLStyle interface. + /// An original IDL definition of listStyleType property was the following: BSTR listStyleType; + // IDL: BSTR listStyleType; + // VB6: listStyleType As String + string listStyleType + { + // IDL: HRESULT listStyleType ([out, retval] BSTR* ReturnValue); + // VB6: Function listStyleType As String + [DispId(-2147413040)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT listStyleType (BSTR value); + // VB6: Sub listStyleType (ByVal value As String) + [DispId(-2147413040)] set; + } + + /// margin property of IHTMLStyle interface. + /// An original IDL definition of margin property was the following: BSTR margin; + // IDL: BSTR margin; + // VB6: margin As String + string margin + { + // IDL: HRESULT margin ([out, retval] BSTR* ReturnValue); + // VB6: Function margin As String + [DispId(-2147413076)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT margin (BSTR value); + // VB6: Sub margin (ByVal value As String) + [DispId(-2147413076)] set; + } + + /// marginBottom property of IHTMLStyle interface. + /// An original IDL definition of marginBottom property was the following: VARIANT marginBottom; + // IDL: VARIANT marginBottom; + // VB6: marginBottom As Any + object marginBottom + { + // IDL: HRESULT marginBottom ([out, retval] VARIANT* ReturnValue); + // VB6: Function marginBottom As Any + [DispId(-2147413073)] get; + // IDL: HRESULT marginBottom (VARIANT value); + // VB6: Sub marginBottom (ByVal value As Any) + [DispId(-2147413073)] set; + } + + /// marginLeft property of IHTMLStyle interface. + /// An original IDL definition of marginLeft property was the following: VARIANT marginLeft; + // IDL: VARIANT marginLeft; + // VB6: marginLeft As Any + object marginLeft + { + // IDL: HRESULT marginLeft ([out, retval] VARIANT* ReturnValue); + // VB6: Function marginLeft As Any + [DispId(-2147413072)] get; + // IDL: HRESULT marginLeft (VARIANT value); + // VB6: Sub marginLeft (ByVal value As Any) + [DispId(-2147413072)] set; + } + + /// marginRight property of IHTMLStyle interface. + /// An original IDL definition of marginRight property was the following: VARIANT marginRight; + // IDL: VARIANT marginRight; + // VB6: marginRight As Any + object marginRight + { + // IDL: HRESULT marginRight ([out, retval] VARIANT* ReturnValue); + // VB6: Function marginRight As Any + [DispId(-2147413074)] get; + // IDL: HRESULT marginRight (VARIANT value); + // VB6: Sub marginRight (ByVal value As Any) + [DispId(-2147413074)] set; + } + + /// marginTop property of IHTMLStyle interface. + /// An original IDL definition of marginTop property was the following: VARIANT marginTop; + // IDL: VARIANT marginTop; + // VB6: marginTop As Any + object marginTop + { + // IDL: HRESULT marginTop ([out, retval] VARIANT* ReturnValue); + // VB6: Function marginTop As Any + [DispId(-2147413075)] get; + // IDL: HRESULT marginTop (VARIANT value); + // VB6: Sub marginTop (ByVal value As Any) + [DispId(-2147413075)] set; + } + + /// overflow property of IHTMLStyle interface. + /// An original IDL definition of overflow property was the following: BSTR overflow; + // IDL: BSTR overflow; + // VB6: overflow As String + string overflow + { + // IDL: HRESULT overflow ([out, retval] BSTR* ReturnValue); + // VB6: Function overflow As String + [DispId(-2147413102)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT overflow (BSTR value); + // VB6: Sub overflow (ByVal value As String) + [DispId(-2147413102)] set; + } + + /// padding property of IHTMLStyle interface. + /// An original IDL definition of padding property was the following: BSTR padding; + // IDL: BSTR padding; + // VB6: padding As String + string padding + { + // IDL: HRESULT padding ([out, retval] BSTR* ReturnValue); + // VB6: Function padding As String + [DispId(-2147413101)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + // IDL: HRESULT padding (BSTR value); + // VB6: Sub padding (ByVal value As String) + [DispId(-2147413101)] set; + } + + /// paddingBottom property of IHTMLStyle interface. + /// An original IDL definition of paddingBottom property was the following: VARIANT paddingBottom; + // IDL: VARIANT paddingBottom; + // VB6: paddingBottom As Any + object paddingBottom + { + // IDL: HRESULT paddingBottom ([out, retval] VARIANT* ReturnValue); + // VB6: Function paddingBottom As Any + [DispId(-2147413098)] get; + // IDL: HRESULT paddingBottom (VARIANT value); + // VB6: Sub paddingBottom (ByVal value As Any) + [DispId(-2147413098)] set; + } + + /// paddingLeft property of IHTMLStyle interface. + /// An original IDL definition of paddingLeft property was the following: VARIANT paddingLeft; + // IDL: VARIANT paddingLeft; + // VB6: paddingLeft As Any + object paddingLeft + { + // IDL: HRESULT paddingLeft ([out, retval] VARIANT* ReturnValue); + // VB6: Function paddingLeft As Any + [DispId(-2147413097)] get; + // IDL: HRESULT paddingLeft (VARIANT value); + // VB6: Sub paddingLeft (ByVal value As Any) + [DispId(-2147413097)] set; + } + + /// paddingRight property of IHTMLStyle interface. + object paddingRight { [DispId(-2147413099)] get; } + + /// paddingTop property of IHTMLStyle interface. + object paddingTop { [DispId(-2147413100)] get; } + + /// pageBreakAfter property of IHTMLStyle interface. + string pageBreakAfter + { + [DispId(-2147413034)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// pageBreakBefore property of IHTMLStyle interface. + string pageBreakBefore + { + [DispId(-2147413035)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// pixelHeight property of IHTMLStyle interface. + int pixelHeight { [DispId(-2147414109)] get; } + + /// pixelLeft property of IHTMLStyle interface. + int pixelLeft { [DispId(-2147414111)] get; } + + /// pixelTop property of IHTMLStyle interface. + int pixelTop { [DispId(-2147414112)] get; } + + /// pixelWidth property of IHTMLStyle interface. + int pixelWidth { [DispId(-2147414110)] get; } + + /// posHeight property of IHTMLStyle interface. + float posHeight { [DispId(-2147414105)] get; } + + /// position property of IHTMLStyle interface. + string position + { + [DispId(-2147413022)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// posLeft property of IHTMLStyle interface. + float posLeft { [DispId(-2147414107)] get; } + + /// posTop property of IHTMLStyle interface. + float posTop { [DispId(-2147414108)] get; } + + /// posWidth property of IHTMLStyle interface. + float posWidth { [DispId(-2147414106)] get; } + + /// styleFloat property of IHTMLStyle interface. + string styleFloat + { + [DispId(-2147413042)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// textAlign property of IHTMLStyle interface. + string textAlign + { + [DispId(-2147418040)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// textDecoration property of IHTMLStyle interface. + string textDecoration + { + [DispId(-2147413077)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// textDecorationBlink property of IHTMLStyle interface. + bool textDecorationBlink + { + [DispId(-2147413090)] + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + /// textDecorationLineThrough property of IHTMLStyle interface. + bool textDecorationLineThrough + { + [DispId(-2147413092)] + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + /// textDecorationNone property of IHTMLStyle interface. + bool textDecorationNone + { + [DispId(-2147413089)] + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + /// textDecorationOverline property of IHTMLStyle interface. + bool textDecorationOverline + { + [DispId(-2147413043)] + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + /// textDecorationUnderline property of IHTMLStyle interface. + bool textDecorationUnderline + { + [DispId(-2147413091)] + [return: MarshalAs(UnmanagedType.VariantBool)] + get; + } + + /// textIndent property of IHTMLStyle interface. + object textIndent { [DispId(-2147413105)] get; } + + /// textTransform property of IHTMLStyle interface. + string textTransform + { + [DispId(-2147413108)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// top property of IHTMLStyle interface. + object top { [DispId(-2147418108)] get; } + + /// verticalAlign property of IHTMLStyle interface. + object verticalAlign { [DispId(-2147413064)] get; } + + /// visibility property of IHTMLStyle interface. + string visibility + { + [DispId(-2147413032)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// whiteSpace property of IHTMLStyle interface. + string whiteSpace + { + [DispId(-2147413036)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + /// width property of IHTMLStyle interface. + object width { [DispId(-2147418107)] get; } + + /// wordSpacing property of IHTMLStyle interface. + object wordSpacing { [DispId(-2147413065)] get; } + + /// zIndex property of IHTMLStyle interface. + object zIndex { [DispId(-2147413021)] get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLTxtRange.cs b/src/Greenshot.Base/IEInterop/IHTMLTxtRange.cs similarity index 96% rename from src/GreenshotPlugin/IEInterop/IHTMLTxtRange.cs rename to src/Greenshot.Base/IEInterop/IHTMLTxtRange.cs index 2a2cf3986..8f77258f1 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLTxtRange.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLTxtRange.cs @@ -1,141 +1,141 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - // See: http://msdn.microsoft.com/en-us/library/aa741548%28v=vs.85%29.aspx - [ComImport, Guid("3050F220-98B5-11CF-BB82-00AA00BDCE0B"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLTxtRange - { - [DispId(1006)] - IHTMLElement parentElement(); - - [DispId(1008)] - IHTMLTxtRange duplicate(); - - [DispId(1010)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool inRange(IHTMLTxtRange range); - - [DispId(1011)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool isEqual(IHTMLTxtRange range); - - [DispId(1012)] - void scrollIntoView([MarshalAs(UnmanagedType.VariantBool)] bool fStart); - - [DispId(1013)] - void collapse([MarshalAs(UnmanagedType.VariantBool)] bool Start); - - [DispId(1014)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool expand([MarshalAs(UnmanagedType.BStr)] string Unit); - - [DispId(1015)] - int move([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); - - [DispId(1016)] - int moveStart([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); - - [DispId(1017)] - int moveEnd([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); - - [DispId(1024)] - void select(); - - [DispId(1026)] - void pasteHTML([MarshalAs(UnmanagedType.BStr)] string html); - - [DispId(1001)] - void moveToElementText(IHTMLElement element); - - [DispId(1025)] - void setEndPoint([MarshalAs(UnmanagedType.BStr)] string how, IHTMLTxtRange SourceRange); - - [DispId(1018)] - int compareEndPoints([MarshalAs(UnmanagedType.BStr)] string how, IHTMLTxtRange SourceRange); - - [DispId(1019)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool findText([MarshalAs(UnmanagedType.BStr)] string String, int Count, int Flags); - - [DispId(1020)] - void moveToPoint(int x, int y); - - [DispId(1021)] - [return: MarshalAs(UnmanagedType.BStr)] - string getBookmark(); - - [DispId(1009)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool moveToBookmark([MarshalAs(UnmanagedType.BStr)] string Bookmark); - - [DispId(1027)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool queryCommandSupported([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1028)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool queryCommandEnabled([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1029)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool queryCommandState([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1030)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool queryCommandIndeterm([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1031)] - [return: MarshalAs(UnmanagedType.BStr)] - string queryCommandText([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1032)] - object queryCommandValue([MarshalAs(UnmanagedType.BStr)] string cmdID); - - [DispId(1033)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool execCommand([MarshalAs(UnmanagedType.BStr)] string cmdID, [MarshalAs(UnmanagedType.VariantBool)] bool showUI, object value); - - [DispId(1034)] - [return: MarshalAs(UnmanagedType.VariantBool)] - bool execCommandShowHelp([MarshalAs(UnmanagedType.BStr)] string cmdID); - - string htmlText - { - [DispId(1003)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - - string text - { - [DispId(1004)] - [return: MarshalAs(UnmanagedType.BStr)] - get; - [DispId(1004)] set; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + // See: http://msdn.microsoft.com/en-us/library/aa741548%28v=vs.85%29.aspx + [ComImport, Guid("3050F220-98B5-11CF-BB82-00AA00BDCE0B"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLTxtRange + { + [DispId(1006)] + IHTMLElement parentElement(); + + [DispId(1008)] + IHTMLTxtRange duplicate(); + + [DispId(1010)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool inRange(IHTMLTxtRange range); + + [DispId(1011)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool isEqual(IHTMLTxtRange range); + + [DispId(1012)] + void scrollIntoView([MarshalAs(UnmanagedType.VariantBool)] bool fStart); + + [DispId(1013)] + void collapse([MarshalAs(UnmanagedType.VariantBool)] bool Start); + + [DispId(1014)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool expand([MarshalAs(UnmanagedType.BStr)] string Unit); + + [DispId(1015)] + int move([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); + + [DispId(1016)] + int moveStart([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); + + [DispId(1017)] + int moveEnd([MarshalAs(UnmanagedType.BStr)] string Unit, int Count); + + [DispId(1024)] + void select(); + + [DispId(1026)] + void pasteHTML([MarshalAs(UnmanagedType.BStr)] string html); + + [DispId(1001)] + void moveToElementText(IHTMLElement element); + + [DispId(1025)] + void setEndPoint([MarshalAs(UnmanagedType.BStr)] string how, IHTMLTxtRange SourceRange); + + [DispId(1018)] + int compareEndPoints([MarshalAs(UnmanagedType.BStr)] string how, IHTMLTxtRange SourceRange); + + [DispId(1019)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool findText([MarshalAs(UnmanagedType.BStr)] string String, int Count, int Flags); + + [DispId(1020)] + void moveToPoint(int x, int y); + + [DispId(1021)] + [return: MarshalAs(UnmanagedType.BStr)] + string getBookmark(); + + [DispId(1009)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool moveToBookmark([MarshalAs(UnmanagedType.BStr)] string Bookmark); + + [DispId(1027)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool queryCommandSupported([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1028)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool queryCommandEnabled([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1029)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool queryCommandState([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1030)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool queryCommandIndeterm([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1031)] + [return: MarshalAs(UnmanagedType.BStr)] + string queryCommandText([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1032)] + object queryCommandValue([MarshalAs(UnmanagedType.BStr)] string cmdID); + + [DispId(1033)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool execCommand([MarshalAs(UnmanagedType.BStr)] string cmdID, [MarshalAs(UnmanagedType.VariantBool)] bool showUI, object value); + + [DispId(1034)] + [return: MarshalAs(UnmanagedType.VariantBool)] + bool execCommandShowHelp([MarshalAs(UnmanagedType.BStr)] string cmdID); + + string htmlText + { + [DispId(1003)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + string text + { + [DispId(1004)] + [return: MarshalAs(UnmanagedType.BStr)] + get; + [DispId(1004)] set; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLWindow2.cs b/src/Greenshot.Base/IEInterop/IHTMLWindow2.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLWindow2.cs rename to src/Greenshot.Base/IEInterop/IHTMLWindow2.cs index 316aa821c..c37956cf0 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLWindow2.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLWindow2.cs @@ -1,52 +1,52 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComVisible(true), ComImport(), Guid("332c4427-26cb-11d0-b483-00c04fd90119"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLWindow2 - { - [DispId(1156)] - IHTMLScreen screen - { - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(1151)] - IHTMLDocument2 document - { - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(11)] - string name - { - [return: MarshalAs(UnmanagedType.BStr)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComVisible(true), ComImport(), Guid("332c4427-26cb-11d0-b483-00c04fd90119"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLWindow2 + { + [DispId(1156)] + IHTMLScreen screen + { + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(1151)] + IHTMLDocument2 document + { + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(11)] + string name + { + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLWindow3.cs b/src/Greenshot.Base/IEInterop/IHTMLWindow3.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLWindow3.cs rename to src/Greenshot.Base/IEInterop/IHTMLWindow3.cs index 47089f067..2e8e4f095 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLWindow3.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLWindow3.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComVisible(true), ComImport(), Guid("3050f4ae-98b5-11cf-bb82-00aa00bdce0b"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLWindow3 - { - [DispId(1170)] int screenLeft { get; } - - [DispId(1171)] int screenTop { get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComVisible(true), ComImport(), Guid("3050f4ae-98b5-11cf-bb82-00aa00bdce0b"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLWindow3 + { + [DispId(1170)] int screenLeft { get; } + + [DispId(1171)] int screenTop { get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IHTMLWindow4.cs b/src/Greenshot.Base/IEInterop/IHTMLWindow4.cs similarity index 94% rename from src/GreenshotPlugin/IEInterop/IHTMLWindow4.cs rename to src/Greenshot.Base/IEInterop/IHTMLWindow4.cs index 1409852fb..c97982afc 100644 --- a/src/GreenshotPlugin/IEInterop/IHTMLWindow4.cs +++ b/src/Greenshot.Base/IEInterop/IHTMLWindow4.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - [ComVisible(true), ComImport(), Guid("3050f6cf-98b5-11cf-bb82-00aa00bdce0b"), - TypeLibType(TypeLibTypeFlags.FDual), - InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IHTMLWindow4 - { - [DispId(1181)] - IHTMLFrameBase frameElement - { - [return: MarshalAs(UnmanagedType.IDispatch)] - get; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + [ComVisible(true), ComImport(), Guid("3050f6cf-98b5-11cf-bb82-00aa00bdce0b"), + TypeLibType(TypeLibTypeFlags.FDual), + InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IHTMLWindow4 + { + [DispId(1181)] + IHTMLFrameBase frameElement + { + [return: MarshalAs(UnmanagedType.IDispatch)] + get; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IEInterop/IWebBrowser2.cs b/src/Greenshot.Base/IEInterop/IWebBrowser2.cs similarity index 96% rename from src/GreenshotPlugin/IEInterop/IWebBrowser2.cs rename to src/Greenshot.Base/IEInterop/IWebBrowser2.cs index 5a4a4c5d5..3a500338a 100644 --- a/src/GreenshotPlugin/IEInterop/IWebBrowser2.cs +++ b/src/Greenshot.Base/IEInterop/IWebBrowser2.cs @@ -1,152 +1,152 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.IEInterop -{ - // IWebBrowser: EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B -// [ComVisible(true), ComImport(), Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"), -// TypeLibType(TypeLibTypeFlags.FDual), -// InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] -// public interface IWebBrowser2 { -// [DispId(203)] -// object Document { -// [return: MarshalAs(UnmanagedType.IDispatch)] -// get; -// } -// } - [ComImport, /*SuppressUnmanagedCodeSecurity,*/ - TypeLibType(TypeLibTypeFlags.FOleAutomation | - TypeLibTypeFlags.FDual | - TypeLibTypeFlags.FHidden), - Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")] - public interface IWebBrowser2 - { - [DispId(100)] - void GoBack(); - - [DispId(0x65)] - void GoForward(); - - [DispId(0x66)] - void GoHome(); - - [DispId(0x67)] - void GoSearch(); - - [DispId(0x68)] - void Navigate([In] string Url, - [In] ref object flags, - [In] ref object targetFrameName, - [In] ref object postData, - [In] ref object headers); - - [DispId(-550)] - void Refresh(); - - [DispId(0x69)] - void Refresh2([In] ref object level); - - [DispId(0x6a)] - void Stop(); - - [DispId(200)] - object Application - { - [return: - MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(0xc9)] - object Parent - { - [return: - MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(0xca)] - object Container - { - [return: - MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(0xcb)] - object Document - { - [return: - MarshalAs(UnmanagedType.IDispatch)] - get; - } - - [DispId(0xcc)] bool TopLevelContainer { get; } - [DispId(0xcd)] string Type { get; } - [DispId(0xce)] int Left { get; set; } - [DispId(0xcf)] int Top { get; set; } - [DispId(0xd0)] int Width { get; set; } - [DispId(0xd1)] int Height { get; set; } - [DispId(210)] string LocationName { get; } - [DispId(0xd3)] string LocationURL { get; } - [DispId(0xd4)] bool Busy { get; } - - [DispId(300)] - void Quit(); - - [DispId(0x12d)] - void ClientToWindow(out int pcx, out int pcy); - - [DispId(0x12e)] - void PutProperty([In] string property, [In] object vtValue); - - [DispId(0x12f)] - object GetProperty([In] string property); - - [DispId(0)] string Name { get; } - [DispId(-515)] int HWND { get; } - [DispId(400)] string FullName { get; } - [DispId(0x191)] string Path { get; } - [DispId(0x192)] bool Visible { get; set; } - [DispId(0x193)] bool StatusBar { get; set; } - [DispId(0x194)] string StatusText { get; set; } - [DispId(0x195)] int ToolBar { get; set; } - [DispId(0x196)] bool MenuBar { get; set; } - [DispId(0x197)] bool FullScreen { get; set; } - - [DispId(500)] - void Navigate2([In] ref object URL, - [In] ref object flags, - [In] ref object targetFrameName, - [In] ref object postData, - [In] ref object headers); - - [DispId(550)] bool Offline { get; set; } - [DispId(0x227)] bool Silent { get; set; } - [DispId(0x228)] bool RegisterAsBrowser { get; set; } - [DispId(0x229)] bool RegisterAsDropTarget { get; set; } - [DispId(0x22a)] bool TheaterMode { get; set; } - [DispId(0x22b)] bool AddressBar { get; set; } - [DispId(0x22c)] bool Resizable { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; + +namespace Greenshot.Base.IEInterop +{ + // IWebBrowser: EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B +// [ComVisible(true), ComImport(), Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"), +// TypeLibType(TypeLibTypeFlags.FDual), +// InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] +// public interface IWebBrowser2 { +// [DispId(203)] +// object Document { +// [return: MarshalAs(UnmanagedType.IDispatch)] +// get; +// } +// } + [ComImport, /*SuppressUnmanagedCodeSecurity,*/ + TypeLibType(TypeLibTypeFlags.FOleAutomation | + TypeLibTypeFlags.FDual | + TypeLibTypeFlags.FHidden), + Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")] + public interface IWebBrowser2 + { + [DispId(100)] + void GoBack(); + + [DispId(0x65)] + void GoForward(); + + [DispId(0x66)] + void GoHome(); + + [DispId(0x67)] + void GoSearch(); + + [DispId(0x68)] + void Navigate([In] string Url, + [In] ref object flags, + [In] ref object targetFrameName, + [In] ref object postData, + [In] ref object headers); + + [DispId(-550)] + void Refresh(); + + [DispId(0x69)] + void Refresh2([In] ref object level); + + [DispId(0x6a)] + void Stop(); + + [DispId(200)] + object Application + { + [return: + MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(0xc9)] + object Parent + { + [return: + MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(0xca)] + object Container + { + [return: + MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(0xcb)] + object Document + { + [return: + MarshalAs(UnmanagedType.IDispatch)] + get; + } + + [DispId(0xcc)] bool TopLevelContainer { get; } + [DispId(0xcd)] string Type { get; } + [DispId(0xce)] int Left { get; set; } + [DispId(0xcf)] int Top { get; set; } + [DispId(0xd0)] int Width { get; set; } + [DispId(0xd1)] int Height { get; set; } + [DispId(210)] string LocationName { get; } + [DispId(0xd3)] string LocationURL { get; } + [DispId(0xd4)] bool Busy { get; } + + [DispId(300)] + void Quit(); + + [DispId(0x12d)] + void ClientToWindow(out int pcx, out int pcy); + + [DispId(0x12e)] + void PutProperty([In] string property, [In] object vtValue); + + [DispId(0x12f)] + object GetProperty([In] string property); + + [DispId(0)] string Name { get; } + [DispId(-515)] int HWND { get; } + [DispId(400)] string FullName { get; } + [DispId(0x191)] string Path { get; } + [DispId(0x192)] bool Visible { get; set; } + [DispId(0x193)] bool StatusBar { get; set; } + [DispId(0x194)] string StatusText { get; set; } + [DispId(0x195)] int ToolBar { get; set; } + [DispId(0x196)] bool MenuBar { get; set; } + [DispId(0x197)] bool FullScreen { get; set; } + + [DispId(500)] + void Navigate2([In] ref object URL, + [In] ref object flags, + [In] ref object targetFrameName, + [In] ref object postData, + [In] ref object headers); + + [DispId(550)] bool Offline { get; set; } + [DispId(0x227)] bool Silent { get; set; } + [DispId(0x228)] bool RegisterAsBrowser { get; set; } + [DispId(0x229)] bool RegisterAsDropTarget { get; set; } + [DispId(0x22a)] bool TheaterMode { get; set; } + [DispId(0x22b)] bool AddressBar { get; set; } + [DispId(0x22c)] bool Resizable { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IniFile/IniAttributes.cs b/src/Greenshot.Base/IniFile/IniAttributes.cs similarity index 95% rename from src/GreenshotPlugin/IniFile/IniAttributes.cs rename to src/Greenshot.Base/IniFile/IniAttributes.cs index 6f41b98b5..4563a406b 100644 --- a/src/GreenshotPlugin/IniFile/IniAttributes.cs +++ b/src/Greenshot.Base/IniFile/IniAttributes.cs @@ -1,71 +1,71 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.IniFile -{ - /// - /// Attribute for telling that this class is linked to a section in the ini-configuration - /// - [AttributeUsage(AttributeTargets.Class)] - public class IniSectionAttribute : Attribute - { - public IniSectionAttribute(string name) - { - Name = name; - } - - public string Description; - public string Name { get; set; } - } - - /// - /// Attribute for telling that a field is linked to a property in the ini-configuration selection - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - public class IniPropertyAttribute : Attribute - { - public IniPropertyAttribute() - { - Separator = ","; - } - - public IniPropertyAttribute(string name) : this() - { - Name = name; - } - - public string Description { get; set; } - public string Separator { get; set; } - public string DefaultValue { get; set; } - - public string LanguageKey { get; set; } - - // If Encrypted is set to true, the value will be decrypted on load and encrypted on save - public bool Encrypted { get; set; } - public bool FixedValue { get; set; } - public bool Expert { get; set; } - public bool ExcludeIfNull { get; set; } - - public string Name { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.IniFile +{ + /// + /// Attribute for telling that this class is linked to a section in the ini-configuration + /// + [AttributeUsage(AttributeTargets.Class)] + public class IniSectionAttribute : Attribute + { + public IniSectionAttribute(string name) + { + Name = name; + } + + public string Description; + public string Name { get; set; } + } + + /// + /// Attribute for telling that a field is linked to a property in the ini-configuration selection + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + public class IniPropertyAttribute : Attribute + { + public IniPropertyAttribute() + { + Separator = ","; + } + + public IniPropertyAttribute(string name) : this() + { + Name = name; + } + + public string Description { get; set; } + public string Separator { get; set; } + public string DefaultValue { get; set; } + + public string LanguageKey { get; set; } + + // If Encrypted is set to true, the value will be decrypted on load and encrypted on save + public bool Encrypted { get; set; } + public bool FixedValue { get; set; } + public bool Expert { get; set; } + public bool ExcludeIfNull { get; set; } + + public string Name { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IniFile/IniConfig.cs b/src/Greenshot.Base/IniFile/IniConfig.cs similarity index 97% rename from src/GreenshotPlugin/IniFile/IniConfig.cs rename to src/Greenshot.Base/IniFile/IniConfig.cs index 691bd6eb2..57bc8f55e 100644 --- a/src/GreenshotPlugin/IniFile/IniConfig.cs +++ b/src/Greenshot.Base/IniFile/IniConfig.cs @@ -1,574 +1,574 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using log4net; - -namespace GreenshotPlugin.IniFile -{ - public class IniConfig - { - private static readonly ILog Log = LogManager.GetLogger(typeof(IniConfig)); - private const string IniExtension = ".ini"; - private const string DefaultsPostfix = "-defaults"; - private const string FixedPostfix = "-fixed"; - - /// - /// A lock object for the ini file saving - /// - private static readonly object IniLock = new object(); - - /// - /// As the ini implementation is kept someone generic, for reusing, this holds the name of the application - /// - private static string _applicationName; - - /// - /// As the ini implementation is kept someone generic, for reusing, this holds the name of the configuration - /// - private static string _configName; - - /// - /// A Dictionary with all the sections stored by section name - /// - private static readonly IDictionary SectionMap = new Dictionary(); - - /// - /// A Dictionary with the properties for a section stored by section name - /// - private static IDictionary> _sections = new Dictionary>(); - - /// - /// A Dictionary with the fixed-properties for a section stored by section name - /// - private static IDictionary> _fixedProperties; - - /// - /// Stores if we checked for portable - /// - private static bool _portableCheckMade; - - /// - /// Is the configuration portable (meaning we don't store it in the AppData directory) - /// - public static bool IsPortable { get; private set; } - - /// - /// Config directory when set from external - /// - public static string IniDirectory { get; set; } - - /// - /// Initialize the ini config - /// - /// - /// - public static void Init(string appName, string configName) - { - _applicationName = appName; - _configName = configName; - Reload(); - } - - /// - /// Checks if we initialized the ini - /// - public static bool IsInitialized => _applicationName != null && _configName != null && SectionMap.Count > 0; - - /// - /// This forces the ini to be stored in the startup path, used for portable applications - /// - public static void ForceIniInStartupPath() - { - if (_portableCheckMade) - { - throw new Exception("ForceLocal should be called before any file is read"); - } - - IsPortable = false; - _portableCheckMade = true; - string applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - if (_applicationName == null || _configName == null) - { - Init(); - } - - if (applicationStartupPath == null) - { - return; - } - - string forcedIni = Path.Combine(applicationStartupPath, _applicationName + IniExtension); - if (!File.Exists(forcedIni)) - { - using (File.Create(forcedIni)) - { - } - } - } - - /// - /// Default init - /// - public static void Init() - { - AssemblyProductAttribute[] assemblyProductAttributes = - Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false) as AssemblyProductAttribute[]; - if (assemblyProductAttributes != null && assemblyProductAttributes.Length > 0) - { - string productName = assemblyProductAttributes[0].Product; - Log.InfoFormat("Using ProductName {0}", productName); - Init(productName, productName); - } - else - { - throw new InvalidOperationException("Assembly ProductName not set."); - } - } - - /// - /// Get the location of the configuration - /// - public static string ConfigLocation - { - get - { - if (IsInitialized) - { - return CreateIniLocation(_configName + IniExtension, false); - } - - throw new InvalidOperationException("Ini configuration was not initialized!"); - } - } - - /// - /// Create the location of the configuration file - /// - private static string CreateIniLocation(string configFilename, bool isReadOnly) - { - if (_applicationName == null || _configName == null) - { - throw new InvalidOperationException("IniConfig.Init not called!"); - } - - string iniFilePath = null; - - // Check if a Ini-Directory was supplied, and it's valid, use this before any others. - try - { - if (IniDirectory != null && Directory.Exists(IniDirectory)) - { - // If the greenshot.ini is requested, use the supplied directory even if empty - if (!isReadOnly) - { - return Path.Combine(IniDirectory, configFilename); - } - - iniFilePath = Path.Combine(IniDirectory, configFilename); - if (File.Exists(iniFilePath)) - { - return iniFilePath; - } - - iniFilePath = null; - } - } - catch (Exception exception) - { - Log.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message); - } - - string applicationStartupPath; - try - { - applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - } - catch (Exception exception) - { - Log.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message); - applicationStartupPath = @"."; - } - - if (applicationStartupPath != null) - { - string pafPath = Path.Combine(applicationStartupPath, @"App\" + _applicationName); - - if (IsPortable || !_portableCheckMade) - { - if (!IsPortable) - { - Log.Info("Checking for portable mode."); - _portableCheckMade = true; - if (Directory.Exists(pafPath)) - { - IsPortable = true; - Log.Info("Portable mode active!"); - } - } - - if (IsPortable) - { - string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings"); - try - { - if (!Directory.Exists(pafConfigPath)) - { - Directory.CreateDirectory(pafConfigPath); - } - - iniFilePath = Path.Combine(pafConfigPath, configFilename); - } - catch (Exception e) - { - Log.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message); - } - } - } - } - - if (iniFilePath == null) - { - // check if file is in the same location as started from, if this is the case - // we will use this file instead of the ApplicationData folder - // Done for Feature Request #2741508 - if (applicationStartupPath != null) - { - iniFilePath = Path.Combine(applicationStartupPath, configFilename); - } - - if (!File.Exists(iniFilePath)) - { - string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), _applicationName); - if (!Directory.Exists(iniDirectory)) - { - Directory.CreateDirectory(iniDirectory); - } - - iniFilePath = Path.Combine(iniDirectory, configFilename); - } - } - - Log.InfoFormat("Using ini file {0}", iniFilePath); - return iniFilePath; - } - - /// - /// Reload the Ini file - /// - public static void Reload() - { - // Clear the current properties - _sections = new Dictionary>(); - // Load the defaults - Read(CreateIniLocation(_configName + DefaultsPostfix + IniExtension, true)); - // Load the normal - Read(CreateIniLocation(_configName + IniExtension, false)); - // Load the fixed settings - _fixedProperties = Read(CreateIniLocation(_configName + FixedPostfix + IniExtension, true)); - - foreach (IniSection section in SectionMap.Values) - { - try - { - section.Fill(PropertiesForSection(section)); - FixProperties(section); - } - catch (Exception ex) - { - string sectionName = "unknown"; - if (section?.IniSectionAttribute?.Name != null) - { - sectionName = section.IniSectionAttribute.Name; - } - - Log.WarnFormat("Problem reading the ini section {0}", sectionName); - Log.Warn("Exception", ex); - } - } - } - - /// - /// This "fixes" the properties of the section, meaning any properties in the fixed file can't be changed. - /// - /// IniSection - private static void FixProperties(IniSection section) - { - // Make properties unchangeable - if (_fixedProperties == null) - { - return; - } - - if (!_fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out var fixedPropertiesForSection)) - { - return; - } - - foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) - { - if (section.Values.ContainsKey(fixedPropertyKey)) - { - section.Values[fixedPropertyKey].IsFixed = true; - } - } - } - - /// - /// Read the ini file into the Dictionary - /// - /// Path & Filename of ini file - private static IDictionary> Read(string iniLocation) - { - if (!File.Exists(iniLocation)) - { - Log.Info("Can't find file: " + iniLocation); - return null; - } - - Log.InfoFormat("Loading ini-file: {0}", iniLocation); - //LOG.Info("Reading ini-properties from file: " + iniLocation); - var newSections = IniReader.Read(iniLocation, Encoding.UTF8); - // Merge the newly loaded properties to the already available - foreach (string section in newSections.Keys) - { - IDictionary newProperties = newSections[section]; - if (!_sections.ContainsKey(section)) - { - // This section is not yet loaded, simply add the complete section - _sections.Add(section, newProperties); - } - else - { - // Overwrite or add every property from the newly loaded section to the available one - var currentProperties = _sections[section]; - foreach (string propertyName in newProperties.Keys) - { - string propertyValue = newProperties[propertyName]; - if (currentProperties.ContainsKey(propertyName)) - { - // Override current value as we are loading in a certain order which insures the default, current and fixed - currentProperties[propertyName] = propertyValue; - } - else - { - // Add "new" value - currentProperties.Add(propertyName, propertyValue); - } - } - } - } - - return newSections; - } - - public static IEnumerable IniSectionNames - { - get - { - foreach (string sectionName in SectionMap.Keys) - { - yield return sectionName; - } - } - } - - /// - /// Method used for internal tricks... - /// - /// - /// - public static IniSection GetIniSection(string sectionName) - { - SectionMap.TryGetValue(sectionName, out var returnValue); - return returnValue; - } - - /// - /// A generic method which returns an instance of the supplied type, filled with it's configuration - /// - /// IniSection Type to get the configuration for - /// Filled instance of IniSection type which was supplied - public static T GetIniSection() where T : IniSection - { - return GetIniSection(true); - } - - /// - /// - /// - /// IniSection Type to get the configuration for - /// false to skip saving - /// IniSection - public static T GetIniSection(bool allowSave) where T : IniSection - { - T section; - - Type iniSectionType = typeof(T); - string sectionName = IniSection.GetIniSectionAttribute(iniSectionType).Name; - if (SectionMap.ContainsKey(sectionName)) - { - //LOG.Debug("Returning pre-mapped section " + sectionName); - section = (T) SectionMap[sectionName]; - } - else - { - // Create instance of this type - section = (T) Activator.CreateInstance(iniSectionType); - - // Store for later save & retrieval - SectionMap.Add(sectionName, section); - section.Fill(PropertiesForSection(section)); - FixProperties(section); - } - - if (allowSave && section.IsDirty) - { - Log.DebugFormat("Section {0} is marked dirty, saving!", sectionName); - Save(); - } - - return section; - } - - /// - /// Get the raw properties for a section - /// - /// - /// - public static IDictionary PropertiesForSection(IniSection section) - { - string sectionName = section.IniSectionAttribute.Name; - // Get the properties for the section - IDictionary properties; - if (_sections.ContainsKey(sectionName)) - { - properties = _sections[sectionName]; - } - else - { - _sections.Add(sectionName, new Dictionary()); - properties = _sections[sectionName]; - } - - return properties; - } - - /// - /// Save the ini file - /// - public static void Save() - { - bool acquiredLock = false; - try - { - acquiredLock = Monitor.TryEnter(IniLock, TimeSpan.FromMilliseconds(200)); - if (acquiredLock) - { - // Code that accesses resources that are protected by the lock. - string iniLocation = CreateIniLocation(_configName + IniExtension, false); - try - { - SaveInternally(iniLocation); - } - catch (Exception ex) - { - Log.Error("A problem occured while writing the configuration file to: " + iniLocation); - Log.Error(ex); - } - } - else - { - // Code to deal with the fact that the lock was not acquired. - Log.Warn("A second thread tried to save the ini-file, we blocked as the first took too long."); - } - } - finally - { - if (acquiredLock) - { - Monitor.Exit(IniLock); - } - } - } - - /// - /// The real save implementation - /// - /// - private static void SaveInternally(string iniLocation) - { - Log.Info("Saving configuration to: " + iniLocation); - var iniPath = Path.GetDirectoryName(iniLocation); - if (iniPath != null && !Directory.Exists(iniPath)) - { - Directory.CreateDirectory(iniPath); - } - - using var memoryStream = new MemoryStream(); - using TextWriter writer = new StreamWriter(memoryStream, Encoding.UTF8); - foreach (var section in SectionMap.Values) - { - section.Write(writer, false); - // Add empty line after section - writer.WriteLine(); - section.IsDirty = false; - } - - writer.WriteLine(); - // Write left over properties - foreach (string sectionName in _sections.Keys) - { - // Check if the section is one that is "registered", if so skip it! - if (SectionMap.ContainsKey(sectionName)) - { - continue; - } - - writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName); - writer.WriteLine( - "; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", - sectionName); - // Write section name - writer.WriteLine("[{0}]", sectionName); - var properties = _sections[sectionName]; - // Loop and write properties - foreach (string propertyName in properties.Keys) - { - writer.WriteLine("{0}={1}", propertyName, properties[propertyName]); - } - - writer.WriteLine(); - } - - // Don't forget to flush the buffer - writer.Flush(); - // Now write the created .ini string to the real file - using FileStream fileStream = new FileStream(iniLocation, FileMode.Create, FileAccess.Write); - memoryStream.WriteTo(fileStream); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; +using log4net; + +namespace Greenshot.Base.IniFile +{ + public class IniConfig + { + private static readonly ILog Log = LogManager.GetLogger(typeof(IniConfig)); + private const string IniExtension = ".ini"; + private const string DefaultsPostfix = "-defaults"; + private const string FixedPostfix = "-fixed"; + + /// + /// A lock object for the ini file saving + /// + private static readonly object IniLock = new object(); + + /// + /// As the ini implementation is kept someone generic, for reusing, this holds the name of the application + /// + private static string _applicationName; + + /// + /// As the ini implementation is kept someone generic, for reusing, this holds the name of the configuration + /// + private static string _configName; + + /// + /// A Dictionary with all the sections stored by section name + /// + private static readonly IDictionary SectionMap = new Dictionary(); + + /// + /// A Dictionary with the properties for a section stored by section name + /// + private static IDictionary> _sections = new Dictionary>(); + + /// + /// A Dictionary with the fixed-properties for a section stored by section name + /// + private static IDictionary> _fixedProperties; + + /// + /// Stores if we checked for portable + /// + private static bool _portableCheckMade; + + /// + /// Is the configuration portable (meaning we don't store it in the AppData directory) + /// + public static bool IsPortable { get; private set; } + + /// + /// Config directory when set from external + /// + public static string IniDirectory { get; set; } + + /// + /// Initialize the ini config + /// + /// + /// + public static void Init(string appName, string configName) + { + _applicationName = appName; + _configName = configName; + Reload(); + } + + /// + /// Checks if we initialized the ini + /// + public static bool IsInitialized => _applicationName != null && _configName != null && SectionMap.Count > 0; + + /// + /// This forces the ini to be stored in the startup path, used for portable applications + /// + public static void ForceIniInStartupPath() + { + if (_portableCheckMade) + { + throw new Exception("ForceLocal should be called before any file is read"); + } + + IsPortable = false; + _portableCheckMade = true; + string applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + if (_applicationName == null || _configName == null) + { + Init(); + } + + if (applicationStartupPath == null) + { + return; + } + + string forcedIni = Path.Combine(applicationStartupPath, _applicationName + IniExtension); + if (!File.Exists(forcedIni)) + { + using (File.Create(forcedIni)) + { + } + } + } + + /// + /// Default init + /// + public static void Init() + { + AssemblyProductAttribute[] assemblyProductAttributes = + Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false) as AssemblyProductAttribute[]; + if (assemblyProductAttributes != null && assemblyProductAttributes.Length > 0) + { + string productName = assemblyProductAttributes[0].Product; + Log.InfoFormat("Using ProductName {0}", productName); + Init(productName, productName); + } + else + { + throw new InvalidOperationException("Assembly ProductName not set."); + } + } + + /// + /// Get the location of the configuration + /// + public static string ConfigLocation + { + get + { + if (IsInitialized) + { + return CreateIniLocation(_configName + IniExtension, false); + } + + throw new InvalidOperationException("Ini configuration was not initialized!"); + } + } + + /// + /// Create the location of the configuration file + /// + private static string CreateIniLocation(string configFilename, bool isReadOnly) + { + if (_applicationName == null || _configName == null) + { + throw new InvalidOperationException("IniConfig.Init not called!"); + } + + string iniFilePath = null; + + // Check if a Ini-Directory was supplied, and it's valid, use this before any others. + try + { + if (IniDirectory != null && Directory.Exists(IniDirectory)) + { + // If the greenshot.ini is requested, use the supplied directory even if empty + if (!isReadOnly) + { + return Path.Combine(IniDirectory, configFilename); + } + + iniFilePath = Path.Combine(IniDirectory, configFilename); + if (File.Exists(iniFilePath)) + { + return iniFilePath; + } + + iniFilePath = null; + } + } + catch (Exception exception) + { + Log.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message); + } + + string applicationStartupPath; + try + { + applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + } + catch (Exception exception) + { + Log.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message); + applicationStartupPath = @"."; + } + + if (applicationStartupPath != null) + { + string pafPath = Path.Combine(applicationStartupPath, @"App\" + _applicationName); + + if (IsPortable || !_portableCheckMade) + { + if (!IsPortable) + { + Log.Info("Checking for portable mode."); + _portableCheckMade = true; + if (Directory.Exists(pafPath)) + { + IsPortable = true; + Log.Info("Portable mode active!"); + } + } + + if (IsPortable) + { + string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings"); + try + { + if (!Directory.Exists(pafConfigPath)) + { + Directory.CreateDirectory(pafConfigPath); + } + + iniFilePath = Path.Combine(pafConfigPath, configFilename); + } + catch (Exception e) + { + Log.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message); + } + } + } + } + + if (iniFilePath == null) + { + // check if file is in the same location as started from, if this is the case + // we will use this file instead of the ApplicationData folder + // Done for Feature Request #2741508 + if (applicationStartupPath != null) + { + iniFilePath = Path.Combine(applicationStartupPath, configFilename); + } + + if (!File.Exists(iniFilePath)) + { + string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), _applicationName); + if (!Directory.Exists(iniDirectory)) + { + Directory.CreateDirectory(iniDirectory); + } + + iniFilePath = Path.Combine(iniDirectory, configFilename); + } + } + + Log.InfoFormat("Using ini file {0}", iniFilePath); + return iniFilePath; + } + + /// + /// Reload the Ini file + /// + public static void Reload() + { + // Clear the current properties + _sections = new Dictionary>(); + // Load the defaults + Read(CreateIniLocation(_configName + DefaultsPostfix + IniExtension, true)); + // Load the normal + Read(CreateIniLocation(_configName + IniExtension, false)); + // Load the fixed settings + _fixedProperties = Read(CreateIniLocation(_configName + FixedPostfix + IniExtension, true)); + + foreach (IniSection section in SectionMap.Values) + { + try + { + section.Fill(PropertiesForSection(section)); + FixProperties(section); + } + catch (Exception ex) + { + string sectionName = "unknown"; + if (section?.IniSectionAttribute?.Name != null) + { + sectionName = section.IniSectionAttribute.Name; + } + + Log.WarnFormat("Problem reading the ini section {0}", sectionName); + Log.Warn("Exception", ex); + } + } + } + + /// + /// This "fixes" the properties of the section, meaning any properties in the fixed file can't be changed. + /// + /// IniSection + private static void FixProperties(IniSection section) + { + // Make properties unchangeable + if (_fixedProperties == null) + { + return; + } + + if (!_fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out var fixedPropertiesForSection)) + { + return; + } + + foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) + { + if (section.Values.ContainsKey(fixedPropertyKey)) + { + section.Values[fixedPropertyKey].IsFixed = true; + } + } + } + + /// + /// Read the ini file into the Dictionary + /// + /// Path & Filename of ini file + private static IDictionary> Read(string iniLocation) + { + if (!File.Exists(iniLocation)) + { + Log.Info("Can't find file: " + iniLocation); + return null; + } + + Log.InfoFormat("Loading ini-file: {0}", iniLocation); + //LOG.Info("Reading ini-properties from file: " + iniLocation); + var newSections = IniReader.Read(iniLocation, Encoding.UTF8); + // Merge the newly loaded properties to the already available + foreach (string section in newSections.Keys) + { + IDictionary newProperties = newSections[section]; + if (!_sections.ContainsKey(section)) + { + // This section is not yet loaded, simply add the complete section + _sections.Add(section, newProperties); + } + else + { + // Overwrite or add every property from the newly loaded section to the available one + var currentProperties = _sections[section]; + foreach (string propertyName in newProperties.Keys) + { + string propertyValue = newProperties[propertyName]; + if (currentProperties.ContainsKey(propertyName)) + { + // Override current value as we are loading in a certain order which insures the default, current and fixed + currentProperties[propertyName] = propertyValue; + } + else + { + // Add "new" value + currentProperties.Add(propertyName, propertyValue); + } + } + } + } + + return newSections; + } + + public static IEnumerable IniSectionNames + { + get + { + foreach (string sectionName in SectionMap.Keys) + { + yield return sectionName; + } + } + } + + /// + /// Method used for internal tricks... + /// + /// + /// + public static IniSection GetIniSection(string sectionName) + { + SectionMap.TryGetValue(sectionName, out var returnValue); + return returnValue; + } + + /// + /// A generic method which returns an instance of the supplied type, filled with it's configuration + /// + /// IniSection Type to get the configuration for + /// Filled instance of IniSection type which was supplied + public static T GetIniSection() where T : IniSection + { + return GetIniSection(true); + } + + /// + /// + /// + /// IniSection Type to get the configuration for + /// false to skip saving + /// IniSection + public static T GetIniSection(bool allowSave) where T : IniSection + { + T section; + + Type iniSectionType = typeof(T); + string sectionName = IniSection.GetIniSectionAttribute(iniSectionType).Name; + if (SectionMap.ContainsKey(sectionName)) + { + //LOG.Debug("Returning pre-mapped section " + sectionName); + section = (T) SectionMap[sectionName]; + } + else + { + // Create instance of this type + section = (T) Activator.CreateInstance(iniSectionType); + + // Store for later save & retrieval + SectionMap.Add(sectionName, section); + section.Fill(PropertiesForSection(section)); + FixProperties(section); + } + + if (allowSave && section.IsDirty) + { + Log.DebugFormat("Section {0} is marked dirty, saving!", sectionName); + Save(); + } + + return section; + } + + /// + /// Get the raw properties for a section + /// + /// + /// + public static IDictionary PropertiesForSection(IniSection section) + { + string sectionName = section.IniSectionAttribute.Name; + // Get the properties for the section + IDictionary properties; + if (_sections.ContainsKey(sectionName)) + { + properties = _sections[sectionName]; + } + else + { + _sections.Add(sectionName, new Dictionary()); + properties = _sections[sectionName]; + } + + return properties; + } + + /// + /// Save the ini file + /// + public static void Save() + { + bool acquiredLock = false; + try + { + acquiredLock = Monitor.TryEnter(IniLock, TimeSpan.FromMilliseconds(200)); + if (acquiredLock) + { + // Code that accesses resources that are protected by the lock. + string iniLocation = CreateIniLocation(_configName + IniExtension, false); + try + { + SaveInternally(iniLocation); + } + catch (Exception ex) + { + Log.Error("A problem occured while writing the configuration file to: " + iniLocation); + Log.Error(ex); + } + } + else + { + // Code to deal with the fact that the lock was not acquired. + Log.Warn("A second thread tried to save the ini-file, we blocked as the first took too long."); + } + } + finally + { + if (acquiredLock) + { + Monitor.Exit(IniLock); + } + } + } + + /// + /// The real save implementation + /// + /// + private static void SaveInternally(string iniLocation) + { + Log.Info("Saving configuration to: " + iniLocation); + var iniPath = Path.GetDirectoryName(iniLocation); + if (iniPath != null && !Directory.Exists(iniPath)) + { + Directory.CreateDirectory(iniPath); + } + + using var memoryStream = new MemoryStream(); + using TextWriter writer = new StreamWriter(memoryStream, Encoding.UTF8); + foreach (var section in SectionMap.Values) + { + section.Write(writer, false); + // Add empty line after section + writer.WriteLine(); + section.IsDirty = false; + } + + writer.WriteLine(); + // Write left over properties + foreach (string sectionName in _sections.Keys) + { + // Check if the section is one that is "registered", if so skip it! + if (SectionMap.ContainsKey(sectionName)) + { + continue; + } + + writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName); + writer.WriteLine( + "; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", + sectionName); + // Write section name + writer.WriteLine("[{0}]", sectionName); + var properties = _sections[sectionName]; + // Loop and write properties + foreach (string propertyName in properties.Keys) + { + writer.WriteLine("{0}={1}", propertyName, properties[propertyName]); + } + + writer.WriteLine(); + } + + // Don't forget to flush the buffer + writer.Flush(); + // Now write the created .ini string to the real file + using FileStream fileStream = new FileStream(iniLocation, FileMode.Create, FileAccess.Write); + memoryStream.WriteTo(fileStream); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IniFile/IniReader.cs b/src/Greenshot.Base/IniFile/IniReader.cs similarity index 96% rename from src/GreenshotPlugin/IniFile/IniReader.cs rename to src/Greenshot.Base/IniFile/IniReader.cs index de83fde26..e9db1787c 100644 --- a/src/GreenshotPlugin/IniFile/IniReader.cs +++ b/src/Greenshot.Base/IniFile/IniReader.cs @@ -1,104 +1,104 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace GreenshotPlugin.IniFile -{ - /// - /// The IniReader does exactly what it says, it reads the .ini file - /// - public static class IniReader - { - private const char SectionStartToken = '['; - private const char SectionEndToken = ']'; - private const char CommentToken = ';'; - - private static readonly char[] Assignment = - { - '=' - }; - - /// - /// Read an ini file to a Dictionary, each key is a section and the value is a Dictionary with name and values. - /// - /// - /// - /// - public static IDictionary> Read(string path, Encoding encoding) - { - var ini = new Dictionary>(); - using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024)) - { - using var streamReader = new StreamReader(fileStream, encoding); - IDictionary nameValues = new Dictionary(); - while (!streamReader.EndOfStream) - { - string line = streamReader.ReadLine(); - if (line == null) - { - continue; - } - - string cleanLine = line.Trim(); - if (cleanLine.Length == 0 || cleanLine[0] == CommentToken) - { - continue; - } - - if (cleanLine[0] == SectionStartToken) - { - var sectionEndIndex = line.IndexOf(SectionEndToken, 1); - if (sectionEndIndex < 0) - { - continue; - } - - string section = line.Substring(1, sectionEndIndex - 1).Trim(); - if (!ini.TryGetValue(section, out nameValues)) - { - nameValues = new Dictionary(); - ini.Add(section, nameValues); - } - } - else - { - string[] keyvalueSplitter = line.Split(Assignment, 2); - string name = keyvalueSplitter[0]; - string inivalue = keyvalueSplitter.Length > 1 ? keyvalueSplitter[1] : null; - if (nameValues.ContainsKey(name)) - { - nameValues[name] = inivalue; - } - else - { - nameValues.Add(name, inivalue); - } - } - } - } - - return ini; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Greenshot.Base.IniFile +{ + /// + /// The IniReader does exactly what it says, it reads the .ini file + /// + public static class IniReader + { + private const char SectionStartToken = '['; + private const char SectionEndToken = ']'; + private const char CommentToken = ';'; + + private static readonly char[] Assignment = + { + '=' + }; + + /// + /// Read an ini file to a Dictionary, each key is a section and the value is a Dictionary with name and values. + /// + /// + /// + /// + public static IDictionary> Read(string path, Encoding encoding) + { + var ini = new Dictionary>(); + using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024)) + { + using var streamReader = new StreamReader(fileStream, encoding); + IDictionary nameValues = new Dictionary(); + while (!streamReader.EndOfStream) + { + string line = streamReader.ReadLine(); + if (line == null) + { + continue; + } + + string cleanLine = line.Trim(); + if (cleanLine.Length == 0 || cleanLine[0] == CommentToken) + { + continue; + } + + if (cleanLine[0] == SectionStartToken) + { + var sectionEndIndex = line.IndexOf(SectionEndToken, 1); + if (sectionEndIndex < 0) + { + continue; + } + + string section = line.Substring(1, sectionEndIndex - 1).Trim(); + if (!ini.TryGetValue(section, out nameValues)) + { + nameValues = new Dictionary(); + ini.Add(section, nameValues); + } + } + else + { + string[] keyvalueSplitter = line.Split(Assignment, 2); + string name = keyvalueSplitter[0]; + string inivalue = keyvalueSplitter.Length > 1 ? keyvalueSplitter[1] : null; + if (nameValues.ContainsKey(name)) + { + nameValues[name] = inivalue; + } + else + { + nameValues.Add(name, inivalue); + } + } + } + } + + return ini; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IniFile/IniSection.cs b/src/Greenshot.Base/IniFile/IniSection.cs similarity index 96% rename from src/GreenshotPlugin/IniFile/IniSection.cs rename to src/Greenshot.Base/IniFile/IniSection.cs index 1c5b501a9..813534c13 100644 --- a/src/GreenshotPlugin/IniFile/IniSection.cs +++ b/src/Greenshot.Base/IniFile/IniSection.cs @@ -1,235 +1,235 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using GreenshotPlugin.Core; -using log4net; - -namespace GreenshotPlugin.IniFile -{ - /// - /// Base class for all IniSections - /// - [Serializable] - public abstract class IniSection - { - protected static ILog LOG = LogManager.GetLogger(typeof(IniSection)); - - [NonSerialized] private readonly IDictionary values = new Dictionary(); - [NonSerialized] private IniSectionAttribute iniSectionAttribute; - - public IniSectionAttribute IniSectionAttribute - { - get - { - if (iniSectionAttribute == null) - { - iniSectionAttribute = GetIniSectionAttribute(GetType()); - } - - return iniSectionAttribute; - } - } - - /// - /// Get the dictionary with all the IniValues - /// - public IDictionary Values - { - get { return values; } - } - - /// - /// Flag to specify if values have been changed - /// - public bool IsDirty { get; set; } - - /// - /// 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 virtual object GetDefault(string property) - { - return 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 - /// - /// The name of the property - /// The string value of the property - /// string with the propertyValue, modified or not... - public virtual string PreCheckValue(string propertyName, string propertyValue) - { - return propertyValue; - } - - /// - /// This method will be called after reading the configuration, so eventually some corrections can be made - /// - public virtual void AfterLoad() - { - } - - /// - /// This will be called before saving the Section, so we can encrypt passwords etc... - /// - public virtual void BeforeSave() - { - } - - /// - /// This will be called before saving the Section, so we can decrypt passwords etc... - /// - public virtual void AfterSave() - { - } - - /// - /// Helper method to get the IniSectionAttribute of a type - /// - /// - /// - public static IniSectionAttribute GetIniSectionAttribute(Type iniSectionType) - { - Attribute[] classAttributes = Attribute.GetCustomAttributes(iniSectionType); - foreach (Attribute attribute in classAttributes) - { - if (attribute is IniSectionAttribute) - { - return (IniSectionAttribute) attribute; - } - } - - return null; - } - - /// - /// Fill the section with the supplied properties - /// - /// - public void Fill(IDictionary properties) - { - Type iniSectionType = GetType(); - - // Iterate over the members and create IniValueContainers - foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) - { - if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) - { - IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute) fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; - if (!Values.ContainsKey(iniPropertyAttribute.Name)) - { - Values.Add(iniPropertyAttribute.Name, new IniValue(this, fieldInfo, iniPropertyAttribute)); - } - } - } - - foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) - { - if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) - { - if (!Values.ContainsKey(propertyInfo.Name)) - { - IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute) propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; - Values.Add(iniPropertyAttribute.Name, new IniValue(this, propertyInfo, iniPropertyAttribute)); - } - } - } - - foreach (string fieldName in Values.Keys) - { - IniValue iniValue = Values[fieldName]; - try - { - iniValue.SetValueFromProperties(properties); - if (iniValue.Attributes.Encrypted) - { - if (iniValue.Value is string stringValue && stringValue.Length > 2) - { - iniValue.Value = stringValue.Decrypt(); - } - } - } - catch (Exception ex) - { - LOG.Error(ex); - } - } - - AfterLoad(); - } - - /// - /// Write the section to the writer - /// - /// - /// - public void Write(TextWriter writer, bool onlyProperties) - { - if (IniSectionAttribute == null) - { - throw new ArgumentException("Section didn't implement the IniSectionAttribute"); - } - - BeforeSave(); - try - { - if (!onlyProperties) - { - writer.WriteLine("; {0}", IniSectionAttribute.Description); - } - - writer.WriteLine("[{0}]", IniSectionAttribute.Name); - - foreach (IniValue value in Values.Values) - { - if (value.Attributes.Encrypted) - { - if (value.Value is string stringValue && stringValue.Length > 2) - { - value.Value = stringValue.Encrypt(); - } - } - - // Write the value - value.Write(writer, onlyProperties); - if (value.Attributes.Encrypted) - { - if (value.Value is string stringValue && stringValue.Length > 2) - { - value.Value = stringValue.Decrypt(); - } - } - } - } - finally - { - AfterSave(); - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Greenshot.Base.Core; +using log4net; + +namespace Greenshot.Base.IniFile +{ + /// + /// Base class for all IniSections + /// + [Serializable] + public abstract class IniSection + { + protected static ILog LOG = LogManager.GetLogger(typeof(IniSection)); + + [NonSerialized] private readonly IDictionary values = new Dictionary(); + [NonSerialized] private IniSectionAttribute iniSectionAttribute; + + public IniSectionAttribute IniSectionAttribute + { + get + { + if (iniSectionAttribute == null) + { + iniSectionAttribute = GetIniSectionAttribute(GetType()); + } + + return iniSectionAttribute; + } + } + + /// + /// Get the dictionary with all the IniValues + /// + public IDictionary Values + { + get { return values; } + } + + /// + /// Flag to specify if values have been changed + /// + public bool IsDirty { get; set; } + + /// + /// 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 virtual object GetDefault(string property) + { + return 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 + /// + /// The name of the property + /// The string value of the property + /// string with the propertyValue, modified or not... + public virtual string PreCheckValue(string propertyName, string propertyValue) + { + return propertyValue; + } + + /// + /// This method will be called after reading the configuration, so eventually some corrections can be made + /// + public virtual void AfterLoad() + { + } + + /// + /// This will be called before saving the Section, so we can encrypt passwords etc... + /// + public virtual void BeforeSave() + { + } + + /// + /// This will be called before saving the Section, so we can decrypt passwords etc... + /// + public virtual void AfterSave() + { + } + + /// + /// Helper method to get the IniSectionAttribute of a type + /// + /// + /// + public static IniSectionAttribute GetIniSectionAttribute(Type iniSectionType) + { + Attribute[] classAttributes = Attribute.GetCustomAttributes(iniSectionType); + foreach (Attribute attribute in classAttributes) + { + if (attribute is IniSectionAttribute) + { + return (IniSectionAttribute) attribute; + } + } + + return null; + } + + /// + /// Fill the section with the supplied properties + /// + /// + public void Fill(IDictionary properties) + { + Type iniSectionType = GetType(); + + // Iterate over the members and create IniValueContainers + foreach (FieldInfo fieldInfo in iniSectionType.GetFields()) + { + if (Attribute.IsDefined(fieldInfo, typeof(IniPropertyAttribute))) + { + IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute) fieldInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; + if (!Values.ContainsKey(iniPropertyAttribute.Name)) + { + Values.Add(iniPropertyAttribute.Name, new IniValue(this, fieldInfo, iniPropertyAttribute)); + } + } + } + + foreach (PropertyInfo propertyInfo in iniSectionType.GetProperties()) + { + if (Attribute.IsDefined(propertyInfo, typeof(IniPropertyAttribute))) + { + if (!Values.ContainsKey(propertyInfo.Name)) + { + IniPropertyAttribute iniPropertyAttribute = (IniPropertyAttribute) propertyInfo.GetCustomAttributes(typeof(IniPropertyAttribute), false)[0]; + Values.Add(iniPropertyAttribute.Name, new IniValue(this, propertyInfo, iniPropertyAttribute)); + } + } + } + + foreach (string fieldName in Values.Keys) + { + IniValue iniValue = Values[fieldName]; + try + { + iniValue.SetValueFromProperties(properties); + if (iniValue.Attributes.Encrypted) + { + if (iniValue.Value is string stringValue && stringValue.Length > 2) + { + iniValue.Value = stringValue.Decrypt(); + } + } + } + catch (Exception ex) + { + LOG.Error(ex); + } + } + + AfterLoad(); + } + + /// + /// Write the section to the writer + /// + /// + /// + public void Write(TextWriter writer, bool onlyProperties) + { + if (IniSectionAttribute == null) + { + throw new ArgumentException("Section didn't implement the IniSectionAttribute"); + } + + BeforeSave(); + try + { + if (!onlyProperties) + { + writer.WriteLine("; {0}", IniSectionAttribute.Description); + } + + writer.WriteLine("[{0}]", IniSectionAttribute.Name); + + foreach (IniValue value in Values.Values) + { + if (value.Attributes.Encrypted) + { + if (value.Value is string stringValue && stringValue.Length > 2) + { + value.Value = stringValue.Encrypt(); + } + } + + // Write the value + value.Write(writer, onlyProperties); + if (value.Attributes.Encrypted) + { + if (value.Value is string stringValue && stringValue.Length > 2) + { + value.Value = stringValue.Decrypt(); + } + } + } + } + finally + { + AfterSave(); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/IniFile/IniValue.cs b/src/Greenshot.Base/IniFile/IniValue.cs similarity index 97% rename from src/GreenshotPlugin/IniFile/IniValue.cs rename to src/Greenshot.Base/IniFile/IniValue.cs index a6599990a..312ce25be 100644 --- a/src/GreenshotPlugin/IniFile/IniValue.cs +++ b/src/Greenshot.Base/IniFile/IniValue.cs @@ -1,621 +1,621 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Reflection; -using System.Text; -using log4net; - -namespace GreenshotPlugin.IniFile -{ - /// - /// A container to be able to pass the value from a IniSection around. - /// - public class IniValue - { - private static readonly ILog Log = LogManager.GetLogger(typeof(IniValue)); - private readonly PropertyInfo _propertyInfo; - private readonly FieldInfo _fieldInfo; - private readonly IniSection _containingIniSection; - private readonly IniPropertyAttribute _attributes; - - public IniValue(IniSection containingIniSection, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) - { - _containingIniSection = containingIniSection; - _propertyInfo = propertyInfo; - _attributes = iniPropertyAttribute; - } - - public IniValue(IniSection containingIniSection, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) - { - _containingIniSection = containingIniSection; - _fieldInfo = fieldInfo; - _attributes = iniPropertyAttribute; - } - - /// - /// Return true when the value is fixed - /// - public bool IsFixed - { - get - { - if (_attributes != null) - { - return _attributes.FixedValue; - } - - return false; - } - set - { - if (_attributes != null) - { - _attributes.FixedValue = value; - } - } - } - - /// - /// Return true when the value is for experts - /// - public bool IsExpert - { - get - { - if (_attributes != null) - { - return _attributes.Expert; - } - - return false; - } - set - { - if (_attributes != null) - { - _attributes.Expert = value; - } - } - } - - - /// - /// Return true when the value is can be changed by the GUI - /// - public bool IsEditable => !IsFixed; - - /// - /// Return true when the value is visible in the GUI - /// - public bool IsVisible => !IsExpert; - - public MemberInfo MemberInfo - { - get - { - if (_propertyInfo == null) - { - return _fieldInfo; - } - - return _propertyInfo; - } - } - - /// - /// Returns the IniSection this value is contained in - /// - public IniSection ContainingIniSection => _containingIniSection; - - /// - /// Get the in the ini file defined attributes - /// - public IniPropertyAttribute Attributes => _attributes; - - /// - /// Get the value for this IniValue - /// - public object Value - { - get - { - if (_propertyInfo == null) - { - return _fieldInfo.GetValue(_containingIniSection); - } - - return _propertyInfo.GetValue(_containingIniSection, null); - } - set - { - if (_propertyInfo == null) - { - _fieldInfo.SetValue(_containingIniSection, value); - } - else - { - _propertyInfo.SetValue(_containingIniSection, value, null); - } - } - } - - /// - /// Get the Type of the value - /// - public Type ValueType - { - get - { - var valueType = _propertyInfo?.PropertyType ?? _fieldInfo.FieldType; - if (!valueType.IsGenericType) - { - return valueType; - } - - var genericTypeDefinition = valueType.GetGenericTypeDefinition(); - if (genericTypeDefinition != null && genericTypeDefinition == typeof(Nullable<>)) - { - // We are dealing with a generic type that is nullable - valueType = Nullable.GetUnderlyingType(valueType); - } - - return valueType; - } - } - - /// - /// Write the value to the text writer - /// - /// TextWriter to write to - /// true if we do not want the comment - public void Write(TextWriter writer, bool onlyProperties) - { - object myValue = Value; - Type valueType = ValueType; - if (myValue == null) - { - if (_attributes.ExcludeIfNull) - { - return; - } - - if (_attributes.DefaultValue != null) - { - myValue = _attributes.DefaultValue; - valueType = typeof(string); - } - else - { - myValue = _containingIniSection.GetDefault(_attributes.Name); - if (myValue != null) - { - valueType = myValue.GetType(); - } - } - } - - if (myValue == null) - { - if (_attributes.ExcludeIfNull) - { - return; - } - } - - if (!onlyProperties) - { - writer.WriteLine("; {0}", _attributes.Description); - } - - if (myValue == null) - { - writer.WriteLine("{0}=", _attributes.Name); - return; - } - - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) - { - // Handle dictionaries. - Type valueType1 = valueType.GetGenericArguments()[0]; - Type valueType2 = valueType.GetGenericArguments()[1]; - // Get the methods we need to deal with dictionaries. - var keys = valueType.GetProperty("Keys").GetValue(myValue, null); - var item = valueType.GetProperty("Item"); - var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null); - var moveNext = enumerator.GetType().GetMethod("MoveNext"); - var current = enumerator.GetType().GetProperty("Current").GetGetMethod(); - // Get all the values. - while ((bool) moveNext.Invoke(enumerator, null)) - { - var key = current.Invoke(enumerator, null); - var valueObject = item.GetValue(myValue, new[] - { - key - }); - // Write to ini file! - writer.WriteLine("{0}.{1}={2}", _attributes.Name, ConvertValueToString(valueType1, key, _attributes.Separator), - ConvertValueToString(valueType2, valueObject, _attributes.Separator)); - } - } - else - { - writer.WriteLine("{0}={1}", _attributes.Name, ConvertValueToString(valueType, myValue, _attributes.Separator)); - } - } - - /// - /// Set the value to the value in the ini file, or default - /// - /// - public void SetValueFromProperties(IDictionary properties) - { - string propertyName = _attributes.Name; - string propertyValue = null; - if (properties.ContainsKey(propertyName) && properties[propertyName] != null) - { - propertyValue = _containingIniSection.PreCheckValue(propertyName, properties[propertyName]); - } - - UseValueOrDefault(propertyValue); - } - - /// - /// This method will set the ini value to the supplied value or use the default if non supplied - /// - /// - public void UseValueOrDefault(string propertyValue) - { - Type valueType = ValueType; - string propertyName = _attributes.Name; - string defaultValue = _attributes.DefaultValue; - bool defaultUsed = false; - object defaultValueFromConfig = _containingIniSection.GetDefault(propertyName); - - if (string.IsNullOrEmpty(propertyValue)) - { - if (defaultValue != null && defaultValue.Trim().Length != 0) - { - propertyValue = defaultValue; - defaultUsed = true; - } - else if (defaultValueFromConfig != null) - { - Log.DebugFormat("Default for Property {0} implemented!", propertyName); - } - else - { - if (_attributes.ExcludeIfNull) - { - Value = null; - return; - } - - Log.DebugFormat("Property {0} has no value or default value!", propertyName); - } - } - - // Now set the value - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) - { - // Logic for Dictionary<,> - Type type1 = valueType.GetGenericArguments()[0]; - Type type2 = valueType.GetGenericArguments()[1]; - //LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name)); - object dictionary = Activator.CreateInstance(valueType); - MethodInfo addMethodInfo = valueType.GetMethod("Add"); - bool addedElements = false; - IDictionary properties = IniConfig.PropertiesForSection(_containingIniSection); - foreach (string key in properties.Keys) - { - if (key != null && key.StartsWith(propertyName + ".")) - { - // What "key" do we need to store it under? - string subPropertyName = key.Substring(propertyName.Length + 1); - string stringValue = properties[key]; - object newValue1 = null; - object newValue2 = null; - try - { - newValue1 = ConvertStringToValueType(type1, subPropertyName, _attributes.Separator); - } - catch (Exception ex) - { - Log.Warn(ex); - //LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e); - } - - try - { - newValue2 = ConvertStringToValueType(type2, stringValue, _attributes.Separator); - } - catch (Exception ex) - { - Log.Warn(ex); - //LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e); - } - - addMethodInfo.Invoke(dictionary, new[] - { - newValue1, newValue2 - }); - addedElements = true; - } - } - - // No need to return something that isn't filled! - if (addedElements) - { - Value = dictionary; - return; - } - - if (defaultValueFromConfig != null) - { - Value = defaultValueFromConfig; - return; - } - } - else if (!string.IsNullOrEmpty(propertyValue)) - { - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - // We are dealing with a generic type that is nullable - valueType = Nullable.GetUnderlyingType(valueType); - } - - object newValue; - try - { - newValue = ConvertStringToValueType(valueType, propertyValue, _attributes.Separator); - } - catch (Exception ex1) - { - newValue = null; - if (!defaultUsed) - { - try - { - Log.WarnFormat("Problem '{0}' while converting {1} to type {2} trying fallback...", ex1.Message, propertyValue, valueType.FullName); - newValue = ConvertStringToValueType(valueType, defaultValue, _attributes.Separator); - ContainingIniSection.IsDirty = true; - Log.InfoFormat("Used default value {0} for property {1}", defaultValue, propertyName); - } - catch (Exception ex2) - { - Log.Warn("Problem converting fallback value " + defaultValue + " to type " + valueType.FullName, ex2); - } - } - else - { - Log.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1); - } - } - - Value = newValue; - return; - } - - // If nothing is set, we can use the default value from the config (if we habe one) - if (defaultValueFromConfig != null) - { - Value = defaultValueFromConfig; - return; - } - - if (ValueType != typeof(string)) - { - try - { - Value = Activator.CreateInstance(ValueType); - } - catch (Exception) - { - Log.WarnFormat("Couldn't create instance of {0} for {1}, using default value.", ValueType.FullName, _attributes.Name); - Value = default(ValueType); - } - } - else - { - Value = default(ValueType); - } - } - - /// - /// Convert a string to a value of type "valueType" - /// - /// Type to convert tp - /// string to convert from - /// - /// Value - private static object ConvertStringToValueType(Type valueType, string valueString, string separator) - { - if (valueString == null) - { - return null; - } - - if (valueType == typeof(string)) - { - return valueString; - } - - if (string.IsNullOrEmpty(valueString)) - { - return null; - } - - // The following makes the enum string values a bit less restrictive - if (valueType.IsEnum) - { - string searchingEnumString = valueString.Replace("_", string.Empty).ToLowerInvariant(); - foreach (var possibleValue in Enum.GetValues(valueType)) - { - var possibleString = possibleValue.ToString().Replace("_", string.Empty).ToLowerInvariant(); - if (possibleString.Equals(searchingEnumString)) - { - return possibleValue; - } - } - } - - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) - { - string arraySeparator = separator; - object list = Activator.CreateInstance(valueType); - // Logic for List<> - string[] arrayValues = valueString.Split(new[] - { - arraySeparator - }, StringSplitOptions.None); - if (arrayValues.Length == 0) - { - return list; - } - - MethodInfo addMethodInfo = valueType.GetMethod("Add"); - - foreach (string arrayValue in arrayValues) - { - if (!string.IsNullOrEmpty(arrayValue)) - { - object newValue = null; - try - { - newValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], arrayValue, separator); - } - catch (Exception ex) - { - Log.Warn("Problem converting " + arrayValue + " to type " + valueType.FullName, ex); - } - - if (newValue != null) - { - addMethodInfo.Invoke(list, new[] - { - newValue - }); - } - } - } - - return list; - } - - //LOG.Debug("No convertor for " + fieldType.ToString()); - if (valueType == typeof(object) && valueString.Length > 0) - { - //LOG.Debug("Parsing: " + valueString); - string[] values = valueString.Split(':'); - //LOG.Debug("Type: " + values[0]); - //LOG.Debug("Value: " + values[1]); - Type fieldTypeForValue = Type.GetType(values[0], true); - //LOG.Debug("Type after GetType: " + fieldTypeForValue); - return ConvertStringToValueType(fieldTypeForValue, values[1], separator); - } - - TypeConverter converter = TypeDescriptor.GetConverter(valueType); - return converter.ConvertFromInvariantString(valueString); - } - - /// - /// Override of ToString which calls the ConvertValueToString - /// - /// string representation of this - public override string ToString() - { - return ConvertValueToString(ValueType, Value, _attributes.Separator); - } - - /// - /// Convert the supplied value to a string - /// - /// Type to convert - /// Value to convert - /// separator for lists - /// string representation of the value - private static string ConvertValueToString(Type valueType, object valueObject, string separator) - { - if (valueObject == null) - { - // If there is nothing, deliver nothing! - return string.Empty; - } - - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) - { - StringBuilder stringBuilder = new StringBuilder(); - Type specificValueType = valueType.GetGenericArguments()[0]; - int listCount = (int) valueType.GetProperty("Count").GetValue(valueObject, null); - // Loop though generic list - for (int index = 0; index < listCount; index++) - { - object item = valueType.GetMethod("get_Item").Invoke(valueObject, new object[] - { - index - }); - - // Now you have an instance of the item in the generic list - if (index < listCount - 1) - { - stringBuilder.AppendFormat("{0}{1}", ConvertValueToString(specificValueType, item, separator), separator); - } - else - { - stringBuilder.AppendFormat("{0}", ConvertValueToString(specificValueType, item, separator)); - } - } - - return stringBuilder.ToString(); - } - - if (valueType == typeof(object)) - { - // object to String, this is the hardest - // Format will be "FQTypename[,Assemblyname]:Value" - - // Get the type so we can call ourselves recursive - Type objectType = valueObject.GetType(); - - // Get the value as string - string ourValue = ConvertValueToString(objectType, valueObject, separator); - - // Get the valuetype as string - string valueTypeName = objectType.FullName; - // Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing) - string assemblyName = objectType.Assembly.FullName; - // correct assemblyName, this also has version information etc. - if (assemblyName.StartsWith("Green")) - { - assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(',')); - } - - return $"{valueTypeName},{assemblyName}:{ourValue}"; - } - - TypeConverter converter = TypeDescriptor.GetConverter(valueType); - return converter.ConvertToInvariantString(valueObject); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Reflection; +using System.Text; +using log4net; + +namespace Greenshot.Base.IniFile +{ + /// + /// A container to be able to pass the value from a IniSection around. + /// + public class IniValue + { + private static readonly ILog Log = LogManager.GetLogger(typeof(IniValue)); + private readonly PropertyInfo _propertyInfo; + private readonly FieldInfo _fieldInfo; + private readonly IniSection _containingIniSection; + private readonly IniPropertyAttribute _attributes; + + public IniValue(IniSection containingIniSection, PropertyInfo propertyInfo, IniPropertyAttribute iniPropertyAttribute) + { + _containingIniSection = containingIniSection; + _propertyInfo = propertyInfo; + _attributes = iniPropertyAttribute; + } + + public IniValue(IniSection containingIniSection, FieldInfo fieldInfo, IniPropertyAttribute iniPropertyAttribute) + { + _containingIniSection = containingIniSection; + _fieldInfo = fieldInfo; + _attributes = iniPropertyAttribute; + } + + /// + /// Return true when the value is fixed + /// + public bool IsFixed + { + get + { + if (_attributes != null) + { + return _attributes.FixedValue; + } + + return false; + } + set + { + if (_attributes != null) + { + _attributes.FixedValue = value; + } + } + } + + /// + /// Return true when the value is for experts + /// + public bool IsExpert + { + get + { + if (_attributes != null) + { + return _attributes.Expert; + } + + return false; + } + set + { + if (_attributes != null) + { + _attributes.Expert = value; + } + } + } + + + /// + /// Return true when the value is can be changed by the GUI + /// + public bool IsEditable => !IsFixed; + + /// + /// Return true when the value is visible in the GUI + /// + public bool IsVisible => !IsExpert; + + public MemberInfo MemberInfo + { + get + { + if (_propertyInfo == null) + { + return _fieldInfo; + } + + return _propertyInfo; + } + } + + /// + /// Returns the IniSection this value is contained in + /// + public IniSection ContainingIniSection => _containingIniSection; + + /// + /// Get the in the ini file defined attributes + /// + public IniPropertyAttribute Attributes => _attributes; + + /// + /// Get the value for this IniValue + /// + public object Value + { + get + { + if (_propertyInfo == null) + { + return _fieldInfo.GetValue(_containingIniSection); + } + + return _propertyInfo.GetValue(_containingIniSection, null); + } + set + { + if (_propertyInfo == null) + { + _fieldInfo.SetValue(_containingIniSection, value); + } + else + { + _propertyInfo.SetValue(_containingIniSection, value, null); + } + } + } + + /// + /// Get the Type of the value + /// + public Type ValueType + { + get + { + var valueType = _propertyInfo?.PropertyType ?? _fieldInfo.FieldType; + if (!valueType.IsGenericType) + { + return valueType; + } + + var genericTypeDefinition = valueType.GetGenericTypeDefinition(); + if (genericTypeDefinition != null && genericTypeDefinition == typeof(Nullable<>)) + { + // We are dealing with a generic type that is nullable + valueType = Nullable.GetUnderlyingType(valueType); + } + + return valueType; + } + } + + /// + /// Write the value to the text writer + /// + /// TextWriter to write to + /// true if we do not want the comment + public void Write(TextWriter writer, bool onlyProperties) + { + object myValue = Value; + Type valueType = ValueType; + if (myValue == null) + { + if (_attributes.ExcludeIfNull) + { + return; + } + + if (_attributes.DefaultValue != null) + { + myValue = _attributes.DefaultValue; + valueType = typeof(string); + } + else + { + myValue = _containingIniSection.GetDefault(_attributes.Name); + if (myValue != null) + { + valueType = myValue.GetType(); + } + } + } + + if (myValue == null) + { + if (_attributes.ExcludeIfNull) + { + return; + } + } + + if (!onlyProperties) + { + writer.WriteLine("; {0}", _attributes.Description); + } + + if (myValue == null) + { + writer.WriteLine("{0}=", _attributes.Name); + return; + } + + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + { + // Handle dictionaries. + Type valueType1 = valueType.GetGenericArguments()[0]; + Type valueType2 = valueType.GetGenericArguments()[1]; + // Get the methods we need to deal with dictionaries. + var keys = valueType.GetProperty("Keys").GetValue(myValue, null); + var item = valueType.GetProperty("Item"); + var enumerator = keys.GetType().GetMethod("GetEnumerator").Invoke(keys, null); + var moveNext = enumerator.GetType().GetMethod("MoveNext"); + var current = enumerator.GetType().GetProperty("Current").GetGetMethod(); + // Get all the values. + while ((bool) moveNext.Invoke(enumerator, null)) + { + var key = current.Invoke(enumerator, null); + var valueObject = item.GetValue(myValue, new[] + { + key + }); + // Write to ini file! + writer.WriteLine("{0}.{1}={2}", _attributes.Name, ConvertValueToString(valueType1, key, _attributes.Separator), + ConvertValueToString(valueType2, valueObject, _attributes.Separator)); + } + } + else + { + writer.WriteLine("{0}={1}", _attributes.Name, ConvertValueToString(valueType, myValue, _attributes.Separator)); + } + } + + /// + /// Set the value to the value in the ini file, or default + /// + /// + public void SetValueFromProperties(IDictionary properties) + { + string propertyName = _attributes.Name; + string propertyValue = null; + if (properties.ContainsKey(propertyName) && properties[propertyName] != null) + { + propertyValue = _containingIniSection.PreCheckValue(propertyName, properties[propertyName]); + } + + UseValueOrDefault(propertyValue); + } + + /// + /// This method will set the ini value to the supplied value or use the default if non supplied + /// + /// + public void UseValueOrDefault(string propertyValue) + { + Type valueType = ValueType; + string propertyName = _attributes.Name; + string defaultValue = _attributes.DefaultValue; + bool defaultUsed = false; + object defaultValueFromConfig = _containingIniSection.GetDefault(propertyName); + + if (string.IsNullOrEmpty(propertyValue)) + { + if (defaultValue != null && defaultValue.Trim().Length != 0) + { + propertyValue = defaultValue; + defaultUsed = true; + } + else if (defaultValueFromConfig != null) + { + Log.DebugFormat("Default for Property {0} implemented!", propertyName); + } + else + { + if (_attributes.ExcludeIfNull) + { + Value = null; + return; + } + + Log.DebugFormat("Property {0} has no value or default value!", propertyName); + } + } + + // Now set the value + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + { + // Logic for Dictionary<,> + Type type1 = valueType.GetGenericArguments()[0]; + Type type2 = valueType.GetGenericArguments()[1]; + //LOG.Info(String.Format("Found Dictionary<{0},{1}>", type1.Name, type2.Name)); + object dictionary = Activator.CreateInstance(valueType); + MethodInfo addMethodInfo = valueType.GetMethod("Add"); + bool addedElements = false; + IDictionary properties = IniConfig.PropertiesForSection(_containingIniSection); + foreach (string key in properties.Keys) + { + if (key != null && key.StartsWith(propertyName + ".")) + { + // What "key" do we need to store it under? + string subPropertyName = key.Substring(propertyName.Length + 1); + string stringValue = properties[key]; + object newValue1 = null; + object newValue2 = null; + try + { + newValue1 = ConvertStringToValueType(type1, subPropertyName, _attributes.Separator); + } + catch (Exception ex) + { + Log.Warn(ex); + //LOG.Error("Problem converting " + subPropertyName + " to type " + type1.FullName, e); + } + + try + { + newValue2 = ConvertStringToValueType(type2, stringValue, _attributes.Separator); + } + catch (Exception ex) + { + Log.Warn(ex); + //LOG.Error("Problem converting " + stringValue + " to type " + type2.FullName, e); + } + + addMethodInfo.Invoke(dictionary, new[] + { + newValue1, newValue2 + }); + addedElements = true; + } + } + + // No need to return something that isn't filled! + if (addedElements) + { + Value = dictionary; + return; + } + + if (defaultValueFromConfig != null) + { + Value = defaultValueFromConfig; + return; + } + } + else if (!string.IsNullOrEmpty(propertyValue)) + { + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + // We are dealing with a generic type that is nullable + valueType = Nullable.GetUnderlyingType(valueType); + } + + object newValue; + try + { + newValue = ConvertStringToValueType(valueType, propertyValue, _attributes.Separator); + } + catch (Exception ex1) + { + newValue = null; + if (!defaultUsed) + { + try + { + Log.WarnFormat("Problem '{0}' while converting {1} to type {2} trying fallback...", ex1.Message, propertyValue, valueType.FullName); + newValue = ConvertStringToValueType(valueType, defaultValue, _attributes.Separator); + ContainingIniSection.IsDirty = true; + Log.InfoFormat("Used default value {0} for property {1}", defaultValue, propertyName); + } + catch (Exception ex2) + { + Log.Warn("Problem converting fallback value " + defaultValue + " to type " + valueType.FullName, ex2); + } + } + else + { + Log.Warn("Problem converting " + propertyValue + " to type " + valueType.FullName, ex1); + } + } + + Value = newValue; + return; + } + + // If nothing is set, we can use the default value from the config (if we habe one) + if (defaultValueFromConfig != null) + { + Value = defaultValueFromConfig; + return; + } + + if (ValueType != typeof(string)) + { + try + { + Value = Activator.CreateInstance(ValueType); + } + catch (Exception) + { + Log.WarnFormat("Couldn't create instance of {0} for {1}, using default value.", ValueType.FullName, _attributes.Name); + Value = default(ValueType); + } + } + else + { + Value = default(ValueType); + } + } + + /// + /// Convert a string to a value of type "valueType" + /// + /// Type to convert tp + /// string to convert from + /// + /// Value + private static object ConvertStringToValueType(Type valueType, string valueString, string separator) + { + if (valueString == null) + { + return null; + } + + if (valueType == typeof(string)) + { + return valueString; + } + + if (string.IsNullOrEmpty(valueString)) + { + return null; + } + + // The following makes the enum string values a bit less restrictive + if (valueType.IsEnum) + { + string searchingEnumString = valueString.Replace("_", string.Empty).ToLowerInvariant(); + foreach (var possibleValue in Enum.GetValues(valueType)) + { + var possibleString = possibleValue.ToString().Replace("_", string.Empty).ToLowerInvariant(); + if (possibleString.Equals(searchingEnumString)) + { + return possibleValue; + } + } + } + + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) + { + string arraySeparator = separator; + object list = Activator.CreateInstance(valueType); + // Logic for List<> + string[] arrayValues = valueString.Split(new[] + { + arraySeparator + }, StringSplitOptions.None); + if (arrayValues.Length == 0) + { + return list; + } + + MethodInfo addMethodInfo = valueType.GetMethod("Add"); + + foreach (string arrayValue in arrayValues) + { + if (!string.IsNullOrEmpty(arrayValue)) + { + object newValue = null; + try + { + newValue = ConvertStringToValueType(valueType.GetGenericArguments()[0], arrayValue, separator); + } + catch (Exception ex) + { + Log.Warn("Problem converting " + arrayValue + " to type " + valueType.FullName, ex); + } + + if (newValue != null) + { + addMethodInfo.Invoke(list, new[] + { + newValue + }); + } + } + } + + return list; + } + + //LOG.Debug("No convertor for " + fieldType.ToString()); + if (valueType == typeof(object) && valueString.Length > 0) + { + //LOG.Debug("Parsing: " + valueString); + string[] values = valueString.Split(':'); + //LOG.Debug("Type: " + values[0]); + //LOG.Debug("Value: " + values[1]); + Type fieldTypeForValue = Type.GetType(values[0], true); + //LOG.Debug("Type after GetType: " + fieldTypeForValue); + return ConvertStringToValueType(fieldTypeForValue, values[1], separator); + } + + TypeConverter converter = TypeDescriptor.GetConverter(valueType); + return converter.ConvertFromInvariantString(valueString); + } + + /// + /// Override of ToString which calls the ConvertValueToString + /// + /// string representation of this + public override string ToString() + { + return ConvertValueToString(ValueType, Value, _attributes.Separator); + } + + /// + /// Convert the supplied value to a string + /// + /// Type to convert + /// Value to convert + /// separator for lists + /// string representation of the value + private static string ConvertValueToString(Type valueType, object valueObject, string separator) + { + if (valueObject == null) + { + // If there is nothing, deliver nothing! + return string.Empty; + } + + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) + { + StringBuilder stringBuilder = new StringBuilder(); + Type specificValueType = valueType.GetGenericArguments()[0]; + int listCount = (int) valueType.GetProperty("Count").GetValue(valueObject, null); + // Loop though generic list + for (int index = 0; index < listCount; index++) + { + object item = valueType.GetMethod("get_Item").Invoke(valueObject, new object[] + { + index + }); + + // Now you have an instance of the item in the generic list + if (index < listCount - 1) + { + stringBuilder.AppendFormat("{0}{1}", ConvertValueToString(specificValueType, item, separator), separator); + } + else + { + stringBuilder.AppendFormat("{0}", ConvertValueToString(specificValueType, item, separator)); + } + } + + return stringBuilder.ToString(); + } + + if (valueType == typeof(object)) + { + // object to String, this is the hardest + // Format will be "FQTypename[,Assemblyname]:Value" + + // Get the type so we can call ourselves recursive + Type objectType = valueObject.GetType(); + + // Get the value as string + string ourValue = ConvertValueToString(objectType, valueObject, separator); + + // Get the valuetype as string + string valueTypeName = objectType.FullName; + // Find the assembly name and only append it if it's not already in the fqtypename (like System.Drawing) + string assemblyName = objectType.Assembly.FullName; + // correct assemblyName, this also has version information etc. + if (assemblyName.StartsWith("Green")) + { + assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(',')); + } + + return $"{valueTypeName},{assemblyName}:{ourValue}"; + } + + TypeConverter converter = TypeDescriptor.GetConverter(valueType); + return converter.ConvertToInvariantString(valueObject); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/CaptureMode.cs b/src/Greenshot.Base/Interfaces/CaptureMode.cs similarity index 97% rename from src/GreenshotPlugin/Interfaces/CaptureMode.cs rename to src/Greenshot.Base/Interfaces/CaptureMode.cs index 161726a2f..f3a063673 100644 --- a/src/GreenshotPlugin/Interfaces/CaptureMode.cs +++ b/src/Greenshot.Base/Interfaces/CaptureMode.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { /// /// The capture mode for Greenshot diff --git a/src/GreenshotPlugin/Interfaces/Drawing/Adorners/IAdorner.cs b/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs similarity index 95% rename from src/GreenshotPlugin/Interfaces/Drawing/Adorners/IAdorner.cs rename to src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs index 60206099a..cbfd004b4 100644 --- a/src/GreenshotPlugin/Interfaces/Drawing/Adorners/IAdorner.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs @@ -1,102 +1,102 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; - -namespace GreenshotPlugin.Interfaces.Drawing.Adorners -{ - public interface IAdorner - { - /// - /// Returns if this adorner is active - /// - bool IsActive { get; } - - /// - /// These are the bounds of the adorner - /// - Rectangle Bounds { get; } - - /// - /// The current edit status, this is needed to locate the adorner to send events to - /// - EditStatus EditStatus { get; } - - /// - /// The owner of this adorner - /// - IDrawableContainer Owner { get; } - - /// - /// Is the current point "over" the Adorner? - /// If this is the case, the - /// - /// Point to test - /// true if so - bool HitTest(Point point); - - /// - /// Handle the MouseDown event - /// - /// - /// MouseEventArgs - void MouseDown(object sender, MouseEventArgs mouseEventArgs); - - /// - /// Handle the MouseUp event - /// - /// - /// MouseEventArgs - void MouseUp(object sender, MouseEventArgs mouseEventArgs); - - /// - /// Handle the MouseMove event - /// - /// - /// MouseEventArgs - void MouseMove(object sender, MouseEventArgs mouseEventArgs); - - /// - /// Gets the cursor that should be displayed for this behavior. - /// - Cursor Cursor { get; } - - /// - /// Draw the adorner - /// - /// PaintEventArgs - void Paint(PaintEventArgs paintEventArgs); - - /// - /// Called if the owner is transformed - /// - /// Matrix - void Transform(Matrix matrix); - - /// - /// Adjust UI elements to the supplied DPI settings - /// - /// - void AdjustToDpi(uint dpi); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace Greenshot.Base.Interfaces.Drawing.Adorners +{ + public interface IAdorner + { + /// + /// Returns if this adorner is active + /// + bool IsActive { get; } + + /// + /// These are the bounds of the adorner + /// + Rectangle Bounds { get; } + + /// + /// The current edit status, this is needed to locate the adorner to send events to + /// + EditStatus EditStatus { get; } + + /// + /// The owner of this adorner + /// + IDrawableContainer Owner { get; } + + /// + /// Is the current point "over" the Adorner? + /// If this is the case, the + /// + /// Point to test + /// true if so + bool HitTest(Point point); + + /// + /// Handle the MouseDown event + /// + /// + /// MouseEventArgs + void MouseDown(object sender, MouseEventArgs mouseEventArgs); + + /// + /// Handle the MouseUp event + /// + /// + /// MouseEventArgs + void MouseUp(object sender, MouseEventArgs mouseEventArgs); + + /// + /// Handle the MouseMove event + /// + /// + /// MouseEventArgs + void MouseMove(object sender, MouseEventArgs mouseEventArgs); + + /// + /// Gets the cursor that should be displayed for this behavior. + /// + Cursor Cursor { get; } + + /// + /// Draw the adorner + /// + /// PaintEventArgs + void Paint(PaintEventArgs paintEventArgs); + + /// + /// Called if the owner is transformed + /// + /// Matrix + void Transform(Matrix matrix); + + /// + /// Adjust UI elements to the supplied DPI settings + /// + /// + void AdjustToDpi(uint dpi); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Drawing/Container.cs b/src/Greenshot.Base/Interfaces/Drawing/Container.cs similarity index 94% rename from src/GreenshotPlugin/Interfaces/Drawing/Container.cs rename to src/Greenshot.Base/Interfaces/Drawing/Container.cs index 0180886bc..feebb4dfc 100644 --- a/src/GreenshotPlugin/Interfaces/Drawing/Container.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/Container.cs @@ -1,149 +1,149 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; -using GreenshotPlugin.Interfaces.Drawing.Adorners; - -namespace GreenshotPlugin.Interfaces.Drawing -{ - public enum RenderMode - { - EDIT, - EXPORT - }; - - public enum EditStatus - { - UNDRAWN, - DRAWING, - MOVING, - RESIZING, - IDLE - }; - - public interface IDrawableContainer : INotifyPropertyChanged, IDisposable - { - ISurface Parent { get; set; } - bool Selected { get; set; } - - int Left { get; set; } - - int Top { get; set; } - - int Width { get; set; } - - int Height { get; set; } - - Point Location { get; } - - Size Size { get; } - - Rectangle Bounds { get; } - - Rectangle DrawingBounds { get; } - - void ApplyBounds(RectangleF newBounds); - - bool hasFilters { get; } - - EditStatus Status { get; set; } - void Invalidate(); - bool ClickableAt(int x, int y); - void MoveBy(int x, int y); - void Transform(Matrix matrix); - bool HandleMouseDown(int x, int y); - void HandleMouseUp(int x, int y); - bool HandleMouseMove(int x, int y); - bool InitContent(); - void MakeBoundsChangeUndoable(bool allowMerge); - EditStatus DefaultEditMode { get; } - - /// - /// Available adorners for the DrawableContainer - /// - IList Adorners { get; } - - /// - /// Adjust UI elements to the supplied DPI settings - /// - /// uint - void AdjustToDpi(uint dpi); - } - - public interface IDrawableContainerList : IList, IDisposable - { - Guid ParentID { get; } - - bool Selected { get; set; } - - ISurface Parent { get; set; } - EditStatus Status { get; set; } - Rectangle DrawingBounds { get; } - void MakeBoundsChangeUndoable(bool allowMerge); - void Transform(Matrix matrix); - void MoveBy(int dx, int dy); - bool ClickableAt(int x, int y); - IDrawableContainer ClickableElementAt(int x, int y); - void OnDoubleClick(); - bool HasIntersectingFilters(Rectangle clipRectangle); - bool IntersectsWith(Rectangle clipRectangle); - void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle); - void Invalidate(); - void PullElementsToTop(IDrawableContainerList elements); - bool CanPushDown(IDrawableContainerList elements); - void PullElementsUp(IDrawableContainerList elements); - bool CanPullUp(IDrawableContainerList elements); - void PushElementsDown(IDrawableContainerList elements); - void PushElementsToBottom(IDrawableContainerList elements); - void ShowContextMenu(MouseEventArgs e, ISurface surface); - void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e); - void AdjustToDpi(uint dpi); - } - - public interface ITextContainer : IDrawableContainer - { - string Text { get; set; } - void FitToText(); - } - - public interface IImageContainer : IDrawableContainer - { - Image Image { get; set; } - void Load(string filename); - } - - public interface ICursorContainer : IDrawableContainer - { - Cursor Cursor { get; set; } - void Load(string filename); - } - - public interface IIconContainer : IDrawableContainer - { - Icon Icon { get; set; } - void Load(string filename); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using Greenshot.Base.Interfaces.Drawing.Adorners; + +namespace Greenshot.Base.Interfaces.Drawing +{ + public enum RenderMode + { + EDIT, + EXPORT + }; + + public enum EditStatus + { + UNDRAWN, + DRAWING, + MOVING, + RESIZING, + IDLE + }; + + public interface IDrawableContainer : INotifyPropertyChanged, IDisposable + { + ISurface Parent { get; set; } + bool Selected { get; set; } + + int Left { get; set; } + + int Top { get; set; } + + int Width { get; set; } + + int Height { get; set; } + + Point Location { get; } + + Size Size { get; } + + Rectangle Bounds { get; } + + Rectangle DrawingBounds { get; } + + void ApplyBounds(RectangleF newBounds); + + bool hasFilters { get; } + + EditStatus Status { get; set; } + void Invalidate(); + bool ClickableAt(int x, int y); + void MoveBy(int x, int y); + void Transform(Matrix matrix); + bool HandleMouseDown(int x, int y); + void HandleMouseUp(int x, int y); + bool HandleMouseMove(int x, int y); + bool InitContent(); + void MakeBoundsChangeUndoable(bool allowMerge); + EditStatus DefaultEditMode { get; } + + /// + /// Available adorners for the DrawableContainer + /// + IList Adorners { get; } + + /// + /// Adjust UI elements to the supplied DPI settings + /// + /// uint + void AdjustToDpi(uint dpi); + } + + public interface IDrawableContainerList : IList, IDisposable + { + Guid ParentID { get; } + + bool Selected { get; set; } + + ISurface Parent { get; set; } + EditStatus Status { get; set; } + Rectangle DrawingBounds { get; } + void MakeBoundsChangeUndoable(bool allowMerge); + void Transform(Matrix matrix); + void MoveBy(int dx, int dy); + bool ClickableAt(int x, int y); + IDrawableContainer ClickableElementAt(int x, int y); + void OnDoubleClick(); + bool HasIntersectingFilters(Rectangle clipRectangle); + bool IntersectsWith(Rectangle clipRectangle); + void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle); + void Invalidate(); + void PullElementsToTop(IDrawableContainerList elements); + bool CanPushDown(IDrawableContainerList elements); + void PullElementsUp(IDrawableContainerList elements); + bool CanPullUp(IDrawableContainerList elements); + void PushElementsDown(IDrawableContainerList elements); + void PushElementsToBottom(IDrawableContainerList elements); + void ShowContextMenu(MouseEventArgs e, ISurface surface); + void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e); + void AdjustToDpi(uint dpi); + } + + public interface ITextContainer : IDrawableContainer + { + string Text { get; set; } + void FitToText(); + } + + public interface IImageContainer : IDrawableContainer + { + Image Image { get; set; } + void Load(string filename); + } + + public interface ICursorContainer : IDrawableContainer + { + Cursor Cursor { get; set; } + void Load(string filename); + } + + public interface IIconContainer : IDrawableContainer + { + Icon Icon { get; set; } + void Load(string filename); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Drawing/IField.cs b/src/Greenshot.Base/Interfaces/Drawing/IField.cs similarity index 94% rename from src/GreenshotPlugin/Interfaces/Drawing/IField.cs rename to src/Greenshot.Base/Interfaces/Drawing/IField.cs index f241e6a53..a848fa7d7 100644 --- a/src/GreenshotPlugin/Interfaces/Drawing/IField.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/IField.cs @@ -1,65 +1,65 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.ComponentModel; - -namespace GreenshotPlugin.Interfaces.Drawing -{ - [Flags] - public enum FieldFlag - { - NONE = 0, - CONFIRMABLE = 1, - COUNTER = 2 - } - - public interface IFieldType - { - string Name { get; set; } - } - - public interface IField : INotifyPropertyChanged - { - object Value { get; set; } - IFieldType FieldType { get; set; } - string Scope { get; set; } - bool HasValue { get; } - } - - /// - /// EventHandler to be used when a field value changes - /// - public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e); - - /// - /// EventArgs to be used with FieldChangedEventHandler - /// - public class FieldChangedEventArgs : EventArgs - { - public IField Field { get; private set; } - - public FieldChangedEventArgs(IField field) - { - Field = field; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.ComponentModel; + +namespace Greenshot.Base.Interfaces.Drawing +{ + [Flags] + public enum FieldFlag + { + NONE = 0, + CONFIRMABLE = 1, + COUNTER = 2 + } + + public interface IFieldType + { + string Name { get; set; } + } + + public interface IField : INotifyPropertyChanged + { + object Value { get; set; } + IFieldType FieldType { get; set; } + string Scope { get; set; } + bool HasValue { get; } + } + + /// + /// EventHandler to be used when a field value changes + /// + public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e); + + /// + /// EventArgs to be used with FieldChangedEventHandler + /// + public class FieldChangedEventArgs : EventArgs + { + public IField Field { get; private set; } + + public FieldChangedEventArgs(IField field) + { + Field = field; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs b/src/Greenshot.Base/Interfaces/Drawing/IFieldholder.cs similarity index 94% rename from src/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs rename to src/Greenshot.Base/Interfaces/Drawing/IFieldholder.cs index 9cc046b82..7d2a11adb 100644 --- a/src/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/IFieldholder.cs @@ -1,39 +1,39 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Collections.Generic; - -namespace GreenshotPlugin.Interfaces.Drawing -{ - /// - /// Any element holding Fields must provide access to it. - /// AbstractFieldHolder is the basic implementation. - /// If you need the fieldHolder to have child fieldHolders, - /// you should consider using IFieldHolderWithChildren. - /// - public interface IFieldHolder - { - event FieldChangedEventHandler FieldChanged; - IList GetFields(); - IField GetField(IFieldType fieldType); - bool HasField(IFieldType fieldType); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Collections.Generic; + +namespace Greenshot.Base.Interfaces.Drawing +{ + /// + /// Any element holding Fields must provide access to it. + /// AbstractFieldHolder is the basic implementation. + /// If you need the fieldHolder to have child fieldHolders, + /// you should consider using IFieldHolderWithChildren. + /// + public interface IFieldHolder + { + event FieldChangedEventHandler FieldChanged; + IList GetFields(); + IField GetField(IFieldType fieldType); + bool HasField(IFieldType fieldType); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Drawing/IMemento.cs b/src/Greenshot.Base/Interfaces/Drawing/IMemento.cs similarity index 94% rename from src/GreenshotPlugin/Interfaces/Drawing/IMemento.cs rename to src/Greenshot.Base/Interfaces/Drawing/IMemento.cs index cc5a357f3..1d8e425c4 100644 --- a/src/GreenshotPlugin/Interfaces/Drawing/IMemento.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/IMemento.cs @@ -1,46 +1,46 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.Interfaces.Drawing -{ - /// - /// Description of IMemento. - /// - public interface IMemento : IDisposable - { - /// - /// Restores target to the state memorized by this memento. - /// - /// - /// A memento of the state before restoring - /// - IMemento Restore(); - - /// - /// Try to merge the current memento with another, preventing loads of items on the stack - /// - /// The memento to try to merge with - /// - bool Merge(IMemento other); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.Interfaces.Drawing +{ + /// + /// Description of IMemento. + /// + public interface IMemento : IDisposable + { + /// + /// Restores target to the state memorized by this memento. + /// + /// + /// A memento of the state before restoring + /// + IMemento Restore(); + + /// + /// Try to merge the current memento with another, preventing loads of items on the stack + /// + /// The memento to try to merge with + /// + bool Merge(IMemento other); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/DrawingModes.cs b/src/Greenshot.Base/Interfaces/DrawingModes.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/DrawingModes.cs rename to src/Greenshot.Base/Interfaces/DrawingModes.cs index e6d25a359..cc5e91607 100644 --- a/src/GreenshotPlugin/Interfaces/DrawingModes.cs +++ b/src/Greenshot.Base/Interfaces/DrawingModes.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public enum DrawingModes { diff --git a/src/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs b/src/Greenshot.Base/Interfaces/Forms/ImageEditor.cs similarity index 95% rename from src/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs rename to src/Greenshot.Base/Interfaces/Forms/ImageEditor.cs index 912f2987d..617a469de 100644 --- a/src/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs +++ b/src/Greenshot.Base/Interfaces/Forms/ImageEditor.cs @@ -1,46 +1,46 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; - -namespace GreenshotPlugin.Interfaces.Forms -{ - /// - /// The IImageEditor is the Interface that the Greenshot ImageEditor has to implement - /// - public interface IImageEditor - { - /// - /// Get the current Image from the Editor for Exporting (save/upload etc) - /// This is actually a wrapper which calls Surface.GetImageForExport(). - /// Don't forget to call image.Dispose() when finished!!! - /// - /// Bitmap - Image GetImageForExport(); - - /// - /// Make the ICaptureDetails from the current Surface in the EditorForm available. - /// - ICaptureDetails CaptureDetails { get; } - - ISurface Surface { get; set; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; + +namespace Greenshot.Base.Interfaces.Forms +{ + /// + /// The IImageEditor is the Interface that the Greenshot ImageEditor has to implement + /// + public interface IImageEditor + { + /// + /// Get the current Image from the Editor for Exporting (save/upload etc) + /// This is actually a wrapper which calls Surface.GetImageForExport(). + /// Don't forget to call image.Dispose() when finished!!! + /// + /// Bitmap + Image GetImageForExport(); + + /// + /// Make the ICaptureDetails from the current Surface in the EditorForm available. + /// + ICaptureDetails CaptureDetails { get; } + + ISurface Surface { get; set; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/ICapture.cs b/src/Greenshot.Base/Interfaces/ICapture.cs similarity index 98% rename from src/GreenshotPlugin/Interfaces/ICapture.cs rename to src/Greenshot.Base/Interfaces/ICapture.cs index 425d936de..f10d49b8b 100644 --- a/src/GreenshotPlugin/Interfaces/ICapture.cs +++ b/src/Greenshot.Base/Interfaces/ICapture.cs @@ -22,7 +22,7 @@ using System; using System.Drawing; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { /// /// The interface to the Capture object, so Plugins can use it. diff --git a/src/GreenshotPlugin/Interfaces/ICaptureDetails.cs b/src/Greenshot.Base/Interfaces/ICaptureDetails.cs similarity index 97% rename from src/GreenshotPlugin/Interfaces/ICaptureDetails.cs rename to src/Greenshot.Base/Interfaces/ICaptureDetails.cs index 5001f7bd0..2dc49d4a7 100644 --- a/src/GreenshotPlugin/Interfaces/ICaptureDetails.cs +++ b/src/Greenshot.Base/Interfaces/ICaptureDetails.cs @@ -21,9 +21,9 @@ using System; using System.Collections.Generic; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Interfaces.Ocr; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { /// /// Details for the capture, like the window title and date/time etc. diff --git a/src/GreenshotPlugin/Interfaces/IDestination.cs b/src/Greenshot.Base/Interfaces/IDestination.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/IDestination.cs rename to src/Greenshot.Base/Interfaces/IDestination.cs index d57244c69..0e60d04b4 100644 --- a/src/GreenshotPlugin/Interfaces/IDestination.cs +++ b/src/Greenshot.Base/Interfaces/IDestination.cs @@ -1,131 +1,131 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; - -namespace GreenshotPlugin.Interfaces -{ - public class ExportInformation - { - public ExportInformation(string destinationDesignation, string destinationDescription) - { - DestinationDesignation = destinationDesignation; - DestinationDescription = destinationDescription; - } - - public ExportInformation(string destinationDesignation, string destinationDescription, bool exportMade) : this(destinationDesignation, destinationDescription) - { - ExportMade = exportMade; - } - - public string DestinationDesignation { get; } - - public string DestinationDescription { get; set; } - - /// - /// Set to true to specify if the export worked. - /// - public bool ExportMade { get; set; } - - public string Uri { get; set; } - - public string ErrorMessage { get; set; } - - public string Filepath { get; set; } - } - - /// - /// Description of IDestination. - /// - public interface IDestination : IDisposable, IComparable - { - /// - /// Simple "designation" like "File", "Editor" etc, used to store the configuration - /// - string Designation { get; } - - /// - /// Description which will be shown in the settings form, destination picker etc - /// - string Description { get; } - - /// - /// Priority, used for sorting - /// - int Priority { get; } - - /// - /// Gets an icon for the destination - /// - Image DisplayIcon { get; } - - /// - /// Returns if the destination is active - /// - bool IsActive { get; } - - /// - /// Return a menu item - /// - /// Resolve the dynamic destinations too? - /// The menu for which the item is created - /// Handler which is called when clicked - /// ToolStripMenuItem - ToolStripMenuItem GetMenuItem(bool addDynamics, ContextMenuStrip menu, EventHandler destinationClickHandler); - - /// - /// Gets the ShortcutKeys for the Editor - /// - Keys EditorShortcutKeys { get; } - - /// - /// Gets the dynamic destinations - /// - IEnumerable DynamicDestinations(); - - /// - /// Returns true if this destination can be dynamic - /// - bool IsDynamic { get; } - - /// - /// Returns if the destination is active - /// - bool UseDynamicsOnly { get; } - - /// - /// Returns true if this destination returns a link - /// - bool IsLinkable { get; } - - /// - /// If a capture is made, and the destination is enabled, this method is called. - /// - /// true if the user selected this destination from a GUI, false if it was called as part of a process - /// - /// - /// DestinationExportInformation with information, like if the destination has "exported" the capture - ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace Greenshot.Base.Interfaces +{ + public class ExportInformation + { + public ExportInformation(string destinationDesignation, string destinationDescription) + { + DestinationDesignation = destinationDesignation; + DestinationDescription = destinationDescription; + } + + public ExportInformation(string destinationDesignation, string destinationDescription, bool exportMade) : this(destinationDesignation, destinationDescription) + { + ExportMade = exportMade; + } + + public string DestinationDesignation { get; } + + public string DestinationDescription { get; set; } + + /// + /// Set to true to specify if the export worked. + /// + public bool ExportMade { get; set; } + + public string Uri { get; set; } + + public string ErrorMessage { get; set; } + + public string Filepath { get; set; } + } + + /// + /// Description of IDestination. + /// + public interface IDestination : IDisposable, IComparable + { + /// + /// Simple "designation" like "File", "Editor" etc, used to store the configuration + /// + string Designation { get; } + + /// + /// Description which will be shown in the settings form, destination picker etc + /// + string Description { get; } + + /// + /// Priority, used for sorting + /// + int Priority { get; } + + /// + /// Gets an icon for the destination + /// + Image DisplayIcon { get; } + + /// + /// Returns if the destination is active + /// + bool IsActive { get; } + + /// + /// Return a menu item + /// + /// Resolve the dynamic destinations too? + /// The menu for which the item is created + /// Handler which is called when clicked + /// ToolStripMenuItem + ToolStripMenuItem GetMenuItem(bool addDynamics, ContextMenuStrip menu, EventHandler destinationClickHandler); + + /// + /// Gets the ShortcutKeys for the Editor + /// + Keys EditorShortcutKeys { get; } + + /// + /// Gets the dynamic destinations + /// + IEnumerable DynamicDestinations(); + + /// + /// Returns true if this destination can be dynamic + /// + bool IsDynamic { get; } + + /// + /// Returns if the destination is active + /// + bool UseDynamicsOnly { get; } + + /// + /// Returns true if this destination returns a link + /// + bool IsLinkable { get; } + + /// + /// If a capture is made, and the destination is enabled, this method is called. + /// + /// true if the user selected this destination from a GUI, false if it was called as part of a process + /// + /// + /// DestinationExportInformation with information, like if the destination has "exported" the capture + ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/INotificationService.cs b/src/Greenshot.Base/Interfaces/INotificationService.cs similarity index 98% rename from src/GreenshotPlugin/Interfaces/INotificationService.cs rename to src/Greenshot.Base/Interfaces/INotificationService.cs index 43980a8e2..c4b47849d 100644 --- a/src/GreenshotPlugin/Interfaces/INotificationService.cs +++ b/src/Greenshot.Base/Interfaces/INotificationService.cs @@ -21,7 +21,7 @@ using System; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { /// /// This is the interface for the different notification service implementations diff --git a/src/GreenshotPlugin/Interfaces/IProcessor.cs b/src/Greenshot.Base/Interfaces/IProcessor.cs similarity index 95% rename from src/GreenshotPlugin/Interfaces/IProcessor.cs rename to src/Greenshot.Base/Interfaces/IProcessor.cs index 1e8d8a9eb..47216bbbc 100644 --- a/src/GreenshotPlugin/Interfaces/IProcessor.cs +++ b/src/Greenshot.Base/Interfaces/IProcessor.cs @@ -1,59 +1,59 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.Interfaces -{ - /// - /// Description of IProcessor. - /// - public interface IProcessor : IDisposable, IComparable - { - /// - /// Simple "designation" like "FixTitle" - /// - string Designation { get; } - - /// - /// Description which will be shown in the settings form, destination picker etc - /// - string Description { get; } - - /// - /// Priority, used for sorting - /// - int Priority { get; } - - /// - /// Returns if the destination is active - /// - bool isActive { get; } - - /// - /// If a capture is made, and the destination is enabled, this method is called. - /// - /// - /// - /// true if the processor has "processed" the capture - bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.Interfaces +{ + /// + /// Description of IProcessor. + /// + public interface IProcessor : IDisposable, IComparable + { + /// + /// Simple "designation" like "FixTitle" + /// + string Designation { get; } + + /// + /// Description which will be shown in the settings form, destination picker etc + /// + string Description { get; } + + /// + /// Priority, used for sorting + /// + int Priority { get; } + + /// + /// Returns if the destination is active + /// + bool isActive { get; } + + /// + /// If a capture is made, and the destination is enabled, this method is called. + /// + /// + /// + /// true if the processor has "processed" the capture + bool ProcessCapture(ISurface surface, ICaptureDetails captureDetails); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/IServiceLocator.cs b/src/Greenshot.Base/Interfaces/IServiceLocator.cs similarity index 86% rename from src/GreenshotPlugin/Interfaces/IServiceLocator.cs rename to src/Greenshot.Base/Interfaces/IServiceLocator.cs index 10de96ff8..cd107e707 100644 --- a/src/GreenshotPlugin/Interfaces/IServiceLocator.cs +++ b/src/Greenshot.Base/Interfaces/IServiceLocator.cs @@ -1,14 +1,14 @@ -using System.Collections.Generic; - -namespace GreenshotPlugin.Interfaces -{ - public interface IServiceLocator - { - IEnumerable GetAllInstances(); - TService GetInstance(); - - void AddService(params TService[] services); - - void AddService(IEnumerable services); - } +using System.Collections.Generic; + +namespace Greenshot.Base.Interfaces +{ + public interface IServiceLocator + { + IEnumerable GetAllInstances(); + TService GetInstance(); + + void AddService(params TService[] services); + + void AddService(IEnumerable services); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/ISurface.cs b/src/Greenshot.Base/Interfaces/ISurface.cs similarity index 98% rename from src/GreenshotPlugin/Interfaces/ISurface.cs rename to src/Greenshot.Base/Interfaces/ISurface.cs index 51815f580..254d6304f 100644 --- a/src/GreenshotPlugin/Interfaces/ISurface.cs +++ b/src/Greenshot.Base/Interfaces/ISurface.cs @@ -23,11 +23,11 @@ using System; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.Interfaces.Drawing; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { /// /// The interface to the Surface object, so Plugins can use it. diff --git a/src/GreenshotPlugin/Interfaces/Ocr/IOcrProvider.cs b/src/Greenshot.Base/Interfaces/Ocr/IOcrProvider.cs similarity index 97% rename from src/GreenshotPlugin/Interfaces/Ocr/IOcrProvider.cs rename to src/Greenshot.Base/Interfaces/Ocr/IOcrProvider.cs index a70c661c0..09928dbe7 100644 --- a/src/GreenshotPlugin/Interfaces/Ocr/IOcrProvider.cs +++ b/src/Greenshot.Base/Interfaces/Ocr/IOcrProvider.cs @@ -22,7 +22,7 @@ using System.Drawing; using System.Threading.Tasks; -namespace GreenshotPlugin.Interfaces.Ocr +namespace Greenshot.Base.Interfaces.Ocr { /// /// This interface describes something that can do OCR of a bitmap diff --git a/src/GreenshotPlugin/Interfaces/Ocr/Line.cs b/src/Greenshot.Base/Interfaces/Ocr/Line.cs similarity index 98% rename from src/GreenshotPlugin/Interfaces/Ocr/Line.cs rename to src/Greenshot.Base/Interfaces/Ocr/Line.cs index b00e5a957..fc21f72ae 100644 --- a/src/GreenshotPlugin/Interfaces/Ocr/Line.cs +++ b/src/Greenshot.Base/Interfaces/Ocr/Line.cs @@ -1,6 +1,6 @@ using System.Drawing; -namespace GreenshotPlugin.Interfaces.Ocr +namespace Greenshot.Base.Interfaces.Ocr { /// /// Describes a line of words diff --git a/src/GreenshotPlugin/Interfaces/Ocr/OcrInformation.cs b/src/Greenshot.Base/Interfaces/Ocr/OcrInformation.cs similarity index 93% rename from src/GreenshotPlugin/Interfaces/Ocr/OcrInformation.cs rename to src/Greenshot.Base/Interfaces/Ocr/OcrInformation.cs index f1dd829ff..d7cb82559 100644 --- a/src/GreenshotPlugin/Interfaces/Ocr/OcrInformation.cs +++ b/src/Greenshot.Base/Interfaces/Ocr/OcrInformation.cs @@ -1,53 +1,53 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace GreenshotPlugin.Interfaces.Ocr -{ - /// - /// Contains all the information on the OCR result - /// - public class OcrInformation - { - /// - /// Check if there is any content - /// - public bool HasContent => Lines.Any(); - - /// - /// The complete text - /// - public string Text - { - get - { - // Build the text from the lines, otherwise it's just everything concatenated together - var text = new StringBuilder(); - foreach (var line in Lines) - { - text.AppendLine(line.Text); - } - - return text.ToString(); - } - } - - /// - /// The lines of test which the OCR engine found - /// - public IList Lines { get; } = new List(); - - /// - /// Change the offset of the - /// - /// int - /// int - public void Offset(int x, int y) - { - foreach (var line in Lines) - { - line.Offset(x, y); - } - } - } +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Greenshot.Base.Interfaces.Ocr +{ + /// + /// Contains all the information on the OCR result + /// + public class OcrInformation + { + /// + /// Check if there is any content + /// + public bool HasContent => Lines.Any(); + + /// + /// The complete text + /// + public string Text + { + get + { + // Build the text from the lines, otherwise it's just everything concatenated together + var text = new StringBuilder(); + foreach (var line in Lines) + { + text.AppendLine(line.Text); + } + + return text.ToString(); + } + } + + /// + /// The lines of test which the OCR engine found + /// + public IList Lines { get; } = new List(); + + /// + /// Change the offset of the + /// + /// int + /// int + public void Offset(int x, int y) + { + foreach (var line in Lines) + { + line.Offset(x, y); + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Ocr/Word.cs b/src/Greenshot.Base/Interfaces/Ocr/Word.cs similarity index 90% rename from src/GreenshotPlugin/Interfaces/Ocr/Word.cs rename to src/Greenshot.Base/Interfaces/Ocr/Word.cs index 30982caa4..467b5278b 100644 --- a/src/GreenshotPlugin/Interfaces/Ocr/Word.cs +++ b/src/Greenshot.Base/Interfaces/Ocr/Word.cs @@ -1,6 +1,6 @@ using System.Drawing; -namespace GreenshotPlugin.Interfaces.Ocr +namespace Greenshot.Base.Interfaces.Ocr { /// /// Contains the information about a word diff --git a/src/Greenshot.Base/Interfaces/Plugin/HotKeyHandler.cs b/src/Greenshot.Base/Interfaces/Plugin/HotKeyHandler.cs new file mode 100644 index 000000000..db59840e2 --- /dev/null +++ b/src/Greenshot.Base/Interfaces/Plugin/HotKeyHandler.cs @@ -0,0 +1,4 @@ +namespace Greenshot.Base.Interfaces.Plugin +{ + public delegate void HotKeyHandler(); +} \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Plugin/IGreenshotHost.cs b/src/Greenshot.Base/Interfaces/Plugin/IGreenshotHost.cs similarity index 95% rename from src/GreenshotPlugin/Interfaces/Plugin/IGreenshotHost.cs rename to src/Greenshot.Base/Interfaces/Plugin/IGreenshotHost.cs index fc362436d..5c8457178 100644 --- a/src/GreenshotPlugin/Interfaces/Plugin/IGreenshotHost.cs +++ b/src/Greenshot.Base/Interfaces/Plugin/IGreenshotHost.cs @@ -1,49 +1,49 @@ -using System.Drawing; - -namespace GreenshotPlugin.Interfaces.Plugin -{ - /// - /// This interface is the GreenshotPluginHost, that which "Hosts" the plugin. - /// For Greenshot this is implemented in the PluginHelper - /// - public interface IGreenshotHost - { - /// - /// Create a Thumbnail - /// - /// Image of which we need a Thumbnail - /// - /// - /// Image with Thumbnail - Image GetThumbnail(Image image, int width, int height); - - /// - /// Export a surface to the destination with has the supplied designation - /// - /// - /// - /// - /// - ExportInformation ExportCapture(bool manuallyInitiated, string designation, ISurface surface, ICaptureDetails captureDetails); - - /// - /// Make region capture with specified Handler - /// - /// bool false if the mouse should not be captured, true if the configuration should be checked - /// IDestination destination - void CaptureRegion(bool captureMouseCursor, IDestination destination); - - /// - /// Use the supplied capture, and handle it as if it's captured. - /// - /// ICapture to import - void ImportCapture(ICapture captureToImport); - - /// - /// Use the supplied image, and ICapture a capture object for it - /// - /// Image to create capture for - /// ICapture - ICapture GetCapture(Image imageToCapture); - } +using System.Drawing; + +namespace Greenshot.Base.Interfaces.Plugin +{ + /// + /// This interface is the GreenshotPluginHost, that which "Hosts" the plugin. + /// For Greenshot this is implemented in the PluginHelper + /// + public interface IGreenshotHost + { + /// + /// Create a Thumbnail + /// + /// Image of which we need a Thumbnail + /// + /// + /// Image with Thumbnail + Image GetThumbnail(Image image, int width, int height); + + /// + /// Export a surface to the destination with has the supplied designation + /// + /// + /// + /// + /// + ExportInformation ExportCapture(bool manuallyInitiated, string designation, ISurface surface, ICaptureDetails captureDetails); + + /// + /// Make region capture with specified Handler + /// + /// bool false if the mouse should not be captured, true if the configuration should be checked + /// IDestination destination + void CaptureRegion(bool captureMouseCursor, IDestination destination); + + /// + /// Use the supplied capture, and handle it as if it's captured. + /// + /// ICapture to import + void ImportCapture(ICapture captureToImport); + + /// + /// Use the supplied image, and ICapture a capture object for it + /// + /// Image to create capture for + /// ICapture + ICapture GetCapture(Image imageToCapture); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Plugin/IGreenshotPlugin.cs b/src/Greenshot.Base/Interfaces/Plugin/IGreenshotPlugin.cs similarity index 91% rename from src/GreenshotPlugin/Interfaces/Plugin/IGreenshotPlugin.cs rename to src/Greenshot.Base/Interfaces/Plugin/IGreenshotPlugin.cs index b7863e231..b61f49f44 100644 --- a/src/GreenshotPlugin/Interfaces/Plugin/IGreenshotPlugin.cs +++ b/src/Greenshot.Base/Interfaces/Plugin/IGreenshotPlugin.cs @@ -1,26 +1,26 @@ -using System; - -namespace GreenshotPlugin.Interfaces.Plugin -{ - /// - /// This defines the plugin - /// - public interface IGreenshotPlugin : IDisposable - { - /// - /// Is called after the plugin is instantiated, the Plugin should keep a copy of the host and pluginAttribute. - /// - /// true if plugin is initialized, false if not (doesn't show) - bool Initialize(); - - /// - /// Unload of the plugin - /// - void Shutdown(); - - /// - /// Open the Configuration Form, will/should not be called before handshaking is done - /// - void Configure(); - } +using System; + +namespace Greenshot.Base.Interfaces.Plugin +{ + /// + /// This defines the plugin + /// + public interface IGreenshotPlugin : IDisposable + { + /// + /// Is called after the plugin is instantiated, the Plugin should keep a copy of the host and pluginAttribute. + /// + /// true if plugin is initialized, false if not (doesn't show) + bool Initialize(); + + /// + /// Unload of the plugin + /// + void Shutdown(); + + /// + /// Open the Configuration Form, will/should not be called before handshaking is done + /// + void Configure(); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Plugin/PluginAttribute.cs b/src/Greenshot.Base/Interfaces/Plugin/PluginAttribute.cs similarity index 94% rename from src/GreenshotPlugin/Interfaces/Plugin/PluginAttribute.cs rename to src/Greenshot.Base/Interfaces/Plugin/PluginAttribute.cs index 02f0ee14b..f0f66949a 100644 --- a/src/GreenshotPlugin/Interfaces/Plugin/PluginAttribute.cs +++ b/src/Greenshot.Base/Interfaces/Plugin/PluginAttribute.cs @@ -1,50 +1,50 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.Interfaces.Plugin -{ - [Serializable] - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] - public sealed class PluginAttribute : Attribute, IComparable - { - public string Name { get; set; } - - public bool Configurable { get; private set; } - - public PluginAttribute(string name, bool configurable) - { - Name = name; - Configurable = configurable; - } - - public int CompareTo(object obj) - { - if (obj is PluginAttribute other) - { - return string.Compare(Name, other.Name, StringComparison.Ordinal); - } - - throw new ArgumentException("object is not a PluginAttribute"); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.Interfaces.Plugin +{ + [Serializable] + [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public sealed class PluginAttribute : Attribute, IComparable + { + public string Name { get; set; } + + public bool Configurable { get; private set; } + + public PluginAttribute(string name, bool configurable) + { + Name = name; + Configurable = configurable; + } + + public int CompareTo(object obj) + { + if (obj is PluginAttribute other) + { + return string.Compare(Name, other.Name, StringComparison.Ordinal); + } + + throw new ArgumentException("object is not a PluginAttribute"); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/Plugin/SurfaceOutputSettings.cs b/src/Greenshot.Base/Interfaces/Plugin/SurfaceOutputSettings.cs similarity index 92% rename from src/GreenshotPlugin/Interfaces/Plugin/SurfaceOutputSettings.cs rename to src/Greenshot.Base/Interfaces/Plugin/SurfaceOutputSettings.cs index cf77c866b..82946acdd 100644 --- a/src/GreenshotPlugin/Interfaces/Plugin/SurfaceOutputSettings.cs +++ b/src/Greenshot.Base/Interfaces/Plugin/SurfaceOutputSettings.cs @@ -1,91 +1,91 @@ -using System.Collections.Generic; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; - -namespace GreenshotPlugin.Interfaces.Plugin -{ - public class SurfaceOutputSettings - { - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private bool _reduceColors; - private bool _disableReduceColors; - - public SurfaceOutputSettings() - { - _disableReduceColors = false; - Format = CoreConfig.OutputFileFormat; - JPGQuality = CoreConfig.OutputFileJpegQuality; - ReduceColors = CoreConfig.OutputFileReduceColors; - } - - public SurfaceOutputSettings(OutputFormat format) : this() - { - Format = format; - } - - public SurfaceOutputSettings(OutputFormat format, int quality) : this(format) - { - JPGQuality = quality; - } - - public SurfaceOutputSettings(OutputFormat format, int quality, bool reduceColors) : this(format, quality) - { - ReduceColors = reduceColors; - } - - /// - /// BUG-2056 reported a logical issue, using greenshot format as the default causes issues with the external commands. - /// - /// this for fluent API usage - public SurfaceOutputSettings PreventGreenshotFormat() - { - // If OutputFormat is Greenshot, use PNG instead. - if (Format == OutputFormat.greenshot) - { - Format = OutputFormat.png; - } - - return this; - } - - public OutputFormat Format { get; set; } - - public int JPGQuality { get; set; } - - public bool SaveBackgroundOnly { get; set; } - - public List Effects { get; } = new List(); - - public bool ReduceColors - { - get - { - // Fix for Bug #3468436, force quantizing when output format is gif as this has only 256 colors! - if (OutputFormat.gif.Equals(Format)) - { - return true; - } - - return _reduceColors; - } - set { _reduceColors = value; } - } - - /// - /// Disable the reduce colors option, this overrules the enabling - /// - public bool DisableReduceColors - { - get { return _disableReduceColors; } - set - { - // Quantizing os needed when output format is gif as this has only 256 colors! - if (!OutputFormat.gif.Equals(Format)) - { - _disableReduceColors = value; - } - } - } - } +using System.Collections.Generic; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; + +namespace Greenshot.Base.Interfaces.Plugin +{ + public class SurfaceOutputSettings + { + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private bool _reduceColors; + private bool _disableReduceColors; + + public SurfaceOutputSettings() + { + _disableReduceColors = false; + Format = CoreConfig.OutputFileFormat; + JPGQuality = CoreConfig.OutputFileJpegQuality; + ReduceColors = CoreConfig.OutputFileReduceColors; + } + + public SurfaceOutputSettings(OutputFormat format) : this() + { + Format = format; + } + + public SurfaceOutputSettings(OutputFormat format, int quality) : this(format) + { + JPGQuality = quality; + } + + public SurfaceOutputSettings(OutputFormat format, int quality, bool reduceColors) : this(format, quality) + { + ReduceColors = reduceColors; + } + + /// + /// BUG-2056 reported a logical issue, using greenshot format as the default causes issues with the external commands. + /// + /// this for fluent API usage + public SurfaceOutputSettings PreventGreenshotFormat() + { + // If OutputFormat is Greenshot, use PNG instead. + if (Format == OutputFormat.greenshot) + { + Format = OutputFormat.png; + } + + return this; + } + + public OutputFormat Format { get; set; } + + public int JPGQuality { get; set; } + + public bool SaveBackgroundOnly { get; set; } + + public List Effects { get; } = new List(); + + public bool ReduceColors + { + get + { + // Fix for Bug #3468436, force quantizing when output format is gif as this has only 256 colors! + if (OutputFormat.gif.Equals(Format)) + { + return true; + } + + return _reduceColors; + } + set { _reduceColors = value; } + } + + /// + /// Disable the reduce colors option, this overrules the enabling + /// + public bool DisableReduceColors + { + get { return _disableReduceColors; } + set + { + // Quantizing os needed when output format is gif as this has only 256 colors! + if (!OutputFormat.gif.Equals(Format)) + { + _disableReduceColors = value; + } + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/ScreenCaptureMode.cs b/src/Greenshot.Base/Interfaces/ScreenCaptureMode.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/ScreenCaptureMode.cs rename to src/Greenshot.Base/Interfaces/ScreenCaptureMode.cs index bdcc14d81..5481a58e5 100644 --- a/src/GreenshotPlugin/Interfaces/ScreenCaptureMode.cs +++ b/src/Greenshot.Base/Interfaces/ScreenCaptureMode.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public enum ScreenCaptureMode { diff --git a/src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventArgs.cs b/src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventArgs.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventArgs.cs rename to src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventArgs.cs index c3abaa642..32ca381bb 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventArgs.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventArgs.cs @@ -21,7 +21,7 @@ using System; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public class SurfaceDrawingModeEventArgs : EventArgs { diff --git a/src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventHandler.cs b/src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventHandler.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventHandler.cs rename to src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventHandler.cs index 5582f77d3..d71508eea 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceDrawingModeEventHandler.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceDrawingModeEventHandler.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public delegate void SurfaceDrawingModeEventHandler(object sender, SurfaceDrawingModeEventArgs e); } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/SurfaceElementEventArgs.cs b/src/Greenshot.Base/Interfaces/SurfaceElementEventArgs.cs similarity index 93% rename from src/GreenshotPlugin/Interfaces/SurfaceElementEventArgs.cs rename to src/Greenshot.Base/Interfaces/SurfaceElementEventArgs.cs index 3212e8613..f081a6fd8 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceElementEventArgs.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceElementEventArgs.cs @@ -20,9 +20,9 @@ */ using System; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public class SurfaceElementEventArgs : EventArgs { diff --git a/src/GreenshotPlugin/Interfaces/SurfaceElementEventHandler.cs b/src/Greenshot.Base/Interfaces/SurfaceElementEventHandler.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceElementEventHandler.cs rename to src/Greenshot.Base/Interfaces/SurfaceElementEventHandler.cs index eef546545..0d788d854 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceElementEventHandler.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceElementEventHandler.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public delegate void SurfaceElementEventHandler(object sender, SurfaceElementEventArgs e); } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/SurfaceMessageEventArgs.cs b/src/Greenshot.Base/Interfaces/SurfaceMessageEventArgs.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceMessageEventArgs.cs rename to src/Greenshot.Base/Interfaces/SurfaceMessageEventArgs.cs index 783ce1277..5c2019385 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceMessageEventArgs.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceMessageEventArgs.cs @@ -21,7 +21,7 @@ using System; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public class SurfaceMessageEventArgs : EventArgs { diff --git a/src/GreenshotPlugin/Interfaces/SurfaceMessageEventHandler.cs b/src/Greenshot.Base/Interfaces/SurfaceMessageEventHandler.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceMessageEventHandler.cs rename to src/Greenshot.Base/Interfaces/SurfaceMessageEventHandler.cs index 1bea86b37..2fb9083ca 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceMessageEventHandler.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceMessageEventHandler.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public delegate void SurfaceMessageEventHandler(object sender, SurfaceMessageEventArgs e); } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interfaces/SurfaceMessageTyp.cs b/src/Greenshot.Base/Interfaces/SurfaceMessageTyp.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceMessageTyp.cs rename to src/Greenshot.Base/Interfaces/SurfaceMessageTyp.cs index 84efe7609..625dc7d36 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceMessageTyp.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceMessageTyp.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public enum SurfaceMessageTyp { diff --git a/src/GreenshotPlugin/Interfaces/SurfaceSizeChangeEventHandler.cs b/src/Greenshot.Base/Interfaces/SurfaceSizeChangeEventHandler.cs similarity index 96% rename from src/GreenshotPlugin/Interfaces/SurfaceSizeChangeEventHandler.cs rename to src/Greenshot.Base/Interfaces/SurfaceSizeChangeEventHandler.cs index f9fe667f3..47d296074 100644 --- a/src/GreenshotPlugin/Interfaces/SurfaceSizeChangeEventHandler.cs +++ b/src/Greenshot.Base/Interfaces/SurfaceSizeChangeEventHandler.cs @@ -21,7 +21,7 @@ using System; -namespace GreenshotPlugin.Interfaces +namespace Greenshot.Base.Interfaces { public delegate void SurfaceSizeChangeEventHandler(object sender, EventArgs e); } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/Base.cs b/src/Greenshot.Base/Interop/Base.cs similarity index 80% rename from src/GreenshotPlugin/Interop/Base.cs rename to src/Greenshot.Base/Interop/Base.cs index 117e5be59..ef4e5dfa0 100644 --- a/src/GreenshotPlugin/Interop/Base.cs +++ b/src/Greenshot.Base/Interop/Base.cs @@ -1,11 +1,11 @@ -using System; - -namespace GreenshotPlugin.Interop -{ - /// - /// Common properties that has appreared in almost all objects - /// - public interface ICommon : IDisposable - { - } +using System; + +namespace Greenshot.Base.Interop +{ + /// + /// Common properties that has appreared in almost all objects + /// + public interface ICommon : IDisposable + { + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/COMWrapper.cs b/src/Greenshot.Base/Interop/COMWrapper.cs similarity index 97% rename from src/GreenshotPlugin/Interop/COMWrapper.cs rename to src/Greenshot.Base/Interop/COMWrapper.cs index c215809b0..e33c7ee08 100644 --- a/src/GreenshotPlugin/Interop/COMWrapper.cs +++ b/src/Greenshot.Base/Interop/COMWrapper.cs @@ -1,621 +1,621 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; -using System.Windows.Forms; -using GreenshotPlugin.Core; -using log4net; - -namespace GreenshotPlugin.Interop -{ - /// - /// Wraps a late-bound COM server. - /// - public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo - { - private static readonly ILog Log = LogManager.GetLogger(typeof(COMWrapper)); - public const int RPC_E_CALL_REJECTED = unchecked((int) 0x80010001); - public const int RPC_E_FAIL = unchecked((int) 0x80004005); - - /// - /// Holds reference to the actual COM object which is wrapped by this proxy - /// - private readonly object _comObject; - - /// - /// Type of the COM object, set on constructor after getting the COM reference - /// - private readonly Type _comType; - - /// - /// The type of which method calls are intercepted and executed on the COM object. - /// - private readonly Type _interceptType; - - /// - /// The humanly readable target name - /// - private readonly string _targetName; - - /// - /// A simple create instance, doesn't create a wrapper!! - /// - /// T - public static T CreateInstance() - { - Type type = typeof(T); - if (null == type) - { - throw new ArgumentNullException(nameof(T)); - } - - if (!type.IsInterface) - { - throw new ArgumentException("The specified type must be an interface.", nameof(T)); - } - - ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type); - if (string.IsNullOrEmpty(progIdAttribute?.Value)) - { - throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); - } - - string progId = progIdAttribute.Value; - Type comType = null; - if (progId.StartsWith("clsid:")) - { - Guid guid = new Guid(progId.Substring(6)); - try - { - comType = Type.GetTypeFromCLSID(guid); - } - catch (Exception ex) - { - Log.WarnFormat("Error {1} type for {0}", progId, ex.Message); - } - } - else - { - try - { - comType = Type.GetTypeFromProgID(progId, true); - } - catch (Exception ex) - { - Log.WarnFormat("Error {1} type for {0}", progId, ex.Message); - } - } - - object comObject = null; - if (comType != null) - { - try - { - comObject = Activator.CreateInstance(comType); - if (comObject != null) - { - Log.DebugFormat("Created new instance of {0} object.", progId); - } - } - catch (Exception e) - { - Log.WarnFormat("Error {1} creating object for {0}", progId, e.Message); - throw; - } - } - - if (comObject != null) - { - return (T) comObject; - } - - return default; - } - - /// - /// Wrap an object and return the transparent proxy which intercepts all calls to the object - /// - /// An object to intercept - /// Interface which defines the method and properties to intercept - /// - /// Transparent proxy to the real proxy for the object - private static object Wrap(object comObject, Type type, string targetName) - { - if (null == comObject) - { - throw new ArgumentNullException(nameof(comObject)); - } - - if (null == type) - { - throw new ArgumentNullException(nameof(type)); - } - - COMWrapper wrapper = new COMWrapper(comObject, type, targetName); - return wrapper.GetTransparentProxy(); - } - - /// - /// Constructor - /// - /// - /// The COM object to wrap. - /// - /// - /// The interface type to impersonate. - /// - /// - private COMWrapper(object comObject, Type type, string targetName) : base(type) - { - _comObject = comObject; - _comType = comObject.GetType(); - _interceptType = type; - _targetName = targetName; - } - - /// - /// If is not called, we need to make - /// sure that the COM object is still cleaned up. - /// - ~COMWrapper() - { - Log.DebugFormat("Finalize {0}", _interceptType); - Dispose(false); - } - - /// - /// Cleans up the COM object. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Release the COM reference - /// - /// - /// if this was called from the - /// interface. - /// - private void Dispose(bool disposing) - { - if (null != _comObject) - { - Log.DebugFormat("Disposing {0}", _interceptType); - if (Marshal.IsComObject(_comObject)) - { - try - { - int count; - do - { - count = Marshal.ReleaseComObject(_comObject); - Log.DebugFormat("RCW count for {0} now is {1}", _interceptType, count); - } while (count > 0); - } - catch (Exception ex) - { - Log.WarnFormat("Problem releasing COM object {0}", _comType); - Log.Warn("Error: ", ex); - } - } - else - { - Log.WarnFormat("{0} is not a COM object", _comType); - } - } - } - - /// - /// Returns a string representing the wrapped object. - /// - /// - /// The full name of the intercepted type. - /// - public override string ToString() - { - return _interceptType.FullName; - } - - /// - /// Returns the hash code of the wrapped object. - /// - /// - /// The hash code of the wrapped object. - /// - public override int GetHashCode() - { - return _comObject.GetHashCode(); - } - - /// - /// Compares this object to another. - /// - /// - /// The value to compare to. - /// - /// - /// if the objects are equal. - /// - public override bool Equals(object value) - { - if (null != value && RemotingServices.IsTransparentProxy(value)) - { - COMWrapper wrapper = RemotingServices.GetRealProxy(value) as COMWrapper; - if (null != wrapper) - { - return _comObject == wrapper._comObject; - } - } - - return base.Equals(value); - } - - /// - /// Returns the base type for a reference type. - /// - /// - /// The reference type. - /// - /// - /// The base value type. - /// - /// - /// is . - /// - private static Type GetByValType(Type byRefType) - { - if (null == byRefType) - { - throw new ArgumentNullException(nameof(byRefType)); - } - - if (byRefType.IsByRef) - { - string name = byRefType.FullName; - name = name.Substring(0, name.Length - 1); - byRefType = byRefType.Assembly.GetType(name, true); - } - - return byRefType; - } - - /// - /// Intercept method calls - /// - /// - /// Contains information about the method being called - /// - /// - /// A . - /// - public override IMessage Invoke(IMessage myMessage) - { - if (!(myMessage is IMethodCallMessage callMessage)) - { - Log.DebugFormat("Message type not implemented: {0}", myMessage.GetType()); - return null; - } - - MethodInfo method = callMessage.MethodBase as MethodInfo; - if (null == method) - { - Log.DebugFormat("Unrecognized Invoke call: {0}", callMessage.MethodBase); - return null; - } - - object returnValue = null; - object[] outArgs = null; - int outArgsCount = 0; - - string methodName = method.Name; - Type returnType = method.ReturnType; - BindingFlags flags = BindingFlags.InvokeMethod; - int argCount = callMessage.ArgCount; - - ParameterModifier[] argModifiers = null; - ParameterInfo[] parameters = null; - - if ("Dispose" == methodName && 0 == argCount && typeof(void) == returnType) - { - Dispose(); - } - else if ("ToString" == methodName && 0 == argCount && typeof(string) == returnType) - { - returnValue = ToString(); - } - else if ("GetType" == methodName && 0 == argCount && typeof(Type) == returnType) - { - returnValue = _interceptType; - } - else if ("GetHashCode" == methodName && 0 == argCount && typeof(int) == returnType) - { - returnValue = GetHashCode(); - } - else if ("Equals" == methodName && 1 == argCount && typeof(bool) == returnType) - { - returnValue = Equals(callMessage.Args[0]); - } - else if (1 == argCount && typeof(void) == returnType && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) - { - bool removeHandler = methodName.StartsWith("remove_"); - methodName = methodName.Substring(removeHandler ? 7 : 4); - // TODO: Something is missing here - if (!(callMessage.InArgs[0] is Delegate handler)) - { - return new ReturnMessage(new ArgumentNullException(nameof(handler)), callMessage); - } - } - else - { - var invokeObject = _comObject; - var invokeType = _comType; - - object[] args; - ParameterInfo parameter; - if (methodName.StartsWith("get_")) - { - // Property Get - methodName = methodName.Substring(4); - flags = BindingFlags.GetProperty; - args = callMessage.InArgs; - } - else if (methodName.StartsWith("set_")) - { - // Property Set - methodName = methodName.Substring(4); - flags = BindingFlags.SetProperty; - args = callMessage.InArgs; - } - else - { - args = callMessage.Args; - if (null != args && 0 != args.Length) - { - // Modifiers for ref / out parameters - argModifiers = new ParameterModifier[1]; - argModifiers[0] = new ParameterModifier(args.Length); - - parameters = method.GetParameters(); - for (int i = 0; i < parameters.Length; i++) - { - parameter = parameters[i]; - if (parameter.IsOut || parameter.ParameterType.IsByRef) - { - argModifiers[0][i] = true; - outArgsCount++; - } - } - - if (0 == outArgsCount) - { - argModifiers = null; - } - } - } - - // Un-wrap wrapped COM objects before passing to the method - Type byValType; - COMWrapper wrapper; - COMWrapper[] originalArgs; - if (null == args || 0 == args.Length) - { - originalArgs = null; - } - else - { - originalArgs = new COMWrapper[args.Length]; - for (int i = 0; i < args.Length; i++) - { - if (null != args[i] && RemotingServices.IsTransparentProxy(args[i])) - { - wrapper = RemotingServices.GetRealProxy(args[i]) as COMWrapper; - if (null != wrapper) - { - originalArgs[i] = wrapper; - args[i] = wrapper._comObject; - } - } - else if (0 != outArgsCount && argModifiers[0][i]) - { - byValType = GetByValType(parameters[i].ParameterType); - if (byValType.IsInterface) - { - // If we're passing a COM object by reference, and - // the parameter is null, we need to pass a - // DispatchWrapper to avoid a type mismatch exception. - if (null == args[i]) - { - args[i] = new DispatchWrapper(null); - } - } - else if (typeof(decimal) == byValType) - { - // If we're passing a decimal value by reference, - // we need to pass a CurrencyWrapper to avoid a - // type mismatch exception. - // http://support.microsoft.com/?kbid=837378 - args[i] = new CurrencyWrapper(args[i]); - } - } - } - } - - do - { - try - { - returnValue = invokeType.InvokeMember(methodName, flags, null, invokeObject, args, argModifiers, null, null); - break; - } - catch (InvalidComObjectException icoEx) - { - // Should assist BUG-1616 and others - Log.WarnFormat( - "COM object {0} has been separated from its underlying RCW cannot be used. The COM object was released while it was still in use on another thread.", - _interceptType.FullName); - return new ReturnMessage(icoEx, callMessage); - } - catch (Exception ex) - { - // Test for rejected - if (!(ex is COMException comEx)) - { - comEx = ex.InnerException as COMException; - } - - if (comEx != null && (comEx.ErrorCode == RPC_E_CALL_REJECTED || comEx.ErrorCode == RPC_E_FAIL)) - { - string destinationName = _targetName; - // Try to find a "catchy" name for the rejecting application - if (destinationName != null && destinationName.Contains(".")) - { - destinationName = destinationName.Substring(0, destinationName.IndexOf(".", StringComparison.Ordinal)); - } - - if (destinationName == null) - { - destinationName = _interceptType.FullName; - } - - var form = SimpleServiceProvider.Current.GetInstance
(); - - DialogResult result = MessageBox.Show(form, Language.GetFormattedString("com_rejected", destinationName), Language.GetString("com_rejected_title"), - MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); - if (result == DialogResult.OK) - { - continue; - } - } - - // Not rejected OR pressed cancel - return new ReturnMessage(ex, callMessage); - } - } while (true); - - // Handle enum and interface return types - if (null != returnValue) - { - if (returnType.IsInterface) - { - // Wrap the returned value in an intercepting COM wrapper - if (Marshal.IsComObject(returnValue)) - { - returnValue = Wrap(returnValue, returnType, _targetName); - } - } - else if (returnType.IsEnum) - { - // Convert to proper Enum type - returnValue = Enum.Parse(returnType, returnValue.ToString()); - } - } - - // Handle out args - if (0 != outArgsCount) - { - outArgs = new object[args.Length]; - for (int i = 0; i < parameters.Length; i++) - { - if (!argModifiers[0][i]) - { - continue; - } - - var arg = args[i]; - if (null == arg) - { - continue; - } - - parameter = parameters[i]; - wrapper = null; - - byValType = GetByValType(parameter.ParameterType); - if (typeof(decimal) == byValType) - { - if (arg is CurrencyWrapper) - { - arg = ((CurrencyWrapper) arg).WrappedObject; - } - } - else if (byValType.IsEnum) - { - arg = Enum.Parse(byValType, arg.ToString()); - } - else if (byValType.IsInterface) - { - if (Marshal.IsComObject(arg)) - { - wrapper = originalArgs[i]; - if (null != wrapper && wrapper._comObject != arg) - { - wrapper.Dispose(); - wrapper = null; - } - - if (null == wrapper) - { - wrapper = new COMWrapper(arg, byValType, _targetName); - } - - arg = wrapper.GetTransparentProxy(); - } - } - - outArgs[i] = arg; - } - } - } - - return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage); - } - - /// - /// Implementation for the interface IRemotingTypeInfo - /// This makes it possible to cast the COMWrapper - /// - /// Type to cast to - /// object to cast - /// - public bool CanCastTo(Type toType, object o) - { - bool returnValue = _interceptType.IsAssignableFrom(toType); - return returnValue; - } - - /// - /// Implementation for the interface IRemotingTypeInfo - /// - public string TypeName - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Messaging; +using System.Runtime.Remoting.Proxies; +using System.Windows.Forms; +using Greenshot.Base.Core; +using log4net; + +namespace Greenshot.Base.Interop +{ + /// + /// Wraps a late-bound COM server. + /// + public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo + { + private static readonly ILog Log = LogManager.GetLogger(typeof(COMWrapper)); + public const int RPC_E_CALL_REJECTED = unchecked((int) 0x80010001); + public const int RPC_E_FAIL = unchecked((int) 0x80004005); + + /// + /// Holds reference to the actual COM object which is wrapped by this proxy + /// + private readonly object _comObject; + + /// + /// Type of the COM object, set on constructor after getting the COM reference + /// + private readonly Type _comType; + + /// + /// The type of which method calls are intercepted and executed on the COM object. + /// + private readonly Type _interceptType; + + /// + /// The humanly readable target name + /// + private readonly string _targetName; + + /// + /// A simple create instance, doesn't create a wrapper!! + /// + /// T + public static T CreateInstance() + { + Type type = typeof(T); + if (null == type) + { + throw new ArgumentNullException(nameof(T)); + } + + if (!type.IsInterface) + { + throw new ArgumentException("The specified type must be an interface.", nameof(T)); + } + + ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type); + if (string.IsNullOrEmpty(progIdAttribute?.Value)) + { + throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); + } + + string progId = progIdAttribute.Value; + Type comType = null; + if (progId.StartsWith("clsid:")) + { + Guid guid = new Guid(progId.Substring(6)); + try + { + comType = Type.GetTypeFromCLSID(guid); + } + catch (Exception ex) + { + Log.WarnFormat("Error {1} type for {0}", progId, ex.Message); + } + } + else + { + try + { + comType = Type.GetTypeFromProgID(progId, true); + } + catch (Exception ex) + { + Log.WarnFormat("Error {1} type for {0}", progId, ex.Message); + } + } + + object comObject = null; + if (comType != null) + { + try + { + comObject = Activator.CreateInstance(comType); + if (comObject != null) + { + Log.DebugFormat("Created new instance of {0} object.", progId); + } + } + catch (Exception e) + { + Log.WarnFormat("Error {1} creating object for {0}", progId, e.Message); + throw; + } + } + + if (comObject != null) + { + return (T) comObject; + } + + return default; + } + + /// + /// Wrap an object and return the transparent proxy which intercepts all calls to the object + /// + /// An object to intercept + /// Interface which defines the method and properties to intercept + /// + /// Transparent proxy to the real proxy for the object + private static object Wrap(object comObject, Type type, string targetName) + { + if (null == comObject) + { + throw new ArgumentNullException(nameof(comObject)); + } + + if (null == type) + { + throw new ArgumentNullException(nameof(type)); + } + + COMWrapper wrapper = new COMWrapper(comObject, type, targetName); + return wrapper.GetTransparentProxy(); + } + + /// + /// Constructor + /// + /// + /// The COM object to wrap. + /// + /// + /// The interface type to impersonate. + /// + /// + private COMWrapper(object comObject, Type type, string targetName) : base(type) + { + _comObject = comObject; + _comType = comObject.GetType(); + _interceptType = type; + _targetName = targetName; + } + + /// + /// If is not called, we need to make + /// sure that the COM object is still cleaned up. + /// + ~COMWrapper() + { + Log.DebugFormat("Finalize {0}", _interceptType); + Dispose(false); + } + + /// + /// Cleans up the COM object. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Release the COM reference + /// + /// + /// if this was called from the + /// interface. + /// + private void Dispose(bool disposing) + { + if (null != _comObject) + { + Log.DebugFormat("Disposing {0}", _interceptType); + if (Marshal.IsComObject(_comObject)) + { + try + { + int count; + do + { + count = Marshal.ReleaseComObject(_comObject); + Log.DebugFormat("RCW count for {0} now is {1}", _interceptType, count); + } while (count > 0); + } + catch (Exception ex) + { + Log.WarnFormat("Problem releasing COM object {0}", _comType); + Log.Warn("Error: ", ex); + } + } + else + { + Log.WarnFormat("{0} is not a COM object", _comType); + } + } + } + + /// + /// Returns a string representing the wrapped object. + /// + /// + /// The full name of the intercepted type. + /// + public override string ToString() + { + return _interceptType.FullName; + } + + /// + /// Returns the hash code of the wrapped object. + /// + /// + /// The hash code of the wrapped object. + /// + public override int GetHashCode() + { + return _comObject.GetHashCode(); + } + + /// + /// Compares this object to another. + /// + /// + /// The value to compare to. + /// + /// + /// if the objects are equal. + /// + public override bool Equals(object value) + { + if (null != value && RemotingServices.IsTransparentProxy(value)) + { + COMWrapper wrapper = RemotingServices.GetRealProxy(value) as COMWrapper; + if (null != wrapper) + { + return _comObject == wrapper._comObject; + } + } + + return base.Equals(value); + } + + /// + /// Returns the base type for a reference type. + /// + /// + /// The reference type. + /// + /// + /// The base value type. + /// + /// + /// is . + /// + private static Type GetByValType(Type byRefType) + { + if (null == byRefType) + { + throw new ArgumentNullException(nameof(byRefType)); + } + + if (byRefType.IsByRef) + { + string name = byRefType.FullName; + name = name.Substring(0, name.Length - 1); + byRefType = byRefType.Assembly.GetType(name, true); + } + + return byRefType; + } + + /// + /// Intercept method calls + /// + /// + /// Contains information about the method being called + /// + /// + /// A . + /// + public override IMessage Invoke(IMessage myMessage) + { + if (!(myMessage is IMethodCallMessage callMessage)) + { + Log.DebugFormat("Message type not implemented: {0}", myMessage.GetType()); + return null; + } + + MethodInfo method = callMessage.MethodBase as MethodInfo; + if (null == method) + { + Log.DebugFormat("Unrecognized Invoke call: {0}", callMessage.MethodBase); + return null; + } + + object returnValue = null; + object[] outArgs = null; + int outArgsCount = 0; + + string methodName = method.Name; + Type returnType = method.ReturnType; + BindingFlags flags = BindingFlags.InvokeMethod; + int argCount = callMessage.ArgCount; + + ParameterModifier[] argModifiers = null; + ParameterInfo[] parameters = null; + + if ("Dispose" == methodName && 0 == argCount && typeof(void) == returnType) + { + Dispose(); + } + else if ("ToString" == methodName && 0 == argCount && typeof(string) == returnType) + { + returnValue = ToString(); + } + else if ("GetType" == methodName && 0 == argCount && typeof(Type) == returnType) + { + returnValue = _interceptType; + } + else if ("GetHashCode" == methodName && 0 == argCount && typeof(int) == returnType) + { + returnValue = GetHashCode(); + } + else if ("Equals" == methodName && 1 == argCount && typeof(bool) == returnType) + { + returnValue = Equals(callMessage.Args[0]); + } + else if (1 == argCount && typeof(void) == returnType && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) + { + bool removeHandler = methodName.StartsWith("remove_"); + methodName = methodName.Substring(removeHandler ? 7 : 4); + // TODO: Something is missing here + if (!(callMessage.InArgs[0] is Delegate handler)) + { + return new ReturnMessage(new ArgumentNullException(nameof(handler)), callMessage); + } + } + else + { + var invokeObject = _comObject; + var invokeType = _comType; + + object[] args; + ParameterInfo parameter; + if (methodName.StartsWith("get_")) + { + // Property Get + methodName = methodName.Substring(4); + flags = BindingFlags.GetProperty; + args = callMessage.InArgs; + } + else if (methodName.StartsWith("set_")) + { + // Property Set + methodName = methodName.Substring(4); + flags = BindingFlags.SetProperty; + args = callMessage.InArgs; + } + else + { + args = callMessage.Args; + if (null != args && 0 != args.Length) + { + // Modifiers for ref / out parameters + argModifiers = new ParameterModifier[1]; + argModifiers[0] = new ParameterModifier(args.Length); + + parameters = method.GetParameters(); + for (int i = 0; i < parameters.Length; i++) + { + parameter = parameters[i]; + if (parameter.IsOut || parameter.ParameterType.IsByRef) + { + argModifiers[0][i] = true; + outArgsCount++; + } + } + + if (0 == outArgsCount) + { + argModifiers = null; + } + } + } + + // Un-wrap wrapped COM objects before passing to the method + Type byValType; + COMWrapper wrapper; + COMWrapper[] originalArgs; + if (null == args || 0 == args.Length) + { + originalArgs = null; + } + else + { + originalArgs = new COMWrapper[args.Length]; + for (int i = 0; i < args.Length; i++) + { + if (null != args[i] && RemotingServices.IsTransparentProxy(args[i])) + { + wrapper = RemotingServices.GetRealProxy(args[i]) as COMWrapper; + if (null != wrapper) + { + originalArgs[i] = wrapper; + args[i] = wrapper._comObject; + } + } + else if (0 != outArgsCount && argModifiers[0][i]) + { + byValType = GetByValType(parameters[i].ParameterType); + if (byValType.IsInterface) + { + // If we're passing a COM object by reference, and + // the parameter is null, we need to pass a + // DispatchWrapper to avoid a type mismatch exception. + if (null == args[i]) + { + args[i] = new DispatchWrapper(null); + } + } + else if (typeof(decimal) == byValType) + { + // If we're passing a decimal value by reference, + // we need to pass a CurrencyWrapper to avoid a + // type mismatch exception. + // http://support.microsoft.com/?kbid=837378 + args[i] = new CurrencyWrapper(args[i]); + } + } + } + } + + do + { + try + { + returnValue = invokeType.InvokeMember(methodName, flags, null, invokeObject, args, argModifiers, null, null); + break; + } + catch (InvalidComObjectException icoEx) + { + // Should assist BUG-1616 and others + Log.WarnFormat( + "COM object {0} has been separated from its underlying RCW cannot be used. The COM object was released while it was still in use on another thread.", + _interceptType.FullName); + return new ReturnMessage(icoEx, callMessage); + } + catch (Exception ex) + { + // Test for rejected + if (!(ex is COMException comEx)) + { + comEx = ex.InnerException as COMException; + } + + if (comEx != null && (comEx.ErrorCode == RPC_E_CALL_REJECTED || comEx.ErrorCode == RPC_E_FAIL)) + { + string destinationName = _targetName; + // Try to find a "catchy" name for the rejecting application + if (destinationName != null && destinationName.Contains(".")) + { + destinationName = destinationName.Substring(0, destinationName.IndexOf(".", StringComparison.Ordinal)); + } + + if (destinationName == null) + { + destinationName = _interceptType.FullName; + } + + var form = SimpleServiceProvider.Current.GetInstance(); + + DialogResult result = MessageBox.Show(form, Language.GetFormattedString("com_rejected", destinationName), Language.GetString("com_rejected_title"), + MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); + if (result == DialogResult.OK) + { + continue; + } + } + + // Not rejected OR pressed cancel + return new ReturnMessage(ex, callMessage); + } + } while (true); + + // Handle enum and interface return types + if (null != returnValue) + { + if (returnType.IsInterface) + { + // Wrap the returned value in an intercepting COM wrapper + if (Marshal.IsComObject(returnValue)) + { + returnValue = Wrap(returnValue, returnType, _targetName); + } + } + else if (returnType.IsEnum) + { + // Convert to proper Enum type + returnValue = Enum.Parse(returnType, returnValue.ToString()); + } + } + + // Handle out args + if (0 != outArgsCount) + { + outArgs = new object[args.Length]; + for (int i = 0; i < parameters.Length; i++) + { + if (!argModifiers[0][i]) + { + continue; + } + + var arg = args[i]; + if (null == arg) + { + continue; + } + + parameter = parameters[i]; + wrapper = null; + + byValType = GetByValType(parameter.ParameterType); + if (typeof(decimal) == byValType) + { + if (arg is CurrencyWrapper) + { + arg = ((CurrencyWrapper) arg).WrappedObject; + } + } + else if (byValType.IsEnum) + { + arg = Enum.Parse(byValType, arg.ToString()); + } + else if (byValType.IsInterface) + { + if (Marshal.IsComObject(arg)) + { + wrapper = originalArgs[i]; + if (null != wrapper && wrapper._comObject != arg) + { + wrapper.Dispose(); + wrapper = null; + } + + if (null == wrapper) + { + wrapper = new COMWrapper(arg, byValType, _targetName); + } + + arg = wrapper.GetTransparentProxy(); + } + } + + outArgs[i] = arg; + } + } + } + + return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage); + } + + /// + /// Implementation for the interface IRemotingTypeInfo + /// This makes it possible to cast the COMWrapper + /// + /// Type to cast to + /// object to cast + /// + public bool CanCastTo(Type toType, object o) + { + bool returnValue = _interceptType.IsAssignableFrom(toType); + return returnValue; + } + + /// + /// Implementation for the interface IRemotingTypeInfo + /// + public string TypeName + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/ComProgIdAttribute.cs b/src/Greenshot.Base/Interop/ComProgIdAttribute.cs similarity index 96% rename from src/GreenshotPlugin/Interop/ComProgIdAttribute.cs rename to src/Greenshot.Base/Interop/ComProgIdAttribute.cs index ecb782773..079bdd149 100644 --- a/src/GreenshotPlugin/Interop/ComProgIdAttribute.cs +++ b/src/Greenshot.Base/Interop/ComProgIdAttribute.cs @@ -1,88 +1,88 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.Interop -{ - /// - /// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner) - /// - [AttributeUsage(AttributeTargets.Interface)] - public sealed class ComProgIdAttribute : Attribute - { - /// - /// Extracts the attribute from the specified type. - /// - /// - /// The interface type. - /// - /// - /// The . - /// - /// - /// is . - /// - public static ComProgIdAttribute GetAttribute(Type interfaceType) - { - if (null == interfaceType) - { - throw new ArgumentNullException(nameof(interfaceType)); - } - - Type attributeType = typeof(ComProgIdAttribute); - object[] attributes = interfaceType.GetCustomAttributes(attributeType, false); - - if (0 == attributes.Length) - { - Type[] interfaces = interfaceType.GetInterfaces(); - foreach (Type t in interfaces) - { - interfaceType = t; - attributes = interfaceType.GetCustomAttributes(attributeType, false); - if (0 != attributes.Length) - { - break; - } - } - } - - if (0 == attributes.Length) - { - return null; - } - - return (ComProgIdAttribute) attributes[0]; - } - - /// Constructor - /// The COM ProgID. - public ComProgIdAttribute(string value) - { - Value = value; - } - - /// - /// Returns the COM ProgID - /// - public string Value { get; } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.Interop +{ + /// + /// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner) + /// + [AttributeUsage(AttributeTargets.Interface)] + public sealed class ComProgIdAttribute : Attribute + { + /// + /// Extracts the attribute from the specified type. + /// + /// + /// The interface type. + /// + /// + /// The . + /// + /// + /// is . + /// + public static ComProgIdAttribute GetAttribute(Type interfaceType) + { + if (null == interfaceType) + { + throw new ArgumentNullException(nameof(interfaceType)); + } + + Type attributeType = typeof(ComProgIdAttribute); + object[] attributes = interfaceType.GetCustomAttributes(attributeType, false); + + if (0 == attributes.Length) + { + Type[] interfaces = interfaceType.GetInterfaces(); + foreach (Type t in interfaces) + { + interfaceType = t; + attributes = interfaceType.GetCustomAttributes(attributeType, false); + if (0 != attributes.Length) + { + break; + } + } + } + + if (0 == attributes.Length) + { + return null; + } + + return (ComProgIdAttribute) attributes[0]; + } + + /// Constructor + /// The COM ProgID. + public ComProgIdAttribute(string value) + { + Value = value; + } + + /// + /// Returns the COM ProgID + /// + public string Value { get; } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IAppVisibility.cs b/src/Greenshot.Base/Interop/IAppVisibility.cs similarity index 95% rename from src/GreenshotPlugin/Interop/IAppVisibility.cs rename to src/Greenshot.Base/Interop/IAppVisibility.cs index f9fa6ed10..b0c392bae 100644 --- a/src/GreenshotPlugin/Interop/IAppVisibility.cs +++ b/src/Greenshot.Base/Interop/IAppVisibility.cs @@ -1,41 +1,41 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Interop -{ - // This is used for Windows 8 to see if the App Launcher is active - // See http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119%28v=vs.85%29.aspx - [ComProgId("clsid:7E5FE3D9-985F-4908-91F9-EE19F9FD1514")] - [ComImport, Guid("2246EA2D-CAEA-4444-A3C4-6DE827E44313"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IAppVisibility - { - MONITOR_APP_VISIBILITY GetAppVisibilityOnMonitor(IntPtr hMonitor); - bool IsLauncherVisible { get; } - } - - public enum MONITOR_APP_VISIBILITY - { - MAV_APP_VISIBLE = 2 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Interop +{ + // This is used for Windows 8 to see if the App Launcher is active + // See http://msdn.microsoft.com/en-us/library/windows/desktop/jj554119%28v=vs.85%29.aspx + [ComProgId("clsid:7E5FE3D9-985F-4908-91F9-EE19F9FD1514")] + [ComImport, Guid("2246EA2D-CAEA-4444-A3C4-6DE827E44313"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IAppVisibility + { + MONITOR_APP_VISIBILITY GetAppVisibilityOnMonitor(IntPtr hMonitor); + bool IsLauncherVisible { get; } + } + + public enum MONITOR_APP_VISIBILITY + { + MAV_APP_VISIBLE = 2 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IDispatch.cs b/src/Greenshot.Base/Interop/IDispatch.cs similarity index 96% rename from src/GreenshotPlugin/Interop/IDispatch.cs rename to src/Greenshot.Base/Interop/IDispatch.cs index 99edf0a87..5e7c0a563 100644 --- a/src/GreenshotPlugin/Interop/IDispatch.cs +++ b/src/Greenshot.Base/Interop/IDispatch.cs @@ -1,47 +1,47 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.CustomMarshalers; - -namespace GreenshotPlugin.Interop -{ - [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsDual)] - public interface IDispatch : IUnknown - { - [PreserveSig] - int GetTypeInfoCount(out int count); - - [PreserveSig] - int GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo, [MarshalAs(UnmanagedType.U4)] int lcid, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] - out Type typeInfo); - - [PreserveSig] - int GetIDsOfNames(ref Guid riid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] - string[] rgsNames, int cNames, int lcid, [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); - - [PreserveSig] - int Invoke(int dispIdMember, ref Guid riid, uint lcid, ushort wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, - out object pVarResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, IntPtr[] pArgErr); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.CustomMarshalers; + +namespace Greenshot.Base.Interop +{ + [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsDual)] + public interface IDispatch : IUnknown + { + [PreserveSig] + int GetTypeInfoCount(out int count); + + [PreserveSig] + int GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo, [MarshalAs(UnmanagedType.U4)] int lcid, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] + out Type typeInfo); + + [PreserveSig] + int GetIDsOfNames(ref Guid riid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] + string[] rgsNames, int cNames, int lcid, [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); + + [PreserveSig] + int Invoke(int dispIdMember, ref Guid riid, uint lcid, ushort wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, + out object pVarResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, IntPtr[] pArgErr); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IOleCommandTarget.cs b/src/Greenshot.Base/Interop/IOleCommandTarget.cs similarity index 95% rename from src/GreenshotPlugin/Interop/IOleCommandTarget.cs rename to src/Greenshot.Base/Interop/IOleCommandTarget.cs index 7e41c51e6..5903bda58 100644 --- a/src/GreenshotPlugin/Interop/IOleCommandTarget.cs +++ b/src/Greenshot.Base/Interop/IOleCommandTarget.cs @@ -1,40 +1,40 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Interop -{ - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(true), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770")] - public interface IOleCommandTarget - { - [return: MarshalAs(UnmanagedType.I4)] - [PreserveSig] - int QueryStatus([In, MarshalAs(UnmanagedType.LPStruct)] - Guid pguidCmdGroup, int cCmds, IntPtr prgCmds, IntPtr pCmdText); - - [return: MarshalAs(UnmanagedType.I4)] - [PreserveSig] - int Exec([In, MarshalAs(UnmanagedType.LPStruct)] - Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Interop +{ + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(true), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770")] + public interface IOleCommandTarget + { + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int QueryStatus([In, MarshalAs(UnmanagedType.LPStruct)] + Guid pguidCmdGroup, int cCmds, IntPtr prgCmds, IntPtr pCmdText); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int Exec([In, MarshalAs(UnmanagedType.LPStruct)] + Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IOleWindow.cs b/src/Greenshot.Base/Interop/IOleWindow.cs similarity index 95% rename from src/GreenshotPlugin/Interop/IOleWindow.cs rename to src/Greenshot.Base/Interop/IOleWindow.cs index b746dc74d..adefc15ef 100644 --- a/src/GreenshotPlugin/Interop/IOleWindow.cs +++ b/src/Greenshot.Base/Interop/IOleWindow.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Interop -{ - // Needed to get the Window handle from the IDocument2 - // See: http://msdn.microsoft.com/en-us/library/ms680102%28v=vs.85%29.aspx - [ComImport, Guid("00000114-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IOleWindow - { - void GetWindow(out IntPtr phWnd); - void ContextSensitiveHelp([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Interop +{ + // Needed to get the Window handle from the IDocument2 + // See: http://msdn.microsoft.com/en-us/library/ms680102%28v=vs.85%29.aspx + [ComImport, Guid("00000114-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleWindow + { + void GetWindow(out IntPtr phWnd); + void ContextSensitiveHelp([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IServiceProvider.cs b/src/Greenshot.Base/Interop/IServiceProvider.cs similarity index 95% rename from src/GreenshotPlugin/Interop/IServiceProvider.cs rename to src/Greenshot.Base/Interop/IServiceProvider.cs index 9b15b78d5..423541e5e 100644 --- a/src/GreenshotPlugin/Interop/IServiceProvider.cs +++ b/src/Greenshot.Base/Interop/IServiceProvider.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Interop -{ - // This is the COM IServiceProvider interface, not System.IServiceProvider .Net interface! - [ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), - InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IServiceProvider - { - [return: MarshalAs(UnmanagedType.I4)] - [PreserveSig] - int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Interop +{ + // This is the COM IServiceProvider interface, not System.IServiceProvider .Net interface! + [ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IServiceProvider + { + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/Interop/IUnknown.cs b/src/Greenshot.Base/Interop/IUnknown.cs similarity index 94% rename from src/GreenshotPlugin/Interop/IUnknown.cs rename to src/Greenshot.Base/Interop/IUnknown.cs index d7cccb743..bdffb0bf9 100644 --- a/src/GreenshotPlugin/Interop/IUnknown.cs +++ b/src/Greenshot.Base/Interop/IUnknown.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.Interop -{ - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000000-0000-0000-C000-000000000046")] - public interface IUnknown - { - IntPtr QueryInterface(ref Guid riid); - - [PreserveSig] - uint AddRef(); - - [PreserveSig] - uint Release(); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.Interop +{ + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000000-0000-0000-C000-000000000046")] + public interface IUnknown + { + IntPtr QueryInterface(ref Guid riid); + + [PreserveSig] + uint AddRef(); + + [PreserveSig] + uint Release(); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/DWM.cs b/src/Greenshot.Base/UnmanagedHelpers/DWM.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/DWM.cs rename to src/Greenshot.Base/UnmanagedHelpers/DWM.cs index 9e7737289..cf5a2c056 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/DWM.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/DWM.cs @@ -1,123 +1,123 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.Enums; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; -using Microsoft.Win32; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Desktop Window Manager helper code - /// - public static class DWM - { - // DWM - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb); - - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmUnregisterThumbnail(IntPtr thumb); - - [DllImport("dwmapi", SetLastError = true)] - public static extern HResult DwmQueryThumbnailSourceSize(IntPtr thumb, out SIZE size); - - [DllImport("dwmapi", SetLastError = true)] - public static extern HResult DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props); - - // Deprecated as of Windows 8 Release Preview - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmIsCompositionEnabled(out bool enabled); - - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT lpRect, int size); - - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute); - - // Key to ColorizationColor for DWM - private const string COLORIZATION_COLOR_KEY = @"SOFTWARE\Microsoft\Windows\DWM"; - - /// - /// Checks if the window is cloaked, this should solve some issues with the window selection code - /// - /// IntPtr as hWmd - /// bool - public static bool IsWindowCloaked(IntPtr hWnd) - { - if (!WindowsVersion.IsWindows8OrLater) - { - return false; - } - - DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, out bool isCloaked, Marshal.SizeOf(typeof(bool))); - return isCloaked; - } - - /// - /// Helper method for an easy DWM check - /// - /// bool true if DWM is available AND active - public static bool IsDwmEnabled - { - get - { - // According to: http://technet.microsoft.com/en-us/subscriptions/aa969538%28v=vs.85%29.aspx - // And: http://msdn.microsoft.com/en-us/library/windows/desktop/aa969510%28v=vs.85%29.aspx - // DMW is always enabled on Windows 8! So return true and save a check! ;-) - if (WindowsVersion.IsWindows8OrLater) - { - return true; - } - - if (WindowsVersion.IsWindowsVistaOrLater) - { - DwmIsCompositionEnabled(out var dwmEnabled); - return dwmEnabled; - } - - return false; - } - } - - public static Color ColorizationColor - { - get - { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(COLORIZATION_COLOR_KEY, false)) - { - object dwordValue = key?.GetValue("ColorizationColor"); - if (dwordValue != null) - { - return Color.FromArgb((int) dwordValue); - } - } - - return Color.White; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using Greenshot.Base.Core; +using Greenshot.Base.Core.Enums; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; +using Microsoft.Win32; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Desktop Window Manager helper code + /// + public static class DWM + { + // DWM + [DllImport("dwmapi", SetLastError = true)] + public static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb); + + [DllImport("dwmapi", SetLastError = true)] + public static extern int DwmUnregisterThumbnail(IntPtr thumb); + + [DllImport("dwmapi", SetLastError = true)] + public static extern HResult DwmQueryThumbnailSourceSize(IntPtr thumb, out SIZE size); + + [DllImport("dwmapi", SetLastError = true)] + public static extern HResult DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props); + + // Deprecated as of Windows 8 Release Preview + [DllImport("dwmapi", SetLastError = true)] + public static extern int DwmIsCompositionEnabled(out bool enabled); + + [DllImport("dwmapi", SetLastError = true)] + public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT lpRect, int size); + + [DllImport("dwmapi", SetLastError = true)] + public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute); + + // Key to ColorizationColor for DWM + private const string COLORIZATION_COLOR_KEY = @"SOFTWARE\Microsoft\Windows\DWM"; + + /// + /// Checks if the window is cloaked, this should solve some issues with the window selection code + /// + /// IntPtr as hWmd + /// bool + public static bool IsWindowCloaked(IntPtr hWnd) + { + if (!WindowsVersion.IsWindows8OrLater) + { + return false; + } + + DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, out bool isCloaked, Marshal.SizeOf(typeof(bool))); + return isCloaked; + } + + /// + /// Helper method for an easy DWM check + /// + /// bool true if DWM is available AND active + public static bool IsDwmEnabled + { + get + { + // According to: http://technet.microsoft.com/en-us/subscriptions/aa969538%28v=vs.85%29.aspx + // And: http://msdn.microsoft.com/en-us/library/windows/desktop/aa969510%28v=vs.85%29.aspx + // DMW is always enabled on Windows 8! So return true and save a check! ;-) + if (WindowsVersion.IsWindows8OrLater) + { + return true; + } + + if (WindowsVersion.IsWindowsVistaOrLater) + { + DwmIsCompositionEnabled(out var dwmEnabled); + return dwmEnabled; + } + + return false; + } + } + + public static Color ColorizationColor + { + get + { + using (RegistryKey key = Registry.CurrentUser.OpenSubKey(COLORIZATION_COLOR_KEY, false)) + { + object dwordValue = key?.GetValue("ColorizationColor"); + if (dwordValue != null) + { + return Color.FromArgb((int) dwordValue); + } + } + + return Color.White; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/EnumWindowsProc.cs b/src/Greenshot.Base/UnmanagedHelpers/EnumWindowsProc.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/EnumWindowsProc.cs rename to src/Greenshot.Base/UnmanagedHelpers/EnumWindowsProc.cs index db0185e07..d5e97162d 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/EnumWindowsProc.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/EnumWindowsProc.cs @@ -1,33 +1,33 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Used with EnumWindows or EnumChildWindows - /// - /// IntPtr - /// int - /// int - public delegate int EnumWindowsProc(IntPtr hWnd, int lParam); +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Used with EnumWindows or EnumChildWindows + /// + /// IntPtr + /// int + /// int + public delegate int EnumWindowsProc(IntPtr hWnd, int lParam); } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/ClassLongIndex.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/ClassLongIndex.cs index d862d0ee8..6c070a25b 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/ClassLongIndex.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ClassLongIndex - { - GCL_HICON = -14, // a handle to the icon associated with the class. - GCL_HICONSM = -34, // a handle to the small icon associated with the class. - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ClassLongIndex + { + GCL_HICON = -14, // a handle to the icon associated with the class. + GCL_HICONSM = -34, // a handle to the small icon associated with the class. + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs similarity index 95% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs index 6c9aeb652..03d1ab7f9 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/DWMWINDOWATTRIBUTE.cs @@ -1,46 +1,46 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum DWMWINDOWATTRIBUTE : uint - { - DWMWA_NCRENDERING_ENABLED = 1, - DWMWA_NCRENDERING_POLICY, - DWMWA_TRANSITIONS_FORCEDISABLED, - DWMWA_ALLOW_NCPAINT, - DWMWA_CAPTION_BUTTON_BOUNDS, - DWMWA_NONCLIENT_RTL_LAYOUT, - DWMWA_FORCE_ICONIC_REPRESENTATION, - DWMWA_FLIP3D_POLICY, - DWMWA_EXTENDED_FRAME_BOUNDS, // This is the one we need for retrieving the Window size since Windows Vista - DWMWA_HAS_ICONIC_BITMAP, // Since Windows 7 - DWMWA_DISALLOW_PEEK, // Since Windows 7 - DWMWA_EXCLUDED_FROM_PEEK, // Since Windows 7 - DWMWA_CLOAK, // Since Windows 8 - DWMWA_CLOAKED, // Since Windows 8 - DWMWA_FREEZE_REPRESENTATION, // Since Windows 8 - DWMWA_LAST - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DWMWINDOWATTRIBUTE : uint + { + DWMWA_NCRENDERING_ENABLED = 1, + DWMWA_NCRENDERING_POLICY, + DWMWA_TRANSITIONS_FORCEDISABLED, + DWMWA_ALLOW_NCPAINT, + DWMWA_CAPTION_BUTTON_BOUNDS, + DWMWA_NONCLIENT_RTL_LAYOUT, + DWMWA_FORCE_ICONIC_REPRESENTATION, + DWMWA_FLIP3D_POLICY, + DWMWA_EXTENDED_FRAME_BOUNDS, // This is the one we need for retrieving the Window size since Windows Vista + DWMWA_HAS_ICONIC_BITMAP, // Since Windows 7 + DWMWA_DISALLOW_PEEK, // Since Windows 7 + DWMWA_EXCLUDED_FROM_PEEK, // Since Windows 7 + DWMWA_CLOAK, // Since Windows 8 + DWMWA_CLOAKED, // Since Windows 8 + DWMWA_FREEZE_REPRESENTATION, // Since Windows 8 + DWMWA_LAST + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs index 37f64de7c..aa808f807 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/DWM_THUMBNAIL_PROPERTIES.cs @@ -1,111 +1,111 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Runtime.InteropServices; -using GreenshotPlugin.UnmanagedHelpers.Structs; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// See: http://msdn.microsoft.com/en-us/library/aa969502(v=vs.85).aspx - /// - [StructLayout(LayoutKind.Sequential)] - public struct DWM_THUMBNAIL_PROPERTIES - { - // A bitwise combination of DWM thumbnail constant values that indicates which members of this structure are set. - public int dwFlags; - - // The area in the destination window where the thumbnail will be rendered. - public RECT rcDestination; - - // The region of the source window to use as the thumbnail. By default, the entire window is used as the thumbnail. - public RECT rcSource; - - // The opacity with which to render the thumbnail. 0 is fully transparent while 255 is fully opaque. The default value is 255. - public byte opacity; - - // TRUE to make the thumbnail visible; otherwise, FALSE. The default is FALSE. - public bool fVisible; - - // TRUE to use only the thumbnail source's client area; otherwise, FALSE. The default is FALSE. - public bool fSourceClientAreaOnly; - - public RECT Destination - { - set - { - dwFlags |= DWM_TNP_RECTDESTINATION; - rcDestination = value; - } - } - - public RECT Source - { - set - { - dwFlags |= DWM_TNP_RECTSOURCE; - rcSource = value; - } - } - - public byte Opacity - { - set - { - dwFlags |= DWM_TNP_OPACITY; - opacity = value; - } - } - - public bool Visible - { - set - { - dwFlags |= DWM_TNP_VISIBLE; - fVisible = value; - } - } - - public bool SourceClientAreaOnly - { - set - { - dwFlags |= DWM_TNP_SOURCECLIENTAREAONLY; - fSourceClientAreaOnly = value; - } - } - - // A value for the rcDestination member has been specified. - public const int DWM_TNP_RECTDESTINATION = 0x00000001; - - // A value for the rcSource member has been specified. - public const int DWM_TNP_RECTSOURCE = 0x00000002; - - // A value for the opacity member has been specified. - public const int DWM_TNP_OPACITY = 0x00000004; - - // A value for the fVisible member has been specified. - public const int DWM_TNP_VISIBLE = 0x00000008; - - // A value for the fSourceClientAreaOnly member has been specified. - public const int DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010; - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Runtime.InteropServices; +using Greenshot.Base.UnmanagedHelpers.Structs; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// See: http://msdn.microsoft.com/en-us/library/aa969502(v=vs.85).aspx + /// + [StructLayout(LayoutKind.Sequential)] + public struct DWM_THUMBNAIL_PROPERTIES + { + // A bitwise combination of DWM thumbnail constant values that indicates which members of this structure are set. + public int dwFlags; + + // The area in the destination window where the thumbnail will be rendered. + public RECT rcDestination; + + // The region of the source window to use as the thumbnail. By default, the entire window is used as the thumbnail. + public RECT rcSource; + + // The opacity with which to render the thumbnail. 0 is fully transparent while 255 is fully opaque. The default value is 255. + public byte opacity; + + // TRUE to make the thumbnail visible; otherwise, FALSE. The default is FALSE. + public bool fVisible; + + // TRUE to use only the thumbnail source's client area; otherwise, FALSE. The default is FALSE. + public bool fSourceClientAreaOnly; + + public RECT Destination + { + set + { + dwFlags |= DWM_TNP_RECTDESTINATION; + rcDestination = value; + } + } + + public RECT Source + { + set + { + dwFlags |= DWM_TNP_RECTSOURCE; + rcSource = value; + } + } + + public byte Opacity + { + set + { + dwFlags |= DWM_TNP_OPACITY; + opacity = value; + } + } + + public bool Visible + { + set + { + dwFlags |= DWM_TNP_VISIBLE; + fVisible = value; + } + } + + public bool SourceClientAreaOnly + { + set + { + dwFlags |= DWM_TNP_SOURCECLIENTAREAONLY; + fSourceClientAreaOnly = value; + } + } + + // A value for the rcDestination member has been specified. + public const int DWM_TNP_RECTDESTINATION = 0x00000001; + + // A value for the rcSource member has been specified. + public const int DWM_TNP_RECTSOURCE = 0x00000002; + + // A value for the opacity member has been specified. + public const int DWM_TNP_OPACITY = 0x00000004; + + // A value for the fVisible member has been specified. + public const int DWM_TNP_VISIBLE = 0x00000008; + + // A value for the fSourceClientAreaOnly member has been specified. + public const int DWM_TNP_SOURCECLIENTAREAONLY = 0x00000010; + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/DesktopAccessRight.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/DesktopAccessRight.cs index a0b5e1be8..219299a35 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/DesktopAccessRight.cs @@ -1,45 +1,45 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum DesktopAccessRight : uint - { - DESKTOP_READOBJECTS = 0x00000001, - DESKTOP_CREATEWINDOW = 0x00000002, - DESKTOP_CREATEMENU = 0x00000004, - DESKTOP_HOOKCONTROL = 0x00000008, - DESKTOP_JOURNALRECORD = 0x00000010, - DESKTOP_JOURNALPLAYBACK = 0x00000020, - DESKTOP_ENUMERATE = 0x00000040, - DESKTOP_WRITEOBJECTS = 0x00000080, - DESKTOP_SWITCHDESKTOP = 0x00000100, - - GENERIC_ALL = (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | - DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | - DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP) - }; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DesktopAccessRight : uint + { + DESKTOP_READOBJECTS = 0x00000001, + DESKTOP_CREATEWINDOW = 0x00000002, + DESKTOP_CREATEMENU = 0x00000004, + DESKTOP_HOOKCONTROL = 0x00000008, + DESKTOP_JOURNALRECORD = 0x00000010, + DESKTOP_JOURNALPLAYBACK = 0x00000020, + DESKTOP_ENUMERATE = 0x00000040, + DESKTOP_WRITEOBJECTS = 0x00000080, + DESKTOP_SWITCHDESKTOP = 0x00000100, + + GENERIC_ALL = (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | + DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | + DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP) + }; } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/DeviceCaps.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/DeviceCaps.cs index ff4f3e3e4..126d9de62 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/DeviceCaps.cs @@ -1,43 +1,43 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Used by GDI32.GetDeviceCaps - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum DeviceCaps - { - /// - /// Logical pixels inch in X - /// - LOGPIXELSX = 88, - - /// - /// Current vertical refresh rate of the display device (for displays only) in Hz - /// - VREFRESH = 116 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// Used by GDI32.GetDeviceCaps + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DeviceCaps + { + /// + /// Logical pixels inch in X + /// + LOGPIXELSX = 88, + + /// + /// Current vertical refresh rate of the display device (for displays only) in Hz + /// + VREFRESH = 116 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/EventObjects.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/EventObjects.cs index a1981e644..81532e912 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/EventObjects.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Used for User32.SetWinEventHook - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd373606%28v=vs.85%29.aspx#OBJID_WINDOW - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum EventObjects - { - OBJID_WINDOW = 0 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// Used for User32.SetWinEventHook + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd373606%28v=vs.85%29.aspx#OBJID_WINDOW + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum EventObjects + { + OBJID_WINDOW = 0 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs index e04af4108..e00166b2d 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ExtendedWindowStyleFlags : uint - { - WS_EX_TOOLWINDOW = 0x00000080, - - WS_EX_NOREDIRECTIONBITMAP = - 0x00200000, //The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual. - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ExtendedWindowStyleFlags : uint + { + WS_EX_TOOLWINDOW = 0x00000080, + + WS_EX_NOREDIRECTIONBITMAP = + 0x00200000, //The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual. + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/ProcessAccessFlags.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/ProcessAccessFlags.cs index 27a89b3b6..d4e593840 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/ProcessAccessFlags.cs @@ -1,34 +1,34 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ProcessAccessFlags : uint - { - VMRead = 0x00000010, - QueryInformation = 0x00000400, - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ProcessAccessFlags : uint + { + VMRead = 0x00000010, + QueryInformation = 0x00000400, + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs index bc1b0f372..4632a6aaf 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum RegionResult - { - REGION_ERROR = 0, - REGION_NULLREGION = 1, - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum RegionResult + { + REGION_ERROR = 0, + REGION_NULLREGION = 1, + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs index 70a6ff104..b6c0b2087 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// See: http://www.pinvoke.net/default.aspx/Enums/SendMessageTimeoutFlags.html - /// - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SendMessageTimeoutFlags : uint - { - SMTO_NORMAL = 0x0 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// See: http://www.pinvoke.net/default.aspx/Enums/SendMessageTimeoutFlags.html + /// + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum SendMessageTimeoutFlags : uint + { + SMTO_NORMAL = 0x0 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/ShowWindowCommand.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/ShowWindowCommand.cs index 76ccb3ce4..c09a10f9e 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/ShowWindowCommand.cs @@ -1,110 +1,110 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ShowWindowCommand : uint - { - /// - /// Hides the window and activates another window. - /// - Hide = 0, - - /// - /// Activates and displays a window. If the window is minimized or - /// maximized, the system restores it to its original size and position. - /// An application should specify this flag when displaying the window - /// for the first time. - /// - Normal = 1, - - /// - /// Activates the window and displays it as a minimized window. - /// - ShowMinimized = 2, - - /// - /// Maximizes the specified window. - /// - Maximize = 3, // is this the right value? - - /// - /// Activates the window and displays it as a maximized window. - /// - ShowMaximized = 3, - - /// - /// Displays a window in its most recent size and position. This value - /// is similar to , except - /// the window is not actived. - /// - ShowNoActivate = 4, - - /// - /// Activates the window and displays it in its current size and position. - /// - Show = 5, - - /// - /// Minimizes the specified window and activates the next top-level - /// window in the Z order. - /// - Minimize = 6, - - /// - /// Displays the window as a minimized window. This value is similar to - /// , except the - /// window is not activated. - /// - ShowMinNoActive = 7, - - /// - /// Displays the window in its current size and position. This value is - /// similar to , except the - /// window is not activated. - /// - ShowNA = 8, - - /// - /// Activates and displays the window. If the window is minimized or - /// maximized, the system restores it to its original size and position. - /// An application should specify this flag when restoring a minimized window. - /// - Restore = 9, - - /// - /// Sets the show state based on the SW_* value specified in the - /// STARTUPINFO structure passed to the CreateProcess function by the - /// program that started the application. - /// - ShowDefault = 10, - - /// - /// Windows 2000/XP: Minimizes a window, even if the thread - /// that owns the window is not responding. This flag should only be - /// used when minimizing windows from a different thread. - /// - ForceMinimize = 11 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ShowWindowCommand : uint + { + /// + /// Hides the window and activates another window. + /// + Hide = 0, + + /// + /// Activates and displays a window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when displaying the window + /// for the first time. + /// + Normal = 1, + + /// + /// Activates the window and displays it as a minimized window. + /// + ShowMinimized = 2, + + /// + /// Maximizes the specified window. + /// + Maximize = 3, // is this the right value? + + /// + /// Activates the window and displays it as a maximized window. + /// + ShowMaximized = 3, + + /// + /// Displays a window in its most recent size and position. This value + /// is similar to , except + /// the window is not actived. + /// + ShowNoActivate = 4, + + /// + /// Activates the window and displays it in its current size and position. + /// + Show = 5, + + /// + /// Minimizes the specified window and activates the next top-level + /// window in the Z order. + /// + Minimize = 6, + + /// + /// Displays the window as a minimized window. This value is similar to + /// , except the + /// window is not activated. + /// + ShowMinNoActive = 7, + + /// + /// Displays the window in its current size and position. This value is + /// similar to , except the + /// window is not activated. + /// + ShowNA = 8, + + /// + /// Activates and displays the window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when restoring a minimized window. + /// + Restore = 9, + + /// + /// Sets the show state based on the SW_* value specified in the + /// STARTUPINFO structure passed to the CreateProcess function by the + /// program that started the application. + /// + ShowDefault = 10, + + /// + /// Windows 2000/XP: Minimizes a window, even if the thread + /// that owns the window is not responding. This flag should only be + /// used when minimizing windows from a different thread. + /// + ForceMinimize = 11 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/SoundFlags.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/SoundFlags.cs index 8ad288c68..aebe3d9a6 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/SoundFlags.cs @@ -1,39 +1,39 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// See: http://msdn.microsoft.com/en-us/library/aa909766.aspx - /// - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SoundFlags - { - SND_ASYNC = 0x0001, // play asynchronously - SND_MEMORY = 0x0004, // pszSound points to a memory file - SND_NOSTOP = 0x0010, // don't stop any currently playing sound - SND_NOWAIT = 0x00002000, // don't wait if the driver is busy - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// See: http://msdn.microsoft.com/en-us/library/aa909766.aspx + /// + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum SoundFlags + { + SND_ASYNC = 0x0001, // play asynchronously + SND_MEMORY = 0x0004, // pszSound points to a memory file + SND_NOSTOP = 0x0010, // don't stop any currently playing sound + SND_NOWAIT = 0x00002000, // don't wait if the driver is busy + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/ThreadAccess.cs similarity index 92% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/ThreadAccess.cs index 50df23caa..979af5708 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/ThreadAccess.cs @@ -1,31 +1,31 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - public enum ThreadAccess : int - { - SUSPEND_RESUME = (0x0002), - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + public enum ThreadAccess : int + { + SUSPEND_RESUME = (0x0002), + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/Win32Error.cs similarity index 95% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/Win32Error.cs index be8ea2965..5e814b223 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/Win32Error.cs @@ -1,89 +1,89 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// A Win32 error code. - /// - public enum Win32Error : uint - { - Success = 0x0, - InvalidFunction = 0x1, - FileNotFound = 0x2, - PathNotFound = 0x3, - TooManyOpenFiles = 0x4, - AccessDenied = 0x5, - InvalidHandle = 0x6, - ArenaTrashed = 0x7, - NotEnoughMemory = 0x8, - InvalidBlock = 0x9, - BadEnvironment = 0xa, - BadFormat = 0xb, - InvalidAccess = 0xc, - InvalidData = 0xd, - OutOfMemory = 0xe, - InvalidDrive = 0xf, - CurrentDirectory = 0x10, - NotSameDevice = 0x11, - NoMoreFiles = 0x12, - WriteProtect = 0x13, - BadUnit = 0x14, - NotReady = 0x15, - BadCommand = 0x16, - Crc = 0x17, - BadLength = 0x18, - Seek = 0x19, - NotDosDisk = 0x1a, - SectorNotFound = 0x1b, - OutOfPaper = 0x1c, - WriteFault = 0x1d, - ReadFault = 0x1e, - GenFailure = 0x1f, - SharingViolation = 0x20, - LockViolation = 0x21, - WrongDisk = 0x22, - SharingBufferExceeded = 0x24, - HandleEof = 0x26, - HandleDiskFull = 0x27, - NotSupported = 0x32, - RemNotList = 0x33, - DupName = 0x34, - BadNetPath = 0x35, - NetworkBusy = 0x36, - DevNotExist = 0x37, - TooManyCmds = 0x38, - FileExists = 0x50, - CannotMake = 0x52, - AlreadyAssigned = 0x55, - InvalidPassword = 0x56, - InvalidParameter = 0x57, - NetWriteFault = 0x58, - NoProcSlots = 0x59, - TooManySemaphores = 0x64, - ExclSemAlreadyOwned = 0x65, - SemIsSet = 0x66, - TooManySemRequests = 0x67, - InvalidAtInterruptTime = 0x68, - SemOwnerDied = 0x69, - SemUserLimit = 0x6a - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// A Win32 error code. + /// + public enum Win32Error : uint + { + Success = 0x0, + InvalidFunction = 0x1, + FileNotFound = 0x2, + PathNotFound = 0x3, + TooManyOpenFiles = 0x4, + AccessDenied = 0x5, + InvalidHandle = 0x6, + ArenaTrashed = 0x7, + NotEnoughMemory = 0x8, + InvalidBlock = 0x9, + BadEnvironment = 0xa, + BadFormat = 0xb, + InvalidAccess = 0xc, + InvalidData = 0xd, + OutOfMemory = 0xe, + InvalidDrive = 0xf, + CurrentDirectory = 0x10, + NotSameDevice = 0x11, + NoMoreFiles = 0x12, + WriteProtect = 0x13, + BadUnit = 0x14, + NotReady = 0x15, + BadCommand = 0x16, + Crc = 0x17, + BadLength = 0x18, + Seek = 0x19, + NotDosDisk = 0x1a, + SectorNotFound = 0x1b, + OutOfPaper = 0x1c, + WriteFault = 0x1d, + ReadFault = 0x1e, + GenFailure = 0x1f, + SharingViolation = 0x20, + LockViolation = 0x21, + WrongDisk = 0x22, + SharingBufferExceeded = 0x24, + HandleEof = 0x26, + HandleDiskFull = 0x27, + NotSupported = 0x32, + RemNotList = 0x33, + DupName = 0x34, + BadNetPath = 0x35, + NetworkBusy = 0x36, + DevNotExist = 0x37, + TooManyCmds = 0x38, + FileExists = 0x50, + CannotMake = 0x52, + AlreadyAssigned = 0x55, + InvalidPassword = 0x56, + InvalidParameter = 0x57, + NetWriteFault = 0x58, + NoProcSlots = 0x59, + TooManySemaphores = 0x64, + ExclSemAlreadyOwned = 0x65, + SemIsSet = 0x66, + TooManySemRequests = 0x67, + InvalidAtInterruptTime = 0x68, + SemOwnerDied = 0x69, + SemUserLimit = 0x6a + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WinEvent.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WinEvent.cs index aaaf0e8e9..0938d4317 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WinEvent.cs @@ -1,37 +1,37 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel - * - * 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Used for User32.SetWinEventHook - /// See MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WinEvent : uint - { - EVENT_OBJECT_CREATE = 32768, - EVENT_OBJECT_DESTROY = 32769, - EVENT_OBJECT_NAMECHANGE = 32780, - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel + * + * 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// Used for User32.SetWinEventHook + /// See MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WinEvent : uint + { + EVENT_OBJECT_CREATE = 32768, + EVENT_OBJECT_DESTROY = 32769, + EVENT_OBJECT_NAMECHANGE = 32780, + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEventHookFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WinEventHookFlags.cs similarity index 87% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEventHookFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WinEventHookFlags.cs index 4ca58d2df..497940960 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WinEventHookFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WinEventHookFlags.cs @@ -1,18 +1,18 @@ -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Used for User32.SetWinEventHook - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx - /// - [SuppressMessage("ReSharper", "InconsistentNaming"), Flags] - public enum WinEventHookFlags - { - WINEVENT_SKIPOWNTHREAD = 1, - WINEVENT_SKIPOWNPROCESS = 2, - WINEVENT_OUTOFCONTEXT = 0, - WINEVENT_INCONTEXT = 4 - } +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// Used for User32.SetWinEventHook + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx + /// + [SuppressMessage("ReSharper", "InconsistentNaming"), Flags] + public enum WinEventHookFlags + { + WINEVENT_SKIPOWNTHREAD = 1, + WINEVENT_SKIPOWNPROCESS = 2, + WINEVENT_OUTOFCONTEXT = 0, + WINEVENT_INCONTEXT = 4 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowLongIndex.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WindowLongIndex.cs index 6da1d01b8..09eddbb32 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowLongIndex.cs @@ -1,32 +1,32 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WindowLongIndex - { - GWL_EXSTYLE = -20, // Sets a new extended window style. - GWL_STYLE = -16, // Sets a new window style. - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WindowLongIndex + { + GWL_EXSTYLE = -20, // Sets a new extended window style. + GWL_STYLE = -16, // Sets a new window style. + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPlacementFlags.cs similarity index 95% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPlacementFlags.cs index feb53a499..a6ac06dbf 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPlacementFlags.cs @@ -1,42 +1,42 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WindowPlacementFlags : uint - { - // The coordinates of the minimized window may be specified. - // This flag must be specified if the coordinates are set in the ptMinPosition member. - WPF_SETMINPOSITION = 0x0001, - - // If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request. - WPF_ASYNCWINDOWPLACEMENT = 0x0004, - - // The restored window will be maximized, regardless of whether it was maximized before it was minimized. This setting is only valid the next time the window is restored. It does not change the default restoration behavior. - // This flag is only valid when the SW_SHOWMINIMIZED value is specified for the showCmd member. - WPF_RESTORETOMAXIMIZED = 0x0002 - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WindowPlacementFlags : uint + { + // The coordinates of the minimized window may be specified. + // This flag must be specified if the coordinates are set in the ptMinPosition member. + WPF_SETMINPOSITION = 0x0001, + + // If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request. + WPF_ASYNCWINDOWPLACEMENT = 0x0004, + + // The restored window will be maximized, regardless of whether it was maximized before it was minimized. This setting is only valid the next time the window is restored. It does not change the default restoration behavior. + // This flag is only valid when the SW_SHOWMINIMIZED value is specified for the showCmd member. + WPF_RESTORETOMAXIMIZED = 0x0002 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPos.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPos.cs index a725e6baf..268819fc4 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowPos.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WindowPos - { - SWP_NOACTIVATE = - 0x0010, // Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter). - SWP_NOMOVE = 0x0002, //Retains the current position (ignores X and Y parameters). - SWP_NOSIZE = 0x0001, // Retains the current size (ignores the cx and cy parameters). - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WindowPos + { + SWP_NOACTIVATE = + 0x0010, // Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter). + SWP_NOMOVE = 0x0002, //Retains the current position (ignores X and Y parameters). + SWP_NOSIZE = 0x0001, // Retains the current size (ignores the cx and cy parameters). + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowStyleFlags.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WindowStyleFlags.cs index de33325d0..914633254 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowStyleFlags.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Window Style Flags - /// - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WindowStyleFlags : long - { - WS_VISIBLE = 0x10000000, - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// Window Style Flags + /// + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WindowStyleFlags : long + { + WS_VISIBLE = 0x10000000, + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowsMessages.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs rename to src/Greenshot.Base/UnmanagedHelpers/Enums/WindowsMessages.cs index d398fbdc3..2aff5fe19 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/WindowsMessages.cs @@ -1,26 +1,26 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// All possible windows messages - /// See also here - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum WindowsMessages : uint - { - WM_MOUSEACTIVATE = 0x0021, - WM_INPUTLANGCHANGEREQUEST = 0x0050, - WM_INPUTLANGCHANGE = 0x0051, - - - /// - /// Sent to a window to retrieve a handle to the large or small icon associated with a window. The system displays the large icon in the ALT+TAB dialog, and the small icon in the window caption. - /// A window receives this message through its WindowProc function. - /// WM_GETICON message - /// - WM_GETICON = 0x007F, - WM_CHAR = 0x0102, - WM_SYSCOMMAND = 0x0112 - } +using System.Diagnostics.CodeAnalysis; + +namespace Greenshot.Base.UnmanagedHelpers.Enums +{ + /// + /// All possible windows messages + /// See also here + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WindowsMessages : uint + { + WM_MOUSEACTIVATE = 0x0021, + WM_INPUTLANGCHANGEREQUEST = 0x0050, + WM_INPUTLANGCHANGE = 0x0051, + + + /// + /// Sent to a window to retrieve a handle to the large or small icon associated with a window. The system displays the large icon in the ALT+TAB dialog, and the small icon in the window caption. + /// A window receives this message through its WindowProc function. + /// WM_GETICON message + /// + WM_GETICON = 0x007F, + WM_CHAR = 0x0102, + WM_SYSCOMMAND = 0x0112 + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/src/Greenshot.Base/UnmanagedHelpers/GDI32.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/GDI32.cs rename to src/Greenshot.Base/UnmanagedHelpers/GDI32.cs index f2591a1d4..ed15abd1a 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/GDI32.cs @@ -1,425 +1,425 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Security; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using Microsoft.Win32.SafeHandles; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - public static class GDIExtensions - { - /// - /// Check if all the corners of the rectangle are visible in the specified region. - /// Not a perfect check, but this currently a workaround for checking if a window is completely visible - /// - /// - /// - /// - public static bool AreRectangleCornersVisisble(this Region region, Rectangle rectangle) - { - Point topLeft = new Point(rectangle.X, rectangle.Y); - Point topRight = new Point(rectangle.X + rectangle.Width, rectangle.Y); - Point bottomLeft = new Point(rectangle.X, rectangle.Y + rectangle.Height); - Point bottomRight = new Point(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height); - bool topLeftVisible = region.IsVisible(topLeft); - bool topRightVisible = region.IsVisible(topRight); - bool bottomLeftVisible = region.IsVisible(bottomLeft); - bool bottomRightVisible = region.IsVisible(bottomRight); - - return topLeftVisible && topRightVisible && bottomLeftVisible && bottomRightVisible; - } - - /// - /// Get a SafeHandle for the GetHdc, so one can use using to automatically cleanup the devicecontext - /// - /// - /// SafeDeviceContextHandle - public static SafeDeviceContextHandle GetSafeDeviceContext(this Graphics graphics) - { - return SafeDeviceContextHandle.FromGraphics(graphics); - } - } - - /// - /// Abstract class SafeObjectHandle which contains all handles that are cleaned with DeleteObject - /// - public abstract class SafeObjectHandle : SafeHandleZeroOrMinusOneIsInvalid - { - [DllImport("gdi32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeleteObject(IntPtr hObject); - - protected SafeObjectHandle(bool ownsHandle) : base(ownsHandle) - { - } - - protected override bool ReleaseHandle() - { - return DeleteObject(handle); - } - } - - /// - /// A hbitmap SafeHandle implementation - /// - public class SafeHBitmapHandle : SafeObjectHandle - { - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeHBitmapHandle() : base(true) - { - } - - [SecurityCritical] - public SafeHBitmapHandle(IntPtr preexistingHandle) : base(true) - { - SetHandle(preexistingHandle); - } - } - - /// - /// A hRegion SafeHandle implementation - /// - public class SafeRegionHandle : SafeObjectHandle - { - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeRegionHandle() : base(true) - { - } - - [SecurityCritical] - public SafeRegionHandle(IntPtr preexistingHandle) : base(true) - { - SetHandle(preexistingHandle); - } - } - - /// - /// A dibsection SafeHandle implementation - /// - public class SafeDibSectionHandle : SafeObjectHandle - { - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeDibSectionHandle() : base(true) - { - } - - [SecurityCritical] - public SafeDibSectionHandle(IntPtr preexistingHandle) : base(true) - { - SetHandle(preexistingHandle); - } - } - - /// - /// A select object safehandle implementation - /// This impl will select the passed SafeHandle to the HDC and replace the returned value when disposing - /// - public class SafeSelectObjectHandle : SafeHandleZeroOrMinusOneIsInvalid - { - [DllImport("gdi32", SetLastError = true)] - private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); - - private readonly SafeHandle _hdc; - - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeSelectObjectHandle() : base(true) - { - } - - [SecurityCritical] - public SafeSelectObjectHandle(SafeDCHandle hdc, SafeHandle newHandle) : base(true) - { - _hdc = hdc; - SetHandle(SelectObject(hdc.DangerousGetHandle(), newHandle.DangerousGetHandle())); - } - - protected override bool ReleaseHandle() - { - SelectObject(_hdc.DangerousGetHandle(), handle); - return true; - } - } - - public abstract class SafeDCHandle : SafeHandleZeroOrMinusOneIsInvalid - { - protected SafeDCHandle(bool ownsHandle) : base(ownsHandle) - { - } - } - - /// - /// A CompatibleDC SafeHandle implementation - /// - public class SafeCompatibleDCHandle : SafeDCHandle - { - [DllImport("gdi32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeleteDC(IntPtr hDC); - - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeCompatibleDCHandle() : base(true) - { - } - - [SecurityCritical] - public SafeCompatibleDCHandle(IntPtr preexistingHandle) : base(true) - { - SetHandle(preexistingHandle); - } - - public SafeSelectObjectHandle SelectObject(SafeHandle newHandle) - { - return new SafeSelectObjectHandle(this, newHandle); - } - - protected override bool ReleaseHandle() - { - return DeleteDC(handle); - } - } - - /// - /// A DeviceContext SafeHandle implementation - /// - public class SafeDeviceContextHandle : SafeDCHandle - { - private readonly Graphics _graphics; - - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeDeviceContextHandle() : base(true) - { - } - - [SecurityCritical] - public SafeDeviceContextHandle(Graphics graphics, IntPtr preexistingHandle) : base(true) - { - _graphics = graphics; - SetHandle(preexistingHandle); - } - - protected override bool ReleaseHandle() - { - _graphics.ReleaseHdc(handle); - return true; - } - - public static SafeDeviceContextHandle FromGraphics(Graphics graphics) - { - return new SafeDeviceContextHandle(graphics, graphics.GetHdc()); - } - } - - /// - /// GDI32 Helpers - /// - public static class GDI32 - { - [DllImport("gdi32", SetLastError = true)] - public static extern bool BitBlt(SafeHandle hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, SafeHandle hdcSrc, int nXSrc, int nYSrc, CopyPixelOperation dwRop); - - [DllImport("gdi32", SetLastError = true)] - public static extern SafeCompatibleDCHandle CreateCompatibleDC(SafeHandle hDC); - - [DllImport("gdi32", SetLastError = true)] - public static extern SafeDibSectionHandle CreateDIBSection(SafeHandle hdc, ref BITMAPINFOHEADER bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset); - - [DllImport("gdi32", SetLastError = true)] - public static extern SafeRegionHandle CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); - - [DllImport("gdi32", SetLastError = true)] - public static extern uint GetPixel(SafeHandle hdc, int nXPos, int nYPos); - - [DllImport("gdi32", SetLastError = true)] - public static extern int GetDeviceCaps(SafeHandle hdc, DeviceCaps nIndex); - } - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct BITMAPFILEHEADER - { - public static readonly short BM = 0x4d42; // BM - public short bfType; - public int bfSize; - public short bfReserved1; - public short bfReserved2; - public int bfOffBits; - } - - [StructLayout(LayoutKind.Sequential)] - public struct BitfieldColorMask - { - public uint blue; - public uint green; - public uint red; - - public void InitValues() - { - red = (uint) 255 << 8; - green = (uint) 255 << 16; - blue = (uint) 255 << 24; - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct CIEXYZ - { - public uint ciexyzX; //FXPT2DOT30 - public uint ciexyzY; //FXPT2DOT30 - public uint ciexyzZ; //FXPT2DOT30 - - public CIEXYZ(uint FXPT2DOT30) - { - ciexyzX = FXPT2DOT30; - ciexyzY = FXPT2DOT30; - ciexyzZ = FXPT2DOT30; - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct CIEXYZTRIPLE - { - public CIEXYZ ciexyzRed; - public CIEXYZ ciexyzGreen; - public CIEXYZ ciexyzBlue; - } - - public enum BI_COMPRESSION : uint - { - BI_RGB = 0, // Uncompressed - BI_RLE8 = 1, // RLE 8BPP - BI_RLE4 = 2, // RLE 4BPP - - BI_BITFIELDS = - 3, // Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components, respectively, of each pixel. This is valid when used with 16- and 32-bpp bitmaps. - BI_JPEG = 4, // Indicates that the image is a JPEG image. - BI_PNG = 5 // Indicates that the image is a PNG image. - } - - [StructLayout(LayoutKind.Explicit)] - public struct BITMAPINFOHEADER - { - [FieldOffset(0)] public uint biSize; - [FieldOffset(4)] public int biWidth; - [FieldOffset(8)] public int biHeight; - [FieldOffset(12)] public ushort biPlanes; - [FieldOffset(14)] public ushort biBitCount; - [FieldOffset(16)] public BI_COMPRESSION biCompression; - [FieldOffset(20)] public uint biSizeImage; - [FieldOffset(24)] public int biXPelsPerMeter; - [FieldOffset(28)] public int biYPelsPerMeter; - [FieldOffset(32)] public uint biClrUsed; - [FieldOffset(36)] public uint biClrImportant; - [FieldOffset(40)] public uint bV5RedMask; - [FieldOffset(44)] public uint bV5GreenMask; - [FieldOffset(48)] public uint bV5BlueMask; - [FieldOffset(52)] public uint bV5AlphaMask; - [FieldOffset(56)] public uint bV5CSType; - [FieldOffset(60)] public CIEXYZTRIPLE bV5Endpoints; - [FieldOffset(96)] public uint bV5GammaRed; - [FieldOffset(100)] public uint bV5GammaGreen; - [FieldOffset(104)] public uint bV5GammaBlue; - [FieldOffset(108)] public uint bV5Intent; // Rendering intent for bitmap - [FieldOffset(112)] public uint bV5ProfileData; - [FieldOffset(116)] public uint bV5ProfileSize; - [FieldOffset(120)] public uint bV5Reserved; - - public const int DIB_RGB_COLORS = 0; - - public BITMAPINFOHEADER(int width, int height, ushort bpp) - { - biSize = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER)); // BITMAPINFOHEADER < DIBV5 is 40 bytes - biPlanes = 1; // Should allways be 1 - biCompression = BI_COMPRESSION.BI_RGB; - biWidth = width; - biHeight = height; - biBitCount = bpp; - biSizeImage = (uint) (width * height * (bpp >> 3)); - biXPelsPerMeter = 0; - biYPelsPerMeter = 0; - biClrUsed = 0; - biClrImportant = 0; - - // V5 - bV5RedMask = (uint) 255 << 16; - bV5GreenMask = (uint) 255 << 8; - bV5BlueMask = 255; - bV5AlphaMask = (uint) 255 << 24; - bV5CSType = 0x73524742; // LCS_sRGB - bV5Endpoints = new CIEXYZTRIPLE - { - ciexyzBlue = new CIEXYZ(0), - ciexyzGreen = new CIEXYZ(0), - ciexyzRed = new CIEXYZ(0) - }; - bV5GammaRed = 0; - bV5GammaGreen = 0; - bV5GammaBlue = 0; - bV5Intent = 4; - bV5ProfileData = 0; - bV5ProfileSize = 0; - bV5Reserved = 0; - } - - public bool IsDibV5 - { - get - { - uint sizeOfBMI = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER)); - return biSize >= sizeOfBMI; - } - } - - public uint OffsetToPixels - { - get - { - if (biCompression == BI_COMPRESSION.BI_BITFIELDS) - { - // Add 3x4 bytes for the bitfield color mask - return biSize + 3 * 4; - } - - return biSize; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Security; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Microsoft.Win32.SafeHandles; + +namespace Greenshot.Base.UnmanagedHelpers +{ + public static class GDIExtensions + { + /// + /// Check if all the corners of the rectangle are visible in the specified region. + /// Not a perfect check, but this currently a workaround for checking if a window is completely visible + /// + /// + /// + /// + public static bool AreRectangleCornersVisisble(this Region region, Rectangle rectangle) + { + Point topLeft = new Point(rectangle.X, rectangle.Y); + Point topRight = new Point(rectangle.X + rectangle.Width, rectangle.Y); + Point bottomLeft = new Point(rectangle.X, rectangle.Y + rectangle.Height); + Point bottomRight = new Point(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height); + bool topLeftVisible = region.IsVisible(topLeft); + bool topRightVisible = region.IsVisible(topRight); + bool bottomLeftVisible = region.IsVisible(bottomLeft); + bool bottomRightVisible = region.IsVisible(bottomRight); + + return topLeftVisible && topRightVisible && bottomLeftVisible && bottomRightVisible; + } + + /// + /// Get a SafeHandle for the GetHdc, so one can use using to automatically cleanup the devicecontext + /// + /// + /// SafeDeviceContextHandle + public static SafeDeviceContextHandle GetSafeDeviceContext(this Graphics graphics) + { + return SafeDeviceContextHandle.FromGraphics(graphics); + } + } + + /// + /// Abstract class SafeObjectHandle which contains all handles that are cleaned with DeleteObject + /// + public abstract class SafeObjectHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [DllImport("gdi32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DeleteObject(IntPtr hObject); + + protected SafeObjectHandle(bool ownsHandle) : base(ownsHandle) + { + } + + protected override bool ReleaseHandle() + { + return DeleteObject(handle); + } + } + + /// + /// A hbitmap SafeHandle implementation + /// + public class SafeHBitmapHandle : SafeObjectHandle + { + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeHBitmapHandle() : base(true) + { + } + + [SecurityCritical] + public SafeHBitmapHandle(IntPtr preexistingHandle) : base(true) + { + SetHandle(preexistingHandle); + } + } + + /// + /// A hRegion SafeHandle implementation + /// + public class SafeRegionHandle : SafeObjectHandle + { + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeRegionHandle() : base(true) + { + } + + [SecurityCritical] + public SafeRegionHandle(IntPtr preexistingHandle) : base(true) + { + SetHandle(preexistingHandle); + } + } + + /// + /// A dibsection SafeHandle implementation + /// + public class SafeDibSectionHandle : SafeObjectHandle + { + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeDibSectionHandle() : base(true) + { + } + + [SecurityCritical] + public SafeDibSectionHandle(IntPtr preexistingHandle) : base(true) + { + SetHandle(preexistingHandle); + } + } + + /// + /// A select object safehandle implementation + /// This impl will select the passed SafeHandle to the HDC and replace the returned value when disposing + /// + public class SafeSelectObjectHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [DllImport("gdi32", SetLastError = true)] + private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); + + private readonly SafeHandle _hdc; + + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeSelectObjectHandle() : base(true) + { + } + + [SecurityCritical] + public SafeSelectObjectHandle(SafeDCHandle hdc, SafeHandle newHandle) : base(true) + { + _hdc = hdc; + SetHandle(SelectObject(hdc.DangerousGetHandle(), newHandle.DangerousGetHandle())); + } + + protected override bool ReleaseHandle() + { + SelectObject(_hdc.DangerousGetHandle(), handle); + return true; + } + } + + public abstract class SafeDCHandle : SafeHandleZeroOrMinusOneIsInvalid + { + protected SafeDCHandle(bool ownsHandle) : base(ownsHandle) + { + } + } + + /// + /// A CompatibleDC SafeHandle implementation + /// + public class SafeCompatibleDCHandle : SafeDCHandle + { + [DllImport("gdi32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DeleteDC(IntPtr hDC); + + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeCompatibleDCHandle() : base(true) + { + } + + [SecurityCritical] + public SafeCompatibleDCHandle(IntPtr preexistingHandle) : base(true) + { + SetHandle(preexistingHandle); + } + + public SafeSelectObjectHandle SelectObject(SafeHandle newHandle) + { + return new SafeSelectObjectHandle(this, newHandle); + } + + protected override bool ReleaseHandle() + { + return DeleteDC(handle); + } + } + + /// + /// A DeviceContext SafeHandle implementation + /// + public class SafeDeviceContextHandle : SafeDCHandle + { + private readonly Graphics _graphics; + + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeDeviceContextHandle() : base(true) + { + } + + [SecurityCritical] + public SafeDeviceContextHandle(Graphics graphics, IntPtr preexistingHandle) : base(true) + { + _graphics = graphics; + SetHandle(preexistingHandle); + } + + protected override bool ReleaseHandle() + { + _graphics.ReleaseHdc(handle); + return true; + } + + public static SafeDeviceContextHandle FromGraphics(Graphics graphics) + { + return new SafeDeviceContextHandle(graphics, graphics.GetHdc()); + } + } + + /// + /// GDI32 Helpers + /// + public static class GDI32 + { + [DllImport("gdi32", SetLastError = true)] + public static extern bool BitBlt(SafeHandle hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, SafeHandle hdcSrc, int nXSrc, int nYSrc, CopyPixelOperation dwRop); + + [DllImport("gdi32", SetLastError = true)] + public static extern SafeCompatibleDCHandle CreateCompatibleDC(SafeHandle hDC); + + [DllImport("gdi32", SetLastError = true)] + public static extern SafeDibSectionHandle CreateDIBSection(SafeHandle hdc, ref BITMAPINFOHEADER bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset); + + [DllImport("gdi32", SetLastError = true)] + public static extern SafeRegionHandle CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); + + [DllImport("gdi32", SetLastError = true)] + public static extern uint GetPixel(SafeHandle hdc, int nXPos, int nYPos); + + [DllImport("gdi32", SetLastError = true)] + public static extern int GetDeviceCaps(SafeHandle hdc, DeviceCaps nIndex); + } + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct BITMAPFILEHEADER + { + public static readonly short BM = 0x4d42; // BM + public short bfType; + public int bfSize; + public short bfReserved1; + public short bfReserved2; + public int bfOffBits; + } + + [StructLayout(LayoutKind.Sequential)] + public struct BitfieldColorMask + { + public uint blue; + public uint green; + public uint red; + + public void InitValues() + { + red = (uint) 255 << 8; + green = (uint) 255 << 16; + blue = (uint) 255 << 24; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CIEXYZ + { + public uint ciexyzX; //FXPT2DOT30 + public uint ciexyzY; //FXPT2DOT30 + public uint ciexyzZ; //FXPT2DOT30 + + public CIEXYZ(uint FXPT2DOT30) + { + ciexyzX = FXPT2DOT30; + ciexyzY = FXPT2DOT30; + ciexyzZ = FXPT2DOT30; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct CIEXYZTRIPLE + { + public CIEXYZ ciexyzRed; + public CIEXYZ ciexyzGreen; + public CIEXYZ ciexyzBlue; + } + + public enum BI_COMPRESSION : uint + { + BI_RGB = 0, // Uncompressed + BI_RLE8 = 1, // RLE 8BPP + BI_RLE4 = 2, // RLE 4BPP + + BI_BITFIELDS = + 3, // Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components, respectively, of each pixel. This is valid when used with 16- and 32-bpp bitmaps. + BI_JPEG = 4, // Indicates that the image is a JPEG image. + BI_PNG = 5 // Indicates that the image is a PNG image. + } + + [StructLayout(LayoutKind.Explicit)] + public struct BITMAPINFOHEADER + { + [FieldOffset(0)] public uint biSize; + [FieldOffset(4)] public int biWidth; + [FieldOffset(8)] public int biHeight; + [FieldOffset(12)] public ushort biPlanes; + [FieldOffset(14)] public ushort biBitCount; + [FieldOffset(16)] public BI_COMPRESSION biCompression; + [FieldOffset(20)] public uint biSizeImage; + [FieldOffset(24)] public int biXPelsPerMeter; + [FieldOffset(28)] public int biYPelsPerMeter; + [FieldOffset(32)] public uint biClrUsed; + [FieldOffset(36)] public uint biClrImportant; + [FieldOffset(40)] public uint bV5RedMask; + [FieldOffset(44)] public uint bV5GreenMask; + [FieldOffset(48)] public uint bV5BlueMask; + [FieldOffset(52)] public uint bV5AlphaMask; + [FieldOffset(56)] public uint bV5CSType; + [FieldOffset(60)] public CIEXYZTRIPLE bV5Endpoints; + [FieldOffset(96)] public uint bV5GammaRed; + [FieldOffset(100)] public uint bV5GammaGreen; + [FieldOffset(104)] public uint bV5GammaBlue; + [FieldOffset(108)] public uint bV5Intent; // Rendering intent for bitmap + [FieldOffset(112)] public uint bV5ProfileData; + [FieldOffset(116)] public uint bV5ProfileSize; + [FieldOffset(120)] public uint bV5Reserved; + + public const int DIB_RGB_COLORS = 0; + + public BITMAPINFOHEADER(int width, int height, ushort bpp) + { + biSize = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER)); // BITMAPINFOHEADER < DIBV5 is 40 bytes + biPlanes = 1; // Should allways be 1 + biCompression = BI_COMPRESSION.BI_RGB; + biWidth = width; + biHeight = height; + biBitCount = bpp; + biSizeImage = (uint) (width * height * (bpp >> 3)); + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + biClrUsed = 0; + biClrImportant = 0; + + // V5 + bV5RedMask = (uint) 255 << 16; + bV5GreenMask = (uint) 255 << 8; + bV5BlueMask = 255; + bV5AlphaMask = (uint) 255 << 24; + bV5CSType = 0x73524742; // LCS_sRGB + bV5Endpoints = new CIEXYZTRIPLE + { + ciexyzBlue = new CIEXYZ(0), + ciexyzGreen = new CIEXYZ(0), + ciexyzRed = new CIEXYZ(0) + }; + bV5GammaRed = 0; + bV5GammaGreen = 0; + bV5GammaBlue = 0; + bV5Intent = 4; + bV5ProfileData = 0; + bV5ProfileSize = 0; + bV5Reserved = 0; + } + + public bool IsDibV5 + { + get + { + uint sizeOfBMI = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER)); + return biSize >= sizeOfBMI; + } + } + + public uint OffsetToPixels + { + get + { + if (biCompression == BI_COMPRESSION.BI_BITFIELDS) + { + // Add 3x4 bytes for the bitfield color mask + return biSize + 3 * 4; + } + + return biSize; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs b/src/Greenshot.Base/UnmanagedHelpers/GDIplus.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs rename to src/Greenshot.Base/UnmanagedHelpers/GDIplus.cs index 6da5b3850..6fc9f061f 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/GDIplus.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/GDIplus.cs @@ -1,387 +1,387 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using log4net; -using System.Reflection; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using GreenshotPlugin.UnmanagedHelpers.Structs; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Contains members that specify the nature of a Gaussian blur. - /// - /// Cannot be pinned with GCHandle due to bool value. - [StructLayout(LayoutKind.Sequential, Pack = 1)] - internal struct BlurParams - { - /// - /// Real number that specifies the blur radius (the radius of the Gaussian convolution kernel) in - /// pixels. The radius must be in the range 0 through 255. As the radius increases, the resulting - /// bitmap becomes more blurry. - /// - public float Radius; - - /// - /// Boolean value that specifies whether the bitmap expands by an amount equal to the blur radius. - /// If TRUE, the bitmap expands by an amount equal to the radius so that it can have soft edges. - /// If FALSE, the bitmap remains the same size and the soft edges are clipped. - /// - public bool ExpandEdges; - } - - /// - /// GDI Plus unit description. - /// - public enum GpUnit - { - /// - /// World coordinate (non-physical unit). - /// - UnitWorld, - - /// - /// Variable - for PageTransform only. - /// - UnitDisplay, - - /// - /// Each unit is one device pixel. - /// - UnitPixel, - - /// - /// Each unit is a printer's point, or 1/72 inch. - /// - UnitPoint, - - /// - /// Each unit is 1 inch. - /// - UnitInch, - - /// - /// Each unit is 1/300 inch. - /// - UnitDocument, - - /// - /// Each unit is 1 millimeter. - /// - UnitMillimeter - } - - /// - /// GDIplus Helpers - /// - public static class GDIplus - { - private static readonly ILog Log = LogManager.GetLogger(typeof(GDIplus)); - - [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] - private static extern int GdipBitmapApplyEffect(IntPtr bitmap, IntPtr effect, ref RECT rectOfInterest, bool useAuxData, IntPtr auxData, int auxDataSize); - - [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] - private static extern int GdipDrawImageFX(IntPtr graphics, IntPtr bitmap, ref RECTF source, IntPtr matrix, IntPtr effect, IntPtr imageAttributes, GpUnit srcUnit); - - [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] - private static extern int GdipSetEffectParameters(IntPtr effect, IntPtr parameters, uint size); - - [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] - private static extern int GdipCreateEffect(Guid guid, out IntPtr effect); - - [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] - private static extern int GdipDeleteEffect(IntPtr effect); - - private static readonly Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}"); - - // Constant "FieldInfo" for getting the nativeImage from the Bitmap - private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); - - // Constant "FieldInfo" for getting the NativeGraphics from the Graphics - private static readonly FieldInfo FIELD_INFO_NATIVE_GRAPHICS = - typeof(Graphics).GetField("nativeGraphics", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); - - // Constant "FieldInfo" for getting the nativeMatrix from the Matrix - private static readonly FieldInfo FIELD_INFO_NATIVE_MATRIX = - typeof(Matrix).GetField("nativeMatrix", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); - - // Constant "FieldInfo" for getting the nativeImageAttributes from the ImageAttributes - private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGEATTRIBUTES = - typeof(ImageAttributes).GetField("nativeImageAttributes", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); - - private static bool _isBlurEnabled = Environment.OSVersion.Version.Major >= 6; - - /// - /// Get the nativeImage field from the bitmap - /// - /// - /// IntPtr - private static IntPtr GetNativeImage(Bitmap bitmap) - { - if (bitmap == null) - { - return IntPtr.Zero; - } - - return (IntPtr) FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap); - } - - /// - /// Get the NativeGraphics field from the graphics - /// - /// - /// IntPtr - private static IntPtr GetNativeGraphics(Graphics graphics) - { - if (graphics == null) - { - return IntPtr.Zero; - } - - return (IntPtr) FIELD_INFO_NATIVE_GRAPHICS.GetValue(graphics); - } - - /// - /// Get the nativeMatrix field from the matrix - /// - /// - /// IntPtr - private static IntPtr GetNativeMatrix(Matrix matrix) - { - if (matrix == null) - { - return IntPtr.Zero; - } - - return (IntPtr) FIELD_INFO_NATIVE_MATRIX.GetValue(matrix); - } - - /// - /// Get the nativeImageAttributes field from the ImageAttributes - /// - /// - /// IntPtr - private static IntPtr GetNativeImageAttributes(ImageAttributes imageAttributes) - { - if (imageAttributes == null) - { - return IntPtr.Zero; - } - - return (IntPtr) FIELD_INFO_NATIVE_IMAGEATTRIBUTES.GetValue(imageAttributes); - } - - /// - /// Returns if a GDIPlus blur can be made for the supplied radius. - /// This accounts for the "bug" I reported here: http://social.technet.microsoft.com/Forums/en/w8itprogeneral/thread/99ddbe9d-556d-475a-8bab-84e25aa13a2c - /// - /// - /// false if blur is not possible - public static bool IsBlurPossible(int radius) - { - if (!_isBlurEnabled) - { - return false; - } - - if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor < 2) - { - return true; - } - - return Environment.OSVersion.Version.Major > 6 && radius >= 20; - } - - /// - /// Use the GDI+ blur effect on the bitmap - /// - /// Bitmap to apply the effect to - /// Rectangle to apply the blur effect to - /// 0-255 - /// bool true if the edges are expanded with the radius - /// false if there is no GDI+ available or an exception occured - public static bool ApplyBlur(Bitmap destinationBitmap, Rectangle area, int radius, bool expandEdges) - { - if (!IsBlurPossible(radius)) - { - return false; - } - - IntPtr hBlurParams = IntPtr.Zero; - IntPtr hEffect = IntPtr.Zero; - - try - { - // Create the GDI+ BlurEffect, using the Guid - int status = GdipCreateEffect(BlurEffectGuid, out hEffect); - if (status != 0) - { - return false; - } - - // Create a BlurParams struct and set the values - var blurParams = new BlurParams - { - Radius = radius, - ExpandEdges = expandEdges - }; - - // Allocate space in unmanaged memory - hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); - // Copy the structure to the unmanaged memory - Marshal.StructureToPtr(blurParams, hBlurParams, false); - - - // Set the blurParams to the effect - GdipSetEffectParameters(hEffect, hBlurParams, (uint) Marshal.SizeOf(blurParams)); - - // Somewhere it said we can use destinationBitmap.GetHbitmap(), this doesn't work!! - // Get the private nativeImage property from the Bitmap - IntPtr hBitmap = GetNativeImage(destinationBitmap); - - // Create a RECT from the Rectangle - RECT rec = new RECT(area); - // Apply the effect to the bitmap in the specified area - GdipBitmapApplyEffect(hBitmap, hEffect, ref rec, false, IntPtr.Zero, 0); - - // Everything worked, return true - return true; - } - catch (Exception ex) - { - _isBlurEnabled = false; - Log.Error("Problem using GdipBitmapApplyEffect: ", ex); - return false; - } - finally - { - try - { - if (hEffect != IntPtr.Zero) - { - // Delete the effect - GdipDeleteEffect(hEffect); - } - - if (hBlurParams != IntPtr.Zero) - { - // Free the memory - Marshal.FreeHGlobal(hBlurParams); - } - } - catch (Exception ex) - { - _isBlurEnabled = false; - Log.Error("Problem cleaning up ApplyBlur: ", ex); - } - } - } - - /// - /// Draw the image on the graphics with GDI+ blur effect - /// - /// false if there is no GDI+ available or an exception occured - public static bool DrawWithBlur(Graphics graphics, Bitmap image, Rectangle source, Matrix transform, ImageAttributes imageAttributes, int radius, bool expandEdges) - { - if (!IsBlurPossible(radius)) - { - return false; - } - - IntPtr hBlurParams = IntPtr.Zero; - IntPtr hEffect = IntPtr.Zero; - - try - { - // Create the GDI+ BlurEffect, using the Guid - int status = GdipCreateEffect(BlurEffectGuid, out hEffect); - if (status != 0) - { - return false; - } - - // Create a BlurParams struct and set the values - var blurParams = new BlurParams - { - Radius = radius, - ExpandEdges = false - }; - //blurParams.Padding = radius; - - // Allocate space in unmanaged memory - hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); - // Copy the structure to the unmanaged memory - Marshal.StructureToPtr(blurParams, hBlurParams, true); - - // Set the blurParams to the effect - GdipSetEffectParameters(hEffect, hBlurParams, (uint) Marshal.SizeOf(blurParams)); - - // Somewhere it said we can use destinationBitmap.GetHbitmap(), this doesn't work!! - // Get the private nativeImage property from the Bitmap - IntPtr hBitmap = GetNativeImage(image); - IntPtr hGraphics = GetNativeGraphics(graphics); - IntPtr hMatrix = GetNativeMatrix(transform); - IntPtr hAttributes = GetNativeImageAttributes(imageAttributes); - - // Create a RECT from the Rectangle - RECTF sourceRecf = new RECTF(source); - // Apply the effect to the bitmap in the specified area - GdipDrawImageFX(hGraphics, hBitmap, ref sourceRecf, hMatrix, hEffect, hAttributes, GpUnit.UnitPixel); - - // Everything worked, return true - return true; - } - catch (Exception ex) - { - _isBlurEnabled = false; - Log.Error("Problem using GdipDrawImageFX: ", ex); - return false; - } - finally - { - try - { - if (hEffect != IntPtr.Zero) - { - // Delete the effect - GdipDeleteEffect(hEffect); - } - - if (hBlurParams != IntPtr.Zero) - { - // Free the memory - Marshal.FreeHGlobal(hBlurParams); - } - } - catch (Exception ex) - { - _isBlurEnabled = false; - Log.Error("Problem cleaning up DrawWithBlur: ", ex); - } - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Reflection; +using System.Runtime.InteropServices; +using Greenshot.Base.UnmanagedHelpers.Structs; +using log4net; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Contains members that specify the nature of a Gaussian blur. + /// + /// Cannot be pinned with GCHandle due to bool value. + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct BlurParams + { + /// + /// Real number that specifies the blur radius (the radius of the Gaussian convolution kernel) in + /// pixels. The radius must be in the range 0 through 255. As the radius increases, the resulting + /// bitmap becomes more blurry. + /// + public float Radius; + + /// + /// Boolean value that specifies whether the bitmap expands by an amount equal to the blur radius. + /// If TRUE, the bitmap expands by an amount equal to the radius so that it can have soft edges. + /// If FALSE, the bitmap remains the same size and the soft edges are clipped. + /// + public bool ExpandEdges; + } + + /// + /// GDI Plus unit description. + /// + public enum GpUnit + { + /// + /// World coordinate (non-physical unit). + /// + UnitWorld, + + /// + /// Variable - for PageTransform only. + /// + UnitDisplay, + + /// + /// Each unit is one device pixel. + /// + UnitPixel, + + /// + /// Each unit is a printer's point, or 1/72 inch. + /// + UnitPoint, + + /// + /// Each unit is 1 inch. + /// + UnitInch, + + /// + /// Each unit is 1/300 inch. + /// + UnitDocument, + + /// + /// Each unit is 1 millimeter. + /// + UnitMillimeter + } + + /// + /// GDIplus Helpers + /// + public static class GDIplus + { + private static readonly ILog Log = LogManager.GetLogger(typeof(GDIplus)); + + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] + private static extern int GdipBitmapApplyEffect(IntPtr bitmap, IntPtr effect, ref RECT rectOfInterest, bool useAuxData, IntPtr auxData, int auxDataSize); + + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] + private static extern int GdipDrawImageFX(IntPtr graphics, IntPtr bitmap, ref RECTF source, IntPtr matrix, IntPtr effect, IntPtr imageAttributes, GpUnit srcUnit); + + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] + private static extern int GdipSetEffectParameters(IntPtr effect, IntPtr parameters, uint size); + + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] + private static extern int GdipCreateEffect(Guid guid, out IntPtr effect); + + [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true)] + private static extern int GdipDeleteEffect(IntPtr effect); + + private static readonly Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}"); + + // Constant "FieldInfo" for getting the nativeImage from the Bitmap + private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGE = typeof(Bitmap).GetField("nativeImage", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); + + // Constant "FieldInfo" for getting the NativeGraphics from the Graphics + private static readonly FieldInfo FIELD_INFO_NATIVE_GRAPHICS = + typeof(Graphics).GetField("nativeGraphics", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); + + // Constant "FieldInfo" for getting the nativeMatrix from the Matrix + private static readonly FieldInfo FIELD_INFO_NATIVE_MATRIX = + typeof(Matrix).GetField("nativeMatrix", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); + + // Constant "FieldInfo" for getting the nativeImageAttributes from the ImageAttributes + private static readonly FieldInfo FIELD_INFO_NATIVE_IMAGEATTRIBUTES = + typeof(ImageAttributes).GetField("nativeImageAttributes", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); + + private static bool _isBlurEnabled = Environment.OSVersion.Version.Major >= 6; + + /// + /// Get the nativeImage field from the bitmap + /// + /// + /// IntPtr + private static IntPtr GetNativeImage(Bitmap bitmap) + { + if (bitmap == null) + { + return IntPtr.Zero; + } + + return (IntPtr) FIELD_INFO_NATIVE_IMAGE.GetValue(bitmap); + } + + /// + /// Get the NativeGraphics field from the graphics + /// + /// + /// IntPtr + private static IntPtr GetNativeGraphics(Graphics graphics) + { + if (graphics == null) + { + return IntPtr.Zero; + } + + return (IntPtr) FIELD_INFO_NATIVE_GRAPHICS.GetValue(graphics); + } + + /// + /// Get the nativeMatrix field from the matrix + /// + /// + /// IntPtr + private static IntPtr GetNativeMatrix(Matrix matrix) + { + if (matrix == null) + { + return IntPtr.Zero; + } + + return (IntPtr) FIELD_INFO_NATIVE_MATRIX.GetValue(matrix); + } + + /// + /// Get the nativeImageAttributes field from the ImageAttributes + /// + /// + /// IntPtr + private static IntPtr GetNativeImageAttributes(ImageAttributes imageAttributes) + { + if (imageAttributes == null) + { + return IntPtr.Zero; + } + + return (IntPtr) FIELD_INFO_NATIVE_IMAGEATTRIBUTES.GetValue(imageAttributes); + } + + /// + /// Returns if a GDIPlus blur can be made for the supplied radius. + /// This accounts for the "bug" I reported here: http://social.technet.microsoft.com/Forums/en/w8itprogeneral/thread/99ddbe9d-556d-475a-8bab-84e25aa13a2c + /// + /// + /// false if blur is not possible + public static bool IsBlurPossible(int radius) + { + if (!_isBlurEnabled) + { + return false; + } + + if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor < 2) + { + return true; + } + + return Environment.OSVersion.Version.Major > 6 && radius >= 20; + } + + /// + /// Use the GDI+ blur effect on the bitmap + /// + /// Bitmap to apply the effect to + /// Rectangle to apply the blur effect to + /// 0-255 + /// bool true if the edges are expanded with the radius + /// false if there is no GDI+ available or an exception occured + public static bool ApplyBlur(Bitmap destinationBitmap, Rectangle area, int radius, bool expandEdges) + { + if (!IsBlurPossible(radius)) + { + return false; + } + + IntPtr hBlurParams = IntPtr.Zero; + IntPtr hEffect = IntPtr.Zero; + + try + { + // Create the GDI+ BlurEffect, using the Guid + int status = GdipCreateEffect(BlurEffectGuid, out hEffect); + if (status != 0) + { + return false; + } + + // Create a BlurParams struct and set the values + var blurParams = new BlurParams + { + Radius = radius, + ExpandEdges = expandEdges + }; + + // Allocate space in unmanaged memory + hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); + // Copy the structure to the unmanaged memory + Marshal.StructureToPtr(blurParams, hBlurParams, false); + + + // Set the blurParams to the effect + GdipSetEffectParameters(hEffect, hBlurParams, (uint) Marshal.SizeOf(blurParams)); + + // Somewhere it said we can use destinationBitmap.GetHbitmap(), this doesn't work!! + // Get the private nativeImage property from the Bitmap + IntPtr hBitmap = GetNativeImage(destinationBitmap); + + // Create a RECT from the Rectangle + RECT rec = new RECT(area); + // Apply the effect to the bitmap in the specified area + GdipBitmapApplyEffect(hBitmap, hEffect, ref rec, false, IntPtr.Zero, 0); + + // Everything worked, return true + return true; + } + catch (Exception ex) + { + _isBlurEnabled = false; + Log.Error("Problem using GdipBitmapApplyEffect: ", ex); + return false; + } + finally + { + try + { + if (hEffect != IntPtr.Zero) + { + // Delete the effect + GdipDeleteEffect(hEffect); + } + + if (hBlurParams != IntPtr.Zero) + { + // Free the memory + Marshal.FreeHGlobal(hBlurParams); + } + } + catch (Exception ex) + { + _isBlurEnabled = false; + Log.Error("Problem cleaning up ApplyBlur: ", ex); + } + } + } + + /// + /// Draw the image on the graphics with GDI+ blur effect + /// + /// false if there is no GDI+ available or an exception occured + public static bool DrawWithBlur(Graphics graphics, Bitmap image, Rectangle source, Matrix transform, ImageAttributes imageAttributes, int radius, bool expandEdges) + { + if (!IsBlurPossible(radius)) + { + return false; + } + + IntPtr hBlurParams = IntPtr.Zero; + IntPtr hEffect = IntPtr.Zero; + + try + { + // Create the GDI+ BlurEffect, using the Guid + int status = GdipCreateEffect(BlurEffectGuid, out hEffect); + if (status != 0) + { + return false; + } + + // Create a BlurParams struct and set the values + var blurParams = new BlurParams + { + Radius = radius, + ExpandEdges = false + }; + //blurParams.Padding = radius; + + // Allocate space in unmanaged memory + hBlurParams = Marshal.AllocHGlobal(Marshal.SizeOf(blurParams)); + // Copy the structure to the unmanaged memory + Marshal.StructureToPtr(blurParams, hBlurParams, true); + + // Set the blurParams to the effect + GdipSetEffectParameters(hEffect, hBlurParams, (uint) Marshal.SizeOf(blurParams)); + + // Somewhere it said we can use destinationBitmap.GetHbitmap(), this doesn't work!! + // Get the private nativeImage property from the Bitmap + IntPtr hBitmap = GetNativeImage(image); + IntPtr hGraphics = GetNativeGraphics(graphics); + IntPtr hMatrix = GetNativeMatrix(transform); + IntPtr hAttributes = GetNativeImageAttributes(imageAttributes); + + // Create a RECT from the Rectangle + RECTF sourceRecf = new RECTF(source); + // Apply the effect to the bitmap in the specified area + GdipDrawImageFX(hGraphics, hBitmap, ref sourceRecf, hMatrix, hEffect, hAttributes, GpUnit.UnitPixel); + + // Everything worked, return true + return true; + } + catch (Exception ex) + { + _isBlurEnabled = false; + Log.Error("Problem using GdipDrawImageFX: ", ex); + return false; + } + finally + { + try + { + if (hEffect != IntPtr.Zero) + { + // Delete the effect + GdipDeleteEffect(hEffect); + } + + if (hBlurParams != IntPtr.Zero) + { + // Free the memory + Marshal.FreeHGlobal(hBlurParams); + } + } + catch (Exception ex) + { + _isBlurEnabled = false; + Log.Error("Problem cleaning up DrawWithBlur: ", ex); + } + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs b/src/Greenshot.Base/UnmanagedHelpers/Kernel32.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs rename to src/Greenshot.Base/UnmanagedHelpers/Kernel32.cs index df512ee08..9e34b7341 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Kernel32.cs @@ -1,131 +1,131 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; -using System.Text; -using GreenshotPlugin.UnmanagedHelpers.Enums; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Description of Kernel32. - /// - public class Kernel32 - { - public const uint ATTACHCONSOLE_ATTACHPARENTPROCESS = 0x0ffffffff; // default value if not specifing a process ID - - [DllImport("kernel32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AttachConsole(uint dwProcessId); - - [DllImport("kernel32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AllocConsole(); - - [DllImport("kernel32", SetLastError = true)] - public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); - - [DllImport("kernel32", SetLastError = true)] - public static extern uint SuspendThread(IntPtr hThread); - - [DllImport("kernel32", SetLastError = true)] - public static extern int ResumeThread(IntPtr hThread); - - [DllImport("kernel32", SetLastError = true)] - public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize); - - [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, uint uuchMax); - - [DllImport("kernel32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool CloseHandle(IntPtr hObject); - - /// - /// Method to get the process path - /// - /// - /// - public static string GetProcessPath(int processid) - { - StringBuilder _PathBuffer = new StringBuilder(512); - // Try the GetModuleFileName method first since it's the fastest. - // May return ACCESS_DENIED (due to VM_READ flag) if the process is not owned by the current user. - // Will fail if we are compiled as x86 and we're trying to open a 64 bit process...not allowed. - IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead, false, processid); - if (hprocess != IntPtr.Zero) - { - try - { - if (PsAPI.GetModuleFileNameEx(hprocess, IntPtr.Zero, _PathBuffer, (uint) _PathBuffer.Capacity) > 0) - { - return _PathBuffer.ToString(); - } - } - finally - { - CloseHandle(hprocess); - } - } - - hprocess = OpenProcess(ProcessAccessFlags.QueryInformation, false, processid); - if (hprocess != IntPtr.Zero) - { - try - { - // Try this method for Vista or higher operating systems - uint size = (uint) _PathBuffer.Capacity; - if ((Environment.OSVersion.Version.Major >= 6) && (QueryFullProcessImageName(hprocess, 0, _PathBuffer, ref size) && (size > 0))) - { - return _PathBuffer.ToString(); - } - - // Try the GetProcessImageFileName method - if (PsAPI.GetProcessImageFileName(hprocess, _PathBuffer, (uint) _PathBuffer.Capacity) > 0) - { - string dospath = _PathBuffer.ToString(); - foreach (string drive in Environment.GetLogicalDrives()) - { - if (QueryDosDevice(drive.TrimEnd('\\'), _PathBuffer, (uint) _PathBuffer.Capacity) > 0) - { - if (dospath.StartsWith(_PathBuffer.ToString())) - { - return drive + dospath.Remove(0, _PathBuffer.Length); - } - } - } - } - } - finally - { - CloseHandle(hprocess); - } - } - - return string.Empty; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; +using System.Text; +using Greenshot.Base.UnmanagedHelpers.Enums; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Description of Kernel32. + /// + public class Kernel32 + { + public const uint ATTACHCONSOLE_ATTACHPARENTPROCESS = 0x0ffffffff; // default value if not specifing a process ID + + [DllImport("kernel32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AttachConsole(uint dwProcessId); + + [DllImport("kernel32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AllocConsole(); + + [DllImport("kernel32", SetLastError = true)] + public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + + [DllImport("kernel32", SetLastError = true)] + public static extern uint SuspendThread(IntPtr hThread); + + [DllImport("kernel32", SetLastError = true)] + public static extern int ResumeThread(IntPtr hThread); + + [DllImport("kernel32", SetLastError = true)] + public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize); + + [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, uint uuchMax); + + [DllImport("kernel32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseHandle(IntPtr hObject); + + /// + /// Method to get the process path + /// + /// + /// + public static string GetProcessPath(int processid) + { + StringBuilder _PathBuffer = new StringBuilder(512); + // Try the GetModuleFileName method first since it's the fastest. + // May return ACCESS_DENIED (due to VM_READ flag) if the process is not owned by the current user. + // Will fail if we are compiled as x86 and we're trying to open a 64 bit process...not allowed. + IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead, false, processid); + if (hprocess != IntPtr.Zero) + { + try + { + if (PsAPI.GetModuleFileNameEx(hprocess, IntPtr.Zero, _PathBuffer, (uint) _PathBuffer.Capacity) > 0) + { + return _PathBuffer.ToString(); + } + } + finally + { + CloseHandle(hprocess); + } + } + + hprocess = OpenProcess(ProcessAccessFlags.QueryInformation, false, processid); + if (hprocess != IntPtr.Zero) + { + try + { + // Try this method for Vista or higher operating systems + uint size = (uint) _PathBuffer.Capacity; + if ((Environment.OSVersion.Version.Major >= 6) && (QueryFullProcessImageName(hprocess, 0, _PathBuffer, ref size) && (size > 0))) + { + return _PathBuffer.ToString(); + } + + // Try the GetProcessImageFileName method + if (PsAPI.GetProcessImageFileName(hprocess, _PathBuffer, (uint) _PathBuffer.Capacity) > 0) + { + string dospath = _PathBuffer.ToString(); + foreach (string drive in Environment.GetLogicalDrives()) + { + if (QueryDosDevice(drive.TrimEnd('\\'), _PathBuffer, (uint) _PathBuffer.Capacity) > 0) + { + if (dospath.StartsWith(_PathBuffer.ToString())) + { + return drive + dospath.Remove(0, _PathBuffer.Length); + } + } + } + } + } + finally + { + CloseHandle(hprocess); + } + } + + return string.Empty; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/PsAPI.cs b/src/Greenshot.Base/UnmanagedHelpers/PsAPI.cs similarity index 95% rename from src/GreenshotPlugin/UnmanagedHelpers/PsAPI.cs rename to src/Greenshot.Base/UnmanagedHelpers/PsAPI.cs index 67bc5f764..bafe9e28c 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/PsAPI.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/PsAPI.cs @@ -1,56 +1,56 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Text; -using log4net; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Description of PsAPI. - /// - public class PsAPI - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(PsAPI)); - - [DllImport("psapi", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, StringBuilder lpFilename, uint nSize); - - [DllImport("psapi", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern uint GetProcessImageFileName(IntPtr hProcess, StringBuilder lpImageFileName, uint nSize); - - [DllImport("psapi")] - private static extern int EmptyWorkingSet(IntPtr hwProc); - - /// - /// Make the process use less memory by emptying the working set - /// - public static void EmptyWorkingSet() - { - LOG.Info("Calling EmptyWorkingSet"); - using Process currentProcess = Process.GetCurrentProcess(); - EmptyWorkingSet(currentProcess.Handle); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; +using log4net; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Description of PsAPI. + /// + public class PsAPI + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(PsAPI)); + + [DllImport("psapi", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, StringBuilder lpFilename, uint nSize); + + [DllImport("psapi", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint GetProcessImageFileName(IntPtr hProcess, StringBuilder lpImageFileName, uint nSize); + + [DllImport("psapi")] + private static extern int EmptyWorkingSet(IntPtr hwProc); + + /// + /// Make the process use less memory by emptying the working set + /// + public static void EmptyWorkingSet() + { + LOG.Info("Calling EmptyWorkingSet"); + using Process currentProcess = Process.GetCurrentProcess(); + EmptyWorkingSet(currentProcess.Handle); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs b/src/Greenshot.Base/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs similarity index 91% rename from src/GreenshotPlugin/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs rename to src/Greenshot.Base/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs index f1178a424..113117eae 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/SafeCurrentInputDesktopHandle.cs @@ -1,45 +1,45 @@ -using System; -using System.Security.Permissions; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using log4net; -using Microsoft.Win32.SafeHandles; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// A SafeHandle class implementation for the current input desktop - /// - public class SafeCurrentInputDesktopHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(SafeCurrentInputDesktopHandle)); - - public SafeCurrentInputDesktopHandle() : base(true) - { - IntPtr hDesktop = User32.OpenInputDesktop(0, true, DesktopAccessRight.GENERIC_ALL); - if (hDesktop != IntPtr.Zero) - { - SetHandle(hDesktop); - if (User32.SetThreadDesktop(hDesktop)) - { - LOG.DebugFormat("Switched to desktop {0}", hDesktop); - } - else - { - LOG.WarnFormat("Couldn't switch to desktop {0}", hDesktop); - LOG.Error(User32.CreateWin32Exception("SetThreadDesktop")); - } - } - else - { - LOG.Warn("Couldn't get current desktop."); - LOG.Error(User32.CreateWin32Exception("OpenInputDesktop")); - } - } - - [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] - protected override bool ReleaseHandle() - { - return User32.CloseDesktop(handle); - } - } +using System; +using System.Security.Permissions; +using Greenshot.Base.UnmanagedHelpers.Enums; +using log4net; +using Microsoft.Win32.SafeHandles; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// A SafeHandle class implementation for the current input desktop + /// + public class SafeCurrentInputDesktopHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(SafeCurrentInputDesktopHandle)); + + public SafeCurrentInputDesktopHandle() : base(true) + { + IntPtr hDesktop = User32.OpenInputDesktop(0, true, DesktopAccessRight.GENERIC_ALL); + if (hDesktop != IntPtr.Zero) + { + SetHandle(hDesktop); + if (User32.SetThreadDesktop(hDesktop)) + { + LOG.DebugFormat("Switched to desktop {0}", hDesktop); + } + else + { + LOG.WarnFormat("Couldn't switch to desktop {0}", hDesktop); + LOG.Error(User32.CreateWin32Exception("SetThreadDesktop")); + } + } + else + { + LOG.Warn("Couldn't get current desktop."); + LOG.Error(User32.CreateWin32Exception("OpenInputDesktop")); + } + } + + [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] + protected override bool ReleaseHandle() + { + return User32.CloseDesktop(handle); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/SafeIconHandle.cs b/src/Greenshot.Base/UnmanagedHelpers/SafeIconHandle.cs similarity index 91% rename from src/GreenshotPlugin/UnmanagedHelpers/SafeIconHandle.cs rename to src/Greenshot.Base/UnmanagedHelpers/SafeIconHandle.cs index 50f6a4369..acb280287 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/SafeIconHandle.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/SafeIconHandle.cs @@ -1,33 +1,33 @@ -using System; -using System.Security; -using System.Security.Permissions; -using Microsoft.Win32.SafeHandles; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// A SafeHandle class implementation for the hIcon - /// - public class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid - { - /// - /// Needed for marshalling return values - /// - [SecurityCritical] - public SafeIconHandle() : base(true) - { - } - - - public SafeIconHandle(IntPtr hIcon) : base(true) - { - SetHandle(hIcon); - } - - [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] - protected override bool ReleaseHandle() - { - return User32.DestroyIcon(handle); - } - } +using System; +using System.Security; +using System.Security.Permissions; +using Microsoft.Win32.SafeHandles; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// A SafeHandle class implementation for the hIcon + /// + public class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid + { + /// + /// Needed for marshalling return values + /// + [SecurityCritical] + public SafeIconHandle() : base(true) + { + } + + + public SafeIconHandle(IntPtr hIcon) : base(true) + { + SetHandle(hIcon); + } + + [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] + protected override bool ReleaseHandle() + { + return User32.DestroyIcon(handle); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/SafeWindowDcHandle.cs b/src/Greenshot.Base/UnmanagedHelpers/SafeWindowDcHandle.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/SafeWindowDcHandle.cs rename to src/Greenshot.Base/UnmanagedHelpers/SafeWindowDcHandle.cs index 671c07a3f..7ccdbf684 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/SafeWindowDcHandle.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/SafeWindowDcHandle.cs @@ -1,66 +1,66 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; -using System.Security.Permissions; -using Microsoft.Win32.SafeHandles; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// A WindowDC SafeHandle implementation - /// - public class SafeWindowDcHandle : SafeHandleZeroOrMinusOneIsInvalid - { - [DllImport("user32", SetLastError = true)] - private static extern IntPtr GetWindowDC(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); - - private readonly IntPtr _hWnd; - - /// - /// Needed for marshalling return values - /// - public SafeWindowDcHandle() : base(true) - { - } - - [SecurityCritical] - public SafeWindowDcHandle(IntPtr hWnd, IntPtr preexistingHandle) : base(true) - { - _hWnd = hWnd; - SetHandle(preexistingHandle); - } - - [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] - protected override bool ReleaseHandle() - { - bool returnValue = ReleaseDC(_hWnd, handle); - return returnValue; - } - - /// - /// Creates a DC as SafeWindowDcHandle for the whole of the specified hWnd - /// - /// IntPtr - /// SafeWindowDcHandle - public static SafeWindowDcHandle FromWindow(IntPtr hWnd) - { - if (hWnd == IntPtr.Zero) - { - return null; - } - - var hDcDesktop = GetWindowDC(hWnd); - return new SafeWindowDcHandle(hWnd, hDcDesktop); - } - - public static SafeWindowDcHandle FromDesktop() - { - IntPtr hWndDesktop = User32.GetDesktopWindow(); - IntPtr hDCDesktop = GetWindowDC(hWndDesktop); - return new SafeWindowDcHandle(hWndDesktop, hDCDesktop); - } - } +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using Microsoft.Win32.SafeHandles; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// A WindowDC SafeHandle implementation + /// + public class SafeWindowDcHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [DllImport("user32", SetLastError = true)] + private static extern IntPtr GetWindowDC(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); + + private readonly IntPtr _hWnd; + + /// + /// Needed for marshalling return values + /// + public SafeWindowDcHandle() : base(true) + { + } + + [SecurityCritical] + public SafeWindowDcHandle(IntPtr hWnd, IntPtr preexistingHandle) : base(true) + { + _hWnd = hWnd; + SetHandle(preexistingHandle); + } + + [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] + protected override bool ReleaseHandle() + { + bool returnValue = ReleaseDC(_hWnd, handle); + return returnValue; + } + + /// + /// Creates a DC as SafeWindowDcHandle for the whole of the specified hWnd + /// + /// IntPtr + /// SafeWindowDcHandle + public static SafeWindowDcHandle FromWindow(IntPtr hWnd) + { + if (hWnd == IntPtr.Zero) + { + return null; + } + + var hDcDesktop = GetWindowDC(hWnd); + return new SafeWindowDcHandle(hWnd, hDcDesktop); + } + + public static SafeWindowDcHandle FromDesktop() + { + IntPtr hWndDesktop = User32.GetDesktopWindow(); + IntPtr hDCDesktop = GetWindowDC(hWndDesktop); + return new SafeWindowDcHandle(hWndDesktop, hDCDesktop); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Shell32.cs b/src/Greenshot.Base/UnmanagedHelpers/Shell32.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/Shell32.cs rename to src/Greenshot.Base/UnmanagedHelpers/Shell32.cs index a1eb7e890..14c603225 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Shell32.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Shell32.cs @@ -1,123 +1,123 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.IO; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Description of Shell32. - /// - public static class Shell32 - { - [DllImport("shell32", CharSet = CharSet.Unicode)] - public static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); - - [DllImport("shell32", CharSet = CharSet.Unicode)] - private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct SHFILEINFO - { - public readonly IntPtr hIcon; - public readonly int iIcon; - public readonly uint dwAttributes; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public readonly string szDisplayName; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] - public readonly string szTypeName; - }; - - // Browsing for directory. - - private const uint SHGFI_ICON = 0x000000100; // get icon - private const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon - private const uint SHGFI_LARGEICON = 0x000000000; // get large icon - private const uint SHGFI_SMALLICON = 0x000000001; // get small icon - private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute - private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; - - /// - /// Options to specify the size of icons to return. - /// - public enum IconSize - { - /// - /// Specify large icon - 32 pixels by 32 pixels. - /// - Large = 0, - - /// - /// Specify small icon - 16 pixels by 16 pixels. - /// - Small = 1 - } - - /// - /// Returns an icon for a given file extension - indicated by the name parameter. - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179(v=vs.85).aspx - /// - /// Filename - /// Large or small - /// Whether to include the link icon - /// System.Drawing.Icon - public static Icon GetFileIcon(string filename, IconSize size, bool linkOverlay) - { - SHFILEINFO shfi = new SHFILEINFO(); - // SHGFI_USEFILEATTRIBUTES makes it simulate, just gets the icon for the extension - uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; - - if (linkOverlay) - { - flags += SHGFI_LINKOVERLAY; - } - - // Check the size specified for return. - if (IconSize.Small == size) - { - flags += SHGFI_SMALLICON; - } - else - { - flags += SHGFI_LARGEICON; - } - - SHGetFileInfo(Path.GetFileName(filename), FILE_ATTRIBUTE_NORMAL, ref shfi, (uint) Marshal.SizeOf(shfi), flags); - - // Only return an icon if we really got one - if (shfi.hIcon != IntPtr.Zero) - { - // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly - Icon icon = (Icon) Icon.FromHandle(shfi.hIcon).Clone(); - // Cleanup - User32.DestroyIcon(shfi.hIcon); - return icon; - } - - return null; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Description of Shell32. + /// + public static class Shell32 + { + [DllImport("shell32", CharSet = CharSet.Unicode)] + public static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); + + [DllImport("shell32", CharSet = CharSet.Unicode)] + private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct SHFILEINFO + { + public readonly IntPtr hIcon; + public readonly int iIcon; + public readonly uint dwAttributes; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public readonly string szDisplayName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] + public readonly string szTypeName; + }; + + // Browsing for directory. + + private const uint SHGFI_ICON = 0x000000100; // get icon + private const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon + private const uint SHGFI_LARGEICON = 0x000000000; // get large icon + private const uint SHGFI_SMALLICON = 0x000000001; // get small icon + private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute + private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; + + /// + /// Options to specify the size of icons to return. + /// + public enum IconSize + { + /// + /// Specify large icon - 32 pixels by 32 pixels. + /// + Large = 0, + + /// + /// Specify small icon - 16 pixels by 16 pixels. + /// + Small = 1 + } + + /// + /// Returns an icon for a given file extension - indicated by the name parameter. + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179(v=vs.85).aspx + /// + /// Filename + /// Large or small + /// Whether to include the link icon + /// System.Drawing.Icon + public static Icon GetFileIcon(string filename, IconSize size, bool linkOverlay) + { + SHFILEINFO shfi = new SHFILEINFO(); + // SHGFI_USEFILEATTRIBUTES makes it simulate, just gets the icon for the extension + uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; + + if (linkOverlay) + { + flags += SHGFI_LINKOVERLAY; + } + + // Check the size specified for return. + if (IconSize.Small == size) + { + flags += SHGFI_SMALLICON; + } + else + { + flags += SHGFI_LARGEICON; + } + + SHGetFileInfo(Path.GetFileName(filename), FILE_ATTRIBUTE_NORMAL, ref shfi, (uint) Marshal.SizeOf(shfi), flags); + + // Only return an icon if we really got one + if (shfi.hIcon != IntPtr.Zero) + { + // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly + Icon icon = (Icon) Icon.FromHandle(shfi.hIcon).Clone(); + // Cleanup + User32.DestroyIcon(shfi.hIcon); + return icon; + } + + return null; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/CursorInfo.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/CursorInfo.cs index 1eae0c0ad..9974ddeb7 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/CursorInfo.cs @@ -1,35 +1,35 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [StructLayout(LayoutKind.Sequential)] - public struct CursorInfo - { - public int cbSize; - public int flags; - public IntPtr hCursor; - public POINT ptScreenPos; - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [StructLayout(LayoutKind.Sequential)] + public struct CursorInfo + { + public int cbSize; + public int flags; + public IntPtr hCursor; + public POINT ptScreenPos; + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/IconInfo.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/IconInfo.cs index cd953d244..b7a430449 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/IconInfo.cs @@ -1,36 +1,36 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [StructLayout(LayoutKind.Sequential)] - public struct IconInfo - { - public bool fIcon; - public int xHotspot; - public int yHotspot; - public IntPtr hbmMask; - public IntPtr hbmColor; - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [StructLayout(LayoutKind.Sequential)] + public struct IconInfo + { + public bool fIcon; + public int xHotspot; + public int yHotspot; + public IntPtr hbmMask; + public IntPtr hbmColor; + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/POINT.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/POINT.cs index f22f34e49..a274933c7 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/POINT.cs @@ -1,66 +1,66 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [StructLayout(LayoutKind.Sequential), Serializable()] - public struct POINT - { - public int X; - public int Y; - - public POINT(int x, int y) - { - X = x; - Y = y; - } - - public POINT(Point point) - { - X = point.X; - Y = point.Y; - } - - public static implicit operator Point(POINT p) - { - return new Point(p.X, p.Y); - } - - public static implicit operator POINT(Point p) - { - return new POINT(p.X, p.Y); - } - - public Point ToPoint() - { - return new Point(X, Y); - } - - public override string ToString() - { - return X + "," + Y; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [StructLayout(LayoutKind.Sequential), Serializable()] + public struct POINT + { + public int X; + public int Y; + + public POINT(int x, int y) + { + X = x; + Y = y; + } + + public POINT(Point point) + { + X = point.X; + Y = point.Y; + } + + public static implicit operator Point(POINT p) + { + return new Point(p.X, p.Y); + } + + public static implicit operator POINT(Point p) + { + return new POINT(p.X, p.Y); + } + + public Point ToPoint() + { + return new Point(X, Y); + } + + public override string ToString() + { + return X + "," + Y; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/RECT.cs similarity index 95% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/RECT.cs index 4541c7445..f50b17544 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/RECT.cs @@ -1,176 +1,176 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [StructLayout(LayoutKind.Sequential), Serializable()] - public struct RECT - { - private int _Left; - private int _Top; - private int _Right; - private int _Bottom; - - public RECT(RECT rectangle) - : this(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom) - { - } - - public RECT(Rectangle rectangle) - : this(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom) - { - } - - public RECT(int left, int top, int right, int bottom) - { - _Left = left; - _Top = top; - _Right = right; - _Bottom = bottom; - } - - public int X - { - get { return _Left; } - set { _Left = value; } - } - - public int Y - { - get { return _Top; } - set { _Top = value; } - } - - public int Left - { - get { return _Left; } - set { _Left = value; } - } - - public int Top - { - get { return _Top; } - set { _Top = value; } - } - - public int Right - { - get { return _Right; } - set { _Right = value; } - } - - public int Bottom - { - get { return _Bottom; } - set { _Bottom = value; } - } - - public int Height - { - get { return _Bottom - _Top; } - set { _Bottom = value - _Top; } - } - - public int Width - { - get { return _Right - _Left; } - set { _Right = value + _Left; } - } - - public Point Location - { - get { return new Point(Left, Top); } - set - { - _Left = value.X; - _Top = value.Y; - } - } - - public Size Size - { - get { return new Size(Width, Height); } - set - { - _Right = value.Width + _Left; - _Bottom = value.Height + _Top; - } - } - - public static implicit operator Rectangle(RECT rectangle) - { - return new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height); - } - - public static implicit operator RECT(Rectangle rectangle) - { - return new RECT(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom); - } - - public static bool operator ==(RECT rectangle1, RECT rectangle2) - { - return rectangle1.Equals(rectangle2); - } - - public static bool operator !=(RECT rectangle1, RECT rectangle2) - { - return !rectangle1.Equals(rectangle2); - } - - public override string ToString() - { - return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}"; - } - - public override int GetHashCode() - { - return ToString().GetHashCode(); - } - - public bool Equals(RECT rectangle) - { - return rectangle.Left == _Left && rectangle.Top == _Top && rectangle.Right == _Right && rectangle.Bottom == _Bottom; - } - - public Rectangle ToRectangle() - { - return new Rectangle(Left, Top, Width, Height); - } - - public override bool Equals(object Object) - { - if (Object is RECT) - { - return Equals((RECT) Object); - } - else if (Object is Rectangle) - { - return Equals(new RECT((Rectangle) Object)); - } - - return false; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [StructLayout(LayoutKind.Sequential), Serializable()] + public struct RECT + { + private int _Left; + private int _Top; + private int _Right; + private int _Bottom; + + public RECT(RECT rectangle) + : this(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom) + { + } + + public RECT(Rectangle rectangle) + : this(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom) + { + } + + public RECT(int left, int top, int right, int bottom) + { + _Left = left; + _Top = top; + _Right = right; + _Bottom = bottom; + } + + public int X + { + get { return _Left; } + set { _Left = value; } + } + + public int Y + { + get { return _Top; } + set { _Top = value; } + } + + public int Left + { + get { return _Left; } + set { _Left = value; } + } + + public int Top + { + get { return _Top; } + set { _Top = value; } + } + + public int Right + { + get { return _Right; } + set { _Right = value; } + } + + public int Bottom + { + get { return _Bottom; } + set { _Bottom = value; } + } + + public int Height + { + get { return _Bottom - _Top; } + set { _Bottom = value - _Top; } + } + + public int Width + { + get { return _Right - _Left; } + set { _Right = value + _Left; } + } + + public Point Location + { + get { return new Point(Left, Top); } + set + { + _Left = value.X; + _Top = value.Y; + } + } + + public Size Size + { + get { return new Size(Width, Height); } + set + { + _Right = value.Width + _Left; + _Bottom = value.Height + _Top; + } + } + + public static implicit operator Rectangle(RECT rectangle) + { + return new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height); + } + + public static implicit operator RECT(Rectangle rectangle) + { + return new RECT(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom); + } + + public static bool operator ==(RECT rectangle1, RECT rectangle2) + { + return rectangle1.Equals(rectangle2); + } + + public static bool operator !=(RECT rectangle1, RECT rectangle2) + { + return !rectangle1.Equals(rectangle2); + } + + public override string ToString() + { + return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}"; + } + + public override int GetHashCode() + { + return ToString().GetHashCode(); + } + + public bool Equals(RECT rectangle) + { + return rectangle.Left == _Left && rectangle.Top == _Top && rectangle.Right == _Right && rectangle.Bottom == _Bottom; + } + + public Rectangle ToRectangle() + { + return new Rectangle(Left, Top, Width, Height); + } + + public override bool Equals(object Object) + { + if (Object is RECT) + { + return Equals((RECT) Object); + } + else if (Object is Rectangle) + { + return Equals(new RECT((Rectangle) Object)); + } + + return false; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/RECTF.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/RECTF.cs index 00aa12c09..2434e9266 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/RECTF.cs @@ -1,131 +1,131 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System.Drawing; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - /// - /// A floating point GDI Plus width/hight based rectangle. - /// - [StructLayout(LayoutKind.Sequential)] - public struct RECTF - { - /// - /// The X corner location of the rectangle. - /// - public float X; - - /// - /// The Y corner location of the rectangle. - /// - public float Y; - - /// - /// The width of the rectangle. - /// - public float Width; - - /// - /// The height of the rectangle. - /// - public float Height; - - /// - /// Creates a new GDI Plus rectangle. - /// - /// The X corner location of the rectangle. - /// The Y corner location of the rectangle. - /// The width of the rectangle. - /// The height of the rectangle. - public RECTF(float x, float y, float width, float height) - { - X = x; - Y = y; - Width = width; - Height = height; - } - - /// - /// Creates a new GDI Plus rectangle from a System.Drawing.RectangleF. - /// - /// The rectangle to base this GDI Plus rectangle on. - public RECTF(RectangleF rect) - { - X = rect.X; - Y = rect.Y; - Width = rect.Width; - Height = rect.Height; - } - - /// - /// Creates a new GDI Plus rectangle from a System.Drawing.Rectangle. - /// - /// The rectangle to base this GDI Plus rectangle on. - public RECTF(Rectangle rect) - { - X = rect.X; - Y = rect.Y; - Width = rect.Width; - Height = rect.Height; - } - - /// - /// Returns a RectangleF for this GDI Plus rectangle. - /// - /// A System.Drawing.RectangleF structure. - public RectangleF ToRectangle() - { - return new RectangleF(X, Y, Width, Height); - } - - /// - /// Returns a RectangleF for a GDI Plus rectangle. - /// - /// The GDI Plus rectangle to get the RectangleF for. - /// A System.Drawing.RectangleF structure. - public static RectangleF ToRectangle(RECTF rect) - { - return rect.ToRectangle(); - } - - /// - /// Returns a GDI Plus rectangle for a RectangleF structure. - /// - /// The RectangleF to get the GDI Plus rectangle for. - /// A GDI Plus rectangle structure. - public static RECTF FromRectangle(RectangleF rect) - { - return new RECTF(rect); - } - - /// - /// Returns a GDI Plus rectangle for a Rectangle structure. - /// - /// The Rectangle to get the GDI Plus rectangle for. - /// A GDI Plus rectangle structure. - public static RECTF FromRectangle(Rectangle rect) - { - return new RECTF(rect); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + /// + /// A floating point GDI Plus width/hight based rectangle. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RECTF + { + /// + /// The X corner location of the rectangle. + /// + public float X; + + /// + /// The Y corner location of the rectangle. + /// + public float Y; + + /// + /// The width of the rectangle. + /// + public float Width; + + /// + /// The height of the rectangle. + /// + public float Height; + + /// + /// Creates a new GDI Plus rectangle. + /// + /// The X corner location of the rectangle. + /// The Y corner location of the rectangle. + /// The width of the rectangle. + /// The height of the rectangle. + public RECTF(float x, float y, float width, float height) + { + X = x; + Y = y; + Width = width; + Height = height; + } + + /// + /// Creates a new GDI Plus rectangle from a System.Drawing.RectangleF. + /// + /// The rectangle to base this GDI Plus rectangle on. + public RECTF(RectangleF rect) + { + X = rect.X; + Y = rect.Y; + Width = rect.Width; + Height = rect.Height; + } + + /// + /// Creates a new GDI Plus rectangle from a System.Drawing.Rectangle. + /// + /// The rectangle to base this GDI Plus rectangle on. + public RECTF(Rectangle rect) + { + X = rect.X; + Y = rect.Y; + Width = rect.Width; + Height = rect.Height; + } + + /// + /// Returns a RectangleF for this GDI Plus rectangle. + /// + /// A System.Drawing.RectangleF structure. + public RectangleF ToRectangle() + { + return new RectangleF(X, Y, Width, Height); + } + + /// + /// Returns a RectangleF for a GDI Plus rectangle. + /// + /// The GDI Plus rectangle to get the RectangleF for. + /// A System.Drawing.RectangleF structure. + public static RectangleF ToRectangle(RECTF rect) + { + return rect.ToRectangle(); + } + + /// + /// Returns a GDI Plus rectangle for a RectangleF structure. + /// + /// The RectangleF to get the GDI Plus rectangle for. + /// A GDI Plus rectangle structure. + public static RECTF FromRectangle(RectangleF rect) + { + return new RECTF(rect); + } + + /// + /// Returns a GDI Plus rectangle for a Rectangle structure. + /// + /// The Rectangle to get the GDI Plus rectangle for. + /// A GDI Plus rectangle structure. + public static RECTF FromRectangle(Rectangle rect) + { + return new RECTF(rect); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/SCROLLINFO.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/SCROLLINFO.cs index d2157e966..718abebcf 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/SCROLLINFO.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [Serializable, StructLayout(LayoutKind.Sequential)] - public struct SCROLLINFO - { - public int cbSize; - public int fMask; - public int nMin; - public int nMax; - public int nPage; - public int nPos; - public int nTrackPos; - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [Serializable, StructLayout(LayoutKind.Sequential)] + public struct SCROLLINFO + { + public int cbSize; + public int fMask; + public int nMin; + public int nMax; + public int nPage; + public int nPos; + public int nTrackPos; + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/SIZE.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/SIZE.cs index 531fa977d..93d583c4c 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/SIZE.cs @@ -1,51 +1,51 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Drawing; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - [StructLayout(LayoutKind.Sequential), Serializable()] - public struct SIZE - { - public int Width; - public int Height; - - public SIZE(Size size) : this(size.Width, size.Height) - { - } - - public SIZE(int width, int height) - { - Width = width; - Height = height; - } - - public Size ToSize() - { - return new Size(Width, Height); - } - - public bool IsEmpty => Width * Height == 0; - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + [StructLayout(LayoutKind.Sequential), Serializable()] + public struct SIZE + { + public int Width; + public int Height; + + public SIZE(Size size) : this(size.Width, size.Height) + { + } + + public SIZE(int width, int height) + { + Width = width; + Height = height; + } + + public Size ToSize() + { + return new Size(Width, Height); + } + + public bool IsEmpty => Width * Height == 0; + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/WindowInfo.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/WindowInfo.cs index 237fca4b8..ad8c60812 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/WindowInfo.cs @@ -1,52 +1,52 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - /// - /// The structure for the WindowInfo - /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632610%28v=vs.85%29.aspx - /// - [StructLayout(LayoutKind.Sequential), Serializable] - public struct WindowInfo - { - public uint cbSize; - public RECT rcWindow; - public RECT rcClient; - public uint dwStyle; - public uint dwExStyle; - public uint dwWindowStatus; - public uint cxWindowBorders; - public uint cyWindowBorders; - public ushort atomWindowType; - - public ushort wCreatorVersion; - - // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)". - public WindowInfo(bool? filler) : this() - { - cbSize = (uint) (Marshal.SizeOf(typeof(WindowInfo))); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + /// + /// The structure for the WindowInfo + /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632610%28v=vs.85%29.aspx + /// + [StructLayout(LayoutKind.Sequential), Serializable] + public struct WindowInfo + { + public uint cbSize; + public RECT rcWindow; + public RECT rcClient; + public uint dwStyle; + public uint dwExStyle; + public uint dwWindowStatus; + public uint cxWindowBorders; + public uint cyWindowBorders; + public ushort atomWindowType; + + public ushort wCreatorVersion; + + // Allows automatic initialization of "cbSize" with "new WINDOWINFO(null/true/false)". + public WindowInfo(bool? filler) : this() + { + cbSize = (uint) (Marshal.SizeOf(typeof(WindowInfo))); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs b/src/Greenshot.Base/UnmanagedHelpers/Structs/WindowPlacement.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs rename to src/Greenshot.Base/UnmanagedHelpers/Structs/WindowPlacement.cs index c1f064c48..fa981b8bf 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Structs/WindowPlacement.cs @@ -1,80 +1,80 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; -using GreenshotPlugin.UnmanagedHelpers.Enums; - -namespace GreenshotPlugin.UnmanagedHelpers.Structs -{ - /// - /// Contains information about the placement of a window on the screen. - /// - [StructLayout(LayoutKind.Sequential), Serializable()] - public struct WindowPlacement - { - /// - /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT). - /// - /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly. - /// - /// - public int Length; - - /// - /// Specifies flags that control the position of the minimized window and the method by which the window is restored. - /// - public WindowPlacementFlags Flags; - - /// - /// The current show state of the window. - /// - public ShowWindowCommand ShowCmd; - - /// - /// The coordinates of the window's upper-left corner when the window is minimized. - /// - public POINT MinPosition; - - /// - /// The coordinates of the window's upper-left corner when the window is maximized. - /// - public POINT MaxPosition; - - /// - /// The window's coordinates when the window is in the restored position. - /// - public RECT NormalPosition; - - /// - /// Gets the default (empty) value. - /// - public static WindowPlacement Default - { - get - { - WindowPlacement result = new WindowPlacement(); - result.Length = Marshal.SizeOf(result); - return result; - } - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; +using Greenshot.Base.UnmanagedHelpers.Enums; + +namespace Greenshot.Base.UnmanagedHelpers.Structs +{ + /// + /// Contains information about the placement of a window on the screen. + /// + [StructLayout(LayoutKind.Sequential), Serializable()] + public struct WindowPlacement + { + /// + /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT). + /// + /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly. + /// + /// + public int Length; + + /// + /// Specifies flags that control the position of the minimized window and the method by which the window is restored. + /// + public WindowPlacementFlags Flags; + + /// + /// The current show state of the window. + /// + public ShowWindowCommand ShowCmd; + + /// + /// The coordinates of the window's upper-left corner when the window is minimized. + /// + public POINT MinPosition; + + /// + /// The coordinates of the window's upper-left corner when the window is maximized. + /// + public POINT MaxPosition; + + /// + /// The window's coordinates when the window is in the restored position. + /// + public RECT NormalPosition; + + /// + /// Gets the default (empty) value. + /// + public static WindowPlacement Default + { + get + { + WindowPlacement result = new WindowPlacement(); + result.Length = Marshal.SizeOf(result); + return result; + } + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/User32.cs b/src/Greenshot.Base/UnmanagedHelpers/User32.cs similarity index 96% rename from src/GreenshotPlugin/UnmanagedHelpers/User32.cs rename to src/Greenshot.Base/UnmanagedHelpers/User32.cs index 2cedb28f7..1f6c39c24 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/User32.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/User32.cs @@ -1,333 +1,333 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Text; -using System.Windows.Forms; -using log4net; -using GreenshotPlugin.Core.Enums; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// User32 Wrappers - /// - public static class User32 - { - private static readonly ILog LOG = LogManager.GetLogger(typeof(User32)); - private static bool _CanCallGetPhysicalCursorPos = true; - public const int SC_RESTORE = 0xF120; - public const int SC_MAXIMIZE = 0xF030; - public const int SC_MINIMIZE = 0xF020; - - // For MonitorFromWindow - public const int MONITOR_DEFAULTTONULL = 0; - public const int MONITOR_DEFAULTTONEAREST = 2; - public const int CURSOR_SHOWING = 0x00000001; - - /// - /// Determines whether the specified window handle identifies an existing window. - /// - /// A handle to the window to be tested. - /// - /// If the window handle identifies an existing window, the return value is true. - /// If the window handle does not identify an existing window, the return value is false. - /// - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWindow(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWindowVisible(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId); - - [DllImport("user32", SetLastError = true)] - public static extern int GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId); - - [DllImport("user32")] - public static extern IntPtr AttachThreadInput(int idAttach, int idAttachTo, int fAttach); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetParent(IntPtr hWnd); - - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int cch); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool BringWindowToTop(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetForegroundWindow(); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetDesktopWindow(); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetForegroundWindow(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WindowPlacement lpwndpl); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsIconic(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsZoomed(IntPtr hWnd); - - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); - - [DllImport("user32", SetLastError = true)] - public static extern uint GetClassLong(IntPtr hWnd, int nIndex); - - [DllImport("user32", SetLastError = true, EntryPoint = "GetClassLongPtr")] - public static extern IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PrintWindow(IntPtr hWnd, IntPtr hDc, uint nFlags); - - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")] - public static extern int GetWindowLong(IntPtr hWnd, int index); - - [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLongPtr")] - public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); - - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int SetWindowLong(IntPtr hWnd, int index, int styleFlags); - - [DllImport("user32", SetLastError = true, EntryPoint = "SetWindowLongPtr")] - public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int index, IntPtr styleFlags); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr MonitorFromWindow(IntPtr hWnd, MonitorFrom dwFlags); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetWindowInfo(IntPtr hWnd, ref WindowInfo pwi); - - [DllImport("user32", SetLastError = true)] - public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); - - [DllImport("user32", SetLastError = true)] - public static extern RegionResult GetWindowRgn(IntPtr hWnd, SafeHandle hRgn); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, WindowPos uFlags); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetClipboardOwner(); - - // Added for finding Metro apps, Greenshot 1.1 - [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); - - [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow); - - /// uiFlags: 0 - Count of GDI objects - /// uiFlags: 1 - Count of USER objects - /// - Win32 GDI objects (pens, brushes, fonts, palettes, regions, device contexts, bitmap headers) - /// - Win32 USER objects: - /// - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources, menu resources, raw data resources, string table entries, message table entries, cursors/icons) - /// - Other USER objects (windows, menus) - /// - [DllImport("user32", SetLastError = true)] - public static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags); - - [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern uint RegisterWindowMessage(string lpString); - - [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); - - [DllImport("user32", SetLastError = true)] - private static extern bool GetPhysicalCursorPos(out POINT cursorLocation); - - /// - /// The following is used for Icon handling - /// - /// - /// - [DllImport("user32", SetLastError = true)] - public static extern SafeIconHandle CopyIcon(IntPtr hIcon); - - [DllImport("user32", SetLastError = true)] - public static extern bool DestroyIcon(IntPtr hIcon); - - [DllImport("user32", SetLastError = true)] - public static extern bool GetCursorInfo(out CursorInfo cursorInfo); - - [DllImport("user32", SetLastError = true)] - public static extern bool GetIconInfo(SafeIconHandle iconHandle, out IconInfo iconInfo); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr SetCapture(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ReleaseCapture(); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr CreateIconIndirect(ref IconInfo icon); - - [DllImport("user32", SetLastError = true)] - public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, DesktopAccessRight dwDesiredAccess); - - [DllImport("user32", SetLastError = true)] - public static extern bool SetThreadDesktop(IntPtr hDesktop); - - [DllImport("user32", SetLastError = true)] - public static extern bool CloseDesktop(IntPtr hDesktop); - - /// - /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. - /// - /// Point with cursor location, relative to the origin of the monitor setup - /// (i.e. negative coordinates arepossible in multiscreen setups) - public static Point GetCursorLocation() - { - if (Environment.OSVersion.Version.Major >= 6 && _CanCallGetPhysicalCursorPos) - { - try - { - if (GetPhysicalCursorPos(out var cursorLocation)) - { - return new Point(cursorLocation.X, cursorLocation.Y); - } - - Win32Error error = Win32.GetLastErrorCode(); - LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error)); - } - catch (Exception ex) - { - LOG.Error("Exception retrieving PhysicalCursorPos, no longer calling this. Cause :", ex); - _CanCallGetPhysicalCursorPos = false; - } - } - - return new Point(Cursor.Position.X, Cursor.Position.Y); - } - - /// - /// Wrapper for the GetClassLong which decides if the system is 64-bit or not and calls the right one. - /// - /// IntPtr - /// int - /// IntPtr - public static IntPtr GetClassLongWrapper(IntPtr hWnd, int nIndex) - { - if (IntPtr.Size > 4) - { - return GetClassLongPtr(hWnd, nIndex); - } - else - { - return new IntPtr(GetClassLong(hWnd, nIndex)); - } - } - - /// - /// Wrapper for the GetWindowLong which decides if the system is 64-bit or not and calls the right one. - /// - /// - /// - /// - public static long GetWindowLongWrapper(IntPtr hWnd, int nIndex) - { - if (IntPtr.Size == 8) - { - return GetWindowLongPtr(hWnd, nIndex).ToInt64(); - } - else - { - return GetWindowLong(hWnd, nIndex); - } - } - - /// - /// Wrapper for the SetWindowLong which decides if the system is 64-bit or not and calls the right one. - /// - /// - /// - /// - public static void SetWindowLongWrapper(IntPtr hWnd, int nIndex, IntPtr styleFlags) - { - if (IntPtr.Size == 8) - { - SetWindowLongPtr(hWnd, nIndex, styleFlags); - } - else - { - SetWindowLong(hWnd, nIndex, styleFlags.ToInt32()); - } - } - - public static uint GetGuiResourcesGDICount() - { - using var currentProcess = Process.GetCurrentProcess(); - return GetGuiResources(currentProcess.Handle, 0); - } - - public static uint GetGuiResourcesUserCount() - { - using var currentProcess = Process.GetCurrentProcess(); - return GetGuiResources(currentProcess.Handle, 1); - } - - /// - /// Helper method to create a Win32 exception with the windows message in it - /// - /// string with current method - /// Exception - public static Exception CreateWin32Exception(string method) - { - var exceptionToThrow = new Win32Exception(); - exceptionToThrow.Data.Add("Method", method); - return exceptionToThrow; - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using Greenshot.Base.Core.Enums; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; +using log4net; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// User32 Wrappers + /// + public static class User32 + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(User32)); + private static bool _CanCallGetPhysicalCursorPos = true; + public const int SC_RESTORE = 0xF120; + public const int SC_MAXIMIZE = 0xF030; + public const int SC_MINIMIZE = 0xF020; + + // For MonitorFromWindow + public const int MONITOR_DEFAULTTONULL = 0; + public const int MONITOR_DEFAULTTONEAREST = 2; + public const int CURSOR_SHOWING = 0x00000001; + + /// + /// Determines whether the specified window handle identifies an existing window. + /// + /// A handle to the window to be tested. + /// + /// If the window handle identifies an existing window, the return value is true. + /// If the window handle does not identify an existing window, the return value is false. + /// + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindow(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindowVisible(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId); + + [DllImport("user32", SetLastError = true)] + public static extern int GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId); + + [DllImport("user32")] + public static extern IntPtr AttachThreadInput(int idAttach, int idAttachTo, int fAttach); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr GetParent(IntPtr hWnd); + + [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int cch); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool BringWindowToTop(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr GetDesktopWindow(); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WindowPlacement lpwndpl); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsIconic(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsZoomed(IntPtr hWnd); + + [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + [DllImport("user32", SetLastError = true)] + public static extern uint GetClassLong(IntPtr hWnd, int nIndex); + + [DllImport("user32", SetLastError = true, EntryPoint = "GetClassLongPtr")] + public static extern IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrintWindow(IntPtr hWnd, IntPtr hDc, uint nFlags); + + [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")] + public static extern int GetWindowLong(IntPtr hWnd, int index); + + [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLongPtr")] + public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); + + [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int SetWindowLong(IntPtr hWnd, int index, int styleFlags); + + [DllImport("user32", SetLastError = true, EntryPoint = "SetWindowLongPtr")] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int index, IntPtr styleFlags); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr MonitorFromWindow(IntPtr hWnd, MonitorFrom dwFlags); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetWindowInfo(IntPtr hWnd, ref WindowInfo pwi); + + [DllImport("user32", SetLastError = true)] + public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); + + [DllImport("user32", SetLastError = true)] + public static extern RegionResult GetWindowRgn(IntPtr hWnd, SafeHandle hRgn); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, WindowPos uFlags); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr GetClipboardOwner(); + + // Added for finding Metro apps, Greenshot 1.1 + [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow); + + /// uiFlags: 0 - Count of GDI objects + /// uiFlags: 1 - Count of USER objects + /// - Win32 GDI objects (pens, brushes, fonts, palettes, regions, device contexts, bitmap headers) + /// - Win32 USER objects: + /// - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources, menu resources, raw data resources, string table entries, message table entries, cursors/icons) + /// - Other USER objects (windows, menus) + /// + [DllImport("user32", SetLastError = true)] + public static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags); + + [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern uint RegisterWindowMessage(string lpString); + + [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); + + [DllImport("user32", SetLastError = true)] + private static extern bool GetPhysicalCursorPos(out POINT cursorLocation); + + /// + /// The following is used for Icon handling + /// + /// + /// + [DllImport("user32", SetLastError = true)] + public static extern SafeIconHandle CopyIcon(IntPtr hIcon); + + [DllImport("user32", SetLastError = true)] + public static extern bool DestroyIcon(IntPtr hIcon); + + [DllImport("user32", SetLastError = true)] + public static extern bool GetCursorInfo(out CursorInfo cursorInfo); + + [DllImport("user32", SetLastError = true)] + public static extern bool GetIconInfo(SafeIconHandle iconHandle, out IconInfo iconInfo); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr SetCapture(IntPtr hWnd); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ReleaseCapture(); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr CreateIconIndirect(ref IconInfo icon); + + [DllImport("user32", SetLastError = true)] + public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, DesktopAccessRight dwDesiredAccess); + + [DllImport("user32", SetLastError = true)] + public static extern bool SetThreadDesktop(IntPtr hDesktop); + + [DllImport("user32", SetLastError = true)] + public static extern bool CloseDesktop(IntPtr hDesktop); + + /// + /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. + /// + /// Point with cursor location, relative to the origin of the monitor setup + /// (i.e. negative coordinates arepossible in multiscreen setups) + public static Point GetCursorLocation() + { + if (Environment.OSVersion.Version.Major >= 6 && _CanCallGetPhysicalCursorPos) + { + try + { + if (GetPhysicalCursorPos(out var cursorLocation)) + { + return new Point(cursorLocation.X, cursorLocation.Y); + } + + Win32Error error = Win32.GetLastErrorCode(); + LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error)); + } + catch (Exception ex) + { + LOG.Error("Exception retrieving PhysicalCursorPos, no longer calling this. Cause :", ex); + _CanCallGetPhysicalCursorPos = false; + } + } + + return new Point(Cursor.Position.X, Cursor.Position.Y); + } + + /// + /// Wrapper for the GetClassLong which decides if the system is 64-bit or not and calls the right one. + /// + /// IntPtr + /// int + /// IntPtr + public static IntPtr GetClassLongWrapper(IntPtr hWnd, int nIndex) + { + if (IntPtr.Size > 4) + { + return GetClassLongPtr(hWnd, nIndex); + } + else + { + return new IntPtr(GetClassLong(hWnd, nIndex)); + } + } + + /// + /// Wrapper for the GetWindowLong which decides if the system is 64-bit or not and calls the right one. + /// + /// + /// + /// + public static long GetWindowLongWrapper(IntPtr hWnd, int nIndex) + { + if (IntPtr.Size == 8) + { + return GetWindowLongPtr(hWnd, nIndex).ToInt64(); + } + else + { + return GetWindowLong(hWnd, nIndex); + } + } + + /// + /// Wrapper for the SetWindowLong which decides if the system is 64-bit or not and calls the right one. + /// + /// + /// + /// + public static void SetWindowLongWrapper(IntPtr hWnd, int nIndex, IntPtr styleFlags) + { + if (IntPtr.Size == 8) + { + SetWindowLongPtr(hWnd, nIndex, styleFlags); + } + else + { + SetWindowLong(hWnd, nIndex, styleFlags.ToInt32()); + } + } + + public static uint GetGuiResourcesGDICount() + { + using var currentProcess = Process.GetCurrentProcess(); + return GetGuiResources(currentProcess.Handle, 0); + } + + public static uint GetGuiResourcesUserCount() + { + using var currentProcess = Process.GetCurrentProcess(); + return GetGuiResources(currentProcess.Handle, 1); + } + + /// + /// Helper method to create a Win32 exception with the windows message in it + /// + /// string with current method + /// Exception + public static Exception CreateWin32Exception(string method) + { + var exceptionToThrow = new Win32Exception(); + exceptionToThrow.Data.Add("Method", method); + return exceptionToThrow; + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/Win32.cs b/src/Greenshot.Base/UnmanagedHelpers/Win32.cs similarity index 93% rename from src/GreenshotPlugin/UnmanagedHelpers/Win32.cs rename to src/Greenshot.Base/UnmanagedHelpers/Win32.cs index 2721572f0..940dc4e95 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/Win32.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Win32.cs @@ -1,69 +1,69 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; -using System.Text; -using GreenshotPlugin.UnmanagedHelpers.Enums; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - public static class Win32 - { - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer, int nSize, IntPtr arguments); - - [DllImport("kernel32.dll")] - public static extern void SetLastError(uint dwErrCode); - - public static Win32Error GetLastErrorCode() - { - return (Win32Error) Marshal.GetLastWin32Error(); - } - - public static string GetMessage(Win32Error errorCode) - { - var buffer = new StringBuilder(0x100); - - if (FormatMessage(0x3200, IntPtr.Zero, (uint) errorCode, 0, buffer, buffer.Capacity, IntPtr.Zero) == 0) - { - return "Unknown error (0x" + ((int) errorCode).ToString("x") + ")"; - } - - var result = new StringBuilder(); - int i = 0; - - while (i < buffer.Length) - { - if (!char.IsLetterOrDigit(buffer[i]) && - !char.IsPunctuation(buffer[i]) && - !char.IsSymbol(buffer[i]) && - !char.IsWhiteSpace(buffer[i])) - break; - - result.Append(buffer[i]); - i++; - } - - return result.ToString().Replace("\r\n", string.Empty); - } - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; +using System.Text; +using Greenshot.Base.UnmanagedHelpers.Enums; + +namespace Greenshot.Base.UnmanagedHelpers +{ + public static class Win32 + { + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + private static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer, int nSize, IntPtr arguments); + + [DllImport("kernel32.dll")] + public static extern void SetLastError(uint dwErrCode); + + public static Win32Error GetLastErrorCode() + { + return (Win32Error) Marshal.GetLastWin32Error(); + } + + public static string GetMessage(Win32Error errorCode) + { + var buffer = new StringBuilder(0x100); + + if (FormatMessage(0x3200, IntPtr.Zero, (uint) errorCode, 0, buffer, buffer.Capacity, IntPtr.Zero) == 0) + { + return "Unknown error (0x" + ((int) errorCode).ToString("x") + ")"; + } + + var result = new StringBuilder(); + int i = 0; + + while (i < buffer.Length) + { + if (!char.IsLetterOrDigit(buffer[i]) && + !char.IsPunctuation(buffer[i]) && + !char.IsSymbol(buffer[i]) && + !char.IsWhiteSpace(buffer[i])) + break; + + result.Append(buffer[i]); + i++; + } + + return result.ToString().Replace("\r\n", string.Empty); + } + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/WinEventDelegate.cs b/src/Greenshot.Base/UnmanagedHelpers/WinEventDelegate.cs similarity index 84% rename from src/GreenshotPlugin/UnmanagedHelpers/WinEventDelegate.cs rename to src/Greenshot.Base/UnmanagedHelpers/WinEventDelegate.cs index 551b75410..bd54923f7 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/WinEventDelegate.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/WinEventDelegate.cs @@ -1,17 +1,17 @@ -using System; -using GreenshotPlugin.UnmanagedHelpers.Enums; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Used with SetWinEventHook - /// - /// - /// - /// - /// - /// - /// - /// - public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime); +using System; +using Greenshot.Base.UnmanagedHelpers.Enums; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Used with SetWinEventHook + /// + /// + /// + /// + /// + /// + /// + /// + public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime); } \ No newline at end of file diff --git a/src/GreenshotPlugin/UnmanagedHelpers/WinMM.cs b/src/Greenshot.Base/UnmanagedHelpers/WinMM.cs similarity index 94% rename from src/GreenshotPlugin/UnmanagedHelpers/WinMM.cs rename to src/Greenshot.Base/UnmanagedHelpers/WinMM.cs index 25bb503b4..411ecdca1 100644 --- a/src/GreenshotPlugin/UnmanagedHelpers/WinMM.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/WinMM.cs @@ -1,38 +1,38 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 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 . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers -{ - /// - /// Windows Media - /// - public class WinMM - { - [DllImport("winmm.dll", SetLastError = true)] - public static extern bool PlaySound(byte[] ptrToSound, UIntPtr hmod, uint fdwSound); - - [DllImport("winmm.dll", SetLastError = true)] - public static extern bool PlaySound(IntPtr ptrToSound, UIntPtr hmod, uint fdwSound); - } +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 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 . + */ + +using System; +using System.Runtime.InteropServices; + +namespace Greenshot.Base.UnmanagedHelpers +{ + /// + /// Windows Media + /// + public class WinMM + { + [DllImport("winmm.dll", SetLastError = true)] + public static extern bool PlaySound(byte[] ptrToSound, UIntPtr hmod, uint fdwSound); + + [DllImport("winmm.dll", SetLastError = true)] + public static extern bool PlaySound(IntPtr ptrToSound, UIntPtr hmod, uint fdwSound); + } } \ No newline at end of file diff --git a/src/GreenshotPlugin/log4net-embedded.xml b/src/Greenshot.Base/log4net-embedded.xml similarity index 97% rename from src/GreenshotPlugin/log4net-embedded.xml rename to src/Greenshot.Base/log4net-embedded.xml index ccfa902a7..b4ced5bad 100644 --- a/src/GreenshotPlugin/log4net-embedded.xml +++ b/src/Greenshot.Base/log4net-embedded.xml @@ -1,21 +1,21 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Greenshot.Plugin.Box/BoxConfiguration.cs b/src/Greenshot.Plugin.Box/BoxConfiguration.cs index a4d83ef68..15e458109 100644 --- a/src/Greenshot.Plugin.Box/BoxConfiguration.cs +++ b/src/Greenshot.Plugin.Box/BoxConfiguration.cs @@ -21,9 +21,9 @@ using System; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Box.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Box { diff --git a/src/Greenshot.Plugin.Box/BoxDestination.cs b/src/Greenshot.Plugin.Box/BoxDestination.cs index 0bc547b88..989c0aad0 100644 --- a/src/Greenshot.Plugin.Box/BoxDestination.cs +++ b/src/Greenshot.Plugin.Box/BoxDestination.cs @@ -21,8 +21,8 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.Box { diff --git a/src/Greenshot.Plugin.Box/BoxPlugin.cs b/src/Greenshot.Plugin.Box/BoxPlugin.cs index 9918b5e93..8aba68183 100644 --- a/src/Greenshot.Plugin.Box/BoxPlugin.cs +++ b/src/Greenshot.Plugin.Box/BoxPlugin.cs @@ -24,11 +24,11 @@ using System.ComponentModel; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Box { diff --git a/src/Greenshot.Plugin.Box/BoxUtils.cs b/src/Greenshot.Plugin.Box/BoxUtils.cs index 37a0eac53..4634d845e 100644 --- a/src/Greenshot.Plugin.Box/BoxUtils.cs +++ b/src/Greenshot.Plugin.Box/BoxUtils.cs @@ -23,9 +23,9 @@ using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Json; using System.Text; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Box { diff --git a/src/Greenshot.Plugin.Box/Forms/BoxForm.cs b/src/Greenshot.Plugin.Box/Forms/BoxForm.cs index 646bdf87b..96776ab92 100644 --- a/src/Greenshot.Plugin.Box/Forms/BoxForm.cs +++ b/src/Greenshot.Plugin.Box/Forms/BoxForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.Box.Forms { diff --git a/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs index 6b8f68242..1714ff65e 100644 --- a/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Box/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Box.Forms { partial class SettingsForm { /// @@ -46,12 +49,12 @@ namespace Greenshot.Plugin.Box.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.label_AfterUpload = new GreenshotLabel(); + this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -138,11 +141,11 @@ namespace Greenshot.Plugin.Box.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotLabel label_AfterUpload; + private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; } } diff --git a/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.csproj b/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.csproj index 990e9ddc4..789ebd424 100644 --- a/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.csproj +++ b/src/Greenshot.Plugin.Box/Greenshot.Plugin.Box.csproj @@ -10,6 +10,6 @@ - + \ No newline at end of file diff --git a/src/Greenshot.Plugin.Confluence/Confluence.cs b/src/Greenshot.Plugin.Confluence/Confluence.cs index 79d11a034..b139c041e 100644 --- a/src/Greenshot.Plugin.Confluence/Confluence.cs +++ b/src/Greenshot.Plugin.Confluence/Confluence.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using GreenshotConfluencePlugin.confluence; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/ConfluenceConfiguration.cs b/src/Greenshot.Plugin.Confluence/ConfluenceConfiguration.cs index df23e7768..400f3c352 100644 --- a/src/Greenshot.Plugin.Confluence/ConfluenceConfiguration.cs +++ b/src/Greenshot.Plugin.Confluence/ConfluenceConfiguration.cs @@ -20,8 +20,8 @@ */ using System; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/ConfluenceDestination.cs b/src/Greenshot.Plugin.Confluence/ConfluenceDestination.cs index 275ace4d1..70af706bd 100644 --- a/src/Greenshot.Plugin.Confluence/ConfluenceDestination.cs +++ b/src/Greenshot.Plugin.Confluence/ConfluenceDestination.cs @@ -26,11 +26,11 @@ using System.Drawing; using System.IO; using System.Threading; using System.Windows; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/ConfluencePlugin.cs b/src/Greenshot.Plugin.Confluence/ConfluencePlugin.cs index fbe852691..6878192a1 100644 --- a/src/Greenshot.Plugin.Confluence/ConfluencePlugin.cs +++ b/src/Greenshot.Plugin.Confluence/ConfluencePlugin.cs @@ -21,12 +21,12 @@ using System; using System.Windows; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Confluence.Forms; using Greenshot.Plugin.Confluence.Support; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/ConfluenceUtils.cs b/src/Greenshot.Plugin.Confluence/ConfluenceUtils.cs index 2c878d6d9..249b97f77 100644 --- a/src/Greenshot.Plugin.Confluence/ConfluenceUtils.cs +++ b/src/Greenshot.Plugin.Confluence/ConfluenceUtils.cs @@ -24,7 +24,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Windows.Automation; -using GreenshotPlugin.Core; +using Greenshot.Base.Core; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/EnumDisplayer.cs b/src/Greenshot.Plugin.Confluence/EnumDisplayer.cs index c4023a828..3b3e3f95f 100644 --- a/src/Greenshot.Plugin.Confluence/EnumDisplayer.cs +++ b/src/Greenshot.Plugin.Confluence/EnumDisplayer.cs @@ -26,7 +26,7 @@ using System.Collections.ObjectModel; using System.Globalization; using System.Reflection; using System.Windows.Data; -using GreenshotPlugin.Core; +using Greenshot.Base.Core; namespace Greenshot.Plugin.Confluence { diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceConfigurationForm.xaml b/src/Greenshot.Plugin.Confluence/Forms/ConfluenceConfigurationForm.xaml index 2b747d831..7ab7933e8 100644 --- a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceConfigurationForm.xaml +++ b/src/Greenshot.Plugin.Confluence/Forms/ConfluenceConfigurationForm.xaml @@ -1,8 +1,7 @@  diff --git a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml.cs b/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml.cs index 2b296f5f0..c5f44014b 100644 --- a/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml.cs +++ b/src/Greenshot.Plugin.Confluence/Forms/ConfluenceSearch.xaml.cs @@ -23,7 +23,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Windows; -using GreenshotPlugin.IniFile; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Confluence.Forms { diff --git a/src/Greenshot.Plugin.Confluence/Greenshot.Plugin.Confluence.csproj b/src/Greenshot.Plugin.Confluence/Greenshot.Plugin.Confluence.csproj index 79b55313a..f4a7f9c16 100644 --- a/src/Greenshot.Plugin.Confluence/Greenshot.Plugin.Confluence.csproj +++ b/src/Greenshot.Plugin.Confluence/Greenshot.Plugin.Confluence.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/Greenshot.Plugin.Confluence/Support/LanguageXMLTranslationProvider.cs b/src/Greenshot.Plugin.Confluence/Support/LanguageXMLTranslationProvider.cs index 926e7ad8e..e15e67555 100644 --- a/src/Greenshot.Plugin.Confluence/Support/LanguageXMLTranslationProvider.cs +++ b/src/Greenshot.Plugin.Confluence/Support/LanguageXMLTranslationProvider.cs @@ -1,4 +1,4 @@ -using GreenshotPlugin.Core; +using Greenshot.Base.Core; namespace Greenshot.Plugin.Confluence.Support { diff --git a/src/Greenshot.Plugin.Dropbox/DropboxDestination.cs b/src/Greenshot.Plugin.Dropbox/DropboxDestination.cs index 61f7a8705..715d96ded 100644 --- a/src/Greenshot.Plugin.Dropbox/DropboxDestination.cs +++ b/src/Greenshot.Plugin.Dropbox/DropboxDestination.cs @@ -21,9 +21,9 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.Dropbox { diff --git a/src/Greenshot.Plugin.Dropbox/DropboxPlugin.cs b/src/Greenshot.Plugin.Dropbox/DropboxPlugin.cs index 1ec893423..b3c19d1a5 100644 --- a/src/Greenshot.Plugin.Dropbox/DropboxPlugin.cs +++ b/src/Greenshot.Plugin.Dropbox/DropboxPlugin.cs @@ -23,11 +23,11 @@ using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Dropbox { diff --git a/src/Greenshot.Plugin.Dropbox/DropboxPluginConfiguration.cs b/src/Greenshot.Plugin.Dropbox/DropboxPluginConfiguration.cs index 4a2bd95d0..5925a1729 100644 --- a/src/Greenshot.Plugin.Dropbox/DropboxPluginConfiguration.cs +++ b/src/Greenshot.Plugin.Dropbox/DropboxPluginConfiguration.cs @@ -21,9 +21,9 @@ using System; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Dropbox.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Dropbox { diff --git a/src/Greenshot.Plugin.Dropbox/DropboxUtils.cs b/src/Greenshot.Plugin.Dropbox/DropboxUtils.cs index ebb7b2685..7307b2a26 100644 --- a/src/Greenshot.Plugin.Dropbox/DropboxUtils.cs +++ b/src/Greenshot.Plugin.Dropbox/DropboxUtils.cs @@ -22,11 +22,11 @@ using System; using System.Collections.Generic; using System.IO; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Newtonsoft.Json; namespace Greenshot.Plugin.Dropbox diff --git a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs b/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs index b39d1e14d..1f1bfd5ea 100644 --- a/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs +++ b/src/Greenshot.Plugin.Dropbox/Forms/DropboxForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.Dropbox.Forms { diff --git a/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs index c7f21fd24..e80470dd5 100644 --- a/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Dropbox/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Dropbox.Forms { partial class SettingsForm { /// @@ -45,12 +48,12 @@ namespace Greenshot.Plugin.Dropbox.Forms { /// not be able to load this method if it was changed manually. /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.label_AfterUpload = new GreenshotLabel(); + this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -135,11 +138,11 @@ namespace Greenshot.Plugin.Dropbox.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotLabel label_AfterUpload; + private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; } } diff --git a/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.csproj b/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.csproj index 0ecbf3fec..075667394 100644 --- a/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.csproj +++ b/src/Greenshot.Plugin.Dropbox/Greenshot.Plugin.Dropbox.csproj @@ -10,6 +10,6 @@ - + \ No newline at end of file diff --git a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandConfiguration.cs b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandConfiguration.cs index 8d677e200..3cde91406 100644 --- a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandConfiguration.cs +++ b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandConfiguration.cs @@ -22,8 +22,8 @@ using System; using System.Collections.Generic; using System.IO; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandDestination.cs b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandDestination.cs index c7ab3b957..3814896dd 100644 --- a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandDestination.cs +++ b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandDestination.cs @@ -26,10 +26,10 @@ using System.Diagnostics; using System.Drawing; using System.Text.RegularExpressions; using System.Threading; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandForm.cs b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandForm.cs index 7fdfffa2a..90ba4bcfb 100644 --- a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandForm.cs +++ b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandPlugin.cs b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandPlugin.cs index 43ae03f41..a4a3c20a5 100644 --- a/src/Greenshot.Plugin.ExternalCommand/ExternalCommandPlugin.cs +++ b/src/Greenshot.Plugin.ExternalCommand/ExternalCommandPlugin.cs @@ -24,10 +24,10 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj b/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj index bb0b57ef0..cc3d98fb9 100644 --- a/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj +++ b/src/Greenshot.Plugin.ExternalCommand/Greenshot.Plugin.ExternalCommand.csproj @@ -6,6 +6,6 @@ - + diff --git a/src/Greenshot.Plugin.ExternalCommand/IconCache.cs b/src/Greenshot.Plugin.ExternalCommand/IconCache.cs index f1b854164..c1c8b2e04 100644 --- a/src/Greenshot.Plugin.ExternalCommand/IconCache.cs +++ b/src/Greenshot.Plugin.ExternalCommand/IconCache.cs @@ -22,8 +22,8 @@ using System; using System.Drawing; using System.IO; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs b/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs index 9795bd93f..d2fe3b8c3 100644 --- a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.ExternalCommand/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.ExternalCommand { partial class SettingsForm { /// @@ -45,13 +48,13 @@ namespace Greenshot.Plugin.ExternalCommand { /// not be able to load this method if it was changed manually. /// private void InitializeComponent() { - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonOk = new GreenshotPlugin.Controls.GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.buttonOk = new GreenshotButton(); this.listView1 = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.button_new = new GreenshotPlugin.Controls.GreenshotButton(); - this.button_delete = new GreenshotPlugin.Controls.GreenshotButton(); - this.button_edit = new GreenshotPlugin.Controls.GreenshotButton(); + this.button_new = new GreenshotButton(); + this.button_delete = new GreenshotButton(); + this.button_edit = new GreenshotButton(); this.SuspendLayout(); // // buttonCancel @@ -146,13 +149,13 @@ namespace Greenshot.Plugin.ExternalCommand { this.ResumeLayout(false); } - private GreenshotPlugin.Controls.GreenshotButton button_edit; - private GreenshotPlugin.Controls.GreenshotButton button_delete; - private GreenshotPlugin.Controls.GreenshotButton button_new; + private GreenshotButton button_edit; + private GreenshotButton button_delete; + private GreenshotButton button_new; private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ListView listView1; - private GreenshotPlugin.Controls.GreenshotButton buttonOk; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; + private GreenshotButton buttonOk; + private GreenshotButton buttonCancel; } } diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.cs b/src/Greenshot.Plugin.ExternalCommand/SettingsForm.cs index 49e872d7f..5325173b5 100644 --- a/src/Greenshot.Plugin.ExternalCommand/SettingsForm.cs +++ b/src/Greenshot.Plugin.ExternalCommand/SettingsForm.cs @@ -22,7 +22,7 @@ using System; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.IniFile; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs b/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs index 11d8dc346..ea97436b1 100644 --- a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs +++ b/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.ExternalCommand { partial class SettingsFormDetail { /// @@ -46,16 +49,16 @@ namespace Greenshot.Plugin.ExternalCommand { /// private void InitializeComponent() { - this.buttonOk = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.groupBox1 = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.label4 = new GreenshotPlugin.Controls.GreenshotLabel(); + this.buttonOk = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.groupBox1 = new GreenshotGroupBox(); + this.label4 = new GreenshotLabel(); this.buttonPathSelect = new System.Windows.Forms.Button(); - this.label3 = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label3 = new GreenshotLabel(); this.textBox_name = new System.Windows.Forms.TextBox(); - this.label2 = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label2 = new GreenshotLabel(); this.textBox_arguments = new System.Windows.Forms.TextBox(); - this.label1 = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label1 = new GreenshotLabel(); this.textBox_commandline = new System.Windows.Forms.TextBox(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); @@ -184,13 +187,13 @@ namespace Greenshot.Plugin.ExternalCommand { this.ResumeLayout(false); } - private GreenshotPlugin.Controls.GreenshotLabel label1; - private GreenshotPlugin.Controls.GreenshotLabel label2; - private GreenshotPlugin.Controls.GreenshotLabel label3; - private GreenshotPlugin.Controls.GreenshotLabel label4; - private GreenshotPlugin.Controls.GreenshotGroupBox groupBox1; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOk; + private GreenshotLabel label1; + private GreenshotLabel label2; + private GreenshotLabel label3; + private GreenshotLabel label4; + private GreenshotGroupBox groupBox1; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOk; private System.Windows.Forms.TextBox textBox_commandline; private System.Windows.Forms.TextBox textBox_arguments; private System.Windows.Forms.TextBox textBox_name; diff --git a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.cs b/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.cs index 8aa235a67..c5551b291 100644 --- a/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.cs +++ b/src/Greenshot.Plugin.ExternalCommand/SettingsFormDetail.cs @@ -23,8 +23,8 @@ using System; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.ExternalCommand { diff --git a/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs b/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs index 68fc72a3e..5e4f6801f 100644 --- a/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs +++ b/src/Greenshot.Plugin.Flickr/FlickrConfiguration.cs @@ -20,9 +20,9 @@ */ using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Flickr.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Flickr { diff --git a/src/Greenshot.Plugin.Flickr/FlickrDestination.cs b/src/Greenshot.Plugin.Flickr/FlickrDestination.cs index ec61f3b62..2d432e929 100644 --- a/src/Greenshot.Plugin.Flickr/FlickrDestination.cs +++ b/src/Greenshot.Plugin.Flickr/FlickrDestination.cs @@ -21,8 +21,8 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.Flickr { diff --git a/src/Greenshot.Plugin.Flickr/FlickrPlugin.cs b/src/Greenshot.Plugin.Flickr/FlickrPlugin.cs index 0ce2afaad..25c9095b2 100644 --- a/src/Greenshot.Plugin.Flickr/FlickrPlugin.cs +++ b/src/Greenshot.Plugin.Flickr/FlickrPlugin.cs @@ -24,11 +24,11 @@ using System.ComponentModel; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using log4net; namespace Greenshot.Plugin.Flickr diff --git a/src/Greenshot.Plugin.Flickr/FlickrUtils.cs b/src/Greenshot.Plugin.Flickr/FlickrUtils.cs index 582484433..29a0417e9 100644 --- a/src/Greenshot.Plugin.Flickr/FlickrUtils.cs +++ b/src/Greenshot.Plugin.Flickr/FlickrUtils.cs @@ -23,11 +23,11 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Xml; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using log4net; namespace Greenshot.Plugin.Flickr diff --git a/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs b/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs index 0c8f4130e..0fe3dc300 100644 --- a/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs +++ b/src/Greenshot.Plugin.Flickr/Forms/FlickrForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.Flickr.Forms { diff --git a/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs index c58fe2720..95f7c653d 100644 --- a/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Flickr/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Flickr.Forms { partial class SettingsForm { /// @@ -46,18 +49,18 @@ namespace Greenshot.Plugin.Flickr.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkBoxPublic = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkBoxFamily = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkBoxFriend = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_SafetyLevel = new GreenshotPlugin.Controls.GreenshotLabel(); - this.combobox_safetyLevel = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkBox_hiddenfromsearch = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.checkBoxPublic = new GreenshotCheckBox(); + this.checkBoxFamily = new GreenshotCheckBox(); + this.checkBoxFriend = new GreenshotCheckBox(); + this.label_SafetyLevel = new GreenshotLabel(); + this.combobox_safetyLevel = new GreenshotComboBox(); + this.label_AfterUpload = new GreenshotLabel(); + this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox(); + this.checkBox_hiddenfromsearch = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -213,17 +216,17 @@ namespace Greenshot.Plugin.Flickr.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_hiddenfromsearch; - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxPublic; - private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxFamily; - private GreenshotPlugin.Controls.GreenshotCheckBox checkBoxFriend; - private GreenshotPlugin.Controls.GreenshotLabel label_SafetyLevel; - private GreenshotPlugin.Controls.GreenshotComboBox combobox_safetyLevel; - private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; + private GreenshotCheckBox checkBox_hiddenfromsearch; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotCheckBox checkBoxPublic; + private GreenshotCheckBox checkBoxFamily; + private GreenshotCheckBox checkBoxFriend; + private GreenshotLabel label_SafetyLevel; + private GreenshotComboBox combobox_safetyLevel; + private GreenshotLabel label_AfterUpload; + private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; } } diff --git a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj b/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj index b0acd56db..548307884 100644 --- a/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj +++ b/src/Greenshot.Plugin.Flickr/Greenshot.Plugin.Flickr.csproj @@ -10,6 +10,6 @@ - + \ No newline at end of file diff --git a/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs b/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs index 616398591..9936efcdc 100644 --- a/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs +++ b/src/Greenshot.Plugin.GooglePhotos/Forms/GooglePhotosForm.cs @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.GooglePhotos.Forms { diff --git a/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs index 6b95cbc46..dcc750f55 100644 --- a/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.GooglePhotos/Forms/SettingsForm.Designer.cs @@ -17,6 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.GooglePhotos.Forms { partial class SettingsForm { /// @@ -45,12 +48,12 @@ namespace Greenshot.Plugin.GooglePhotos.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.label_AfterUpload = new GreenshotLabel(); + this.checkboxAfterUploadLinkToClipBoard = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -137,11 +140,11 @@ namespace Greenshot.Plugin.GooglePhotos.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotLabel label_AfterUpload; + private GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; } } diff --git a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosConfiguration.cs b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosConfiguration.cs index 411cf6ba9..34285a7b3 100644 --- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosConfiguration.cs +++ b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosConfiguration.cs @@ -20,9 +20,9 @@ using System; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.GooglePhotos.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.GooglePhotos { diff --git a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosDestination.cs b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosDestination.cs index 8a66faef7..2080f49c2 100644 --- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosDestination.cs +++ b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosDestination.cs @@ -20,8 +20,8 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.GooglePhotos { diff --git a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.cs b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.cs index 91978b8ef..6c4d02b8f 100644 --- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.cs +++ b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosPlugin.cs @@ -23,11 +23,11 @@ using System.ComponentModel; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.GooglePhotos { diff --git a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosUtils.cs b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosUtils.cs index 2b4638839..1f225d895 100644 --- a/src/Greenshot.Plugin.GooglePhotos/GooglePhotosUtils.cs +++ b/src/Greenshot.Plugin.GooglePhotos/GooglePhotosUtils.cs @@ -20,11 +20,11 @@ using System; using System.Xml; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.GooglePhotos { diff --git a/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.csproj b/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.csproj index b15368c8e..a798964c1 100644 --- a/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.csproj +++ b/src/Greenshot.Plugin.GooglePhotos/Greenshot.Plugin.GooglePhotos.csproj @@ -10,6 +10,6 @@ - + \ No newline at end of file diff --git a/src/Greenshot.Plugin.Imgur/Forms/ImgurForm.cs b/src/Greenshot.Plugin.Imgur/Forms/ImgurForm.cs index c94f6d1eb..d80c94f92 100644 --- a/src/Greenshot.Plugin.Imgur/Forms/ImgurForm.cs +++ b/src/Greenshot.Plugin.Imgur/Forms/ImgurForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.Imgur.Forms { diff --git a/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.cs b/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.cs index 417f5e7d5..c2efa03f4 100644 --- a/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.cs +++ b/src/Greenshot.Plugin.Imgur/Forms/ImgurHistory.cs @@ -23,9 +23,9 @@ using System; using System.Globalization; using System.Text; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Imgur.Forms { diff --git a/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs index 175c55bb4..2df2be157 100644 --- a/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Imgur/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Imgur.Forms { partial class SettingsForm { /// @@ -46,13 +49,13 @@ namespace Greenshot.Plugin.Imgur.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.historyButton = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkbox_anonymous_access = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_usepagelink = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.historyButton = new GreenshotButton(); + this.checkbox_anonymous_access = new GreenshotCheckBox(); + this.checkbox_usepagelink = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -150,12 +153,12 @@ namespace Greenshot.Plugin.Imgur.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotButton historyButton; - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_anonymous_access; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usepagelink; + private GreenshotButton historyButton; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotCheckBox checkbox_anonymous_access; + private GreenshotCheckBox checkbox_usepagelink; } } diff --git a/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.csproj b/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.csproj index 170d0aedf..10a7fd241 100644 --- a/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.csproj +++ b/src/Greenshot.Plugin.Imgur/Greenshot.Plugin.Imgur.csproj @@ -6,6 +6,6 @@ - + \ No newline at end of file diff --git a/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs b/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs index fdac54ee3..f5af624ab 100644 --- a/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs +++ b/src/Greenshot.Plugin.Imgur/ImgurConfiguration.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Imgur.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Imgur { diff --git a/src/Greenshot.Plugin.Imgur/ImgurDestination.cs b/src/Greenshot.Plugin.Imgur/ImgurDestination.cs index a0d069f1a..cb747b9bf 100644 --- a/src/Greenshot.Plugin.Imgur/ImgurDestination.cs +++ b/src/Greenshot.Plugin.Imgur/ImgurDestination.cs @@ -21,8 +21,8 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.Imgur { diff --git a/src/Greenshot.Plugin.Imgur/ImgurPlugin.cs b/src/Greenshot.Plugin.Imgur/ImgurPlugin.cs index a936c80d7..400ebc0d8 100644 --- a/src/Greenshot.Plugin.Imgur/ImgurPlugin.cs +++ b/src/Greenshot.Plugin.Imgur/ImgurPlugin.cs @@ -25,12 +25,12 @@ using System.ComponentModel; using System.Drawing; using System.IO; using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Imgur.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Imgur { diff --git a/src/Greenshot.Plugin.Imgur/ImgurUtils.cs b/src/Greenshot.Plugin.Imgur/ImgurUtils.cs index 32b83d6e3..4ec67bd9b 100644 --- a/src/Greenshot.Plugin.Imgur/ImgurUtils.cs +++ b/src/Greenshot.Plugin.Imgur/ImgurUtils.cs @@ -24,11 +24,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Imgur { diff --git a/src/Greenshot.Plugin.Jira/Forms/JiraForm.cs b/src/Greenshot.Plugin.Jira/Forms/JiraForm.cs index 6eb143889..44b97cc43 100644 --- a/src/Greenshot.Plugin.Jira/Forms/JiraForm.cs +++ b/src/Greenshot.Plugin.Jira/Forms/JiraForm.cs @@ -26,9 +26,9 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using Dapplo.Jira.Entities; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Jira.Forms { diff --git a/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs b/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs index 21ab33509..072290ac7 100644 --- a/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs +++ b/src/Greenshot.Plugin.Jira/Forms/JiraFormBase.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Plugin.Jira.Forms { diff --git a/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs index 3e18edb8e..39af09f68 100644 --- a/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Jira/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Jira.Forms { partial class SettingsForm { /// @@ -46,12 +49,12 @@ namespace Greenshot.Plugin.Jira.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.label_url = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textBoxUrl = new GreenshotPlugin.Controls.GreenshotTextBox(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.label_url = new GreenshotLabel(); + this.textBoxUrl = new GreenshotTextBox(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); this.SuspendLayout(); // // buttonOK @@ -136,11 +139,11 @@ namespace Greenshot.Plugin.Jira.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotTextBox textBoxUrl; - private GreenshotPlugin.Controls.GreenshotLabel label_url; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotTextBox textBoxUrl; + private GreenshotLabel label_url; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; } } diff --git a/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj b/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj index cda65dc2f..5d8fde23f 100644 --- a/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj +++ b/src/Greenshot.Plugin.Jira/Greenshot.Plugin.Jira.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/Greenshot.Plugin.Jira/JiraConfiguration.cs b/src/Greenshot.Plugin.Jira/JiraConfiguration.cs index cce59453b..64901f3d7 100644 --- a/src/Greenshot.Plugin.Jira/JiraConfiguration.cs +++ b/src/Greenshot.Plugin.Jira/JiraConfiguration.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Jira { diff --git a/src/Greenshot.Plugin.Jira/JiraConnector.cs b/src/Greenshot.Plugin.Jira/JiraConnector.cs index e25c4fb75..9f9b88835 100644 --- a/src/Greenshot.Plugin.Jira/JiraConnector.cs +++ b/src/Greenshot.Plugin.Jira/JiraConnector.cs @@ -31,8 +31,8 @@ using Dapplo.HttpExtensions.Extensions; using Dapplo.Jira; using Dapplo.Jira.Entities; using Dapplo.Jira.SvgWinForms.Converters; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Jira { diff --git a/src/Greenshot.Plugin.Jira/JiraDestination.cs b/src/Greenshot.Plugin.Jira/JiraDestination.cs index 2dd871cf3..8b283642e 100644 --- a/src/Greenshot.Plugin.Jira/JiraDestination.cs +++ b/src/Greenshot.Plugin.Jira/JiraDestination.cs @@ -27,12 +27,12 @@ using System.IO; using System.Windows.Forms; using Dapplo.HttpExtensions; using Dapplo.Jira.Entities; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Jira.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Jira { diff --git a/src/Greenshot.Plugin.Jira/JiraMonitor.cs b/src/Greenshot.Plugin.Jira/JiraMonitor.cs index 43a5e5487..3ccc84a45 100644 --- a/src/Greenshot.Plugin.Jira/JiraMonitor.cs +++ b/src/Greenshot.Plugin.Jira/JiraMonitor.cs @@ -27,7 +27,7 @@ using System.Threading; using System.Threading.Tasks; using Dapplo.Jira; using Dapplo.Log; -using GreenshotPlugin.Hooking; +using Greenshot.Base.Hooking; namespace Greenshot.Plugin.Jira { diff --git a/src/Greenshot.Plugin.Jira/JiraPlugin.cs b/src/Greenshot.Plugin.Jira/JiraPlugin.cs index e00f0263d..de10ba163 100644 --- a/src/Greenshot.Plugin.Jira/JiraPlugin.cs +++ b/src/Greenshot.Plugin.Jira/JiraPlugin.cs @@ -23,11 +23,11 @@ using System; using System.Threading.Tasks; using System.Windows.Forms; using Dapplo.Log; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Jira.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using log4net; namespace Greenshot.Plugin.Jira diff --git a/src/Greenshot.Plugin.Office/Com/Ole32Api.cs b/src/Greenshot.Plugin.Office/Com/Ole32Api.cs index efbf3614b..07d807ee2 100644 --- a/src/Greenshot.Plugin.Office/Com/Ole32Api.cs +++ b/src/Greenshot.Plugin.Office/Com/Ole32Api.cs @@ -3,8 +3,8 @@ using System; using System.Runtime.InteropServices; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.Core.Enums; namespace Greenshot.Plugin.Office.Com { diff --git a/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs b/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs index 534f8a274..c32b11a19 100644 --- a/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs +++ b/src/Greenshot.Plugin.Office/Com/OleAut32Api.cs @@ -3,8 +3,8 @@ using System; using System.Runtime.InteropServices; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.Core.Enums; namespace Greenshot.Plugin.Office.Com { diff --git a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs index 5df550775..4aeceb12d 100644 --- a/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/ExcelDestination.cs @@ -23,10 +23,10 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Text.RegularExpressions; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.OfficeExport; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Office.Destinations { diff --git a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs index 578f357fb..33f23b58b 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OneNoteDestination.cs @@ -23,10 +23,10 @@ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using Greenshot.Plugin.Office.OfficeExport; using Greenshot.Plugin.Office.OfficeExport.Entities; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; namespace Greenshot.Plugin.Office.Destinations { diff --git a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs index ae80b6f1e..bfc78dd2f 100644 --- a/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/OutlookDestination.cs @@ -24,11 +24,11 @@ using System.Drawing; using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.OfficeExport; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using Microsoft.Office.Interop.Outlook; using Microsoft.Win32; diff --git a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs index bb5a0c453..6e3c22f36 100644 --- a/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/PowerpointDestination.cs @@ -24,10 +24,10 @@ using System.Drawing; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.OfficeExport; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Office.Destinations { diff --git a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs index ff9945824..f6d448505 100644 --- a/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs +++ b/src/Greenshot.Plugin.Office/Destinations/WordDestination.cs @@ -25,10 +25,10 @@ using System.Drawing; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.OfficeExport; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Office.Destinations { diff --git a/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj b/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj index 2ca43d6fe..0e7d00d67 100644 --- a/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj +++ b/src/Greenshot.Plugin.Office/Greenshot.Plugin.Office.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/Greenshot.Plugin.Office/OfficeConfiguration.cs b/src/Greenshot.Plugin.Office/OfficeConfiguration.cs index f2959aa34..897075806 100644 --- a/src/Greenshot.Plugin.Office/OfficeConfiguration.cs +++ b/src/Greenshot.Plugin.Office/OfficeConfiguration.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ +using Greenshot.Base.IniFile; using Greenshot.Plugin.Office.OfficeInterop; -using GreenshotPlugin.IniFile; using Microsoft.Office.Interop.PowerPoint; namespace Greenshot.Plugin.Office diff --git a/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs b/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs index 4455bfd73..e725439da 100644 --- a/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs +++ b/src/Greenshot.Plugin.Office/OfficeExport/ExcelExporter.cs @@ -20,9 +20,9 @@ using System; using System.Collections.Generic; using System.Drawing; +using Greenshot.Base.UnmanagedHelpers; using Greenshot.Plugin.Office.Com; using Greenshot.Plugin.Office.OfficeInterop; -using GreenshotPlugin.UnmanagedHelpers; using Microsoft.Office.Core; using Microsoft.Office.Interop.Excel; using Version = System.Version; diff --git a/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs b/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs index f42622356..68fcf2f6b 100644 --- a/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs +++ b/src/Greenshot.Plugin.Office/OfficeExport/OneNoteExporter.cs @@ -22,11 +22,11 @@ using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Xml; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.Com; using Greenshot.Plugin.Office.OfficeExport.Entities; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using Microsoft.Office.Interop.OneNote; namespace Greenshot.Plugin.Office.OfficeExport diff --git a/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs b/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs index 55cad605e..ab3db1fdb 100644 --- a/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs +++ b/src/Greenshot.Plugin.Office/OfficeExport/OutlookEmailExporter.cs @@ -21,9 +21,9 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Office.Com; using Greenshot.Plugin.Office.OfficeInterop; -using GreenshotPlugin.IniFile; using Microsoft.Office.Interop.Outlook; using Microsoft.Office.Interop.Word; using Microsoft.Win32; diff --git a/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs b/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs index c2bc7e2b3..1b76f54bf 100644 --- a/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs +++ b/src/Greenshot.Plugin.Office/OfficeExport/PowerpointExporter.cs @@ -20,9 +20,9 @@ using System; using System.Collections.Generic; using System.Drawing; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Office.Com; using Greenshot.Plugin.Office.OfficeInterop; -using GreenshotPlugin.IniFile; using Microsoft.Office.Core; using Microsoft.Office.Interop.PowerPoint; using Shape = Microsoft.Office.Interop.PowerPoint.Shape; diff --git a/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs b/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs index 0cef0c696..d4da1cc3a 100644 --- a/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs +++ b/src/Greenshot.Plugin.Office/OfficeExport/WordExporter.cs @@ -19,9 +19,9 @@ using System; using System.Collections.Generic; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Office.Com; using Greenshot.Plugin.Office.OfficeInterop; -using GreenshotPlugin.IniFile; using Microsoft.Office.Core; using Microsoft.Office.Interop.Word; using Version = System.Version; diff --git a/src/Greenshot.Plugin.Office/OfficePlugin.cs b/src/Greenshot.Plugin.Office/OfficePlugin.cs index c7e75afcd..bfb10bfa0 100644 --- a/src/Greenshot.Plugin.Office/OfficePlugin.cs +++ b/src/Greenshot.Plugin.Office/OfficePlugin.cs @@ -21,10 +21,10 @@ using System; using System.Collections.Generic; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Office.Destinations; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Office { diff --git a/src/Greenshot.Plugin.Photobucket/Forms/PhotobucketForm.cs b/src/Greenshot.Plugin.Photobucket/Forms/PhotobucketForm.cs index 6bf170ca5..99f8150b0 100644 --- a/src/Greenshot.Plugin.Photobucket/Forms/PhotobucketForm.cs +++ b/src/Greenshot.Plugin.Photobucket/Forms/PhotobucketForm.cs @@ -19,12 +19,14 @@ * along with this program. If not, see . */ +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Photobucket.Forms { /// /// This class is needed for design-time resolving of the language files /// - public class PhotobucketForm : GreenshotPlugin.Controls.GreenshotForm + public class PhotobucketForm : GreenshotForm { } } \ No newline at end of file diff --git a/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs b/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs index 85d3a588b..5e1910690 100644 --- a/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot.Plugin.Photobucket/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Plugin.Photobucket.Forms { partial class SettingsForm { /// @@ -46,11 +49,11 @@ namespace Greenshot.Plugin.Photobucket.Forms { /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkbox_usepagelink = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotComboBox(); + this.label_upload_format = new GreenshotLabel(); + this.checkbox_usepagelink = new GreenshotCheckBox(); this.SuspendLayout(); // // buttonOK @@ -124,10 +127,10 @@ namespace Greenshot.Plugin.Photobucket.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usepagelink; + private GreenshotComboBox combobox_uploadimageformat; + private GreenshotLabel label_upload_format; + private GreenshotButton buttonCancel; + private GreenshotButton buttonOK; + private GreenshotCheckBox checkbox_usepagelink; } } diff --git a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj b/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj index bb0b57ef0..cc3d98fb9 100644 --- a/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj +++ b/src/Greenshot.Plugin.Photobucket/Greenshot.Plugin.Photobucket.csproj @@ -6,6 +6,6 @@ - + diff --git a/src/Greenshot.Plugin.Photobucket/PhotobucketConfiguration.cs b/src/Greenshot.Plugin.Photobucket/PhotobucketConfiguration.cs index 4c1c976d2..0600448f9 100644 --- a/src/Greenshot.Plugin.Photobucket/PhotobucketConfiguration.cs +++ b/src/Greenshot.Plugin.Photobucket/PhotobucketConfiguration.cs @@ -20,10 +20,10 @@ */ using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Plugin.Photobucket.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; namespace Greenshot.Plugin.Photobucket { diff --git a/src/Greenshot.Plugin.Photobucket/PhotobucketDestination.cs b/src/Greenshot.Plugin.Photobucket/PhotobucketDestination.cs index 34bffa89b..2d10b0864 100644 --- a/src/Greenshot.Plugin.Photobucket/PhotobucketDestination.cs +++ b/src/Greenshot.Plugin.Photobucket/PhotobucketDestination.cs @@ -22,8 +22,8 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; namespace Greenshot.Plugin.Photobucket { diff --git a/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.cs b/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.cs index 394707897..fb86aeb93 100644 --- a/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.cs +++ b/src/Greenshot.Plugin.Photobucket/PhotobucketPlugin.cs @@ -24,11 +24,11 @@ using System.ComponentModel; using System.Drawing; using System.IO; using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Photobucket { diff --git a/src/Greenshot.Plugin.Photobucket/PhotobucketUtils.cs b/src/Greenshot.Plugin.Photobucket/PhotobucketUtils.cs index 61a61f8a3..c149f1cc0 100644 --- a/src/Greenshot.Plugin.Photobucket/PhotobucketUtils.cs +++ b/src/Greenshot.Plugin.Photobucket/PhotobucketUtils.cs @@ -24,11 +24,11 @@ using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Xml; -using GreenshotPlugin.Core; -using GreenshotPlugin.Core.OAuth; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Core.OAuth; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Photobucket { diff --git a/src/Greenshot.Plugin.Win10/Destinations/Win10OcrDestination.cs b/src/Greenshot.Plugin.Win10/Destinations/Win10OcrDestination.cs index cc119b70d..9492a2dfa 100644 --- a/src/Greenshot.Plugin.Win10/Destinations/Win10OcrDestination.cs +++ b/src/Greenshot.Plugin.Win10/Destinations/Win10OcrDestination.cs @@ -23,9 +23,9 @@ using System; using System.Drawing; using System.Threading.Tasks; using Windows.Media.Ocr; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; namespace Greenshot.Plugin.Win10.Destinations { diff --git a/src/Greenshot.Plugin.Win10/Destinations/Win10ShareDestination.cs b/src/Greenshot.Plugin.Win10/Destinations/Win10ShareDestination.cs index e8178a8cf..b1be32d61 100644 --- a/src/Greenshot.Plugin.Win10/Destinations/Win10ShareDestination.cs +++ b/src/Greenshot.Plugin.Win10/Destinations/Win10ShareDestination.cs @@ -29,12 +29,12 @@ using System.Windows.Interop; using System.Windows.Media; using Windows.Storage; using Windows.Storage.Streams; +using Greenshot.Base.Core; +using Greenshot.Base.Hooking; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Win10.Internal; using Greenshot.Plugin.Win10.Native; -using GreenshotPlugin.Core; -using GreenshotPlugin.Hooking; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using Color = Windows.UI.Color; namespace Greenshot.Plugin.Win10.Destinations diff --git a/src/Greenshot.Plugin.Win10/Greenshot.Plugin.Win10.csproj b/src/Greenshot.Plugin.Win10/Greenshot.Plugin.Win10.csproj index bd79af992..182da73b6 100644 --- a/src/Greenshot.Plugin.Win10/Greenshot.Plugin.Win10.csproj +++ b/src/Greenshot.Plugin.Win10/Greenshot.Plugin.Win10.csproj @@ -9,6 +9,6 @@ - + diff --git a/src/Greenshot.Plugin.Win10/Native/DataTransferManagerHelper.cs b/src/Greenshot.Plugin.Win10/Native/DataTransferManagerHelper.cs index 9f2540694..15b70639f 100644 --- a/src/Greenshot.Plugin.Win10/Native/DataTransferManagerHelper.cs +++ b/src/Greenshot.Plugin.Win10/Native/DataTransferManagerHelper.cs @@ -22,7 +22,7 @@ using System; using System.Runtime.InteropServices.WindowsRuntime; using Windows.ApplicationModel.DataTransfer; -using GreenshotPlugin.Core; +using Greenshot.Base.Core; namespace Greenshot.Plugin.Win10.Native { diff --git a/src/Greenshot.Plugin.Win10/Native/IDataTransferManagerInterOp.cs b/src/Greenshot.Plugin.Win10/Native/IDataTransferManagerInterOp.cs index 8bdba3366..1cdfa14de 100644 --- a/src/Greenshot.Plugin.Win10/Native/IDataTransferManagerInterOp.cs +++ b/src/Greenshot.Plugin.Win10/Native/IDataTransferManagerInterOp.cs @@ -20,7 +20,7 @@ using System; using System.Runtime.InteropServices; using Windows.ApplicationModel.DataTransfer; -using GreenshotPlugin.Core.Enums; +using Greenshot.Base.Core.Enums; namespace Greenshot.Plugin.Win10.Native { diff --git a/src/Greenshot.Plugin.Win10/Processors/Win10OcrProcessor.cs b/src/Greenshot.Plugin.Win10/Processors/Win10OcrProcessor.cs index cfbf88d18..45f511d93 100644 --- a/src/Greenshot.Plugin.Win10/Processors/Win10OcrProcessor.cs +++ b/src/Greenshot.Plugin.Win10/Processors/Win10OcrProcessor.cs @@ -20,10 +20,10 @@ */ using System.Threading.Tasks; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; namespace Greenshot.Plugin.Win10.Processors { diff --git a/src/Greenshot.Plugin.Win10/ToastNotificationService.cs b/src/Greenshot.Plugin.Win10/ToastNotificationService.cs index eea987802..1da804c7a 100644 --- a/src/Greenshot.Plugin.Win10/ToastNotificationService.cs +++ b/src/Greenshot.Plugin.Win10/ToastNotificationService.cs @@ -25,9 +25,9 @@ using System.IO; using Windows.Foundation.Collections; using Windows.Foundation.Metadata; using Windows.UI.Notifications; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using log4net; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/src/Greenshot.Plugin.Win10/Win10Configuration.cs b/src/Greenshot.Plugin.Win10/Win10Configuration.cs index bbd1ff35e..acd1238ea 100644 --- a/src/Greenshot.Plugin.Win10/Win10Configuration.cs +++ b/src/Greenshot.Plugin.Win10/Win10Configuration.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.IniFile; +using Greenshot.Base.IniFile; namespace Greenshot.Plugin.Win10 { diff --git a/src/Greenshot.Plugin.Win10/Win10OcrProvider.cs b/src/Greenshot.Plugin.Win10/Win10OcrProvider.cs index e6feb8193..7611499f2 100644 --- a/src/Greenshot.Plugin.Win10/Win10OcrProvider.cs +++ b/src/Greenshot.Plugin.Win10/Win10OcrProvider.cs @@ -26,10 +26,10 @@ using System.Threading.Tasks; using Windows.Graphics.Imaging; using Windows.Media.Ocr; using Windows.Storage.Streams; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Plugin.Win10 { diff --git a/src/Greenshot.Plugin.Win10/Win10Plugin.cs b/src/Greenshot.Plugin.Win10/Win10Plugin.cs index 25d8d048e..aa3342ead 100644 --- a/src/Greenshot.Plugin.Win10/Win10Plugin.cs +++ b/src/Greenshot.Plugin.Win10/Win10Plugin.cs @@ -20,12 +20,12 @@ */ using System; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Plugin.Win10.Destinations; using Greenshot.Plugin.Win10.Processors; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; -using GreenshotPlugin.Interfaces.Plugin; namespace Greenshot.Plugin.Win10 { diff --git a/src/Greenshot.sln b/src/Greenshot.sln index 40b3169b4..daabf8cf2 100644 --- a/src/Greenshot.sln +++ b/src/Greenshot.sln @@ -18,7 +18,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Gree {1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Base", "Greenshot.Base\Greenshot.Base.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Plugin.ExternalCommand", "Greenshot.Plugin.ExternalCommand\Greenshot.Plugin.ExternalCommand.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}" EndProject diff --git a/src/Greenshot/Configuration/EditorConfiguration.cs b/src/Greenshot/Configuration/EditorConfiguration.cs index 97856f5d0..b16c7804d 100644 --- a/src/Greenshot/Configuration/EditorConfiguration.cs +++ b/src/Greenshot/Configuration/EditorConfiguration.cs @@ -22,12 +22,12 @@ using System; using System.Collections.Generic; using System.Drawing; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Structs; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces.Drawing; -using GreenshotPlugin.UnmanagedHelpers.Enums; -using GreenshotPlugin.UnmanagedHelpers.Structs; namespace Greenshot.Configuration { diff --git a/src/Greenshot/Controls/BindableToolStripButton.cs b/src/Greenshot/Controls/BindableToolStripButton.cs index 37088476a..51dfe9538 100644 --- a/src/Greenshot/Controls/BindableToolStripButton.cs +++ b/src/Greenshot/Controls/BindableToolStripButton.cs @@ -22,7 +22,7 @@ using System; using System.ComponentModel; using System.Windows.Forms; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Controls { diff --git a/src/Greenshot/Controls/BindableToolStripComboBox.cs b/src/Greenshot/Controls/BindableToolStripComboBox.cs index b0f87cff8..9f767b1fa 100644 --- a/src/Greenshot/Controls/BindableToolStripComboBox.cs +++ b/src/Greenshot/Controls/BindableToolStripComboBox.cs @@ -22,7 +22,7 @@ using System; using System.ComponentModel; using System.Windows.Forms; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Controls { diff --git a/src/Greenshot/Controls/BindableToolStripDropDownButton.cs b/src/Greenshot/Controls/BindableToolStripDropDownButton.cs index 428b66bb3..04c1a3ee0 100644 --- a/src/Greenshot/Controls/BindableToolStripDropDownButton.cs +++ b/src/Greenshot/Controls/BindableToolStripDropDownButton.cs @@ -21,7 +21,7 @@ using System.ComponentModel; using System.Windows.Forms; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Controls { diff --git a/src/Greenshot/Controls/ColorButton.cs b/src/Greenshot/Controls/ColorButton.cs index 068033522..2c762e216 100644 --- a/src/Greenshot/Controls/ColorButton.cs +++ b/src/Greenshot/Controls/ColorButton.cs @@ -24,7 +24,7 @@ using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; using ColorDialog = Greenshot.Forms.ColorDialog; namespace Greenshot.Controls diff --git a/src/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs b/src/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs index e85817d7f..b1229a293 100644 --- a/src/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs +++ b/src/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs @@ -19,10 +19,10 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Controls { diff --git a/src/Greenshot/Controls/MenuStripEx.cs b/src/Greenshot/Controls/MenuStripEx.cs index 34f1d168a..a9c92f2a6 100644 --- a/src/Greenshot/Controls/MenuStripEx.cs +++ b/src/Greenshot/Controls/MenuStripEx.cs @@ -21,7 +21,7 @@ using System; using System.Windows.Forms; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.UnmanagedHelpers.Enums; namespace Greenshot.Controls { diff --git a/src/Greenshot/Controls/Pipette.cs b/src/Greenshot/Controls/Pipette.cs index d4636b017..32c07459e 100644 --- a/src/Greenshot/Controls/Pipette.cs +++ b/src/Greenshot/Controls/Pipette.cs @@ -23,9 +23,9 @@ using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; using Greenshot.Forms; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.UnmanagedHelpers.Enums; using ColorDialog = Greenshot.Forms.ColorDialog; namespace Greenshot.Controls diff --git a/src/Greenshot/Controls/ToolStripColorButton.cs b/src/Greenshot/Controls/ToolStripColorButton.cs index ffc2606f5..1e21d2725 100644 --- a/src/Greenshot/Controls/ToolStripColorButton.cs +++ b/src/Greenshot/Controls/ToolStripColorButton.cs @@ -24,7 +24,7 @@ using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; using ColorDialog = Greenshot.Forms.ColorDialog; namespace Greenshot.Controls diff --git a/src/Greenshot/Destinations/ClipboardDestination.cs b/src/Greenshot/Destinations/ClipboardDestination.cs index 88a2e2ecb..3946be901 100644 --- a/src/Greenshot/Destinations/ClipboardDestination.cs +++ b/src/Greenshot/Destinations/ClipboardDestination.cs @@ -22,9 +22,9 @@ using System; using System.Drawing; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; namespace Greenshot.Destinations { diff --git a/src/Greenshot/Destinations/EditorDestination.cs b/src/Greenshot/Destinations/EditorDestination.cs index b22cc0894..ba74a70ca 100644 --- a/src/Greenshot/Destinations/EditorDestination.cs +++ b/src/Greenshot/Destinations/EditorDestination.cs @@ -22,12 +22,12 @@ using System; using System.Collections.Generic; using System.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Forms; using Greenshot.Configuration; using Greenshot.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Forms; using log4net; namespace Greenshot.Destinations diff --git a/src/Greenshot/Destinations/EmailDestination.cs b/src/Greenshot/Destinations/EmailDestination.cs index c8e99b870..b3f546f34 100644 --- a/src/Greenshot/Destinations/EmailDestination.cs +++ b/src/Greenshot/Destinations/EmailDestination.cs @@ -22,10 +22,10 @@ using System; using System.Drawing; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; using Greenshot.Helpers; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; using Microsoft.Win32; namespace Greenshot.Destinations diff --git a/src/Greenshot/Destinations/FileDestination.cs b/src/Greenshot/Destinations/FileDestination.cs index 95365677a..cf0c4ed28 100644 --- a/src/Greenshot/Destinations/FileDestination.cs +++ b/src/Greenshot/Destinations/FileDestination.cs @@ -23,13 +23,13 @@ using System; using System.Drawing; using System.IO; using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Configuration; using Greenshot.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Controls; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using log4net; namespace Greenshot.Destinations diff --git a/src/Greenshot/Destinations/FileWithDialogDestination.cs b/src/Greenshot/Destinations/FileWithDialogDestination.cs index 02c5e9bd4..b17659da0 100644 --- a/src/Greenshot/Destinations/FileWithDialogDestination.cs +++ b/src/Greenshot/Destinations/FileWithDialogDestination.cs @@ -21,10 +21,10 @@ using System.Drawing; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; namespace Greenshot.Destinations { diff --git a/src/Greenshot/Destinations/PickerDestination.cs b/src/Greenshot/Destinations/PickerDestination.cs index 2195e1d6b..654726e6a 100644 --- a/src/Greenshot/Destinations/PickerDestination.cs +++ b/src/Greenshot/Destinations/PickerDestination.cs @@ -20,9 +20,9 @@ */ using System.Collections.Generic; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; namespace Greenshot.Destinations { diff --git a/src/Greenshot/Destinations/PrinterDestination.cs b/src/Greenshot/Destinations/PrinterDestination.cs index 09b51880c..7be51bbff 100644 --- a/src/Greenshot/Destinations/PrinterDestination.cs +++ b/src/Greenshot/Destinations/PrinterDestination.cs @@ -24,10 +24,10 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; -using GreenshotPlugin.Core; using Greenshot.Helpers; -using GreenshotPlugin.Interfaces; namespace Greenshot.Destinations { diff --git a/src/Greenshot/Drawing/Adorners/AbstractAdorner.cs b/src/Greenshot/Drawing/Adorners/AbstractAdorner.cs index 19f531a5c..37057d428 100644 --- a/src/Greenshot/Drawing/Adorners/AbstractAdorner.cs +++ b/src/Greenshot/Drawing/Adorners/AbstractAdorner.cs @@ -22,9 +22,9 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Drawing; -using GreenshotPlugin.Interfaces.Drawing.Adorners; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing.Adorners; namespace Greenshot.Drawing.Adorners { diff --git a/src/Greenshot/Drawing/Adorners/MoveAdorner.cs b/src/Greenshot/Drawing/Adorners/MoveAdorner.cs index 73c75141c..9116ff3cf 100644 --- a/src/Greenshot/Drawing/Adorners/MoveAdorner.cs +++ b/src/Greenshot/Drawing/Adorners/MoveAdorner.cs @@ -23,7 +23,7 @@ using Greenshot.Helpers; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Adorners { diff --git a/src/Greenshot/Drawing/Adorners/ResizeAdorner.cs b/src/Greenshot/Drawing/Adorners/ResizeAdorner.cs index b6480180d..38c1eb9af 100644 --- a/src/Greenshot/Drawing/Adorners/ResizeAdorner.cs +++ b/src/Greenshot/Drawing/Adorners/ResizeAdorner.cs @@ -23,7 +23,7 @@ using Greenshot.Helpers; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Adorners { diff --git a/src/Greenshot/Drawing/Adorners/TargetAdorner.cs b/src/Greenshot/Drawing/Adorners/TargetAdorner.cs index 546606b66..2569ae8c3 100644 --- a/src/Greenshot/Drawing/Adorners/TargetAdorner.cs +++ b/src/Greenshot/Drawing/Adorners/TargetAdorner.cs @@ -22,7 +22,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Adorners { diff --git a/src/Greenshot/Drawing/ArrowContainer.cs b/src/Greenshot/Drawing/ArrowContainer.cs index a49ffe863..eaed428f0 100644 --- a/src/Greenshot/Drawing/ArrowContainer.cs +++ b/src/Greenshot/Drawing/ArrowContainer.cs @@ -22,8 +22,8 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/CropContainer.cs b/src/Greenshot/Drawing/CropContainer.cs index 164fd791e..6c89f37d4 100644 --- a/src/Greenshot/Drawing/CropContainer.cs +++ b/src/Greenshot/Drawing/CropContainer.cs @@ -21,9 +21,9 @@ using System.Drawing; using System.Runtime.Serialization; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Helpers; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/CursorContainer.cs b/src/Greenshot/Drawing/CursorContainer.cs index d22b5d672..c961c4d22 100644 --- a/src/Greenshot/Drawing/CursorContainer.cs +++ b/src/Greenshot/Drawing/CursorContainer.cs @@ -26,7 +26,7 @@ using System.Windows.Forms; using System.Drawing.Drawing2D; using log4net; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/DrawableContainer.cs b/src/Greenshot/Drawing/DrawableContainer.cs index 96ef93b9c..4e710e6be 100644 --- a/src/Greenshot/Drawing/DrawableContainer.cs +++ b/src/Greenshot/Drawing/DrawableContainer.cs @@ -25,7 +25,6 @@ using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; using Greenshot.Helpers; using Greenshot.Memento; -using GreenshotPlugin.Interfaces.Drawing; using log4net; using System; using System.Collections.Generic; @@ -34,9 +33,10 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Runtime.Serialization; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Drawing.Adorners; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing.Adorners; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/DrawableContainerList.cs b/src/Greenshot/Drawing/DrawableContainerList.cs index c450ebad4..8dc490013 100644 --- a/src/Greenshot/Drawing/DrawableContainerList.cs +++ b/src/Greenshot/Drawing/DrawableContainerList.cs @@ -21,8 +21,6 @@ using Greenshot.Configuration; using Greenshot.Memento; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Drawing; using System; using System.Collections.Generic; using System.ComponentModel; @@ -30,8 +28,10 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Threading; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Forms; -using GreenshotPlugin.Interfaces; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/EllipseContainer.cs b/src/Greenshot/Drawing/EllipseContainer.cs index 091c03b17..466cf7a77 100644 --- a/src/Greenshot/Drawing/EllipseContainer.cs +++ b/src/Greenshot/Drawing/EllipseContainer.cs @@ -22,9 +22,9 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Helpers; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/Fields/AbstractFieldHolder.cs b/src/Greenshot/Drawing/Fields/AbstractFieldHolder.cs index f4bc0377f..391299d86 100644 --- a/src/Greenshot/Drawing/Fields/AbstractFieldHolder.cs +++ b/src/Greenshot/Drawing/Fields/AbstractFieldHolder.cs @@ -24,10 +24,10 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Runtime.Serialization; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Configuration; -using GreenshotPlugin.IniFile; using log4net; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing.Fields { diff --git a/src/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs b/src/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs index 979a80168..9e0593280 100644 --- a/src/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs +++ b/src/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs @@ -19,10 +19,10 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Interfaces.Drawing; using System; using System.Collections.Generic; using System.Runtime.Serialization; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Fields { diff --git a/src/Greenshot/Drawing/Fields/Field.cs b/src/Greenshot/Drawing/Fields/Field.cs index e58de2122..280c3a519 100644 --- a/src/Greenshot/Drawing/Fields/Field.cs +++ b/src/Greenshot/Drawing/Fields/Field.cs @@ -19,9 +19,9 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Interfaces.Drawing; using System; using System.ComponentModel; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Fields { diff --git a/src/Greenshot/Drawing/Fields/FieldAggregator.cs b/src/Greenshot/Drawing/Fields/FieldAggregator.cs index 39f859503..cda039956 100644 --- a/src/Greenshot/Drawing/Fields/FieldAggregator.cs +++ b/src/Greenshot/Drawing/Fields/FieldAggregator.cs @@ -21,12 +21,12 @@ using System; using Greenshot.Configuration; -using GreenshotPlugin.Interfaces.Drawing; using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Fields { diff --git a/src/Greenshot/Drawing/Fields/FieldType.cs b/src/Greenshot/Drawing/Fields/FieldType.cs index 3e6711898..accd72d4b 100644 --- a/src/Greenshot/Drawing/Fields/FieldType.cs +++ b/src/Greenshot/Drawing/Fields/FieldType.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Interfaces.Drawing; using System; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Fields { diff --git a/src/Greenshot/Drawing/FilterContainer.cs b/src/Greenshot/Drawing/FilterContainer.cs index 93e3352c9..e58363024 100644 --- a/src/Greenshot/Drawing/FilterContainer.cs +++ b/src/Greenshot/Drawing/FilterContainer.cs @@ -25,7 +25,7 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; using System.Drawing.Drawing2D; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/Filters/AbstractFilter.cs b/src/Greenshot/Drawing/Filters/AbstractFilter.cs index 1608fd866..1152956a0 100644 --- a/src/Greenshot/Drawing/Filters/AbstractFilter.cs +++ b/src/Greenshot/Drawing/Filters/AbstractFilter.cs @@ -22,8 +22,8 @@ using System; using System.ComponentModel; using System.Drawing; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/BlurFilter.cs b/src/Greenshot/Drawing/Filters/BlurFilter.cs index 9b8c5d0f9..698ffce4b 100644 --- a/src/Greenshot/Drawing/Filters/BlurFilter.cs +++ b/src/Greenshot/Drawing/Filters/BlurFilter.cs @@ -22,10 +22,10 @@ using System; using System.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers; using System.Drawing.Drawing2D; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.UnmanagedHelpers; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/BrightnessFilter.cs b/src/Greenshot/Drawing/Filters/BrightnessFilter.cs index cba712bbe..4a02e9a7c 100644 --- a/src/Greenshot/Drawing/Filters/BrightnessFilter.cs +++ b/src/Greenshot/Drawing/Filters/BrightnessFilter.cs @@ -22,10 +22,10 @@ using System; using System.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Core; using System.Drawing.Imaging; using System.Drawing.Drawing2D; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/GrayscaleFilter.cs b/src/Greenshot/Drawing/Filters/GrayscaleFilter.cs index 2565999a9..43d8d44c2 100644 --- a/src/Greenshot/Drawing/Filters/GrayscaleFilter.cs +++ b/src/Greenshot/Drawing/Filters/GrayscaleFilter.cs @@ -21,10 +21,10 @@ using System; using System.Drawing; -using GreenshotPlugin.Core; using System.Drawing.Drawing2D; using System.Drawing.Imaging; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/HighlightFilter.cs b/src/Greenshot/Drawing/Filters/HighlightFilter.cs index e311293c5..04542575e 100644 --- a/src/Greenshot/Drawing/Filters/HighlightFilter.cs +++ b/src/Greenshot/Drawing/Filters/HighlightFilter.cs @@ -22,9 +22,9 @@ using System; using System.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Core; using System.Drawing.Drawing2D; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/IFilter.cs b/src/Greenshot/Drawing/Filters/IFilter.cs index bbf255dd1..41e634880 100644 --- a/src/Greenshot/Drawing/Filters/IFilter.cs +++ b/src/Greenshot/Drawing/Filters/IFilter.cs @@ -21,7 +21,7 @@ using System.ComponentModel; using System.Drawing; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/MagnifierFilter.cs b/src/Greenshot/Drawing/Filters/MagnifierFilter.cs index c3f9835fa..9b1587d04 100644 --- a/src/Greenshot/Drawing/Filters/MagnifierFilter.cs +++ b/src/Greenshot/Drawing/Filters/MagnifierFilter.cs @@ -22,9 +22,9 @@ using System; using System.Drawing; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Core; using System.Drawing.Drawing2D; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/Filters/PixelizationFilter.cs b/src/Greenshot/Drawing/Filters/PixelizationFilter.cs index 00a3e2f11..59ca0321f 100644 --- a/src/Greenshot/Drawing/Filters/PixelizationFilter.cs +++ b/src/Greenshot/Drawing/Filters/PixelizationFilter.cs @@ -22,10 +22,10 @@ using System; using System.Collections.Generic; using System.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Helpers; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing.Filters { diff --git a/src/Greenshot/Drawing/FreehandContainer.cs b/src/Greenshot/Drawing/FreehandContainer.cs index a493ee670..3c3fbe92f 100644 --- a/src/Greenshot/Drawing/FreehandContainer.cs +++ b/src/Greenshot/Drawing/FreehandContainer.cs @@ -26,7 +26,7 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/HighlightContainer.cs b/src/Greenshot/Drawing/HighlightContainer.cs index 267e2784b..fb5a78c69 100644 --- a/src/Greenshot/Drawing/HighlightContainer.cs +++ b/src/Greenshot/Drawing/HighlightContainer.cs @@ -21,9 +21,9 @@ using System; using System.Runtime.Serialization; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/IconContainer.cs b/src/Greenshot/Drawing/IconContainer.cs index a89e0a258..fe87c48b9 100644 --- a/src/Greenshot/Drawing/IconContainer.cs +++ b/src/Greenshot/Drawing/IconContainer.cs @@ -25,7 +25,7 @@ using System.IO; using System.Drawing.Drawing2D; using log4net; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/ImageContainer.cs b/src/Greenshot/Drawing/ImageContainer.cs index 3b99e36af..e4538c0f4 100644 --- a/src/Greenshot/Drawing/ImageContainer.cs +++ b/src/Greenshot/Drawing/ImageContainer.cs @@ -23,12 +23,12 @@ using System; using System.Drawing; using System.IO; using Greenshot.Drawing.Fields; -using GreenshotPlugin.Core; using System.Drawing.Drawing2D; using log4net; using System.Runtime.Serialization; -using GreenshotPlugin.Effects; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/LineContainer.cs b/src/Greenshot/Drawing/LineContainer.cs index 6a5229107..1078662ea 100644 --- a/src/Greenshot/Drawing/LineContainer.cs +++ b/src/Greenshot/Drawing/LineContainer.cs @@ -23,10 +23,10 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.Serialization; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Drawing.Adorners; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/ObfuscateContainer.cs b/src/Greenshot/Drawing/ObfuscateContainer.cs index 127ff2b61..f45d6b4a2 100644 --- a/src/Greenshot/Drawing/ObfuscateContainer.cs +++ b/src/Greenshot/Drawing/ObfuscateContainer.cs @@ -21,9 +21,9 @@ using System; using System.Runtime.Serialization; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/RectangleContainer.cs b/src/Greenshot/Drawing/RectangleContainer.cs index b26193ee7..73da99983 100644 --- a/src/Greenshot/Drawing/RectangleContainer.cs +++ b/src/Greenshot/Drawing/RectangleContainer.cs @@ -25,7 +25,7 @@ using System.Drawing.Drawing2D; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/SpeechbubbleContainer.cs b/src/Greenshot/Drawing/SpeechbubbleContainer.cs index ce11402b9..50f18f74a 100644 --- a/src/Greenshot/Drawing/SpeechbubbleContainer.cs +++ b/src/Greenshot/Drawing/SpeechbubbleContainer.cs @@ -26,7 +26,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/StepLabelContainer.cs b/src/Greenshot/Drawing/StepLabelContainer.cs index ff01af1c1..3f2c3b7db 100644 --- a/src/Greenshot/Drawing/StepLabelContainer.cs +++ b/src/Greenshot/Drawing/StepLabelContainer.cs @@ -26,7 +26,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/Surface.cs b/src/Greenshot/Drawing/Surface.cs index 4dd3c55bd..8f2356513 100644 --- a/src/Greenshot/Drawing/Surface.cs +++ b/src/Greenshot/Drawing/Surface.cs @@ -23,9 +23,6 @@ using Greenshot.Configuration; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Memento; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Drawing; using log4net; using System; using System.Collections.Generic; @@ -36,10 +33,13 @@ using System.Drawing.Imaging; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Drawing.Adorners; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing.Adorners; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Drawing/TextContainer.cs b/src/Greenshot/Drawing/TextContainer.cs index 8f1a819f6..4888ef463 100644 --- a/src/Greenshot/Drawing/TextContainer.cs +++ b/src/Greenshot/Drawing/TextContainer.cs @@ -22,8 +22,6 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Memento; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces.Drawing; using System; using System.ComponentModel; using System.Diagnostics; @@ -32,6 +30,8 @@ using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Drawing { diff --git a/src/Greenshot/Forms/AboutForm.Designer.cs b/src/Greenshot/Forms/AboutForm.Designer.cs index 4112df177..e34b65b03 100644 --- a/src/Greenshot/Forms/AboutForm.Designer.cs +++ b/src/Greenshot/Forms/AboutForm.Designer.cs @@ -20,8 +20,9 @@ */ using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; using Greenshot.Helpers; -using GreenshotPlugin.Core; namespace Greenshot.Forms { partial class AboutForm { @@ -50,19 +51,19 @@ namespace Greenshot.Forms { ///
private void InitializeComponent() { this.lblTitle = new System.Windows.Forms.Label(); - this.lblLicense = new GreenshotPlugin.Controls.GreenshotLabel(); - this.lblHost = new GreenshotPlugin.Controls.GreenshotLabel(); + this.lblLicense = new GreenshotLabel(); + this.lblHost = new GreenshotLabel(); this.linkLblLicense = new System.Windows.Forms.LinkLabel(); this.linkLblHost = new System.Windows.Forms.LinkLabel(); this.linkLblBugs = new System.Windows.Forms.LinkLabel(); - this.lblBugs = new GreenshotPlugin.Controls.GreenshotLabel(); + this.lblBugs = new GreenshotLabel(); this.linkLblDonations = new System.Windows.Forms.LinkLabel(); - this.lblDonations = new GreenshotPlugin.Controls.GreenshotLabel(); + this.lblDonations = new GreenshotLabel(); this.linkLblIcons = new System.Windows.Forms.LinkLabel(); - this.lblIcons = new GreenshotPlugin.Controls.GreenshotLabel(); + this.lblIcons = new GreenshotLabel(); this.linkLabel1 = new System.Windows.Forms.LinkLabel(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); - this.lblTranslation = new GreenshotPlugin.Controls.GreenshotLabel(); + this.lblTranslation = new GreenshotLabel(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // @@ -236,11 +237,11 @@ namespace Greenshot.Forms { private System.Windows.Forms.LinkLabel linkLblIcons; private System.Windows.Forms.Label lblTitle; private System.Windows.Forms.PictureBox pictureBox1; - private GreenshotPlugin.Controls.GreenshotLabel lblTranslation; - private GreenshotPlugin.Controls.GreenshotLabel lblHost; - private GreenshotPlugin.Controls.GreenshotLabel lblDonations; - private GreenshotPlugin.Controls.GreenshotLabel lblBugs; - private GreenshotPlugin.Controls.GreenshotLabel lblIcons; - private GreenshotPlugin.Controls.GreenshotLabel lblLicense; + private GreenshotLabel lblTranslation; + private GreenshotLabel lblHost; + private GreenshotLabel lblDonations; + private GreenshotLabel lblBugs; + private GreenshotLabel lblIcons; + private GreenshotLabel lblLicense; } } diff --git a/src/Greenshot/Forms/AboutForm.cs b/src/Greenshot/Forms/AboutForm.cs index 6fdf4eddd..7ecad5ccc 100644 --- a/src/Greenshot/Forms/AboutForm.cs +++ b/src/Greenshot/Forms/AboutForm.cs @@ -28,10 +28,10 @@ using System.Drawing.Imaging; using System.IO; using System.Security.Permissions; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; using Greenshot.Configuration; using Greenshot.Helpers; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; using log4net; namespace Greenshot.Forms diff --git a/src/Greenshot/Forms/AnimatingBaseForm.cs b/src/Greenshot/Forms/AnimatingBaseForm.cs index 7f9fec60e..6f131381b 100644 --- a/src/Greenshot/Forms/AnimatingBaseForm.cs +++ b/src/Greenshot/Forms/AnimatingBaseForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/BaseForm.cs b/src/Greenshot/Forms/BaseForm.cs index e67654df5..c7ea1341f 100644 --- a/src/Greenshot/Forms/BaseForm.cs +++ b/src/Greenshot/Forms/BaseForm.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Controls; +using Greenshot.Base.Controls; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/BugReportForm.Designer.cs b/src/Greenshot/Forms/BugReportForm.Designer.cs index da6da4963..41dcc6447 100644 --- a/src/Greenshot/Forms/BugReportForm.Designer.cs +++ b/src/Greenshot/Forms/BugReportForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class BugReportForm { /// @@ -46,9 +49,9 @@ namespace Greenshot.Forms { /// private void InitializeComponent() { - this.labelBugReportInfo = new GreenshotPlugin.Controls.GreenshotLabel(); + this.labelBugReportInfo = new GreenshotLabel(); this.textBoxDescription = new System.Windows.Forms.TextBox(); - this.btnClose = new GreenshotPlugin.Controls.GreenshotButton(); + this.btnClose = new GreenshotButton(); this.linkLblBugs = new System.Windows.Forms.LinkLabel(); this.SuspendLayout(); // @@ -112,8 +115,8 @@ namespace Greenshot.Forms { } private System.Windows.Forms.LinkLabel linkLblBugs; - private GreenshotPlugin.Controls.GreenshotButton btnClose; + private GreenshotButton btnClose; private System.Windows.Forms.TextBox textBoxDescription; - private GreenshotPlugin.Controls.GreenshotLabel labelBugReportInfo; + private GreenshotLabel labelBugReportInfo; } } diff --git a/src/Greenshot/Forms/BugReportForm.cs b/src/Greenshot/Forms/BugReportForm.cs index b42f20d18..255af0525 100644 --- a/src/Greenshot/Forms/BugReportForm.cs +++ b/src/Greenshot/Forms/BugReportForm.cs @@ -22,8 +22,8 @@ using System; using System.Diagnostics; using System.Windows.Forms; +using Greenshot.Base.Core; using Greenshot.Configuration; -using GreenshotPlugin.Core; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/CaptureForm.cs b/src/Greenshot/Forms/CaptureForm.cs index efdf7583c..f85c57d4a 100644 --- a/src/Greenshot/Forms/CaptureForm.cs +++ b/src/Greenshot/Forms/CaptureForm.cs @@ -21,9 +21,6 @@ using Greenshot.Drawing; using Greenshot.Helpers; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers; using log4net; using System; using System.Collections.Generic; @@ -35,9 +32,12 @@ using System.Security.Permissions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Ocr; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Ocr; +using Greenshot.Base.UnmanagedHelpers; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/ColorDialog.Designer.cs b/src/Greenshot/Forms/ColorDialog.Designer.cs index d5060d8c0..468edf457 100644 --- a/src/Greenshot/Forms/ColorDialog.Designer.cs +++ b/src/Greenshot/Forms/ColorDialog.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { public partial class ColorDialog { /// @@ -47,20 +50,20 @@ namespace Greenshot.Forms { private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ColorDialog)); - this.btnTransparent = new GreenshotPlugin.Controls.GreenshotButton(); + this.btnTransparent = new GreenshotButton(); this.colorPanel = new System.Windows.Forms.Panel(); - this.labelHtmlColor = new GreenshotPlugin.Controls.GreenshotLabel(); + this.labelHtmlColor = new GreenshotLabel(); this.textBoxHtmlColor = new System.Windows.Forms.TextBox(); - this.labelRed = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelGreen = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelBlue = new GreenshotPlugin.Controls.GreenshotLabel(); + this.labelRed = new GreenshotLabel(); + this.labelGreen = new GreenshotLabel(); + this.labelBlue = new GreenshotLabel(); this.textBoxRed = new System.Windows.Forms.TextBox(); this.textBoxGreen = new System.Windows.Forms.TextBox(); this.textBoxBlue = new System.Windows.Forms.TextBox(); - this.labelRecentColors = new GreenshotPlugin.Controls.GreenshotLabel(); + this.labelRecentColors = new GreenshotLabel(); this.textBoxAlpha = new System.Windows.Forms.TextBox(); - this.labelAlpha = new GreenshotPlugin.Controls.GreenshotLabel(); - this.btnApply = new GreenshotPlugin.Controls.GreenshotButton(); + this.labelAlpha = new GreenshotLabel(); + this.btnApply = new GreenshotButton(); this.pipette = new Greenshot.Controls.Pipette(); this.SuspendLayout(); // @@ -260,20 +263,20 @@ namespace Greenshot.Forms { this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotLabel labelRed; - private GreenshotPlugin.Controls.GreenshotLabel labelGreen; - private GreenshotPlugin.Controls.GreenshotLabel labelBlue; + private GreenshotLabel labelRed; + private GreenshotLabel labelGreen; + private GreenshotLabel labelBlue; private System.Windows.Forms.TextBox textBoxHtmlColor; - private GreenshotPlugin.Controls.GreenshotLabel labelRecentColors; - private GreenshotPlugin.Controls.GreenshotLabel labelAlpha; - private GreenshotPlugin.Controls.GreenshotLabel labelHtmlColor; - private GreenshotPlugin.Controls.GreenshotButton btnApply; + private GreenshotLabel labelRecentColors; + private GreenshotLabel labelAlpha; + private GreenshotLabel labelHtmlColor; + private GreenshotButton btnApply; private System.Windows.Forms.TextBox textBoxAlpha; private System.Windows.Forms.TextBox textBoxRed; private System.Windows.Forms.TextBox textBoxGreen; private System.Windows.Forms.TextBox textBoxBlue; private System.Windows.Forms.Panel colorPanel; - private GreenshotPlugin.Controls.GreenshotButton btnTransparent; + private GreenshotButton btnTransparent; private Greenshot.Controls.Pipette pipette; diff --git a/src/Greenshot/Forms/ColorDialog.cs b/src/Greenshot/Forms/ColorDialog.cs index 91c314cd9..6653ecf08 100644 --- a/src/Greenshot/Forms/ColorDialog.cs +++ b/src/Greenshot/Forms/ColorDialog.cs @@ -25,9 +25,9 @@ using System.Drawing; using System.Globalization; using System.Threading; using System.Windows.Forms; +using Greenshot.Base.IniFile; using Greenshot.Configuration; using Greenshot.Controls; -using GreenshotPlugin.IniFile; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/DropShadowSettingsForm.Designer.cs b/src/Greenshot/Forms/DropShadowSettingsForm.Designer.cs index 0f7a89618..489cbfd6f 100644 --- a/src/Greenshot/Forms/DropShadowSettingsForm.Designer.cs +++ b/src/Greenshot/Forms/DropShadowSettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class DropShadowSettingsForm { /// @@ -48,11 +51,11 @@ namespace Greenshot.Forms { this.label3 = new System.Windows.Forms.Label(); this.offsetY = new System.Windows.Forms.NumericUpDown(); this.trackBar1 = new System.Windows.Forms.TrackBar(); - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.labelDarkness = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelOffset = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelThickness = new GreenshotPlugin.Controls.GreenshotLabel(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.labelDarkness = new GreenshotLabel(); + this.labelOffset = new GreenshotLabel(); + this.labelThickness = new GreenshotLabel(); ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit(); @@ -227,10 +230,10 @@ namespace Greenshot.Forms { private System.Windows.Forms.Label label3; private System.Windows.Forms.NumericUpDown offsetY; private System.Windows.Forms.TrackBar trackBar1; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotLabel labelDarkness; - private GreenshotPlugin.Controls.GreenshotLabel labelOffset; - private GreenshotPlugin.Controls.GreenshotLabel labelThickness; + private GreenshotButton buttonOK; + private GreenshotButton buttonCancel; + private GreenshotLabel labelDarkness; + private GreenshotLabel labelOffset; + private GreenshotLabel labelThickness; } } \ No newline at end of file diff --git a/src/Greenshot/Forms/DropShadowSettingsForm.cs b/src/Greenshot/Forms/DropShadowSettingsForm.cs index 8a1e57f56..c798f8109 100644 --- a/src/Greenshot/Forms/DropShadowSettingsForm.cs +++ b/src/Greenshot/Forms/DropShadowSettingsForm.cs @@ -22,7 +22,7 @@ using System; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.Effects; +using Greenshot.Base.Effects; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/ImageEditorForm.Designer.cs b/src/Greenshot/Forms/ImageEditorForm.Designer.cs index 0db33a212..3ebcb0ef0 100644 --- a/src/Greenshot/Forms/ImageEditorForm.Designer.cs +++ b/src/Greenshot/Forms/ImageEditorForm.Designer.cs @@ -19,6 +19,7 @@ * along with this program. If not, see . */ +using Greenshot.Base.Controls; using Greenshot.Controls; namespace Greenshot.Forms { @@ -58,142 +59,142 @@ namespace Greenshot.Forms { this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.panel1 = new NonJumpingPanel(); this.toolsToolStrip = new Greenshot.Controls.ToolStripEx(); - this.btnCursor = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnCursor = new GreenshotToolStripButton(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.btnRect = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnEllipse = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnLine = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnArrow = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnFreehand = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnText = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnSpeechBubble = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnStepLabel = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnRect = new GreenshotToolStripButton(); + this.btnEllipse = new GreenshotToolStripButton(); + this.btnLine = new GreenshotToolStripButton(); + this.btnArrow = new GreenshotToolStripButton(); + this.btnFreehand = new GreenshotToolStripButton(); + this.btnText = new GreenshotToolStripButton(); + this.btnSpeechBubble = new GreenshotToolStripButton(); + this.btnStepLabel = new GreenshotToolStripButton(); this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); - this.btnHighlight = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnObfuscate = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.toolStripSplitButton1 = new GreenshotPlugin.Controls.GreenshotToolStripDropDownButton(); - this.addBorderToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addDropshadowToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.tornEdgesToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.grayscaleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.invertToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.btnResize = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnHighlight = new GreenshotToolStripButton(); + this.btnObfuscate = new GreenshotToolStripButton(); + this.toolStripSplitButton1 = new GreenshotToolStripDropDownButton(); + this.addBorderToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addDropshadowToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.tornEdgesToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.grayscaleToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.invertToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.btnResize = new GreenshotToolStripButton(); this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator(); - this.btnCrop = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.rotateCwToolstripButton = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.rotateCcwToolstripButton = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnCrop = new GreenshotToolStripButton(); + this.rotateCwToolstripButton = new GreenshotToolStripButton(); + this.rotateCcwToolstripButton = new GreenshotToolStripButton(); this.menuStrip1 = new Greenshot.Controls.MenuStripEx(); - this.fileStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.editToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.fileStripMenuItem = new GreenshotToolStripMenuItem(); + this.editToolStripMenuItem = new GreenshotToolStripMenuItem(); this.undoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.redoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator(); - this.cutToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.copyToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.pasteToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.cutToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.copyToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.pasteToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); - this.duplicateToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.duplicateToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); - this.preferencesToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.preferencesToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); - this.autoCropToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.autoCropToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator(); - this.insert_window_toolstripmenuitem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.objectToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addRectangleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addEllipseToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.drawLineToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.drawArrowToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.drawFreehandToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addTextBoxToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addSpeechBubbleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.addCounterToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.insert_window_toolstripmenuitem = new GreenshotToolStripMenuItem(); + this.objectToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addRectangleToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addEllipseToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.drawLineToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.drawArrowToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.drawFreehandToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addTextBoxToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addSpeechBubbleToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.addCounterToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); - this.selectAllToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.removeObjectToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.selectAllToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.removeObjectToolStripMenuItem = new GreenshotToolStripMenuItem(); this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); - this.arrangeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.upToTopToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.upOneLevelToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.downOneLevelToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.downToBottomToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.saveElementsToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.loadElementsToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.pluginToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.helpToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.helpToolStripMenuItem1 = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.aboutToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.arrangeToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.upToTopToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.upOneLevelToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.downOneLevelToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.downToBottomToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.saveElementsToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.loadElementsToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.pluginToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.helpToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.helpToolStripMenuItem1 = new GreenshotToolStripMenuItem(); + this.aboutToolStripMenuItem = new GreenshotToolStripMenuItem(); this.destinationsToolStrip = new Greenshot.Controls.ToolStripEx(); - this.btnSave = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnClipboard = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnPrint = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnSave = new GreenshotToolStripButton(); + this.btnClipboard = new GreenshotToolStripButton(); + this.btnPrint = new GreenshotToolStripButton(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.btnDelete = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnDelete = new GreenshotToolStripButton(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.btnCut = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnCopy = new GreenshotPlugin.Controls.GreenshotToolStripButton(); - this.btnPaste = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnCut = new GreenshotToolStripButton(); + this.btnCopy = new GreenshotToolStripButton(); + this.btnPaste = new GreenshotToolStripButton(); this.btnUndo = new System.Windows.Forms.ToolStripButton(); this.btnRedo = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); - this.btnSettings = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnSettings = new GreenshotToolStripButton(); this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator(); - this.btnHelp = new GreenshotPlugin.Controls.GreenshotToolStripButton(); + this.btnHelp = new GreenshotToolStripButton(); this.propertiesToolStrip = new Greenshot.Controls.ToolStripEx(); this.obfuscateModeButton = new Greenshot.Controls.BindableToolStripDropDownButton(); - this.pixelizeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.blurToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.pixelizeToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.blurToolStripMenuItem = new GreenshotToolStripMenuItem(); this.highlightModeButton = new Greenshot.Controls.BindableToolStripDropDownButton(); - this.textHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.areaHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.grayscaleHighlightMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.magnifyMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.textHighlightMenuItem = new GreenshotToolStripMenuItem(); + this.areaHighlightMenuItem = new GreenshotToolStripMenuItem(); + this.grayscaleHighlightMenuItem = new GreenshotToolStripMenuItem(); + this.magnifyMenuItem = new GreenshotToolStripMenuItem(); this.btnFillColor = new Greenshot.Controls.ToolStripColorButton(); this.btnLineColor = new Greenshot.Controls.ToolStripColorButton(); - this.lineThicknessLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.lineThicknessLabel = new GreenshotToolStripLabel(); this.lineThicknessUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.counterLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.counterLabel = new GreenshotToolStripLabel(); this.counterUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); this.fontFamilyComboBox = new Greenshot.Controls.FontFamilyComboBox(); - this.fontSizeLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.fontSizeLabel = new GreenshotToolStripLabel(); this.fontSizeUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); this.fontBoldButton = new Greenshot.Controls.BindableToolStripButton(); this.fontItalicButton = new Greenshot.Controls.BindableToolStripButton(); this.textVerticalAlignmentButton = new Greenshot.Controls.BindableToolStripDropDownButton(); - this.alignTopToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.alignMiddleToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.alignBottomToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.blurRadiusLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.alignTopToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.alignMiddleToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.alignBottomToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.blurRadiusLabel = new GreenshotToolStripLabel(); this.blurRadiusUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.brightnessLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.brightnessLabel = new GreenshotToolStripLabel(); this.brightnessUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.previewQualityLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.previewQualityLabel = new GreenshotToolStripLabel(); this.previewQualityUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.magnificationFactorLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.magnificationFactorLabel = new GreenshotToolStripLabel(); this.magnificationFactorUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.pixelSizeLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); + this.pixelSizeLabel = new GreenshotToolStripLabel(); this.pixelSizeUpDown = new Greenshot.Controls.ToolStripNumericUpDown(); - this.arrowHeadsLabel = new GreenshotPlugin.Controls.GreenshotToolStripLabel(); - this.arrowHeadsDropDownButton = new GreenshotPlugin.Controls.GreenshotToolStripDropDownButton(); - this.arrowHeadStartMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.arrowHeadEndMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.arrowHeadBothMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.arrowHeadNoneMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.arrowHeadsLabel = new GreenshotToolStripLabel(); + this.arrowHeadsDropDownButton = new GreenshotToolStripDropDownButton(); + this.arrowHeadStartMenuItem = new GreenshotToolStripMenuItem(); + this.arrowHeadEndMenuItem = new GreenshotToolStripMenuItem(); + this.arrowHeadBothMenuItem = new GreenshotToolStripMenuItem(); + this.arrowHeadNoneMenuItem = new GreenshotToolStripMenuItem(); this.shadowButton = new Greenshot.Controls.BindableToolStripButton(); this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); this.btnConfirm = new Greenshot.Controls.BindableToolStripButton(); this.btnCancel = new Greenshot.Controls.BindableToolStripButton(); this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); - this.closeToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.closeToolStripMenuItem = new GreenshotToolStripMenuItem(); this.fileSavedStatusContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.copyPathMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.openDirectoryMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.copyPathMenuItem = new GreenshotToolStripMenuItem(); + this.openDirectoryMenuItem = new GreenshotToolStripMenuItem(); this.textHorizontalAlignmentButton = new Greenshot.Controls.BindableToolStripDropDownButton(); - this.alignLeftToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.alignCenterToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.alignRightToolStripMenuItem = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.alignLeftToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.alignCenterToolStripMenuItem = new GreenshotToolStripMenuItem(); + this.alignRightToolStripMenuItem = new GreenshotToolStripMenuItem(); this.zoomMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.zoomInMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.zoomOutMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -1839,44 +1840,44 @@ namespace Greenshot.Forms { this.fileSavedStatusContextMenu.ResumeLayout(true); this.ResumeLayout(false); } - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignRightToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignCenterToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignLeftToolStripMenuItem; + private GreenshotToolStripMenuItem alignRightToolStripMenuItem; + private GreenshotToolStripMenuItem alignCenterToolStripMenuItem; + private GreenshotToolStripMenuItem alignLeftToolStripMenuItem; private Greenshot.Controls.BindableToolStripDropDownButton textHorizontalAlignmentButton; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignMiddleToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignBottomToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem alignTopToolStripMenuItem; + private GreenshotToolStripMenuItem alignMiddleToolStripMenuItem; + private GreenshotToolStripMenuItem alignBottomToolStripMenuItem; + private GreenshotToolStripMenuItem alignTopToolStripMenuItem; private Greenshot.Controls.BindableToolStripDropDownButton textVerticalAlignmentButton; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem invertToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnResize; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem grayscaleToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripButton rotateCcwToolstripButton; - private GreenshotPlugin.Controls.GreenshotToolStripButton rotateCwToolstripButton; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addBorderToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem tornEdgesToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addDropshadowToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripDropDownButton toolStripSplitButton1; + private GreenshotToolStripMenuItem invertToolStripMenuItem; + private GreenshotToolStripButton btnResize; + private GreenshotToolStripMenuItem grayscaleToolStripMenuItem; + private GreenshotToolStripButton rotateCcwToolstripButton; + private GreenshotToolStripButton rotateCwToolstripButton; + private GreenshotToolStripMenuItem addBorderToolStripMenuItem; + private GreenshotToolStripMenuItem tornEdgesToolStripMenuItem; + private GreenshotToolStripMenuItem addDropshadowToolStripMenuItem; + private GreenshotToolStripDropDownButton toolStripSplitButton1; private System.Windows.Forms.ToolStripStatusLabel dimensionsLabel; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem insert_window_toolstripmenuitem; + private GreenshotToolStripMenuItem insert_window_toolstripmenuitem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem grayscaleHighlightMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem areaHighlightMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem textHighlightMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem magnifyMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadStartMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadEndMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadBothMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrowHeadNoneMenuItem; + private GreenshotToolStripMenuItem grayscaleHighlightMenuItem; + private GreenshotToolStripMenuItem areaHighlightMenuItem; + private GreenshotToolStripMenuItem textHighlightMenuItem; + private GreenshotToolStripMenuItem magnifyMenuItem; + private GreenshotToolStripMenuItem arrowHeadStartMenuItem; + private GreenshotToolStripMenuItem arrowHeadEndMenuItem; + private GreenshotToolStripMenuItem arrowHeadBothMenuItem; + private GreenshotToolStripMenuItem arrowHeadNoneMenuItem; private Greenshot.Controls.BindableToolStripButton btnCancel; private Greenshot.Controls.BindableToolStripButton btnConfirm; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem selectAllToolStripMenuItem; + private GreenshotToolStripMenuItem selectAllToolStripMenuItem; private Greenshot.Controls.BindableToolStripDropDownButton highlightModeButton; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pixelizeToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem blurToolStripMenuItem; + private GreenshotToolStripMenuItem pixelizeToolStripMenuItem; + private GreenshotToolStripMenuItem blurToolStripMenuItem; private Greenshot.Controls.BindableToolStripDropDownButton obfuscateModeButton; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnHighlight; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem loadElementsToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem saveElementsToolStripMenuItem; + private GreenshotToolStripButton btnHighlight; + private GreenshotToolStripMenuItem loadElementsToolStripMenuItem; + private GreenshotToolStripMenuItem saveElementsToolStripMenuItem; private Greenshot.Controls.FontFamilyComboBox fontFamilyComboBox; private System.Windows.Forms.ToolStripSeparator toolStripSeparator10; private System.Windows.Forms.ToolStripSeparator toolStripSeparator; @@ -1884,103 +1885,103 @@ namespace Greenshot.Forms { private Greenshot.Controls.BindableToolStripButton fontItalicButton; private Greenshot.Controls.BindableToolStripButton fontBoldButton; private Greenshot.Controls.ToolStripNumericUpDown fontSizeUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel fontSizeLabel; + private GreenshotToolStripLabel fontSizeLabel; private Greenshot.Controls.ToolStripNumericUpDown brightnessUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel brightnessLabel; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pluginToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripDropDownButton arrowHeadsDropDownButton; - private GreenshotPlugin.Controls.GreenshotToolStripLabel arrowHeadsLabel; + private GreenshotToolStripLabel brightnessLabel; + private GreenshotToolStripMenuItem pluginToolStripMenuItem; + private GreenshotToolStripDropDownButton arrowHeadsDropDownButton; + private GreenshotToolStripLabel arrowHeadsLabel; private Greenshot.Controls.ToolStripNumericUpDown pixelSizeUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel pixelSizeLabel; + private GreenshotToolStripLabel pixelSizeLabel; private Greenshot.Controls.ToolStripNumericUpDown magnificationFactorUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel magnificationFactorLabel; + private GreenshotToolStripLabel magnificationFactorLabel; private Greenshot.Controls.ToolStripNumericUpDown previewQualityUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel previewQualityLabel; + private GreenshotToolStripLabel previewQualityLabel; private Greenshot.Controls.ToolStripNumericUpDown blurRadiusUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel blurRadiusLabel; + private GreenshotToolStripLabel blurRadiusLabel; private Greenshot.Controls.ToolStripEx propertiesToolStrip; - private GreenshotPlugin.Controls.GreenshotToolStripLabel lineThicknessLabel; + private GreenshotToolStripLabel lineThicknessLabel; private Greenshot.Controls.ToolStripNumericUpDown lineThicknessUpDown; - private GreenshotPlugin.Controls.GreenshotToolStripLabel counterLabel; + private GreenshotToolStripLabel counterLabel; private Greenshot.Controls.ToolStripNumericUpDown counterUpDown; private System.Windows.Forms.ToolStripSeparator toolStripSeparator14; private System.Windows.Forms.ToolStripSeparator toolStripSeparator15; private System.Windows.Forms.ToolStripSeparator toolStripSeparator16; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnFreehand; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnObfuscate; + private GreenshotToolStripButton btnFreehand; + private GreenshotToolStripButton btnObfuscate; private System.Windows.Forms.ToolStripSeparator toolStripSeparator13; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnCrop; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem openDirectoryMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem copyPathMenuItem; + private GreenshotToolStripButton btnCrop; + private GreenshotToolStripMenuItem openDirectoryMenuItem; + private GreenshotToolStripMenuItem copyPathMenuItem; private System.Windows.Forms.ContextMenuStrip fileSavedStatusContextMenu; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem downToBottomToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem upToTopToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem downOneLevelToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem upOneLevelToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem arrangeToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnCursor; + private GreenshotToolStripMenuItem downToBottomToolStripMenuItem; + private GreenshotToolStripMenuItem upToTopToolStripMenuItem; + private GreenshotToolStripMenuItem downOneLevelToolStripMenuItem; + private GreenshotToolStripMenuItem upOneLevelToolStripMenuItem; + private GreenshotToolStripMenuItem arrangeToolStripMenuItem; + private GreenshotToolStripButton btnCursor; private Greenshot.Controls.ToolStripEx toolsToolStrip; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnArrow; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawArrowToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawFreehandToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnText; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnSpeechBubble; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnStepLabel; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem drawLineToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnLine; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnSettings; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnHelp; + private GreenshotToolStripButton btnArrow; + private GreenshotToolStripMenuItem drawArrowToolStripMenuItem; + private GreenshotToolStripMenuItem drawFreehandToolStripMenuItem; + private GreenshotToolStripButton btnText; + private GreenshotToolStripButton btnSpeechBubble; + private GreenshotToolStripButton btnStepLabel; + private GreenshotToolStripMenuItem drawLineToolStripMenuItem; + private GreenshotToolStripButton btnLine; + private GreenshotToolStripButton btnSettings; + private GreenshotToolStripButton btnHelp; private System.Windows.Forms.ToolStripSeparator toolStripSeparator11; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem aboutToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem helpToolStripMenuItem1; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem helpToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem preferencesToolStripMenuItem; + private GreenshotToolStripMenuItem aboutToolStripMenuItem; + private GreenshotToolStripMenuItem helpToolStripMenuItem1; + private GreenshotToolStripMenuItem helpToolStripMenuItem; + private GreenshotToolStripMenuItem preferencesToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator12; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem closeToolStripMenuItem; + private GreenshotToolStripMenuItem closeToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnPrint; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem duplicateToolStripMenuItem; + private GreenshotToolStripButton btnPrint; + private GreenshotToolStripMenuItem duplicateToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem fileStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem removeObjectToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addTextBoxToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addSpeechBubbleToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addCounterToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addEllipseToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem addRectangleToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem objectToolStripMenuItem; + private GreenshotToolStripMenuItem fileStripMenuItem; + private GreenshotToolStripMenuItem removeObjectToolStripMenuItem; + private GreenshotToolStripMenuItem addTextBoxToolStripMenuItem; + private GreenshotToolStripMenuItem addSpeechBubbleToolStripMenuItem; + private GreenshotToolStripMenuItem addCounterToolStripMenuItem; + private GreenshotToolStripMenuItem addEllipseToolStripMenuItem; + private GreenshotToolStripMenuItem addRectangleToolStripMenuItem; + private GreenshotToolStripMenuItem objectToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem pasteToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem copyToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem cutToolStripMenuItem; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem editToolStripMenuItem; + private GreenshotToolStripMenuItem pasteToolStripMenuItem; + private GreenshotToolStripMenuItem copyToolStripMenuItem; + private GreenshotToolStripMenuItem cutToolStripMenuItem; + private GreenshotToolStripMenuItem editToolStripMenuItem; private Greenshot.Controls.MenuStripEx menuStrip1; private System.Windows.Forms.ToolStripStatusLabel statusLabel; private System.Windows.Forms.StatusStrip statusStrip1; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnCut; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnCopy; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnPaste; + private GreenshotToolStripButton btnCut; + private GreenshotToolStripButton btnCopy; + private GreenshotToolStripButton btnPaste; private System.Windows.Forms.ToolStripButton btnUndo; private System.Windows.Forms.ToolStripButton btnRedo; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnClipboard; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnDelete; + private GreenshotToolStripButton btnClipboard; + private GreenshotToolStripButton btnDelete; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnEllipse; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnSave; - private GreenshotPlugin.Controls.GreenshotToolStripButton btnRect; + private GreenshotToolStripButton btnEllipse; + private GreenshotToolStripButton btnSave; + private GreenshotToolStripButton btnRect; private System.Windows.Forms.ToolStripContainer topToolStripContainer; private Greenshot.Controls.ToolStripEx destinationsToolStrip; private NonJumpingPanel panel1; private Greenshot.Controls.ToolStripColorButton btnFillColor; private Greenshot.Controls.ToolStripColorButton btnLineColor; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem autoCropToolStripMenuItem; + private GreenshotToolStripMenuItem autoCropToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator17; private System.Windows.Forms.ContextMenuStrip zoomMenuStrip; private System.Windows.Forms.ToolStripMenuItem zoomInMenuItem; diff --git a/src/Greenshot/Forms/ImageEditorForm.cs b/src/Greenshot/Forms/ImageEditorForm.cs index 1764ef4f1..6c7530120 100644 --- a/src/Greenshot/Forms/ImageEditorForm.cs +++ b/src/Greenshot/Forms/ImageEditorForm.cs @@ -26,6 +26,15 @@ using System.Drawing.Drawing2D; using System.IO; using System.Threading; using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Forms; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Structs; using Greenshot.Configuration; using Greenshot.Destinations; using Greenshot.Drawing; @@ -33,15 +42,6 @@ using Greenshot.Drawing.Fields; using Greenshot.Drawing.Fields.Binding; using Greenshot.Help; using Greenshot.Helpers; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Drawing; -using GreenshotPlugin.Interfaces.Forms; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.UnmanagedHelpers.Structs; using log4net; namespace Greenshot.Forms diff --git a/src/Greenshot/Forms/LanguageDialog.cs b/src/Greenshot/Forms/LanguageDialog.cs index a55b7f042..7511eff95 100644 --- a/src/Greenshot/Forms/LanguageDialog.cs +++ b/src/Greenshot/Forms/LanguageDialog.cs @@ -22,7 +22,7 @@ using System; using System.Threading; using System.Windows.Forms; -using GreenshotPlugin.Core; +using Greenshot.Base.Core; using log4net; namespace Greenshot.Forms diff --git a/src/Greenshot/Forms/MainForm.Designer.cs b/src/Greenshot/Forms/MainForm.Designer.cs index 281886180..f33e60f05 100644 --- a/src/Greenshot/Forms/MainForm.Designer.cs +++ b/src/Greenshot/Forms/MainForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class MainForm { /// @@ -50,22 +53,22 @@ namespace Greenshot.Forms { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.contextmenu_capturearea = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_capturelastregion = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_capturewindow = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_capturefullscreen = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_captureie = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_capturewindowfromlist = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_captureiefromlist = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_captureclipboard = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_openfile = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_openrecentcapture = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_quicksettings = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_settings = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_help = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_donate = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_about = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.contextmenu_exit = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); + this.contextmenu_capturearea = new GreenshotToolStripMenuItem(); + this.contextmenu_capturelastregion = new GreenshotToolStripMenuItem(); + this.contextmenu_capturewindow = new GreenshotToolStripMenuItem(); + this.contextmenu_capturefullscreen = new GreenshotToolStripMenuItem(); + this.contextmenu_captureie = new GreenshotToolStripMenuItem(); + this.contextmenu_capturewindowfromlist = new GreenshotToolStripMenuItem(); + this.contextmenu_captureiefromlist = new GreenshotToolStripMenuItem(); + this.contextmenu_captureclipboard = new GreenshotToolStripMenuItem(); + this.contextmenu_openfile = new GreenshotToolStripMenuItem(); + this.contextmenu_openrecentcapture = new GreenshotToolStripMenuItem(); + this.contextmenu_quicksettings = new GreenshotToolStripMenuItem(); + this.contextmenu_settings = new GreenshotToolStripMenuItem(); + this.contextmenu_help = new GreenshotToolStripMenuItem(); + this.contextmenu_donate = new GreenshotToolStripMenuItem(); + this.contextmenu_about = new GreenshotToolStripMenuItem(); + this.contextmenu_exit = new GreenshotToolStripMenuItem(); this.toolStripListCaptureSeparator = new System.Windows.Forms.ToolStripSeparator(); this.toolStripOtherSourcesSeparator = new System.Windows.Forms.ToolStripSeparator(); this.toolStripOpenFolderSeparator = new System.Windows.Forms.ToolStripSeparator(); @@ -270,29 +273,29 @@ namespace Greenshot.Forms { this.contextMenu.ResumeLayout(false); this.ResumeLayout(false); } - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureiefromlist; + private GreenshotToolStripMenuItem contextmenu_captureiefromlist; private System.Windows.Forms.ToolStripSeparator toolStripOtherSourcesSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturewindowfromlist; + private GreenshotToolStripMenuItem contextmenu_capturewindowfromlist; private System.Windows.Forms.ToolStripSeparator toolStripListCaptureSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_openrecentcapture; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureie; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_donate; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_openfile; + private GreenshotToolStripMenuItem contextmenu_openrecentcapture; + private GreenshotToolStripMenuItem contextmenu_captureie; + private GreenshotToolStripMenuItem contextmenu_donate; + private GreenshotToolStripMenuItem contextmenu_openfile; private System.Windows.Forms.ToolStripSeparator toolStripPluginSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureclipboard; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_quicksettings; + private GreenshotToolStripMenuItem contextmenu_captureclipboard; + private GreenshotToolStripMenuItem contextmenu_quicksettings; private System.Windows.Forms.ToolStripSeparator toolStripMiscSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_help; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturewindow; + private GreenshotToolStripMenuItem contextmenu_help; + private GreenshotToolStripMenuItem contextmenu_capturewindow; private System.Windows.Forms.ToolStripSeparator toolStripOpenFolderSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_about; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturefullscreen; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturelastregion; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_capturearea; + private GreenshotToolStripMenuItem contextmenu_about; + private GreenshotToolStripMenuItem contextmenu_capturefullscreen; + private GreenshotToolStripMenuItem contextmenu_capturelastregion; + private GreenshotToolStripMenuItem contextmenu_capturearea; private System.Windows.Forms.NotifyIcon notifyIcon; private System.Windows.Forms.ToolStripSeparator toolStripCloseSeparator; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_exit; + private GreenshotToolStripMenuItem contextmenu_exit; private System.Windows.Forms.ContextMenuStrip contextMenu; - private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_settings; + private GreenshotToolStripMenuItem contextmenu_settings; } } diff --git a/src/Greenshot/Forms/MainForm.cs b/src/Greenshot/Forms/MainForm.cs index 2b56ab7a7..7c3f461fb 100644 --- a/src/Greenshot/Forms/MainForm.cs +++ b/src/Greenshot/Forms/MainForm.cs @@ -32,17 +32,17 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.Integration; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; +using Greenshot.Base.UnmanagedHelpers; using Greenshot.Configuration; using Greenshot.Destinations; using Greenshot.Drawing; using Greenshot.Help; using Greenshot.Helpers; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; -using GreenshotPlugin.UnmanagedHelpers; using log4net; using Timer = System.Timers.Timer; diff --git a/src/Greenshot/Forms/MovableShowColorForm.cs b/src/Greenshot/Forms/MovableShowColorForm.cs index 1005af9c8..36afe9661 100644 --- a/src/Greenshot/Forms/MovableShowColorForm.cs +++ b/src/Greenshot/Forms/MovableShowColorForm.cs @@ -22,7 +22,7 @@ using System; using System.Windows.Forms; using System.Drawing; -using GreenshotPlugin.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs b/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs index 0de6ca3a9..cea22b9ac 100644 --- a/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs +++ b/src/Greenshot/Forms/PrintOptionsDialog.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class PrintOptionsDialog @@ -48,20 +51,20 @@ namespace Greenshot.Forms /// private void InitializeComponent() { - this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowShrink = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowEnlarge = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowCenter = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowRotate = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.button_ok = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkboxDateTime = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.button_cancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkboxPrintInverted = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.radioBtnGrayScale = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.radioBtnMonochrome = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.groupBoxPrintLayout = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.groupBoxColors = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.radioBtnColorPrint = new GreenshotPlugin.Controls.GreenshotRadioButton(); + this.checkbox_dontaskagain = new GreenshotCheckBox(); + this.checkboxAllowShrink = new GreenshotCheckBox(); + this.checkboxAllowEnlarge = new GreenshotCheckBox(); + this.checkboxAllowCenter = new GreenshotCheckBox(); + this.checkboxAllowRotate = new GreenshotCheckBox(); + this.button_ok = new GreenshotButton(); + this.checkboxDateTime = new GreenshotCheckBox(); + this.button_cancel = new GreenshotButton(); + this.checkboxPrintInverted = new GreenshotCheckBox(); + this.radioBtnGrayScale = new GreenshotRadioButton(); + this.radioBtnMonochrome = new GreenshotRadioButton(); + this.groupBoxPrintLayout = new GreenshotGroupBox(); + this.groupBoxColors = new GreenshotGroupBox(); + this.radioBtnColorPrint = new GreenshotRadioButton(); this.groupBoxPrintLayout.SuspendLayout(); this.groupBoxColors.SuspendLayout(); this.SuspendLayout(); @@ -282,19 +285,19 @@ namespace Greenshot.Forms this.PerformLayout(); } - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnGrayScale; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxPrintInverted; - private GreenshotPlugin.Controls.GreenshotButton button_cancel; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxDateTime; - private GreenshotPlugin.Controls.GreenshotButton button_ok; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowRotate; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowCenter; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowEnlarge; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowShrink; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain; - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnMonochrome; - private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxPrintLayout; - private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxColors; - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnColorPrint; + private GreenshotRadioButton radioBtnGrayScale; + private GreenshotCheckBox checkboxPrintInverted; + private GreenshotButton button_cancel; + private GreenshotCheckBox checkboxDateTime; + private GreenshotButton button_ok; + private GreenshotCheckBox checkboxAllowRotate; + private GreenshotCheckBox checkboxAllowCenter; + private GreenshotCheckBox checkboxAllowEnlarge; + private GreenshotCheckBox checkboxAllowShrink; + private GreenshotCheckBox checkbox_dontaskagain; + private GreenshotRadioButton radioBtnMonochrome; + private GreenshotGroupBox groupBoxPrintLayout; + private GreenshotGroupBox groupBoxColors; + private GreenshotRadioButton radioBtnColorPrint; } } diff --git a/src/Greenshot/Forms/PrintOptionsDialog.cs b/src/Greenshot/Forms/PrintOptionsDialog.cs index 537efb352..786b3bfc4 100644 --- a/src/Greenshot/Forms/PrintOptionsDialog.cs +++ b/src/Greenshot/Forms/PrintOptionsDialog.cs @@ -21,7 +21,7 @@ using System; using System.Windows.Forms; -using GreenshotPlugin.IniFile; +using Greenshot.Base.IniFile; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/ResizeSettingsForm.Designer.cs b/src/Greenshot/Forms/ResizeSettingsForm.Designer.cs index e7675bb57..3338fa62b 100644 --- a/src/Greenshot/Forms/ResizeSettingsForm.Designer.cs +++ b/src/Greenshot/Forms/ResizeSettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class ResizeSettingsForm { /// @@ -43,11 +46,11 @@ namespace Greenshot.Forms { /// the contents of this method with the code editor. /// private void InitializeComponent() { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.checkbox_aspectratio = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_width = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_height = new GreenshotPlugin.Controls.GreenshotLabel(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.checkbox_aspectratio = new GreenshotCheckBox(); + this.label_width = new GreenshotLabel(); + this.label_height = new GreenshotLabel(); this.textbox_height = new System.Windows.Forms.TextBox(); this.textbox_width = new System.Windows.Forms.TextBox(); this.combobox_width = new System.Windows.Forms.ComboBox(); @@ -164,11 +167,11 @@ namespace Greenshot.Forms { #endregion - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_aspectratio; - private GreenshotPlugin.Controls.GreenshotLabel label_width; - private GreenshotPlugin.Controls.GreenshotLabel label_height; + private GreenshotButton buttonOK; + private GreenshotButton buttonCancel; + private GreenshotCheckBox checkbox_aspectratio; + private GreenshotLabel label_width; + private GreenshotLabel label_height; private System.Windows.Forms.TextBox textbox_height; private System.Windows.Forms.TextBox textbox_width; private System.Windows.Forms.ComboBox combobox_width; diff --git a/src/Greenshot/Forms/ResizeSettingsForm.cs b/src/Greenshot/Forms/ResizeSettingsForm.cs index f948b777f..e2d61c71d 100644 --- a/src/Greenshot/Forms/ResizeSettingsForm.cs +++ b/src/Greenshot/Forms/ResizeSettingsForm.cs @@ -22,8 +22,8 @@ using System; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/SettingsForm.Designer.cs b/src/Greenshot/Forms/SettingsForm.Designer.cs index f0cb33f46..803eb37d6 100644 --- a/src/Greenshot/Forms/SettingsForm.Designer.cs +++ b/src/Greenshot/Forms/SettingsForm.Designer.cs @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using Greenshot.Base.Controls; + namespace Greenshot.Forms { partial class SettingsForm { /// @@ -47,103 +50,103 @@ namespace Greenshot.Forms { private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm)); - this.textbox_storagelocation = new GreenshotPlugin.Controls.GreenshotTextBox(); - this.label_storagelocation = new GreenshotPlugin.Controls.GreenshotLabel(); - this.settings_cancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.settings_confirm = new GreenshotPlugin.Controls.GreenshotButton(); + this.textbox_storagelocation = new GreenshotTextBox(); + this.label_storagelocation = new GreenshotLabel(); + this.settings_cancel = new GreenshotButton(); + this.settings_confirm = new GreenshotButton(); this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); this.browse = new System.Windows.Forms.Button(); - this.label_screenshotname = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textbox_screenshotname = new GreenshotPlugin.Controls.GreenshotTextBox(); - this.label_language = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label_screenshotname = new GreenshotLabel(); + this.textbox_screenshotname = new GreenshotTextBox(); + this.label_language = new GreenshotLabel(); this.combobox_language = new System.Windows.Forms.ComboBox(); - this.combobox_primaryimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_primaryimageformat = new GreenshotPlugin.Controls.GreenshotLabel(); - this.groupbox_preferredfilesettings = new GreenshotPlugin.Controls.GreenshotGroupBox(); + this.combobox_primaryimageformat = new GreenshotComboBox(); + this.label_primaryimageformat = new GreenshotLabel(); + this.groupbox_preferredfilesettings = new GreenshotGroupBox(); this.btnPatternHelp = new System.Windows.Forms.Button(); - this.checkbox_copypathtoclipboard = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_zoomer = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.groupbox_applicationsettings = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_autostartshortcut = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.groupbox_qualitysettings = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_reducecolors = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_alwaysshowqualitydialog = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_jpegquality = new GreenshotPlugin.Controls.GreenshotLabel(); + this.checkbox_copypathtoclipboard = new GreenshotCheckBox(); + this.checkbox_zoomer = new GreenshotCheckBox(); + this.groupbox_applicationsettings = new GreenshotGroupBox(); + this.checkbox_autostartshortcut = new GreenshotCheckBox(); + this.groupbox_qualitysettings = new GreenshotGroupBox(); + this.checkbox_reducecolors = new GreenshotCheckBox(); + this.checkbox_alwaysshowqualitydialog = new GreenshotCheckBox(); + this.label_jpegquality = new GreenshotLabel(); this.textBoxJpegQuality = new System.Windows.Forms.TextBox(); this.trackBarJpegQuality = new System.Windows.Forms.TrackBar(); - this.groupbox_destination = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_picker = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.groupbox_destination = new GreenshotGroupBox(); + this.checkbox_picker = new GreenshotCheckBox(); this.listview_destinations = new System.Windows.Forms.ListView(); this.destination = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.tabcontrol = new System.Windows.Forms.TabControl(); - this.tab_general = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.groupbox_network = new GreenshotPlugin.Controls.GreenshotGroupBox(); + this.tab_general = new GreenshotTabPage(); + this.groupbox_network = new GreenshotGroupBox(); this.numericUpDown_daysbetweencheck = new System.Windows.Forms.NumericUpDown(); - this.label_checkperiod = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkbox_usedefaultproxy = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.groupbox_hotkeys = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.label_lastregion_hotkey = new GreenshotPlugin.Controls.GreenshotLabel(); - this.lastregion_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl(); - this.label_ie_hotkey = new GreenshotPlugin.Controls.GreenshotLabel(); - this.ie_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl(); - this.label_region_hotkey = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_window_hotkey = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_fullscreen_hotkey = new GreenshotPlugin.Controls.GreenshotLabel(); - this.region_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl(); - this.window_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl(); - this.fullscreen_hotkeyControl = new GreenshotPlugin.Controls.HotkeyControl(); - this.tab_capture = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.groupbox_editor = new GreenshotPlugin.Controls.GreenshotGroupBox(); + this.label_checkperiod = new GreenshotLabel(); + this.checkbox_usedefaultproxy = new GreenshotCheckBox(); + this.groupbox_hotkeys = new GreenshotGroupBox(); + this.label_lastregion_hotkey = new GreenshotLabel(); + this.lastregion_hotkeyControl = new HotkeyControl(); + this.label_ie_hotkey = new GreenshotLabel(); + this.ie_hotkeyControl = new HotkeyControl(); + this.label_region_hotkey = new GreenshotLabel(); + this.label_window_hotkey = new GreenshotLabel(); + this.label_fullscreen_hotkey = new GreenshotLabel(); + this.region_hotkeyControl = new HotkeyControl(); + this.window_hotkeyControl = new HotkeyControl(); + this.fullscreen_hotkeyControl = new HotkeyControl(); + this.tab_capture = new GreenshotTabPage(); + this.groupbox_editor = new GreenshotGroupBox(); this.numericUpdownIconSize = new System.Windows.Forms.NumericUpDown(); - this.label_icon_size = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkbox_editor_match_capture_size = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.groupbox_iecapture = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_ie_capture = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.groupbox_windowscapture = new GreenshotPlugin.Controls.GreenshotGroupBox(); + this.label_icon_size = new GreenshotLabel(); + this.checkbox_editor_match_capture_size = new GreenshotCheckBox(); + this.groupbox_iecapture = new GreenshotGroupBox(); + this.checkbox_ie_capture = new GreenshotCheckBox(); + this.groupbox_windowscapture = new GreenshotGroupBox(); this.colorButton_window_background = new Greenshot.Controls.ColorButton(); - this.radiobuttonWindowCapture = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.radiobuttonInteractiveCapture = new GreenshotPlugin.Controls.GreenshotRadioButton(); + this.radiobuttonWindowCapture = new GreenshotRadioButton(); + this.radiobuttonInteractiveCapture = new GreenshotRadioButton(); this.combobox_window_capture_mode = new System.Windows.Forms.ComboBox(); - this.groupbox_capture = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_notifications = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_playsound = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_capture_mousepointer = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.groupbox_capture = new GreenshotGroupBox(); + this.checkbox_notifications = new GreenshotCheckBox(); + this.checkbox_playsound = new GreenshotCheckBox(); + this.checkbox_capture_mousepointer = new GreenshotCheckBox(); this.numericUpDownWaitTime = new System.Windows.Forms.NumericUpDown(); - this.label_waittime = new GreenshotPlugin.Controls.GreenshotLabel(); - this.tab_output = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.tab_destinations = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.tab_printer = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.groupBoxColors = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkboxPrintInverted = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.radioBtnColorPrint = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.radioBtnGrayScale = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.radioBtnMonochrome = new GreenshotPlugin.Controls.GreenshotRadioButton(); - this.groupBoxPrintLayout = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkboxDateTime = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowShrink = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowEnlarge = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowRotate = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkboxAllowCenter = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_alwaysshowprintoptionsdialog = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.tab_plugins = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.groupbox_plugins = new GreenshotPlugin.Controls.GreenshotGroupBox(); + this.label_waittime = new GreenshotLabel(); + this.tab_output = new GreenshotTabPage(); + this.tab_destinations = new GreenshotTabPage(); + this.tab_printer = new GreenshotTabPage(); + this.groupBoxColors = new GreenshotGroupBox(); + this.checkboxPrintInverted = new GreenshotCheckBox(); + this.radioBtnColorPrint = new GreenshotRadioButton(); + this.radioBtnGrayScale = new GreenshotRadioButton(); + this.radioBtnMonochrome = new GreenshotRadioButton(); + this.groupBoxPrintLayout = new GreenshotGroupBox(); + this.checkboxDateTime = new GreenshotCheckBox(); + this.checkboxAllowShrink = new GreenshotCheckBox(); + this.checkboxAllowEnlarge = new GreenshotCheckBox(); + this.checkboxAllowRotate = new GreenshotCheckBox(); + this.checkboxAllowCenter = new GreenshotCheckBox(); + this.checkbox_alwaysshowprintoptionsdialog = new GreenshotCheckBox(); + this.tab_plugins = new GreenshotTabPage(); + this.groupbox_plugins = new GreenshotGroupBox(); this.listview_plugins = new System.Windows.Forms.ListView(); - this.button_pluginconfigure = new GreenshotPlugin.Controls.GreenshotButton(); - this.tab_expert = new GreenshotPlugin.Controls.GreenshotTabPage(); - this.groupbox_expert = new GreenshotPlugin.Controls.GreenshotGroupBox(); - this.checkbox_reuseeditor = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_minimizememoryfootprint = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_checkunstableupdates = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_suppresssavedialogatclose = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_counter = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textbox_counter = new GreenshotPlugin.Controls.GreenshotTextBox(); - this.label_footerpattern = new GreenshotPlugin.Controls.GreenshotLabel(); - this.textbox_footerpattern = new GreenshotPlugin.Controls.GreenshotTextBox(); - this.checkbox_thumbnailpreview = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_optimizeforrdp = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkbox_autoreducecolors = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_clipboardformats = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkbox_enableexpert = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.button_pluginconfigure = new GreenshotButton(); + this.tab_expert = new GreenshotTabPage(); + this.groupbox_expert = new GreenshotGroupBox(); + this.checkbox_reuseeditor = new GreenshotCheckBox(); + this.checkbox_minimizememoryfootprint = new GreenshotCheckBox(); + this.checkbox_checkunstableupdates = new GreenshotCheckBox(); + this.checkbox_suppresssavedialogatclose = new GreenshotCheckBox(); + this.label_counter = new GreenshotLabel(); + this.textbox_counter = new GreenshotTextBox(); + this.label_footerpattern = new GreenshotLabel(); + this.textbox_footerpattern = new GreenshotTextBox(); + this.checkbox_thumbnailpreview = new GreenshotCheckBox(); + this.checkbox_optimizeforrdp = new GreenshotCheckBox(); + this.checkbox_autoreducecolors = new GreenshotCheckBox(); + this.label_clipboardformats = new GreenshotLabel(); + this.checkbox_enableexpert = new GreenshotCheckBox(); this.listview_clipboardformats = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.groupbox_preferredfilesettings.SuspendLayout(); @@ -1302,104 +1305,104 @@ namespace Greenshot.Forms { this.ResumeLayout(false); } - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_notifications; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_minimizememoryfootprint; + private GreenshotCheckBox checkbox_notifications; + private GreenshotCheckBox checkbox_minimizememoryfootprint; private System.Windows.Forms.ColumnHeader destination; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_picker; + private GreenshotCheckBox checkbox_picker; private System.Windows.Forms.ListView listview_destinations; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_editor; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_editor_match_capture_size; + private GreenshotGroupBox groupbox_editor; + private GreenshotCheckBox checkbox_editor_match_capture_size; private System.Windows.Forms.NumericUpDown numericUpDown_daysbetweencheck; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_network; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_usedefaultproxy; - private GreenshotPlugin.Controls.GreenshotLabel label_checkperiod; - private GreenshotPlugin.Controls.HotkeyControl fullscreen_hotkeyControl; - private GreenshotPlugin.Controls.HotkeyControl window_hotkeyControl; - private GreenshotPlugin.Controls.HotkeyControl region_hotkeyControl; - private GreenshotPlugin.Controls.GreenshotLabel label_fullscreen_hotkey; - private GreenshotPlugin.Controls.GreenshotLabel label_window_hotkey; - private GreenshotPlugin.Controls.GreenshotLabel label_region_hotkey; - private GreenshotPlugin.Controls.HotkeyControl ie_hotkeyControl; - private GreenshotPlugin.Controls.GreenshotLabel label_ie_hotkey; - private GreenshotPlugin.Controls.HotkeyControl lastregion_hotkeyControl; - private GreenshotPlugin.Controls.GreenshotLabel label_lastregion_hotkey; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_hotkeys; + private GreenshotGroupBox groupbox_network; + private GreenshotCheckBox checkbox_usedefaultproxy; + private GreenshotLabel label_checkperiod; + private HotkeyControl fullscreen_hotkeyControl; + private HotkeyControl window_hotkeyControl; + private HotkeyControl region_hotkeyControl; + private GreenshotLabel label_fullscreen_hotkey; + private GreenshotLabel label_window_hotkey; + private GreenshotLabel label_region_hotkey; + private HotkeyControl ie_hotkeyControl; + private GreenshotLabel label_ie_hotkey; + private HotkeyControl lastregion_hotkeyControl; + private GreenshotLabel label_lastregion_hotkey; + private GreenshotGroupBox groupbox_hotkeys; private Greenshot.Controls.ColorButton colorButton_window_background; - private GreenshotPlugin.Controls.GreenshotRadioButton radiobuttonWindowCapture; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_ie_capture; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_capture; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_windowscapture; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_iecapture; - private GreenshotPlugin.Controls.GreenshotTabPage tab_capture; + private GreenshotRadioButton radiobuttonWindowCapture; + private GreenshotCheckBox checkbox_ie_capture; + private GreenshotGroupBox groupbox_capture; + private GreenshotGroupBox groupbox_windowscapture; + private GreenshotGroupBox groupbox_iecapture; + private GreenshotTabPage tab_capture; private System.Windows.Forms.ComboBox combobox_window_capture_mode; private System.Windows.Forms.NumericUpDown numericUpDownWaitTime; - private GreenshotPlugin.Controls.GreenshotLabel label_waittime; - private GreenshotPlugin.Controls.GreenshotRadioButton radiobuttonInteractiveCapture; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_capture_mousepointer; - private GreenshotPlugin.Controls.GreenshotTabPage tab_printer; + private GreenshotLabel label_waittime; + private GreenshotRadioButton radiobuttonInteractiveCapture; + private GreenshotCheckBox checkbox_capture_mousepointer; + private GreenshotTabPage tab_printer; private System.Windows.Forms.ListView listview_plugins; - private GreenshotPlugin.Controls.GreenshotButton button_pluginconfigure; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_plugins; - private GreenshotPlugin.Controls.GreenshotTabPage tab_plugins; + private GreenshotButton button_pluginconfigure; + private GreenshotGroupBox groupbox_plugins; + private GreenshotTabPage tab_plugins; private System.Windows.Forms.Button btnPatternHelp; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_copypathtoclipboard; - private GreenshotPlugin.Controls.GreenshotTabPage tab_output; - private GreenshotPlugin.Controls.GreenshotTabPage tab_general; + private GreenshotCheckBox checkbox_copypathtoclipboard; + private GreenshotTabPage tab_output; + private GreenshotTabPage tab_general; private System.Windows.Forms.TabControl tabcontrol; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_autostartshortcut; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_destination; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_alwaysshowqualitydialog; + private GreenshotCheckBox checkbox_autostartshortcut; + private GreenshotGroupBox groupbox_destination; + private GreenshotCheckBox checkbox_alwaysshowqualitydialog; private System.Windows.Forms.TextBox textBoxJpegQuality; - private GreenshotPlugin.Controls.GreenshotLabel label_jpegquality; + private GreenshotLabel label_jpegquality; private System.Windows.Forms.TrackBar trackBarJpegQuality; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_qualitysettings; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_applicationsettings; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_preferredfilesettings; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_playsound; - private GreenshotPlugin.Controls.GreenshotLabel label_primaryimageformat; - private GreenshotPlugin.Controls.GreenshotComboBox combobox_primaryimageformat; + private GreenshotGroupBox groupbox_qualitysettings; + private GreenshotGroupBox groupbox_applicationsettings; + private GreenshotGroupBox groupbox_preferredfilesettings; + private GreenshotCheckBox checkbox_playsound; + private GreenshotLabel label_primaryimageformat; + private GreenshotComboBox combobox_primaryimageformat; private System.Windows.Forms.ComboBox combobox_language; - private GreenshotPlugin.Controls.GreenshotLabel label_language; - private GreenshotPlugin.Controls.GreenshotTextBox textbox_screenshotname; - private GreenshotPlugin.Controls.GreenshotLabel label_screenshotname; + private GreenshotLabel label_language; + private GreenshotTextBox textbox_screenshotname; + private GreenshotLabel label_screenshotname; private System.Windows.Forms.Button browse; private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; - private GreenshotPlugin.Controls.GreenshotButton settings_cancel; - private GreenshotPlugin.Controls.GreenshotButton settings_confirm; - private GreenshotPlugin.Controls.GreenshotTextBox textbox_storagelocation; - private GreenshotPlugin.Controls.GreenshotLabel label_storagelocation; - private GreenshotPlugin.Controls.GreenshotTabPage tab_destinations; - private GreenshotPlugin.Controls.GreenshotTabPage tab_expert; - private GreenshotPlugin.Controls.GreenshotGroupBox groupbox_expert; - private GreenshotPlugin.Controls.GreenshotLabel label_clipboardformats; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_enableexpert; + private GreenshotButton settings_cancel; + private GreenshotButton settings_confirm; + private GreenshotTextBox textbox_storagelocation; + private GreenshotLabel label_storagelocation; + private GreenshotTabPage tab_destinations; + private GreenshotTabPage tab_expert; + private GreenshotGroupBox groupbox_expert; + private GreenshotLabel label_clipboardformats; + private GreenshotCheckBox checkbox_enableexpert; private System.Windows.Forms.ListView listview_clipboardformats; private System.Windows.Forms.ColumnHeader columnHeader1; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_autoreducecolors; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_optimizeforrdp; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_thumbnailpreview; - private GreenshotPlugin.Controls.GreenshotLabel label_footerpattern; - private GreenshotPlugin.Controls.GreenshotTextBox textbox_footerpattern; - private GreenshotPlugin.Controls.GreenshotLabel label_counter; - private GreenshotPlugin.Controls.GreenshotTextBox textbox_counter; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_reducecolors; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_suppresssavedialogatclose; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_checkunstableupdates; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_reuseeditor; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_alwaysshowprintoptionsdialog; - private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxColors; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxPrintInverted; - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnColorPrint; - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnGrayScale; - private GreenshotPlugin.Controls.GreenshotRadioButton radioBtnMonochrome; - private GreenshotPlugin.Controls.GreenshotGroupBox groupBoxPrintLayout; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxDateTime; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowShrink; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowEnlarge; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowRotate; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAllowCenter; - private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_zoomer; - private GreenshotPlugin.Controls.GreenshotLabel label_icon_size; + private GreenshotCheckBox checkbox_autoreducecolors; + private GreenshotCheckBox checkbox_optimizeforrdp; + private GreenshotCheckBox checkbox_thumbnailpreview; + private GreenshotLabel label_footerpattern; + private GreenshotTextBox textbox_footerpattern; + private GreenshotLabel label_counter; + private GreenshotTextBox textbox_counter; + private GreenshotCheckBox checkbox_reducecolors; + private GreenshotCheckBox checkbox_suppresssavedialogatclose; + private GreenshotCheckBox checkbox_checkunstableupdates; + private GreenshotCheckBox checkbox_reuseeditor; + private GreenshotCheckBox checkbox_alwaysshowprintoptionsdialog; + private GreenshotGroupBox groupBoxColors; + private GreenshotCheckBox checkboxPrintInverted; + private GreenshotRadioButton radioBtnColorPrint; + private GreenshotRadioButton radioBtnGrayScale; + private GreenshotRadioButton radioBtnMonochrome; + private GreenshotGroupBox groupBoxPrintLayout; + private GreenshotCheckBox checkboxDateTime; + private GreenshotCheckBox checkboxAllowShrink; + private GreenshotCheckBox checkboxAllowEnlarge; + private GreenshotCheckBox checkboxAllowRotate; + private GreenshotCheckBox checkboxAllowCenter; + private GreenshotCheckBox checkbox_zoomer; + private GreenshotLabel label_icon_size; private System.Windows.Forms.NumericUpDown numericUpdownIconSize; } } diff --git a/src/Greenshot/Forms/SettingsForm.cs b/src/Greenshot/Forms/SettingsForm.cs index 1e08fd54f..6fc2aa094 100644 --- a/src/Greenshot/Forms/SettingsForm.cs +++ b/src/Greenshot/Forms/SettingsForm.cs @@ -28,15 +28,15 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; +using Greenshot.Base.UnmanagedHelpers; using Greenshot.Configuration; using Greenshot.Destinations; using Greenshot.Helpers; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; -using GreenshotPlugin.UnmanagedHelpers; using log4net; namespace Greenshot.Forms @@ -49,7 +49,7 @@ namespace Greenshot.Forms private static readonly ILog Log = LogManager.GetLogger(typeof(SettingsForm)); private readonly ToolTip _toolTip = new ToolTip(); private bool _inHotkey; - private int _daysbetweencheckPreviousValue; + private int _daysBetweenCheckPreviousValue; public SettingsForm() { @@ -92,7 +92,7 @@ namespace Greenshot.Forms // Changes for BUG-2077 numericUpDown_daysbetweencheck.ValueChanged += NumericUpDownDaysbetweencheckOnValueChanged; - _daysbetweencheckPreviousValue = (int) numericUpDown_daysbetweencheck.Value; + _daysBetweenCheckPreviousValue = (int) numericUpDown_daysbetweencheck.Value; DisplayPluginTab(); UpdateUi(); ExpertSettingsEnableState(false); @@ -112,7 +112,7 @@ namespace Greenshot.Forms // Check if we can into the forbidden range if (currentValue > 0 && currentValue < 7) { - if (_daysbetweencheckPreviousValue <= currentValue) + if (_daysBetweenCheckPreviousValue <= currentValue) { numericUpDown_daysbetweencheck.Value = 7; } @@ -132,7 +132,7 @@ namespace Greenshot.Forms numericUpDown_daysbetweencheck.Value = 365; } - _daysbetweencheckPreviousValue = (int) numericUpDown_daysbetweencheck.Value; + _daysBetweenCheckPreviousValue = (int) numericUpDown_daysbetweencheck.Value; } private void EnterHotkeyControl(object sender, EventArgs e) diff --git a/src/Greenshot/Forms/ToolStripMenuSelectList.cs b/src/Greenshot/Forms/ToolStripMenuSelectList.cs index 4880ec696..e2e52e2e4 100644 --- a/src/Greenshot/Forms/ToolStripMenuSelectList.cs +++ b/src/Greenshot/Forms/ToolStripMenuSelectList.cs @@ -19,12 +19,12 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core; using System; using System.Collections; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.IniFile; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; namespace Greenshot.Forms { diff --git a/src/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs b/src/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs index f2692729f..7e198e04f 100644 --- a/src/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs +++ b/src/Greenshot/Forms/TornEdgeSettingsForm.Designer.cs @@ -20,6 +20,7 @@ */ using System.Windows.Forms; +using Greenshot.Base.Controls; namespace Greenshot.Forms { partial class TornEdgeSettingsForm { @@ -51,23 +52,23 @@ namespace Greenshot.Forms { this.label3 = new System.Windows.Forms.Label(); this.offsetY = new System.Windows.Forms.NumericUpDown(); this.shadowDarkness = new System.Windows.Forms.TrackBar(); - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.labelDarkness = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelOffset = new GreenshotPlugin.Controls.GreenshotLabel(); - this.labelThickness = new GreenshotPlugin.Controls.GreenshotLabel(); + this.buttonOK = new GreenshotButton(); + this.buttonCancel = new GreenshotButton(); + this.labelDarkness = new GreenshotLabel(); + this.labelOffset = new GreenshotLabel(); + this.labelThickness = new GreenshotLabel(); this.toothsize = new System.Windows.Forms.NumericUpDown(); - this.label_toothsize = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_horizontaltoothrange = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label_toothsize = new GreenshotLabel(); + this.label_horizontaltoothrange = new GreenshotLabel(); this.horizontaltoothrange = new System.Windows.Forms.NumericUpDown(); - this.labelVerticaltoothrange = new GreenshotPlugin.Controls.GreenshotLabel(); + this.labelVerticaltoothrange = new GreenshotLabel(); this.verticaltoothrange = new System.Windows.Forms.NumericUpDown(); - this.top = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.right = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.bottom = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.left = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.shadowCheckbox = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.all = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.top = new GreenshotCheckBox(); + this.right = new GreenshotCheckBox(); + this.bottom = new GreenshotCheckBox(); + this.left = new GreenshotCheckBox(); + this.shadowCheckbox = new GreenshotCheckBox(); + this.all = new GreenshotCheckBox(); ((System.ComponentModel.ISupportInitialize)(this.thickness)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.offsetX)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.offsetY)).BeginInit(); @@ -418,22 +419,22 @@ namespace Greenshot.Forms { private System.Windows.Forms.Label label3; private System.Windows.Forms.NumericUpDown offsetY; private System.Windows.Forms.TrackBar shadowDarkness; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotLabel labelDarkness; - private GreenshotPlugin.Controls.GreenshotLabel labelOffset; - private GreenshotPlugin.Controls.GreenshotLabel labelThickness; + private GreenshotButton buttonOK; + private GreenshotButton buttonCancel; + private GreenshotLabel labelDarkness; + private GreenshotLabel labelOffset; + private GreenshotLabel labelThickness; private System.Windows.Forms.NumericUpDown toothsize; - private GreenshotPlugin.Controls.GreenshotLabel label_toothsize; - private GreenshotPlugin.Controls.GreenshotLabel label_horizontaltoothrange; + private GreenshotLabel label_toothsize; + private GreenshotLabel label_horizontaltoothrange; private System.Windows.Forms.NumericUpDown horizontaltoothrange; - private GreenshotPlugin.Controls.GreenshotLabel labelVerticaltoothrange; + private GreenshotLabel labelVerticaltoothrange; private System.Windows.Forms.NumericUpDown verticaltoothrange; - private GreenshotPlugin.Controls.GreenshotCheckBox top; - private GreenshotPlugin.Controls.GreenshotCheckBox right; - private GreenshotPlugin.Controls.GreenshotCheckBox bottom; - private GreenshotPlugin.Controls.GreenshotCheckBox left; - private GreenshotPlugin.Controls.GreenshotCheckBox shadowCheckbox; - private GreenshotPlugin.Controls.GreenshotCheckBox all; + private GreenshotCheckBox top; + private GreenshotCheckBox right; + private GreenshotCheckBox bottom; + private GreenshotCheckBox left; + private GreenshotCheckBox shadowCheckbox; + private GreenshotCheckBox all; } } \ No newline at end of file diff --git a/src/Greenshot/Forms/TornEdgeSettingsForm.cs b/src/Greenshot/Forms/TornEdgeSettingsForm.cs index dac953bd4..49548ce10 100644 --- a/src/Greenshot/Forms/TornEdgeSettingsForm.cs +++ b/src/Greenshot/Forms/TornEdgeSettingsForm.cs @@ -22,7 +22,7 @@ using System; using System.Drawing; using System.Windows.Forms; -using GreenshotPlugin.Effects; +using Greenshot.Base.Effects; namespace Greenshot.Forms { diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index a93eff8fc..0ff0f916b 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -37,7 +37,7 @@ - + diff --git a/src/Greenshot/GreenshotMain.cs b/src/Greenshot/GreenshotMain.cs index 753133f8e..a11b33930 100644 --- a/src/Greenshot/GreenshotMain.cs +++ b/src/Greenshot/GreenshotMain.cs @@ -18,46 +18,53 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + using System; using System.Globalization; using System.Net; using System.Reflection; using Greenshot.Forms; -namespace Greenshot { - /// - /// Description of Main. - /// - public class GreenshotMain { - static GreenshotMain() { - AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; - } +namespace Greenshot +{ + /// + /// Description of Main. + /// + public class GreenshotMain + { + static GreenshotMain() + { + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; + } - private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { - Assembly ayResult = null; - string sShortAssemblyName = args.Name.Split(',')[0]; - Assembly[] ayAssemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly ayAssembly in ayAssemblies) - { + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + Assembly ayResult = null; + string sShortAssemblyName = args.Name.Split(',')[0]; + Assembly[] ayAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly ayAssembly in ayAssemblies) + { if (sShortAssemblyName != ayAssembly.FullName.Split(',')[0]) { continue; } - ayResult = ayAssembly; - break; - } - return ayResult; - } - [STAThread] - public static void Main(string[] args) - { - // Enable TLS 1.2 support - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + ayResult = ayAssembly; + break; + } - CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; - CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; - MainForm.Start(args); - } - } -} + return ayResult; + } + + [STAThread] + public static void Main(string[] args) + { + // Enable TLS 1.2 support + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; + MainForm.Start(args); + } + } +} \ No newline at end of file diff --git a/src/Greenshot/Help/HelpFileLoader.cs b/src/Greenshot/Help/HelpFileLoader.cs index 69396490a..625d84ccf 100644 --- a/src/Greenshot/Help/HelpFileLoader.cs +++ b/src/Greenshot/Help/HelpFileLoader.cs @@ -19,9 +19,9 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core; using System.Diagnostics; using System.Net; +using Greenshot.Base.Core; using log4net; namespace Greenshot.Help diff --git a/src/Greenshot/Helpers/CaptureHelper.cs b/src/Greenshot/Helpers/CaptureHelper.cs index 5b90092d1..b42f3cc1e 100644 --- a/src/Greenshot/Helpers/CaptureHelper.cs +++ b/src/Greenshot/Helpers/CaptureHelper.cs @@ -23,8 +23,6 @@ using Greenshot.Configuration; using Greenshot.Destinations; using Greenshot.Drawing; using Greenshot.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.UnmanagedHelpers; using log4net; using System; using System.Collections.Generic; @@ -35,9 +33,10 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.UnmanagedHelpers; namespace Greenshot.Helpers { diff --git a/src/Greenshot/Helpers/CopyData.cs b/src/Greenshot/Helpers/CopyData.cs index e77ba045f..b927caa42 100644 --- a/src/Greenshot/Helpers/CopyData.cs +++ b/src/Greenshot/Helpers/CopyData.cs @@ -26,7 +26,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; -using GreenshotPlugin.Core; +using Greenshot.Base.Core; namespace Greenshot.Helpers { diff --git a/src/Greenshot/Helpers/DestinationHelper.cs b/src/Greenshot/Helpers/DestinationHelper.cs index 0e2288e36..671231c06 100644 --- a/src/Greenshot/Helpers/DestinationHelper.cs +++ b/src/Greenshot/Helpers/DestinationHelper.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; using System.Linq; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/IECaptureHelper.cs b/src/Greenshot/Helpers/IECaptureHelper.cs index 19b020567..bb0601db9 100644 --- a/src/Greenshot/Helpers/IECaptureHelper.cs +++ b/src/Greenshot/Helpers/IECaptureHelper.cs @@ -25,16 +25,16 @@ using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Runtime.InteropServices; +using Greenshot.Base.Controls; +using Greenshot.Base.Core; +using Greenshot.Base.IEInterop; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interop; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; using Greenshot.Configuration; using Greenshot.Helpers.IEInterop; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IEInterop; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interop; -using GreenshotPlugin.UnmanagedHelpers.Enums; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/IEInterop/IEContainer.cs b/src/Greenshot/Helpers/IEInterop/IEContainer.cs index cfae1481e..6ea590289 100644 --- a/src/Greenshot/Helpers/IEInterop/IEContainer.cs +++ b/src/Greenshot/Helpers/IEInterop/IEContainer.cs @@ -24,10 +24,10 @@ using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.Runtime.InteropServices; -using GreenshotPlugin.Core; -using GreenshotPlugin.IEInterop; +using Greenshot.Base.Core; +using Greenshot.Base.IEInterop; using log4net; -using IServiceProvider = GreenshotPlugin.Interop.IServiceProvider; +using IServiceProvider = Greenshot.Base.Interop.IServiceProvider; namespace Greenshot.Helpers.IEInterop { diff --git a/src/Greenshot/Helpers/MailHelper.cs b/src/Greenshot/Helpers/MailHelper.cs index 1f626a2da..17221609b 100644 --- a/src/Greenshot/Helpers/MailHelper.cs +++ b/src/Greenshot/Helpers/MailHelper.cs @@ -19,7 +19,6 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Core; using log4net; using System; using System.Collections; @@ -28,9 +27,10 @@ using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; namespace Greenshot.Helpers { diff --git a/src/Greenshot/Helpers/NotifyIconNotificationService.cs b/src/Greenshot/Helpers/NotifyIconNotificationService.cs index a00c3f660..fd9fb592f 100644 --- a/src/Greenshot/Helpers/NotifyIconNotificationService.cs +++ b/src/Greenshot/Helpers/NotifyIconNotificationService.cs @@ -21,9 +21,9 @@ using System; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/PluginHelper.cs b/src/Greenshot/Helpers/PluginHelper.cs index d8eb4f811..8c453cead 100644 --- a/src/Greenshot/Helpers/PluginHelper.cs +++ b/src/Greenshot/Helpers/PluginHelper.cs @@ -27,10 +27,10 @@ using System.IO; using System.Linq; using System.Reflection; using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using log4net; namespace Greenshot.Helpers @@ -186,9 +186,7 @@ namespace Greenshot.Helpers if (!Directory.Exists(path)) return pluginFiles; try { - pluginFiles = Directory.GetFiles(path, "*Plugin.dll", SearchOption.AllDirectories) - // Skip the GreenshotPlugin.dll itself - .Where(p => CultureInfo.CurrentCulture.CompareInfo.IndexOf(p, "GreenshotPlugin.dll", CompareOptions.IgnoreCase) < 0); + pluginFiles = Directory.GetFiles(path, "Greenshot.Plugin.*.dll", SearchOption.AllDirectories); } catch (Exception ex) { @@ -203,7 +201,7 @@ namespace Greenshot.Helpers /// public void LoadPlugins() { - List pluginFiles = new List(); + var pluginFiles = new List(); if (IniConfig.IsPortable) { @@ -220,11 +218,11 @@ namespace Greenshot.Helpers { try { - Assembly assembly = Assembly.LoadFrom(pluginFile); + var assembly = Assembly.LoadFrom(pluginFile); var assemblyName = assembly.GetName().Name; - var pluginEntryName = $"{assemblyName}.{assemblyName.Replace("Greenshot", string.Empty)}"; + var pluginEntryName = $"{assemblyName}.{assemblyName.Replace("Greenshot.Plugin.", string.Empty)}Plugin"; var pluginEntryType = assembly.GetType(pluginEntryName, false, true); var pluginAttribute = pluginEntryType.GetCustomAttribute(); @@ -235,7 +233,7 @@ namespace Greenshot.Helpers continue; } - IGreenshotPlugin plugin = (IGreenshotPlugin) Activator.CreateInstance(pluginEntryType); + var plugin = (IGreenshotPlugin) Activator.CreateInstance(pluginEntryType); if (plugin != null) { if (plugin.Initialize()) diff --git a/src/Greenshot/Helpers/PrintHelper.cs b/src/Greenshot/Helpers/PrintHelper.cs index 6ca6cb068..de0bd0eb5 100644 --- a/src/Greenshot/Helpers/PrintHelper.cs +++ b/src/Greenshot/Helpers/PrintHelper.cs @@ -23,13 +23,13 @@ using System; using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; +using Greenshot.Base.Core; +using Greenshot.Base.Effects; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; +using Greenshot.Base.Interfaces.Plugin; using Greenshot.Configuration; using Greenshot.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/ProcessorHelper.cs b/src/Greenshot/Helpers/ProcessorHelper.cs index d43473103..1532b9d2d 100644 --- a/src/Greenshot/Helpers/ProcessorHelper.cs +++ b/src/Greenshot/Helpers/ProcessorHelper.cs @@ -20,8 +20,8 @@ */ using System; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/SoundHelper.cs b/src/Greenshot/Helpers/SoundHelper.cs index 54a25df8c..bb9d86499 100644 --- a/src/Greenshot/Helpers/SoundHelper.cs +++ b/src/Greenshot/Helpers/SoundHelper.cs @@ -23,11 +23,11 @@ using System; using System.Reflection; using System.Resources; using System.Runtime.InteropServices; -using GreenshotPlugin.UnmanagedHelpers; -using GreenshotPlugin.Core; using System.IO; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.UnmanagedHelpers.Enums; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.UnmanagedHelpers; +using Greenshot.Base.UnmanagedHelpers.Enums; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Helpers/UpdateService.cs b/src/Greenshot/Helpers/UpdateService.cs index d4cb57a20..1fb10deab 100644 --- a/src/Greenshot/Helpers/UpdateService.cs +++ b/src/Greenshot/Helpers/UpdateService.cs @@ -24,11 +24,11 @@ using System.Threading; using System.Threading.Tasks; using Dapplo.HttpExtensions; using Dapplo.HttpExtensions.JsonNet; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using Greenshot.Configuration; using Greenshot.Helpers.Entities; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; using log4net; namespace Greenshot.Helpers diff --git a/src/Greenshot/Memento/AddElementMemento.cs b/src/Greenshot/Memento/AddElementMemento.cs index 13b6a5749..23f25fcb4 100644 --- a/src/Greenshot/Memento/AddElementMemento.cs +++ b/src/Greenshot/Memento/AddElementMemento.cs @@ -20,8 +20,8 @@ */ using System; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/AddElementsMemento.cs b/src/Greenshot/Memento/AddElementsMemento.cs index 1701a4d29..f3ad7fee4 100644 --- a/src/Greenshot/Memento/AddElementsMemento.cs +++ b/src/Greenshot/Memento/AddElementsMemento.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/ChangeFieldHolderMemento.cs b/src/Greenshot/Memento/ChangeFieldHolderMemento.cs index b8cd718e3..7018557b9 100644 --- a/src/Greenshot/Memento/ChangeFieldHolderMemento.cs +++ b/src/Greenshot/Memento/ChangeFieldHolderMemento.cs @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/DeleteElementMemento.cs b/src/Greenshot/Memento/DeleteElementMemento.cs index b42992007..b7172fd60 100644 --- a/src/Greenshot/Memento/DeleteElementMemento.cs +++ b/src/Greenshot/Memento/DeleteElementMemento.cs @@ -20,8 +20,8 @@ */ using System; +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/DeleteElementsMemento.cs b/src/Greenshot/Memento/DeleteElementsMemento.cs index 096df18d3..890831ed5 100644 --- a/src/Greenshot/Memento/DeleteElementsMemento.cs +++ b/src/Greenshot/Memento/DeleteElementsMemento.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs b/src/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs index 6db480c39..61ba7bdf8 100644 --- a/src/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs +++ b/src/Greenshot/Memento/DrawableContainerBoundsChangeMemento.cs @@ -20,10 +20,10 @@ */ using Greenshot.Drawing; -using GreenshotPlugin.Core; using System.Collections.Generic; using System.Drawing; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Core; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs b/src/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs index 23e463b1a..72b3de10f 100644 --- a/src/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs +++ b/src/Greenshot/Memento/SurfaceBackgroundChangeMemento.cs @@ -22,7 +22,7 @@ using Greenshot.Drawing; using System.Drawing; using System.Drawing.Drawing2D; -using GreenshotPlugin.Interfaces.Drawing; +using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Memento/TextChangeMemento.cs b/src/Greenshot/Memento/TextChangeMemento.cs index faabd493f..eb1a3baed 100644 --- a/src/Greenshot/Memento/TextChangeMemento.cs +++ b/src/Greenshot/Memento/TextChangeMemento.cs @@ -19,8 +19,8 @@ * along with this program. If not, see . */ +using Greenshot.Base.Interfaces.Drawing; using Greenshot.Drawing; -using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Memento { diff --git a/src/Greenshot/Processors/TitleFixProcessor.cs b/src/Greenshot/Processors/TitleFixProcessor.cs index f4dcba9f9..c5a286eb4 100644 --- a/src/Greenshot/Processors/TitleFixProcessor.cs +++ b/src/Greenshot/Processors/TitleFixProcessor.cs @@ -21,9 +21,9 @@ using System.Collections.Generic; using System.Text.RegularExpressions; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; +using Greenshot.Base.Core; +using Greenshot.Base.IniFile; +using Greenshot.Base.Interfaces; using log4net; namespace Greenshot.Processors diff --git a/src/Greenshot/log4net-debug.xml b/src/Greenshot/log4net-debug.xml index 554edbeb3..f41436235 100644 --- a/src/Greenshot/log4net-debug.xml +++ b/src/Greenshot/log4net-debug.xml @@ -6,7 +6,7 @@ - + diff --git a/src/Greenshot/log4net.xml b/src/Greenshot/log4net.xml index 364756dbf..cc232d052 100644 --- a/src/Greenshot/log4net.xml +++ b/src/Greenshot/log4net.xml @@ -6,7 +6,7 @@ - + diff --git a/src/GreenshotPlugin/Interfaces/Plugin/HotKeyHandler.cs b/src/GreenshotPlugin/Interfaces/Plugin/HotKeyHandler.cs deleted file mode 100644 index 2db074f62..000000000 --- a/src/GreenshotPlugin/Interfaces/Plugin/HotKeyHandler.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace GreenshotPlugin.Interfaces.Plugin -{ - public delegate void HotKeyHandler(); -} \ No newline at end of file