Renamed the GreenshotPlugin to Greenshot.Base

This commit is contained in:
Robin Krom 2021-03-28 21:01:29 +02:00
parent e8c0b307ee
commit 79cdca03eb
No known key found for this signature in database
GPG key ID: BCC01364F1371490
423 changed files with 30044 additions and 30000 deletions

View file

@ -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

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Windows.Forms;
using GreenshotPlugin.UnmanagedHelpers;
using GreenshotPlugin.UnmanagedHelpers.Enums;
using log4net;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Extend this Form to have the possibility for animations on your form
/// </summary>
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;
/// <summary>
/// This flag specifies if any animation is used
/// </summary>
protected bool EnableAnimation { get; set; }
/// <summary>
/// Vertical Refresh Rate
/// </summary>
protected int VRefresh
{
get
{
if (_vRefresh == 0)
{
// get te hDC of the desktop to get the VREFRESH
using SafeWindowDcHandle desktopHandle = SafeWindowDcHandle.FromDesktop();
_vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
}
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
// As there is currently no know way to get the default, we guess it.
if (_vRefresh <= 1)
{
_vRefresh = DEFAULT_VREFRESH;
}
return _vRefresh;
}
}
/// <summary>
/// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections
/// </summary>
protected bool IsTerminalServerSession => !coreConfiguration.DisableRDPOptimizing && (coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession);
/// <summary>
/// Calculate the amount of frames that an animation takes
/// </summary>
/// <param name="milliseconds"></param>
/// <returns>Number of frames, 1 if in Terminal Server Session</returns>
protected int FramesForMillis(int milliseconds)
{
// If we are in a Terminal Server Session we return 1
if (IsTerminalServerSession)
{
return 1;
}
return milliseconds / VRefresh;
}
/// <summary>
/// Initialize the animation
/// </summary>
protected AnimatingForm()
{
Load += delegate
{
if (!EnableAnimation)
{
return;
}
_timer = new Timer
{
Interval = 1000 / VRefresh
};
_timer.Tick += timer_Tick;
_timer.Start();
};
// Unregister at close
FormClosing += delegate { _timer?.Stop(); };
}
/// <summary>
/// The tick handler initiates the animation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
try
{
Animate();
}
catch (Exception ex)
{
Log.Warn("An exception occured while animating:", ex);
}
}
/// <summary>
/// This method will be called every frame, so implement your animation/redraw logic here.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Windows.Forms;
using Greenshot.Base.UnmanagedHelpers;
using Greenshot.Base.UnmanagedHelpers.Enums;
using log4net;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Extend this Form to have the possibility for animations on your form
/// </summary>
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;
/// <summary>
/// This flag specifies if any animation is used
/// </summary>
protected bool EnableAnimation { get; set; }
/// <summary>
/// Vertical Refresh Rate
/// </summary>
protected int VRefresh
{
get
{
if (_vRefresh == 0)
{
// get te hDC of the desktop to get the VREFRESH
using SafeWindowDcHandle desktopHandle = SafeWindowDcHandle.FromDesktop();
_vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
}
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
// As there is currently no know way to get the default, we guess it.
if (_vRefresh <= 1)
{
_vRefresh = DEFAULT_VREFRESH;
}
return _vRefresh;
}
}
/// <summary>
/// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections
/// </summary>
protected bool IsTerminalServerSession => !coreConfiguration.DisableRDPOptimizing && (coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession);
/// <summary>
/// Calculate the amount of frames that an animation takes
/// </summary>
/// <param name="milliseconds"></param>
/// <returns>Number of frames, 1 if in Terminal Server Session</returns>
protected int FramesForMillis(int milliseconds)
{
// If we are in a Terminal Server Session we return 1
if (IsTerminalServerSession)
{
return 1;
}
return milliseconds / VRefresh;
}
/// <summary>
/// Initialize the animation
/// </summary>
protected AnimatingForm()
{
Load += delegate
{
if (!EnableAnimation)
{
return;
}
_timer = new Timer
{
Interval = 1000 / VRefresh
};
_timer.Tick += timer_Tick;
_timer.Start();
};
// Unregister at close
FormClosing += delegate { _timer?.Stop(); };
}
/// <summary>
/// The tick handler initiates the animation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Tick(object sender, EventArgs e)
{
try
{
Animate();
}
catch (Exception ex)
{
Log.Warn("An exception occured while animating:", ex);
}
}
/// <summary>
/// This method will be called every frame, so implement your animation/redraw logic here.
/// </summary>
protected virtual void Animate()
{
throw new NotImplementedException();
}
}
}

View file

@ -1,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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
partial class BackgroundForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls
{
partial class BackgroundForm
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using Greenshot.Base.Core;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
namespace Greenshot.Base.Controls
{
/// <summary>
/// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
/// </summary>
public class FormWithoutActivation : Form
{
protected override bool ShowWithoutActivation
{
get { return true; }
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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; }
}
}

View file

@ -22,7 +22,7 @@
using System.Collections;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
namespace Greenshot.Base.Controls
{
/// <summary>
/// This class is an implementation of the 'IComparer' interface.

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
/// <summary>
/// This is a method to popululate the ComboBox
/// with the items from the enumeration
/// </summary>
/// <param name="enumType">TEnum to populate with</param>
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));
}
}
/// <summary>
/// Store the selected value internally
/// </summary>
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;
}
/// <summary>
/// Get the selected enum value from the combobox, uses generics
/// </summary>
/// <returns>The enum value of the combobox</returns>
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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
/// <summary>
/// This is a method to popululate the ComboBox
/// with the items from the enumeration
/// </summary>
/// <param name="enumType">TEnum to populate with</param>
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));
}
}
/// <summary>
/// Store the selected value internally
/// </summary>
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;
}
/// <summary>
/// Get the selected enum value from the combobox, uses generics
/// </summary>
/// <returns>The enum value of the combobox</returns>
public Enum GetSelectedEnum()
{
return _selectedEnum;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Windows.Forms;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Description of GreenshotCheckbox.
/// </summary>
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
public interface IGreenshotConfigBindable
{
/// <summary>
/// The class where the property-value is stored
/// </summary>
string SectionName { get; set; }
/// <summary>
/// Path to the property value which will be mapped with this control
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls
{
public interface IGreenshotConfigBindable
{
/// <summary>
/// The class where the property-value is stored
/// </summary>
string SectionName { get; set; }
/// <summary>
/// Path to the property value which will be mapped with this control
/// </summary>
string PropertyName { get; set; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls
{
/// <summary>
/// This interface describes the designer fields that need to be implemented for Greenshot controls
/// </summary>
public interface IGreenshotLanguageBindable
{
/// <summary>
/// Language key to use to fill the Text value with
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls
{
/// <summary>
/// This interface describes the designer fields that need to be implemented for Greenshot controls
/// </summary>
public interface IGreenshotLanguageBindable
{
/// <summary>
/// Language key to use to fill the Text value with
/// </summary>
string LanguageKey { get; set; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls {
partial class OAuthLoginForm {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls {
partial class OAuthLoginForm {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using GreenshotPlugin.Core;
using log4net;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application
/// </summary>
public sealed partial class OAuthLoginForm : Form
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
private readonly string _callbackUrl;
public IDictionary<string, string> 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));
}
/// <summary>
/// Make sure the form is visible
/// </summary>
/// <param name="e">EventArgs</param>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Greenshot.Base.Core;
using log4net;
namespace Greenshot.Base.Controls
{
/// <summary>
/// The OAuthLoginForm is used to allow the user to authorize Greenshot with an "Oauth" application
/// </summary>
public sealed partial class OAuthLoginForm : Form
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm));
private readonly string _callbackUrl;
public IDictionary<string, string> 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));
}
/// <summary>
/// Make sure the form is visible
/// </summary>
/// <param name="e">EventArgs</param>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls {
partial class PleaseWaitForm {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent() {
this.label_pleasewait = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label_pleasewait
//
this.label_pleasewait.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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls {
partial class PleaseWaitForm {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent() {
this.label_pleasewait = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label_pleasewait
//
this.label_pleasewait.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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Windows.Forms;
using System.Threading;
using GreenshotPlugin.Core;
using log4net;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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();
}
/// <summary>
/// Prevent the close-window button showing
/// </summary>
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ClassStyle |= CP_NOCLOSE_BUTTON;
return createParams;
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="title">The title of the form (and Thread)</param>
/// <param name="text">The text in the form</param>
/// <param name="waitDelegate">delegate { with your code }</param>
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;
}
}
/// <summary>
/// Called if the cancel button is clicked, will use Thread.Abort()
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Threading;
using System.Windows.Forms;
using Greenshot.Base.Core;
using log4net;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Description of PleaseWaitForm.
/// </summary>
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();
}
/// <summary>
/// Prevent the close-window button showing
/// </summary>
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ClassStyle |= CP_NOCLOSE_BUTTON;
return createParams;
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="title">The title of the form (and Thread)</param>
/// <param name="text">The text in the form</param>
/// <param name="waitDelegate">delegate { with your code }</param>
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;
}
}
/// <summary>
/// Called if the cancel button is clicked, will use Thread.Abort()
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CancelButtonClick(object sender, EventArgs e)
{
LOG.DebugFormat("Cancel clicked on {0}", _title);
cancelButton.Enabled = false;
_waitFor.Abort();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Controls {
partial class QualityDialog {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
this.SuspendLayout();
//
// label_choosejpegquality
//
this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47);
this.label_choosejpegquality.Name = "label_choosejpegquality";
this.label_choosejpegquality.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 <http://www.gnu.org/licenses/>.
*/
namespace Greenshot.Base.Controls {
partial class QualityDialog {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label_choosejpegquality = new 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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces.Plugin;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Description of JpegQualityDialog.
/// </summary>
public partial class QualityDialog : GreenshotForm
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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 <http://www.gnu.org/licenses/>.
*/
using System;
using Greenshot.Base.Core;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces.Plugin;
namespace Greenshot.Base.Controls
{
/// <summary>
/// Description of JpegQualityDialog.
/// </summary>
public partial class QualityDialog : GreenshotForm
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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();
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using System.Windows.Forms;
using GreenshotPlugin.Core;
using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces;
using log4net;
namespace GreenshotPlugin.Controls
{
/// <summary>
/// Custom dialog for saving images, wraps SaveFileDialog.
/// For some reason SFD is sealed :(
/// </summary>
public class SaveImageFileDialog : IDisposable
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(SaveImageFileDialog));
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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);
}
}
/// <summary>
/// filename exactly as typed in the filename field
/// </summary>
public string FileName
{
get { return SaveFileDialog.FileName; }
set { SaveFileDialog.FileName = value; }
}
/// <summary>
/// initial directory of the dialog
/// </summary>
public string InitialDirectory
{
get { return SaveFileDialog.InitialDirectory; }
set { SaveFileDialog.InitialDirectory = value; }
}
/// <summary>
/// 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.
/// </summary>
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);
}
}
/// <summary>
/// gets or sets selected extension
/// </summary>
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;
}
/// <summary>
/// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Custom dialog for saving images, wraps SaveFileDialog.
/// For some reason SFD is sealed :(
/// </summary>
public class SaveImageFileDialog : IDisposable
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(SaveImageFileDialog));
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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);
}
}
/// <summary>
/// filename exactly as typed in the filename field
/// </summary>
public string FileName
{
get { return SaveFileDialog.FileName; }
set { SaveFileDialog.FileName = value; }
}
/// <summary>
/// initial directory of the dialog
/// </summary>
public string InitialDirectory
{
get { return SaveFileDialog.InitialDirectory; }
set { SaveFileDialog.InitialDirectory = value; }
}
/// <summary>
/// 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.
/// </summary>
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);
}
}
/// <summary>
/// gets or sets selected extension
/// </summary>
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;
}
/// <summary>
/// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// 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.
/// </summary>
public sealed class ThumbnailForm : FormWithoutActivation
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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;
}
/// <summary>
/// Show the thumbnail of the supplied window above (or under) the parent Control
/// </summary>
/// <param name="window">WindowDetails</param>
/// <param name="parentControl">Control</param>
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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// 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.
/// </summary>
public sealed class ThumbnailForm : FormWithoutActivation
{
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
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;
}
/// <summary>
/// Show the thumbnail of the supplied window above (or under) the parent Control
/// </summary>
/// <param name="window">WindowDetails</param>
/// <param name="parentControl">Control</param>
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);
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of AbstractDestination.
/// </summary>
public abstract class AbstractDestination : IDestination
{
private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
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<IDestination> 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);
/// <summary>
/// A small helper method to perform some default destination actions, like inform the surface of the export
/// </summary>
/// <param name="exportInformation"></param>
/// <param name="surface"></param>
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;
}
/// <summary>
/// Helper method to add events which set the tag, this way we can see why there might be a close.
/// </summary>
/// <param name="menuItem">Item to add the events to</param>
/// <param name="menu">Menu to set the tag</param>
/// <param name="tagValue">Value for the tag</param>
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;
};
}
}
/// <summary>
/// This method will create and show the destination picker menu
/// </summary>
/// <param name="addDynamics">Boolean if the dynamic values also need to be added</param>
/// <param name="surface">The surface which can be exported</param>
/// <param name="captureDetails">Details for the surface</param>
/// <param name="destinations">The list of destinations to show</param>
/// <returns></returns>
public ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable<IDestination> 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;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="menu"></param>
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<NotifyIcon>().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;
}
}
}
/// <summary>
/// Return a menu item
/// </summary>
/// <param name="menu"></param>
/// <param name="addDynamics"></param>
/// <param name="destinationClickHandler"></param>
/// <returns>ToolStripMenuItem</returns>
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<IDestination> subDestinations = new List<IDestination>();
// 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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of AbstractDestination.
/// </summary>
public abstract class AbstractDestination : IDestination
{
private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
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<IDestination> 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);
/// <summary>
/// A small helper method to perform some default destination actions, like inform the surface of the export
/// </summary>
/// <param name="exportInformation"></param>
/// <param name="surface"></param>
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;
}
/// <summary>
/// Helper method to add events which set the tag, this way we can see why there might be a close.
/// </summary>
/// <param name="menuItem">Item to add the events to</param>
/// <param name="menu">Menu to set the tag</param>
/// <param name="tagValue">Value for the tag</param>
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;
};
}
}
/// <summary>
/// This method will create and show the destination picker menu
/// </summary>
/// <param name="addDynamics">Boolean if the dynamic values also need to be added</param>
/// <param name="surface">The surface which can be exported</param>
/// <param name="captureDetails">Details for the surface</param>
/// <param name="destinations">The list of destinations to show</param>
/// <returns></returns>
public ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable<IDestination> 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;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="menu"></param>
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<NotifyIcon>().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;
}
}
}
/// <summary>
/// Return a menu item
/// </summary>
/// <param name="menu"></param>
/// <param name="addDynamics"></param>
/// <param name="destinationClickHandler"></param>
/// <returns>ToolStripMenuItem</returns>
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<IDestination> subDestinations = new List<IDestination>();
// 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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using GreenshotPlugin.Interfaces;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Description of AbstractProcessor.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using Greenshot.Base.Interfaces;
namespace Greenshot.Base.Core
{
/// <summary>
/// Description of AbstractProcessor.
/// </summary>
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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Accessibility;
namespace GreenshotPlugin.Core
{
/// <summary>
/// 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!?
/// </summary>
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<Accessible> list = new List<Accessible>(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<string> IETabCaptions
{
get
{
var captionList = new List<string>();
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<string> 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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Accessibility;
namespace Greenshot.Base.Core
{
/// <summary>
/// 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!?
/// </summary>
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<Accessible> list = new List<Accessible>(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<string> IETabCaptions
{
get
{
var captionList = new List<string>();
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<string> 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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
namespace GreenshotPlugin.Core
{
/// <summary>
/// A helper class which does the mashalling for structs
/// </summary>
public static class BinaryStructHelper
{
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="bytes">byte[]</param>
/// <returns>struct</returns>
public static T FromByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="intPtr">Pointer to the structor to return</param>
/// <returns>struct</returns>
public static T FromIntPtr<T>(IntPtr intPtr) where T : struct
{
object obj = Marshal.PtrToStructure(intPtr, typeof(T));
return (T) obj;
}
/// <summary>
/// copy a struct to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="obj">struct</param>
/// <returns>byte[]</returns>
public static byte[] ToByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// copy a struct from a pointer to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="ptr">IntPtr to struct</param>
/// <returns>byte[]</returns>
public static byte[] FromPtrToByteArray<T>(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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
namespace Greenshot.Base.Core
{
/// <summary>
/// A helper class which does the mashalling for structs
/// </summary>
public static class BinaryStructHelper
{
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="bytes">byte[]</param>
/// <returns>struct</returns>
public static T FromByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// Get a struct from a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="intPtr">Pointer to the structor to return</param>
/// <returns>struct</returns>
public static T FromIntPtr<T>(IntPtr intPtr) where T : struct
{
object obj = Marshal.PtrToStructure(intPtr, typeof(T));
return (T) obj;
}
/// <summary>
/// copy a struct to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="obj">struct</param>
/// <returns>byte[]</returns>
public static byte[] ToByteArray<T>(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<T>(ptr);
}
finally
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// copy a struct from a pointer to a byte array
/// </summary>
/// <typeparam name="T">typeof struct</typeparam>
/// <param name="ptr">IntPtr to struct</param>
/// <returns>byte[]</returns>
public static byte[] FromPtrToByteArray<T>(IntPtr ptr) where T : struct
{
int size = Marshal.SizeOf(typeof(T));
byte[] bytes = new byte[size];
Marshal.Copy(ptr, bytes, 0, size);
return bytes;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Timers;
using log4net;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Cache class
/// </summary>
/// <typeparam name="TK">Type of key</typeparam>
/// <typeparam name="TV">Type of value</typeparam>
public class Cache<TK, TV>
{
private static readonly ILog Log = LogManager.GetLogger(typeof(Cache<TK, TV>));
private readonly IDictionary<TK, TV> _internalCache = new Dictionary<TK, TV>();
private readonly object _lockObject = new object();
private readonly int _secondsToExpire = 10;
private readonly CacheObjectExpired _expiredCallback;
public delegate void CacheObjectExpired(TK key, TV cacheValue);
/// <summary>
/// Initialize the cache
/// </summary>
public Cache()
{
}
/// <summary>
/// Initialize the cache
/// </summary>
/// <param name="expiredCallback"></param>
public Cache(CacheObjectExpired expiredCallback) : this()
{
_expiredCallback = expiredCallback;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
public Cache(int secondsToExpire) : this()
{
_secondsToExpire = secondsToExpire;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
/// <param name="expiredCallback"></param>
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback)
{
_secondsToExpire = secondsToExpire;
}
/// <summary>
/// Enumerable for the values in the cache
/// </summary>
public IEnumerable<TV> Elements
{
get
{
List<TV> elements = new List<TV>();
lock (_lockObject)
{
foreach (TV element in _internalCache.Values)
{
elements.Add(element);
}
}
foreach (TV element in elements)
{
yield return element;
}
}
}
/// <summary>
/// Get the value by key from the cache
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public TV this[TK key]
{
get
{
TV result = default;
lock (_lockObject)
{
if (_internalCache.ContainsKey(key))
{
result = _internalCache[key];
}
}
return result;
}
}
/// <summary>
/// Contains
/// </summary>
/// <param name="key"></param>
/// <returns>true if the cache contains the key</returns>
public bool Contains(TK key)
{
lock (_lockObject)
{
return _internalCache.ContainsKey(key);
}
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(TK key, TV value)
{
Add(key, value, null);
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="secondsToExpire">optional value for the seconds to expire</param>
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);
}
}
}
/// <summary>
/// Remove item from cache
/// </summary>
/// <param name="key"></param>
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);
}
}
/// <summary>
/// A cache item
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Timers;
using log4net;
namespace Greenshot.Base.Core
{
/// <summary>
/// Cache class
/// </summary>
/// <typeparam name="TK">Type of key</typeparam>
/// <typeparam name="TV">Type of value</typeparam>
public class Cache<TK, TV>
{
private static readonly ILog Log = LogManager.GetLogger(typeof(Cache<TK, TV>));
private readonly IDictionary<TK, TV> _internalCache = new Dictionary<TK, TV>();
private readonly object _lockObject = new object();
private readonly int _secondsToExpire = 10;
private readonly CacheObjectExpired _expiredCallback;
public delegate void CacheObjectExpired(TK key, TV cacheValue);
/// <summary>
/// Initialize the cache
/// </summary>
public Cache()
{
}
/// <summary>
/// Initialize the cache
/// </summary>
/// <param name="expiredCallback"></param>
public Cache(CacheObjectExpired expiredCallback) : this()
{
_expiredCallback = expiredCallback;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
public Cache(int secondsToExpire) : this()
{
_secondsToExpire = secondsToExpire;
}
/// <summary>
/// Initialize the cache with a expire setting
/// </summary>
/// <param name="secondsToExpire"></param>
/// <param name="expiredCallback"></param>
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback) : this(expiredCallback)
{
_secondsToExpire = secondsToExpire;
}
/// <summary>
/// Enumerable for the values in the cache
/// </summary>
public IEnumerable<TV> Elements
{
get
{
List<TV> elements = new List<TV>();
lock (_lockObject)
{
foreach (TV element in _internalCache.Values)
{
elements.Add(element);
}
}
foreach (TV element in elements)
{
yield return element;
}
}
}
/// <summary>
/// Get the value by key from the cache
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public TV this[TK key]
{
get
{
TV result = default;
lock (_lockObject)
{
if (_internalCache.ContainsKey(key))
{
result = _internalCache[key];
}
}
return result;
}
}
/// <summary>
/// Contains
/// </summary>
/// <param name="key"></param>
/// <returns>true if the cache contains the key</returns>
public bool Contains(TK key)
{
lock (_lockObject)
{
return _internalCache.ContainsKey(key);
}
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(TK key, TV value)
{
Add(key, value, null);
}
/// <summary>
/// Add a value to the cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="secondsToExpire">optional value for the seconds to expire</param>
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);
}
}
}
/// <summary>
/// Remove item from cache
/// </summary>
/// <param name="key"></param>
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);
}
}
/// <summary>
/// A cache item
/// </summary>
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;
}
}
}
}

View file

@ -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
{
/// <summary>
/// This class is used to pass an instance of the "Capture" around

View file

@ -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
{
/// <summary>
/// This Class is used to pass details about the capture around.

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
namespace GreenshotPlugin.Core
{
/// <summary>
/// This is the method signature which is used to capture a rectangle from the screen.
/// </summary>
/// <param name="captureBounds"></param>
/// <returns>Captured Bitmap</returns>
public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
/// <summary>
/// This is a hack to experiment with different screen capture routines
/// </summary>
public static class CaptureHandler
{
/// <summary>
/// By changing this value, null is default
/// </summary>
public static CaptureScreenRectangleHandler CaptureScreenRectangle { get; set; }
}
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
namespace Greenshot.Base.Core
{
/// <summary>
/// This is the method signature which is used to capture a rectangle from the screen.
/// </summary>
/// <param name="captureBounds"></param>
/// <returns>Captured Bitmap</returns>
public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
/// <summary>
/// This is a hack to experiment with different screen capture routines
/// </summary>
public static class CaptureHandler
{
/// <summary>
/// By changing this value, null is default
/// </summary>
public static CaptureScreenRectangleHandler CaptureScreenRectangle { get; set; }
}
}

View file

@ -1,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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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()
{
}
}
}

View file

@ -19,15 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// This handles DPI changes see

View file

@ -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]);
}
}
}

View file

@ -19,7 +19,7 @@
using System.Diagnostics.CodeAnalysis;
namespace GreenshotPlugin.Core.Enums
namespace Greenshot.Base.Core.Enums
{
/// <summary>
/// The HRESULT represents Windows error codes

View file

@ -3,7 +3,7 @@
using System;
namespace GreenshotPlugin.Core.Enums
namespace Greenshot.Base.Core.Enums
{
/// <summary>
/// See

View file

@ -3,7 +3,7 @@
using System;
namespace GreenshotPlugin.Core.Enums
namespace Greenshot.Base.Core.Enums
{
/// <summary>
/// Flags for the MonitorFromRect / MonitorFromWindow "flags" field

View file

@ -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
{
/// <summary>
/// Description of EnvironmentInfo.

View file

@ -21,7 +21,7 @@
using System;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
public class EventDelay
{

View file

@ -1,55 +1,55 @@
using System;
using System.Diagnostics;
using System.IO;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Simple utility for the explorer
/// </summary>
public static class ExplorerHelper
{
/// <summary>
/// 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.
/// </summary>
/// <param name="path">Path to file or directory</param>
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
{
/// <summary>
/// Simple utility for the explorer
/// </summary>
public static class ExplorerHelper
{
/// <summary>
/// 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.
/// </summary>
/// <param name="path">Path to file or directory</param>
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;
}
}
}

View file

@ -1,7 +1,7 @@
using System;
using System.Text.RegularExpressions;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
/// <summary>
/// Basic Fraction (Rational) numbers with features only needed to represent scale factors.

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Drawing;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Centralized storage of the icons & bitmaps
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Drawing;
namespace Greenshot.Base.Core
{
/// <summary>
/// Centralized storage of the icons & bitmaps
/// </summary>
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");
}
}
}

View file

@ -1,471 +1,471 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="Greenshot.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
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
</value>
</data>
<data name="Checkerboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
</value>
</data>
<data name="Email.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Printer.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Clipboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<data name="Save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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=
</value>
</data>
<data name="Close.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
</value>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="Greenshot.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
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
</value>
</data>
<data name="Checkerboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
</value>
</data>
<data name="Email.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Printer.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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==
</value>
</data>
<data name="Clipboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<data name="Save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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=
</value>
</data>
<data name="Close.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
</value>
</data>
</root>

View file

@ -17,10 +17,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using GreenshotPlugin.Core.Enums;
using System.Diagnostics.Contracts;
using Greenshot.Base.Core.Enums;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
/// <summary>
/// Extensions to handle the HResult

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using log4net;
using Microsoft.Win32;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Description of IEHelper.
/// </summary>
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";
/// <summary>
/// Get the current browser version
/// </summary>
/// <returns>int with browser version</returns>
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;
}
}
/// <summary>
/// Get the highest possible version for the embedded browser
/// </summary>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
/// <returns>IE Feature</returns>
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;
}
/// <summary>
/// Fix browser version to the highest possible
/// </summary>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
public static void FixBrowserVersion(bool ignoreDoctype = true)
{
var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
FixBrowserVersion(applicationName, ignoreDoctype);
}
/// <summary>
/// Fix the browser version for the specified application
/// </summary>
/// <param name="applicationName">Name of the process</param>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true)
{
FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype));
}
/// <summary>
/// Fix the browser version for the specified application
/// </summary>
/// <param name="applicationName">Name of the process</param>
/// <param name="ieVersion">
/// Version, see
/// <a href="https://msdn.microsoft.com/en-us/library/ee330730(v=vs.85).aspx#browser_emulation">Browser Emulation</a>
/// </param>
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
}
/// <summary>
/// Make the change to the registry
/// </summary>
/// <param name="root">HKEY_CURRENT_USER or something</param>
/// <param name="applicationName">Name of the executable</param>
/// <param name="ieFeatureVersion">Version to use</param>
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);
}
}
/// <summary>
/// Find the DirectUI window for MSAA (Accessible)
/// </summary>
/// <param name="browserWindowDetails">The browser WindowDetails</param>
/// <returns>WindowDetails for the DirectUI window</returns>
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;
}
/// <summary>
/// Return an IEnumerable with the currently opened IE urls
/// </summary>
/// <returns></returns>
public static IEnumerable<string> 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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using log4net;
using Microsoft.Win32;
namespace Greenshot.Base.Core
{
/// <summary>
/// Description of IEHelper.
/// </summary>
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";
/// <summary>
/// Get the current browser version
/// </summary>
/// <returns>int with browser version</returns>
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;
}
}
/// <summary>
/// Get the highest possible version for the embedded browser
/// </summary>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
/// <returns>IE Feature</returns>
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;
}
/// <summary>
/// Fix browser version to the highest possible
/// </summary>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
public static void FixBrowserVersion(bool ignoreDoctype = true)
{
var applicationName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
FixBrowserVersion(applicationName, ignoreDoctype);
}
/// <summary>
/// Fix the browser version for the specified application
/// </summary>
/// <param name="applicationName">Name of the process</param>
/// <param name="ignoreDoctype">true to ignore the doctype when loading a page</param>
public static void FixBrowserVersion(string applicationName, bool ignoreDoctype = true)
{
FixBrowserVersion(applicationName, GetEmbVersion(ignoreDoctype));
}
/// <summary>
/// Fix the browser version for the specified application
/// </summary>
/// <param name="applicationName">Name of the process</param>
/// <param name="ieVersion">
/// Version, see
/// <a href="https://msdn.microsoft.com/en-us/library/ee330730(v=vs.85).aspx#browser_emulation">Browser Emulation</a>
/// </param>
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
}
/// <summary>
/// Make the change to the registry
/// </summary>
/// <param name="root">HKEY_CURRENT_USER or something</param>
/// <param name="applicationName">Name of the executable</param>
/// <param name="ieFeatureVersion">Version to use</param>
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);
}
}
/// <summary>
/// Find the DirectUI window for MSAA (Accessible)
/// </summary>
/// <param name="browserWindowDetails">The browser WindowDetails</param>
/// <returns>WindowDetails for the DirectUI window</returns>
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;
}
/// <summary>
/// Return an IEnumerable with the currently opened IE urls
/// </summary>
/// <returns></returns>
public static IEnumerable<string> 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;
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace GreenshotPlugin.Core
{
/// <summary>
/// The image interface, this abstracts an image
/// </summary>
public interface IImage : IDisposable
{
/// <summary>
/// Height of the image, can be set to change
/// </summary>
int Height { get; set; }
/// <summary>
/// Width of the image, can be set to change.
/// </summary>
int Width { get; set; }
/// <summary>
/// Size of the image
/// </summary>
Size Size { get; }
/// <summary>
/// Pixelformat of the underlying image
/// </summary>
PixelFormat PixelFormat { get; }
/// <summary>
/// Vertical resolution of the underlying image
/// </summary>
float VerticalResolution { get; }
/// <summary>
/// Horizontal resolution of the underlying image
/// </summary>
float HorizontalResolution { get; }
/// <summary>
/// Unterlying image, or an on demand rendered version with different attributes as the original
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace Greenshot.Base.Core
{
/// <summary>
/// The image interface, this abstracts an image
/// </summary>
public interface IImage : IDisposable
{
/// <summary>
/// Height of the image, can be set to change
/// </summary>
int Height { get; set; }
/// <summary>
/// Width of the image, can be set to change.
/// </summary>
int Width { get; set; }
/// <summary>
/// Size of the image
/// </summary>
Size Size { get; }
/// <summary>
/// Pixelformat of the underlying image
/// </summary>
PixelFormat PixelFormat { get; }
/// <summary>
/// Vertical resolution of the underlying image
/// </summary>
float VerticalResolution { get; }
/// <summary>
/// Horizontal resolution of the underlying image
/// </summary>
float HorizontalResolution { get; }
/// <summary>
/// Unterlying image, or an on demand rendered version with different attributes as the original
/// </summary>
Image Image { get; }
}
}

View file

@ -1,77 +1,77 @@
using System.Drawing;
using System.Drawing.Imaging;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Wrap an image, make it resizeable
/// </summary>
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();
}
/// <summary>
/// Height of the image, can be set to change
/// </summary>
public int Height { get; set; }
/// <summary>
/// Width of the image, can be set to change.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Size of the image
/// </summary>
public Size Size => new Size(Width, Height);
/// <summary>
/// Pixelformat of the underlying image
/// </summary>
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
{
/// <summary>
/// Wrap an image, make it resizeable
/// </summary>
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();
}
/// <summary>
/// Height of the image, can be set to change
/// </summary>
public int Height { get; set; }
/// <summary>
/// Width of the image, can be set to change.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Size of the image
/// </summary>
public Size Size => new Size(Width, Height);
/// <summary>
/// Pixelformat of the underlying image
/// </summary>
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;
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using log4net;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Description of InterfaceUtils.
/// </summary>
public static class InterfaceUtils
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils));
public static List<Type> GetSubclassesOf(Type type, bool excludeSystemTypes)
{
var list = new List<Type>();
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using log4net;
namespace Greenshot.Base.Core
{
/// <summary>
/// Description of InterfaceUtils.
/// </summary>
public static class InterfaceUtils
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils));
public static List<Type> GetSubclassesOf(Type type, bool excludeSystemTypes)
{
var list = new List<Type>();
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;
}
}
}

View file

@ -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
{
/// <summary>
/// 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!!
/// </summary>
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;
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
public static IDictionary<string, object> JsonDecode(string json)
{
bool success = true;
return JsonDecode(json, ref success);
}
/// <summary>
/// Parses the string json into a value; and fills 'success' with the successfullness of the parse.
/// </summary>
/// <param name="json">A JSON string.</param>
/// <param name="success">Successful parse?</param>
/// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
public static IDictionary<string, object> JsonDecode(string json, ref bool success)
{
success = true;
if (json != null)
{
char[] charArray = json.ToCharArray();
int index = 0;
IDictionary<string, object> value = ParseValue(charArray, ref index, ref success) as IDictionary<string, object>;
return value;
}
return null;
}
protected static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
{
IDictionary<string, object> table = new Dictionary<string, object>();
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<object> ParseArray(char[] json, ref int index, ref bool success)
{
IList<object> array = new List<object>();
// [
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
{
/// <summary>
/// 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!!
/// </summary>
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;
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
public static IDictionary<string, object> JsonDecode(string json)
{
bool success = true;
return JsonDecode(json, ref success);
}
/// <summary>
/// Parses the string json into a value; and fills 'success' with the successfullness of the parse.
/// </summary>
/// <param name="json">A JSON string.</param>
/// <param name="success">Successful parse?</param>
/// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
public static IDictionary<string, object> JsonDecode(string json, ref bool success)
{
success = true;
if (json != null)
{
char[] charArray = json.ToCharArray();
int index = 0;
IDictionary<string, object> value = ParseValue(charArray, ref index, ref success) as IDictionary<string, object>;
return value;
}
return null;
}
protected static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
{
IDictionary<string, object> table = new Dictionary<string, object>();
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<object> ParseArray(char[] json, ref int index, ref bool success)
{
IList<object> array = new List<object>();
// [
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;
}
}
}

View file

@ -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);
}

View file

@ -1,80 +1,80 @@
using System;
namespace GreenshotPlugin.Core
{
/// <summary>
/// This class contains the information about a language file
/// </summary>
public class LanguageFile : IEquatable<LanguageFile>
{
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; }
/// <summary>
/// Overload equals so we can delete a entry from a collection
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
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
{
/// <summary>
/// This class contains the information about a language file
/// </summary>
public class LanguageFile : IEquatable<LanguageFile>
{
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; }
/// <summary>
/// Overload equals so we can delete a entry from a collection
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Initialize the logger
/// </summary>
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;
}
}
/// <summary>
/// A simple helper class to support the logging to the AppData location
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Initialize the logger
/// </summary>
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;
}
}
/// <summary>
/// A simple helper class to support the logging to the AppData location
/// </summary>
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));
}
}
}

View file

@ -30,7 +30,7 @@ using System.Threading;
using log4net;
using Newtonsoft.Json;
namespace GreenshotPlugin.Core.OAuth
namespace Greenshot.Base.Core.OAuth
{
/// <summary>
/// OAuth 2.0 verification code receiver that runs a local server on a free port

View file

@ -29,7 +29,7 @@ using System.Text;
using System.Threading;
using log4net;
namespace GreenshotPlugin.Core.OAuth
namespace Greenshot.Base.Core.OAuth
{
/// <summary>
/// OAuth 2.0 verification code receiver that runs a local server on a free port

View file

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Core.OAuth
namespace Greenshot.Base.Core.OAuth
{
/// <summary>
/// Specify the authorize mode that is used to get the token from the cloud service.

View file

@ -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
{
/// <summary>
/// Code to simplify OAuth 2

View file

@ -23,7 +23,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
namespace GreenshotPlugin.Core.OAuth
namespace Greenshot.Base.Core.OAuth
{
/// <summary>
/// Settings for the OAuth 2 protocol

View file

@ -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
{
/// <summary>
/// An OAuth 1 session object

View file

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPlugin.Core.OAuth
namespace Greenshot.Base.Core.OAuth
{
/// <summary>
/// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Extension methods which work for objects
/// </summary>
public static class ObjectExtensions
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(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);
}
/// <summary>
/// Clone the content from source to destination
/// </summary>
/// <typeparam name="T">Type to clone</typeparam>
/// <param name="source">Instance to copy from</param>
/// <param name="destination">Instance to copy to</param>
public static void CloneTo<T>(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);
}
}
}
/// <summary>
/// Compare two lists
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="l1">IList</param>
/// <param name="l2">IList</param>
/// <returns>true if they are the same</returns>
public static bool CompareLists<T>(IList<T> l1, IList<T> 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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Extension methods which work for objects
/// </summary>
public static class ObjectExtensions
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(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);
}
/// <summary>
/// Clone the content from source to destination
/// </summary>
/// <typeparam name="T">Type to clone</typeparam>
/// <param name="source">Instance to copy from</param>
/// <param name="destination">Instance to copy to</param>
public static void CloneTo<T>(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);
}
}
}
/// <summary>
/// Compare two lists
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="l1">IList</param>
/// <param name="l2">IList</param>
/// <returns>true if they are the same</returns>
public static bool CompareLists<T>(IList<T> l1, IList<T> 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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of PluginUtils.
/// </summary>
public static class PluginUtils
{
private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
private static readonly IDictionary<string, Image> ExeIconCache = new Dictionary<string, Image>();
static PluginUtils()
{
CoreConfig.PropertyChanged += OnIconSizeChanged;
}
/// <summary>
/// Clear icon cache
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "IconSize") return;
var cachedImages = new List<Image>();
lock (ExeIconCache)
{
foreach (string key in ExeIconCache.Keys)
{
cachedImages.Add(ExeIconCache[key]);
}
ExeIconCache.Clear();
}
foreach (Image cachedImage in cachedImages)
{
cachedImage?.Dispose();
}
}
/// <summary>
/// Get the path of an executable
/// </summary>
/// <param name="exeName">e.g. cmd.exe</param>
/// <returns>Path to file</returns>
public static string GetExePath(string exeName)
{
using (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;
}
/// <summary>
/// Get icon from resource files, from the cache.
/// Examples can be found here: https://diymediahome.org/windows-icons-reference-list-with-details-locations-images/
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
public static Image GetCachedExeIcon(string path, int index)
{
string cacheKey = $"{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;
}
/// <summary>
/// Get icon for executable
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
private static Bitmap GetExeIcon(string path, int index)
{
if (!File.Exists(path))
{
return null;
}
try
{
using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, 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;
}
/// <summary>
/// Helper method to add a plugin MenuItem to the Greenshot context menu
/// </summary>
/// <param name="item">ToolStripMenuItem</param>
public static void AddToContextMenu(ToolStripMenuItem item)
{
// Here we can hang ourselves to the main context menu!
var contextMenu = SimpleServiceProvider.Current.GetInstance<ContextMenuStrip>();
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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of PluginUtils.
/// </summary>
public static class PluginUtils
{
private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
private static readonly IDictionary<string, Image> ExeIconCache = new Dictionary<string, Image>();
static PluginUtils()
{
CoreConfig.PropertyChanged += OnIconSizeChanged;
}
/// <summary>
/// Clear icon cache
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "IconSize") return;
var cachedImages = new List<Image>();
lock (ExeIconCache)
{
foreach (string key in ExeIconCache.Keys)
{
cachedImages.Add(ExeIconCache[key]);
}
ExeIconCache.Clear();
}
foreach (Image cachedImage in cachedImages)
{
cachedImage?.Dispose();
}
}
/// <summary>
/// Get the path of an executable
/// </summary>
/// <param name="exeName">e.g. cmd.exe</param>
/// <returns>Path to file</returns>
public static string GetExePath(string exeName)
{
using (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;
}
/// <summary>
/// Get icon from resource files, from the cache.
/// Examples can be found here: https://diymediahome.org/windows-icons-reference-list-with-details-locations-images/
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
public static Image GetCachedExeIcon(string path, int index)
{
string cacheKey = $"{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;
}
/// <summary>
/// Get icon for executable
/// </summary>
/// <param name="path">path to the exe or dll</param>
/// <param name="index">index of the icon</param>
/// <returns>Bitmap with the icon or null if something happended</returns>
private static Bitmap GetExeIcon(string path, int index)
{
if (!File.Exists(path))
{
return null;
}
try
{
using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, 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;
}
/// <summary>
/// Helper method to add a plugin MenuItem to the Greenshot context menu
/// </summary>
/// <param name="item">ToolStripMenuItem</param>
public static void AddToContextMenu(ToolStripMenuItem item)
{
// Here we can hang ourselves to the main context menu!
var contextMenu = SimpleServiceProvider.Current.GetInstance<ContextMenuStrip>();
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);
}
}
}
}

View file

@ -22,7 +22,7 @@
using System;
using Microsoft.Win32;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
/// <summary>
/// A helper class for accessing the registry

View file

@ -1,61 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GreenshotPlugin.Interfaces;
namespace GreenshotPlugin.Core
{
/// <summary>
/// A really cheap and simple DI system
/// </summary>
public class SimpleServiceProvider : IServiceLocator
{
private readonly Dictionary<Type, List<object>> _services = new Dictionary<Type, List<object>>();
public static IServiceLocator Current { get; } = new SimpleServiceProvider();
public IEnumerable<TService> GetAllInstances<TService>()
{
var typeOfService = typeof(TService);
if (!_services.TryGetValue(typeOfService, out var results))
{
yield break;
}
foreach (TService result in results)
{
yield return result;
}
}
public TService GetInstance<TService>()
{
return GetAllInstances<TService>().SingleOrDefault();
}
public void AddService<TService>(IEnumerable<TService> services)
{
var serviceType = typeof(TService);
if (!_services.TryGetValue(serviceType, out var currentServices))
{
currentServices = new List<object>();
_services.Add(serviceType, currentServices);
}
foreach (var service in services)
{
if (service == null)
{
continue;
}
currentServices.Add(service);
}
}
public void AddService<TService>(params TService[] services)
{
AddService(services.AsEnumerable());
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Greenshot.Base.Interfaces;
namespace Greenshot.Base.Core
{
/// <summary>
/// A really cheap and simple DI system
/// </summary>
public class SimpleServiceProvider : IServiceLocator
{
private readonly Dictionary<Type, List<object>> _services = new Dictionary<Type, List<object>>();
public static IServiceLocator Current { get; } = new SimpleServiceProvider();
public IEnumerable<TService> GetAllInstances<TService>()
{
var typeOfService = typeof(TService);
if (!_services.TryGetValue(typeOfService, out var results))
{
yield break;
}
foreach (TService result in results)
{
yield return result;
}
}
public TService GetInstance<TService>()
{
return GetAllInstances<TService>().SingleOrDefault();
}
public void AddService<TService>(IEnumerable<TService> services)
{
var serviceType = typeof(TService);
if (!_services.TryGetValue(serviceType, out var currentServices))
{
currentServices = new List<object>();
_services.Add(serviceType, currentServices);
}
foreach (var service in services)
{
if (service == null)
{
continue;
}
currentServices.Add(service);
}
}
public void AddService<TService>(params TService[] services)
{
AddService(services.AsEnumerable());
}
}
}

View file

@ -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
{

View file

@ -24,7 +24,7 @@ using System.Drawing.Imaging;
using System.IO;
using Svg;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
/// <summary>
/// Create an image look like of the SVG

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// The Window Capture code
/// </summary>
public static class WindowCapture
{
private static readonly ILog Log = LogManager.GetLogger(typeof(WindowCapture));
private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection<CoreConfiguration>();
/// <summary>
/// Used to cleanup the unmanaged resource in the iconInfo for the CaptureCursor method
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport("gdi32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// Get the bounds of all screens combined.
/// </summary>
/// <returns>A Rectangle of the bounds of the entire display area.</returns>
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)));
}
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
/// </summary>
/// <returns>
/// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen)
/// </returns>
public static Point GetCursorLocationRelativeToScreenBounds()
{
return GetLocationRelativeToScreenBounds(User32.GetCursorLocation());
}
/// <summary>
/// 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.
/// </summary>
/// <param name="locationRelativeToScreenOrigin"></param>
/// <returns>Point</returns>
public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin)
{
Point ret = locationRelativeToScreenOrigin;
Rectangle bounds = GetScreenBounds();
ret.Offset(-bounds.X, -bounds.Y);
return ret;
}
/// <summary>
/// This method will capture the current Cursor by using User32 Code
/// </summary>
/// <returns>A Capture Object with the Mouse Cursor information in it.</returns>
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;
}
/// <summary>
/// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen.
/// </summary>
/// <returns>A Capture Object with the Screen as an Image</returns>
public static ICapture CaptureScreen(ICapture capture)
{
if (capture == null)
{
capture = new Capture();
}
return CaptureRectangle(capture, capture.ScreenBounds);
}
/// <summary>
/// Helper method to create an exception that might explain what is wrong while capturing
/// </summary>
/// <param name="method">string with current method</param>
/// <param name="captureBounds">Rectangle of what we want to capture</param>
/// <returns></returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using DWM
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using GDI
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture 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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds)
{
if (capture == null)
{
capture = new Capture();
}
capture.Image = CaptureRectangle(captureBounds);
capture.Location = captureBounds.Location;
return capture.Image == null ? null : capture;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
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<Screen> screensInsideCapture = new List<Screen>();
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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// The Window Capture code
/// </summary>
public static class WindowCapture
{
private static readonly ILog Log = LogManager.GetLogger(typeof(WindowCapture));
private static readonly CoreConfiguration Configuration = IniConfig.GetIniSection<CoreConfiguration>();
/// <summary>
/// Used to cleanup the unmanaged resource in the iconInfo for the CaptureCursor method
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport("gdi32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// Get the bounds of all screens combined.
/// </summary>
/// <returns>A Rectangle of the bounds of the entire display area.</returns>
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)));
}
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
/// </summary>
/// <returns>
/// Point with cursor location, relative to the top left corner of the monitor setup (which itself might actually not be on any screen)
/// </returns>
public static Point GetCursorLocationRelativeToScreenBounds()
{
return GetLocationRelativeToScreenBounds(User32.GetCursorLocation());
}
/// <summary>
/// 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.
/// </summary>
/// <param name="locationRelativeToScreenOrigin"></param>
/// <returns>Point</returns>
public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin)
{
Point ret = locationRelativeToScreenOrigin;
Rectangle bounds = GetScreenBounds();
ret.Offset(-bounds.X, -bounds.Y);
return ret;
}
/// <summary>
/// This method will capture the current Cursor by using User32 Code
/// </summary>
/// <returns>A Capture Object with the Mouse Cursor information in it.</returns>
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;
}
/// <summary>
/// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen.
/// </summary>
/// <returns>A Capture Object with the Screen as an Image</returns>
public static ICapture CaptureScreen(ICapture capture)
{
if (capture == null)
{
capture = new Capture();
}
return CaptureRectangle(capture, capture.ScreenBounds);
}
/// <summary>
/// Helper method to create an exception that might explain what is wrong while capturing
/// </summary>
/// <param name="method">string with current method</param>
/// <param name="captureBounds">Rectangle of what we want to capture</param>
/// <returns></returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using DWM
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// Helper method to check if it is allowed to capture the process using GDI
/// </summary>
/// <param name="process">Process owning the window</param>
/// <returns>true if it's allowed</returns>
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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture 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;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
public static ICapture CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds)
{
if (capture == null)
{
capture = new Capture();
}
capture.Image = CaptureRectangle(captureBounds);
capture.Location = captureBounds.Location;
return capture.Image == null ? null : capture;
}
/// <summary>
/// This method will use User32 code to capture the specified captureBounds from the screen
/// </summary>
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
/// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
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<Screen> screensInsideCapture = new List<Screen>();
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.UnmanagedHelpers;
using System;
using System.Collections.Generic;
using System.Text;
namespace GreenshotPlugin.Core
{
/// <summary>
/// EnumWindows wrapper for .NET
/// </summary>
public class WindowsEnumerator
{
/// <summary>
/// Returns the collection of windows returned by GetWindows
/// </summary>
public IList<WindowDetails> Items { get; private set; }
/// <summary>
/// Gets all child windows of the specified window
/// </summary>
/// <param name="hWndParent">Window Handle to get children for</param>
/// <param name="classname">Window Classname to copy, use null to copy all</param>
public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname)
{
Items = new List<WindowDetails>();
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<WindowDetails>();
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;
}
/// <summary>
/// The enum Windows callback.
/// </summary>
/// <param name="hWnd">Window Handle</param>
/// <param name="lParam">Application defined value</param>
/// <returns>1 to continue enumeration, 0 to stop</returns>
private int WindowEnum(IntPtr hWnd, int lParam)
{
return OnWindowEnum(hWnd) ? 1 : 0;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="hWnd">Window handle to add</param>
/// <returns>True to continue enumeration, False to stop</returns>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;
using Greenshot.Base.UnmanagedHelpers;
namespace Greenshot.Base.Core
{
/// <summary>
/// EnumWindows wrapper for .NET
/// </summary>
public class WindowsEnumerator
{
/// <summary>
/// Returns the collection of windows returned by GetWindows
/// </summary>
public IList<WindowDetails> Items { get; private set; }
/// <summary>
/// Gets all child windows of the specified window
/// </summary>
/// <param name="hWndParent">Window Handle to get children for</param>
/// <param name="classname">Window Classname to copy, use null to copy all</param>
public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname)
{
Items = new List<WindowDetails>();
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<WindowDetails>();
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;
}
/// <summary>
/// The enum Windows callback.
/// </summary>
/// <param name="hWnd">Window Handle</param>
/// <param name="lParam">Application defined value</param>
/// <returns>1 to continue enumeration, 0 to stop</returns>
private int WindowEnum(IntPtr hWnd, int lParam)
{
return OnWindowEnum(hWnd) ? 1 : 0;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="hWnd">Window handle to add</param>
/// <returns>True to continue enumeration, False to stop</returns>
private bool OnWindowEnum(IntPtr hWnd)
{
if (!WindowDetails.IsIgnoreHandle(hWnd))
{
Items.Add(new WindowDetails(hWnd));
}
return true;
}
}
}

View file

@ -3,7 +3,7 @@
using System;
namespace GreenshotPlugin.Core
namespace Greenshot.Base.Core
{
/// <summary>
/// Extension methods to test the windows version

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
using GreenshotPlugin.UnmanagedHelpers.Enums;
using log4net;
namespace GreenshotPlugin.Core
{
/// <summary>
/// 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
/// </summary>
public class WmInputLangChangeRequestFilter : IMessageFilter
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(WmInputLangChangeRequestFilter));
/// <summary>
/// This will do some filtering
/// </summary>
/// <param name="m">Message</param>
/// <returns>true if the message should be filtered</returns>
public bool PreFilterMessage(ref Message m)
{
return PreFilterMessageExternal(ref m);
}
/// <summary>
/// Also used in the MainForm WndProc
/// </summary>
/// <param name="m">Message</param>
/// <returns>true if the message should be filtered</returns>
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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
using Greenshot.Base.UnmanagedHelpers.Enums;
using log4net;
namespace Greenshot.Base.Core
{
/// <summary>
/// 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
/// </summary>
public class WmInputLangChangeRequestFilter : IMessageFilter
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(WmInputLangChangeRequestFilter));
/// <summary>
/// This will do some filtering
/// </summary>
/// <param name="m">Message</param>
/// <returns>true if the message should be filtered</returns>
public bool PreFilterMessage(ref Message m)
{
return PreFilterMessageExternal(ref m);
}
/// <summary>
/// Also used in the MainForm WndProc
/// </summary>
/// <param name="m">Message</param>
/// <returns>true if the message should be filtered</returns>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// AdjustEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// AdjustEffect
/// </summary>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// BorderEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// BorderEffect
/// </summary>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// DropShadowEffect
/// </summary>
[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 <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// DropShadowEffect
/// </summary>
[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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// GrayscaleEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// GrayscaleEffect
/// </summary>
public class GrayscaleEffect : IEffect
{
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateGrayscale(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// Interface to describe an effect
/// </summary>
public interface IEffect
{
/// <summary>
/// Apply this IEffect to the supplied sourceImage.
/// In the process of applying the supplied matrix will be modified to represent the changes.
/// </summary>
/// <param name="sourceImage">Image to apply the effect to</param>
/// <param name="matrix">Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas</param>
/// <returns>new image with applied effect</returns>
Image Apply(Image sourceImage, Matrix matrix);
/// <summary>
/// Reset all values to their defaults
/// </summary>
void Reset();
}
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Base.Effects
{
/// <summary>
/// Interface to describe an effect
/// </summary>
public interface IEffect
{
/// <summary>
/// Apply this IEffect to the supplied sourceImage.
/// In the process of applying the supplied matrix will be modified to represent the changes.
/// </summary>
/// <param name="sourceImage">Image to apply the effect to</param>
/// <param name="matrix">Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas</param>
/// <returns>new image with applied effect</returns>
Image Apply(Image sourceImage, Matrix matrix);
/// <summary>
/// Reset all values to their defaults
/// </summary>
void Reset();
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// InvertEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// InvertEffect
/// </summary>
public class InvertEffect : IEffect
{
public Image Apply(Image sourceImage, Matrix matrix)
{
return ImageHelper.CreateNegative(sourceImage);
}
public void Reset()
{
// No settings to reset
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// MonochromeEffect
/// </summary>
public class MonochromeEffect : IEffect
{
private readonly byte _threshold;
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// MonochromeEffect
/// </summary>
public class MonochromeEffect : IEffect
{
private readonly byte _threshold;
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
using log4net;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// ReduceColorsEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
using log4net;
namespace Greenshot.Base.Effects
{
/// <summary>
/// ReduceColorsEffect
/// </summary>
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// ResizeCanvasEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// ResizeCanvasEffect
/// </summary>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// ResizeEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// ResizeEffect
/// </summary>
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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using GreenshotPlugin.Core;
namespace GreenshotPlugin.Effects
{
/// <summary>
/// RotateEffect
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using Greenshot.Base.Core;
namespace Greenshot.Base.Effects
{
/// <summary>
/// RotateEffect
/// </summary>
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);
}
}
}

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