This should fix most icon scaling issues

Improved the IniReader a bit and replaced some old code.
This commit is contained in:
Robin Krom 2020-02-11 22:41:55 +01:00
parent 41baf27d84
commit 4a958be8b5
35 changed files with 2767 additions and 301 deletions

View file

@ -16,7 +16,7 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<!-- Optional: Embed source files that are not tracked by the source control manager in the PDB --> <!-- Optional: Embed source files that are not tracked by the source control manager in the PDB -->
<EmbedUntrackedSources>true</EmbedUntrackedSources> <EmbedUntrackedSources>true</EmbedUntrackedSources>
<TargetFramework>net471</TargetFramework> <TargetFramework>net471</TargetFramework>
</PropertyGroup> </PropertyGroup>
<!-- ILLinker and single file settings --> <!-- ILLinker and single file settings -->
@ -25,8 +25,8 @@
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="$(MSBuildProjectName) == 'Greenshot'"> <PropertyGroup Condition="$(MSBuildProjectName) == 'Greenshot'">
<IncludeSymbolsInSingleFile>false</IncludeSymbolsInSingleFile> <IncludeSymbolsInSingleFile>false</IncludeSymbolsInSingleFile>
<ShowLinkerSizeComparison>true</ShowLinkerSizeComparison> <ShowLinkerSizeComparison>true</ShowLinkerSizeComparison>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' != 'Debug' And !$(MSBuildProjectName.Contains('Test')) And !$(MSBuildProjectName.Contains('Demo'))"> <PropertyGroup Condition="'$(Configuration)' != 'Debug' And !$(MSBuildProjectName.Contains('Test')) And !$(MSBuildProjectName.Contains('Demo'))">

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -33,9 +33,9 @@ namespace Greenshot.Controls {
private static Image _scaledCheckbox; private static Image _scaledCheckbox;
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) { protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) {
if (_scaledCheckbox == null || _scaledCheckbox.Size != CoreConfig.IconSize) { if (_scaledCheckbox == null || _scaledCheckbox.Size != CoreConfig.ScaledIconSize) {
_scaledCheckbox?.Dispose(); _scaledCheckbox?.Dispose();
_scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, CoreConfig.IconSize.Width, CoreConfig.IconSize.Height, null); _scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, CoreConfig.ScaledIconSize.Width, CoreConfig.ScaledIconSize.Height, null);
} }
Rectangle old = e.ImageRectangle; Rectangle old = e.ImageRectangle;
ToolStripItemImageRenderEventArgs clone = new ToolStripItemImageRenderEventArgs(e.Graphics, e.Item, _scaledCheckbox, new Rectangle(old.X, 0, old.Width, old.Height)); ToolStripItemImageRenderEventArgs clone = new ToolStripItemImageRenderEventArgs(e.Graphics, e.Item, _scaledCheckbox, new Rectangle(old.X, 0, old.Width, old.Height));

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -32,10 +32,10 @@ namespace Greenshot.Drawing {
/// <summary> /// <summary>
/// Description of LineContainer. /// Description of LineContainer.
/// </summary> /// </summary>
[Serializable()] [Serializable()]
public class LineContainer : DrawableContainer { public class LineContainer : DrawableContainer {
public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10; public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10;
public LineContainer(Surface parent) : base(parent) { public LineContainer(Surface parent) : base(parent) {
Init(); Init();
} }
@ -45,7 +45,7 @@ namespace Greenshot.Drawing {
AddField(GetType(), FieldType.LINE_COLOR, Color.Red); AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
AddField(GetType(), FieldType.SHADOW, true); AddField(GetType(), FieldType.SHADOW, true);
} }
protected override void OnDeserialized(StreamingContext context) protected override void OnDeserialized(StreamingContext context)
{ {
Init(); Init();
@ -55,7 +55,7 @@ namespace Greenshot.Drawing {
Adorners.Add(new MoveAdorner(this, Positions.TopLeft)); Adorners.Add(new MoveAdorner(this, Positions.TopLeft));
Adorners.Add(new MoveAdorner(this, Positions.BottomRight)); Adorners.Add(new MoveAdorner(this, Positions.BottomRight));
} }
public override void Draw(Graphics graphics, RenderMode rm) { public override void Draw(Graphics graphics, RenderMode rm) {
graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
@ -91,7 +91,7 @@ namespace Greenshot.Drawing {
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height); graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
} }
} }
public override bool ClickableAt(int x, int y) { public override bool ClickableAt(int x, int y) {
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) +5; int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) +5;
if (lineThickness > 0) if (lineThickness > 0)
@ -102,13 +102,13 @@ namespace Greenshot.Drawing {
}; };
using GraphicsPath path = new GraphicsPath(); using GraphicsPath path = new GraphicsPath();
path.AddLine(Left, Top, Left + Width, Top + Height); path.AddLine(Left, Top, Left + Width, Top + Height);
return path.IsOutlineVisible(x, y, pen); return path.IsOutlineVisible(x, y, pen);
} }
return false; return false;
} }
protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() { protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() {
return ScaleHelper.LineAngleRoundBehavior.Instance; return ScaleHelper.LineAngleRoundBehavior.Instance;
} }
} }
} }

View file

@ -293,7 +293,7 @@ namespace Greenshot {
// toolsToolStrip // toolsToolStrip
// //
this.toolsToolStrip.ClickThrough = true; this.toolsToolStrip.ClickThrough = true;
this.toolsToolStrip.ImageScalingSize = coreConfiguration.IconSize; this.toolsToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.toolsToolStrip.Dock = System.Windows.Forms.DockStyle.None; this.toolsToolStrip.Dock = System.Windows.Forms.DockStyle.None;
this.toolsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; this.toolsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.toolsToolStrip.Renderer = new CustomToolStripProfessionalRenderer(); this.toolsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
@ -529,7 +529,7 @@ namespace Greenshot {
// menuStrip1 // menuStrip1
// //
this.menuStrip1.ClickThrough = true; this.menuStrip1.ClickThrough = true;
this.menuStrip1.ImageScalingSize = coreConfiguration.IconSize; this.menuStrip1.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.Fill; this.menuStrip1.Dock = System.Windows.Forms.DockStyle.Fill;
this.menuStrip1.Stretch = true; this.menuStrip1.Stretch = true;
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -858,7 +858,7 @@ namespace Greenshot {
// destinationsToolStrip // destinationsToolStrip
// //
this.destinationsToolStrip.ClickThrough = true; this.destinationsToolStrip.ClickThrough = true;
this.destinationsToolStrip.ImageScalingSize = coreConfiguration.IconSize; this.destinationsToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.destinationsToolStrip.Dock = System.Windows.Forms.DockStyle.Fill; this.destinationsToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
this.destinationsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; this.destinationsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.destinationsToolStrip.Name = "toolStrip1"; this.destinationsToolStrip.Name = "toolStrip1";
@ -1014,10 +1014,10 @@ namespace Greenshot {
// //
this.propertiesToolStrip.AutoSize = false; this.propertiesToolStrip.AutoSize = false;
this.propertiesToolStrip.ClickThrough = true; this.propertiesToolStrip.ClickThrough = true;
this.propertiesToolStrip.ImageScalingSize = coreConfiguration.IconSize; this.propertiesToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.propertiesToolStrip.Dock = System.Windows.Forms.DockStyle.Fill; this.propertiesToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertiesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; this.propertiesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.IconSize.Height + 10); this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.ScaledIconSize.Height + 10);
this.propertiesToolStrip.Name = "propertiesToolStrip"; this.propertiesToolStrip.Name = "propertiesToolStrip";
this.propertiesToolStrip.Stretch = true; this.propertiesToolStrip.Stretch = true;
this.propertiesToolStrip.TabIndex = 2; this.propertiesToolStrip.TabIndex = 2;

View file

@ -203,7 +203,7 @@ namespace Greenshot {
// contextmenu_quicksettings // contextmenu_quicksettings
// //
this.contextmenu_quicksettings.Name = "contextmenu_quicksettings"; this.contextmenu_quicksettings.Name = "contextmenu_quicksettings";
this.contextmenu_quicksettings.Size = new System.Drawing.Size(170, coreConfiguration.IconSize.Height + 8); this.contextmenu_quicksettings.Size = new System.Drawing.Size(170, coreConfiguration.ScaledIconSize.Height + 8);
// //
// contextmenu_settings // contextmenu_settings
// //

View file

@ -549,7 +549,7 @@ namespace Greenshot {
/// <param name="e"></param> /// <param name="e"></param>
private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) { private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "IconSize") { if (e.PropertyName == "IconSize") {
contextMenu.ImageScalingSize = coreConfiguration.IconSize; contextMenu.ImageScalingSize = coreConfiguration.ScaledIconSize;
string ieExePath = PluginUtils.GetExePath("iexplore.exe"); string ieExePath = PluginUtils.GetExePath("iexplore.exe");
if (!string.IsNullOrEmpty(ieExePath)) { if (!string.IsNullOrEmpty(ieExePath)) {
contextmenu_captureie.Image = PluginUtils.GetCachedExeIcon(ieExePath, 0); contextmenu_captureie.Image = PluginUtils.GetCachedExeIcon(ieExePath, 0);
@ -614,7 +614,7 @@ namespace Greenshot {
/// <returns>true if onedrive has hotkeys turned on</returns> /// <returns>true if onedrive has hotkeys turned on</returns>
private static bool IsOneDriveBlockingHotkey() private static bool IsOneDriveBlockingHotkey()
{ {
if (!Environment.OSVersion.IsWindows10()) if (!WindowsVersion.IsWindows10OrLater)
{ {
return false; return false;
} }

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -50,7 +50,7 @@ namespace Greenshot {
public SettingsForm() { public SettingsForm() {
InitializeComponent(); InitializeComponent();
// Make sure the store isn't called to early, that's why we do it manually // Make sure the store isn't called to early, that's why we do it manually
ManualStoreFields = true; ManualStoreFields = true;
} }
@ -154,8 +154,8 @@ namespace Greenshot {
} }
comboBox.SelectedItem = Language.Translate(selectedValue); comboBox.SelectedItem = Language.Translate(selectedValue);
} }
/// <summary> /// <summary>
/// Get the selected enum value from the combobox, uses generics /// Get the selected enum value from the combobox, uses generics
/// </summary> /// </summary>
@ -175,7 +175,7 @@ namespace Greenshot {
} }
return returnValue; return returnValue;
} }
private void SetWindowCaptureMode(WindowCaptureMode selectedWindowCaptureMode) { private void SetWindowCaptureMode(WindowCaptureMode selectedWindowCaptureMode) {
WindowCaptureMode[] availableModes; WindowCaptureMode[] availableModes;
if (!DWM.IsDwmEnabled()) { if (!DWM.IsDwmEnabled()) {
@ -189,7 +189,7 @@ namespace Greenshot {
} }
PopulateComboBox(combobox_window_capture_mode, availableModes, selectedWindowCaptureMode); PopulateComboBox(combobox_window_capture_mode, availableModes, selectedWindowCaptureMode);
} }
private void DisplayPluginTab() { private void DisplayPluginTab() {
if (!PluginHelper.Instance.HasPlugins()) { if (!PluginHelper.Instance.HasPlugins()) {
tabcontrol.TabPages.Remove(tab_plugins); tabcontrol.TabPages.Remove(tab_plugins);
@ -199,9 +199,9 @@ namespace Greenshot {
listview_plugins.Items.Clear(); listview_plugins.Items.Clear();
listview_plugins.Columns.Clear(); listview_plugins.Columns.Clear();
string[] columns = { string[] columns = {
Language.GetString("settings_plugins_name"), Language.GetString("settings_plugins_name"),
Language.GetString("settings_plugins_version"), Language.GetString("settings_plugins_version"),
Language.GetString("settings_plugins_createdby"), Language.GetString("settings_plugins_createdby"),
Language.GetString("settings_plugins_dllpath")}; Language.GetString("settings_plugins_dllpath")};
foreach (string column in columns) { foreach (string column in columns) {
listview_plugins.Columns.Add(column); listview_plugins.Columns.Add(column);
@ -218,7 +218,7 @@ namespace Greenshot {
} }
listview_plugins.EndUpdate(); listview_plugins.EndUpdate();
listview_plugins.Refresh(); listview_plugins.Refresh();
// Disable the configure button, it will be enabled when a plugin is selected AND isConfigurable // Disable the configure button, it will be enabled when a plugin is selected AND isConfigurable
button_pluginconfigure.Enabled = false; button_pluginconfigure.Enabled = false;
} }
@ -254,7 +254,7 @@ namespace Greenshot {
UpdateDestinationDescriptions(); UpdateDestinationDescriptions();
UpdateClipboardFormatDescriptions(); UpdateClipboardFormatDescriptions();
} }
// Check the settings and somehow visibly mark when something is incorrect // Check the settings and somehow visibly mark when something is incorrect
private bool CheckSettings() { private bool CheckSettings() {
return CheckFilenamePattern() && CheckStorageLocationPath(); return CheckFilenamePattern() && CheckStorageLocationPath();
@ -273,21 +273,21 @@ namespace Greenshot {
} }
DisplayTextBoxValidity(textbox_screenshotname, settingsOk); DisplayTextBoxValidity(textbox_screenshotname, settingsOk);
return settingsOk; return settingsOk;
} }
private bool CheckStorageLocationPath() { private bool CheckStorageLocationPath() {
bool settingsOk = Directory.Exists(FilenameHelper.FillVariables(textbox_storagelocation.Text, false)); bool settingsOk = Directory.Exists(FilenameHelper.FillVariables(textbox_storagelocation.Text, false));
DisplayTextBoxValidity(textbox_storagelocation, settingsOk); DisplayTextBoxValidity(textbox_storagelocation, settingsOk);
return settingsOk; return settingsOk;
} }
private void DisplayTextBoxValidity(GreenshotTextBox textbox, bool valid) { private void DisplayTextBoxValidity(GreenshotTextBox textbox, bool valid) {
if (valid) { if (valid) {
// "Added" feature #3547158 // "Added" feature #3547158
textbox.BackColor = Environment.OSVersion.Version.Major >= 6 ? SystemColors.Window : SystemColors.Control; textbox.BackColor = Environment.OSVersion.Version.Major >= 6 ? SystemColors.Window : SystemColors.Control;
} else { } else {
textbox.BackColor = Color.Red; textbox.BackColor = Color.Red;
} }
} }
@ -334,6 +334,7 @@ namespace Greenshot {
listview_destinations.Items.Clear(); listview_destinations.Items.Clear();
listview_destinations.ListViewItemSorter = new ListviewWithDestinationComparer(); listview_destinations.ListViewItemSorter = new ListviewWithDestinationComparer();
ImageList imageList = new ImageList(); ImageList imageList = new ImageList();
imageList.ImageSize = coreConfiguration.ScaledIconSize;
listview_destinations.SmallImageList = imageList; listview_destinations.SmallImageList = imageList;
int imageNr = -1; int imageNr = -1;
foreach (IDestination currentDestination in DestinationHelper.GetAllDestinations()) { foreach (IDestination currentDestination in DestinationHelper.GetAllDestinations()) {
@ -376,7 +377,7 @@ namespace Greenshot {
item.Tag = clipboardFormat; item.Tag = clipboardFormat;
item.Checked = coreConfiguration.ClipboardFormats.Contains(clipboardFormat); item.Checked = coreConfiguration.ClipboardFormats.Contains(clipboardFormat);
} }
if (Language.CurrentLanguage != null) { if (Language.CurrentLanguage != null) {
combobox_language.SelectedValue = Language.CurrentLanguage; combobox_language.SelectedValue = Language.CurrentLanguage;
} }
@ -419,10 +420,10 @@ namespace Greenshot {
checkbox_autostartshortcut.Checked = StartupHelper.HasRunUser(); checkbox_autostartshortcut.Checked = StartupHelper.HasRunUser();
} }
} }
numericUpDown_daysbetweencheck.Value = coreConfiguration.UpdateCheckInterval; numericUpDown_daysbetweencheck.Value = coreConfiguration.UpdateCheckInterval;
numericUpDown_daysbetweencheck.Enabled = !coreConfiguration.Values["UpdateCheckInterval"].IsFixed; numericUpDown_daysbetweencheck.Enabled = !coreConfiguration.Values["UpdateCheckInterval"].IsFixed;
numericUpdownIconSize.Value = coreConfiguration.IconSize.Width /16 * 16; numericUpdownIconSize.Value = coreConfiguration.ScaledIconSize.Width /16 * 16;
CheckDestinationSettings(); CheckDestinationSettings();
} }
@ -570,7 +571,7 @@ namespace Greenshot {
} }
colorButton_window_background.Visible = false; colorButton_window_background.Visible = false;
} }
/// <summary> /// <summary>
/// Check the destination settings /// Check the destination settings
/// </summary> /// </summary>
@ -582,7 +583,7 @@ namespace Greenshot {
destinationsEnabled = !coreConfiguration.Values["Destinations"].IsFixed; destinationsEnabled = !coreConfiguration.Values["Destinations"].IsFixed;
} }
listview_destinations.Enabled = destinationsEnabled; listview_destinations.Enabled = destinationsEnabled;
foreach(int index in listview_destinations.CheckedIndices) { foreach(int index in listview_destinations.CheckedIndices) {
ListViewItem item = listview_destinations.Items[index]; ListViewItem item = listview_destinations.Items[index];
if (item.Tag is IDestination destinationFromTag && destinationFromTag.Designation.Equals(ClipboardDestination.DESIGNATION)) { if (item.Tag is IDestination destinationFromTag && destinationFromTag.Designation.Equals(ClipboardDestination.DESIGNATION)) {

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -50,9 +50,9 @@ namespace Greenshot.Forms {
Identifier = identifier; Identifier = identifier;
CheckOnClick = false; CheckOnClick = false;
_multiCheckAllowed = allowMultiCheck; _multiCheckAllowed = allowMultiCheck;
if (_defaultImage == null || _defaultImage.Size != CoreConfig.IconSize) { if (_defaultImage == null || _defaultImage.Size != CoreConfig.ScaledIconSize) {
_defaultImage?.Dispose(); _defaultImage?.Dispose();
_defaultImage = ImageHelper.CreateEmpty(CoreConfig.IconSize.Width, CoreConfig.IconSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb, Color.Transparent, 96f, 96f); _defaultImage = ImageHelper.CreateEmpty(CoreConfig.ScaledIconSize.Width, CoreConfig.ScaledIconSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb, Color.Transparent, 96f, 96f);
} }
Image = _defaultImage; Image = _defaultImage;
} }
@ -63,7 +63,7 @@ namespace Greenshot.Forms {
/// gets or sets the currently checked item /// gets or sets the currently checked item
/// </summary> /// </summary>
public ToolStripMenuSelectListItem CheckedItem { public ToolStripMenuSelectListItem CheckedItem {
get { get {
IEnumerator items = DropDownItems.GetEnumerator(); IEnumerator items = DropDownItems.GetEnumerator();
while (items.MoveNext()) { while (items.MoveNext()) {
@ -86,7 +86,7 @@ namespace Greenshot.Forms {
} }
} }
} }
/// <summary> /// <summary>
/// gets or sets the currently checked items /// gets or sets the currently checked items
/// </summary> /// </summary>
@ -126,7 +126,7 @@ namespace Greenshot.Forms {
} }
} }
} }
private void ItemCheckStateChanged(object sender, EventArgs e) { private void ItemCheckStateChanged(object sender, EventArgs e) {
if (_updateInProgress) { if (_updateInProgress) {
return; return;
@ -140,7 +140,7 @@ namespace Greenshot.Forms {
_updateInProgress = false; _updateInProgress = false;
CheckedChanged?.Invoke(this, new ItemCheckedChangedEventArgs(toolStripMenuSelectListItem)); CheckedChanged?.Invoke(this, new ItemCheckedChangedEventArgs(toolStripMenuSelectListItem));
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -171,7 +171,7 @@ namespace Greenshot.Forms {
} }
DropDownItems.Add(toolStripMenuSelectListItem); DropDownItems.Add(toolStripMenuSelectListItem);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -180,7 +180,7 @@ namespace Greenshot.Forms {
public void AddItem(string label, Image image) { public void AddItem(string label, Image image) {
AddItem(label, image, null, false); AddItem(label, image, null, false);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -189,7 +189,7 @@ namespace Greenshot.Forms {
public void AddItem(string label, object data) { public void AddItem(string label, object data) {
AddItem(label, null, data, false); AddItem(label, null, data, false);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -197,8 +197,8 @@ namespace Greenshot.Forms {
public void AddItem(string label) { public void AddItem(string label) {
AddItem(label, null, null, false); AddItem(label, null, null, false);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -208,7 +208,7 @@ namespace Greenshot.Forms {
public void AddItem(string label, Image image, bool isChecked) { public void AddItem(string label, Image image, bool isChecked) {
AddItem(label, image, null, isChecked); AddItem(label, image, null, isChecked);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -218,7 +218,7 @@ namespace Greenshot.Forms {
public void AddItem(string label, object data, bool isChecked) { public void AddItem(string label, object data, bool isChecked) {
AddItem(label, null, data, isChecked); AddItem(label, null, data, isChecked);
} }
/// <summary> /// <summary>
/// adds an item to the select list /// adds an item to the select list
/// </summary> /// </summary>
@ -227,7 +227,7 @@ namespace Greenshot.Forms {
public void AddItem(string label, bool isChecked) { public void AddItem(string label, bool isChecked) {
AddItem(label, null, null, isChecked); AddItem(label, null, null, isChecked);
} }
/// <summary> /// <summary>
/// unchecks all items of the list /// unchecks all items of the list
/// </summary> /// </summary>
@ -243,7 +243,7 @@ namespace Greenshot.Forms {
} }
} }
} }
/// <summary> /// <summary>
/// Event class for the CheckedChanged event in the ToolStripMenuSelectList /// Event class for the CheckedChanged event in the ToolStripMenuSelectList
/// </summary> /// </summary>
@ -256,7 +256,7 @@ namespace Greenshot.Forms {
Item = item; Item = item;
} }
} }
/// <summary> /// <summary>
/// Wrapper around the ToolStripMenuItem, which can contain an object /// Wrapper around the ToolStripMenuItem, which can contain an object
/// Also the Checked property hides the normal checked property so we can render our own check /// Also the Checked property hides the normal checked property so we can render our own check

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -115,7 +115,7 @@ namespace GreenshotJiraPlugin.Forms {
public async Task UploadAsync(IBinaryContainer attachment) { public async Task UploadAsync(IBinaryContainer attachment) {
attachment.Filename = jiraFilenameBox.Text; attachment.Filename = jiraFilenameBox.Text;
await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment); await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment);
if (!string.IsNullOrEmpty(jiraCommentBox.Text)) { if (!string.IsNullOrEmpty(jiraCommentBox.Text)) {
await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text); await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text);
} }
@ -153,7 +153,7 @@ namespace GreenshotJiraPlugin.Forms {
jiraListView.Columns.Add(translation); jiraListView.Columns.Add(translation);
} }
var imageList = new ImageList { var imageList = new ImageList {
ImageSize = CoreConfig.IconSize ImageSize = CoreConfig.ScaledIconSize
}; };
jiraListView.SmallImageList = imageList; jiraListView.SmallImageList = imageList;
jiraListView.LargeImageList = imageList; jiraListView.LargeImageList = imageList;

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -56,7 +56,7 @@ namespace GreenshotJiraPlugin {
{ {
if (args.PropertyName == nameof(CoreConfig.IconSize)) if (args.PropertyName == nameof(CoreConfig.IconSize))
{ {
JiraPlugin.Instance.JiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height }); JiraPlugin.Instance.JiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height });
} }
}; };
@ -99,7 +99,7 @@ namespace GreenshotJiraPlugin {
return false; return false;
} }
_jiraClient = JiraClient.Create(new Uri(JiraConfig.Url)); _jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
_jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.IconSize.Width, Height = CoreConfig.IconSize.Height }); _jiraClient.Behaviour.SetConfig(new SvgConfiguration { Width = CoreConfig.ScaledIconSize.Width, Height = CoreConfig.ScaledIconSize.Height });
_jiraClient.SetBasicAuthentication(user, password); _jiraClient.SetBasicAuthentication(user, password);
_issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient); _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraClient);
@ -127,7 +127,7 @@ namespace GreenshotJiraPlugin {
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Use the credentials dialog, this will show if there are not correct credentials. /// Use the credentials dialog, this will show if there are not correct credentials.
/// If there are credentials, call the real login. /// If there are credentials, call the real login.
@ -189,7 +189,7 @@ namespace GreenshotJiraPlugin {
} }
/// <summary> /// <summary>
/// Get the favorite filters /// Get the favorite filters
/// </summary> /// </summary>
/// <returns>List with filters</returns> /// <returns>List with filters</returns>
public async Task<IList<Filter>> GetFavoriteFiltersAsync(CancellationToken cancellationToken = default) public async Task<IList<Filter>> GetFavoriteFiltersAsync(CancellationToken cancellationToken = default)

View file

@ -14,18 +14,36 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" /> <ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0" /> <PackageReference Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0">
<PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1000" /> <EmbedInteropTypes>true</EmbedInteropTypes>
<PackageReference Include="Microsoft.Office.Interop.Outlook" Version="15.0.4797.1003" /> <ExcludeAssets>runtime</ExcludeAssets>
<PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1017" /> </PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1003" /> <PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1000">
<PackageReference Include="MicrosoftOfficeCore" Version="15.0.0" /> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Outlook" Version="15.0.4797.1003">
<EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1017">
<EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1003">
<EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="MicrosoftOfficeCore" Version="15.0.0">
<EmbedInteropTypes>True</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
<PackageReference Include="Unofficial.Microsoft.mshtml" Version="7.0.3300"> <PackageReference Include="Unofficial.Microsoft.mshtml" Version="7.0.3300">
<EmbedInteropTypes>True</EmbedInteropTypes> <EmbedInteropTypes>True</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="log4net" Version="2.0.8" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -35,7 +35,7 @@ namespace GreenshotPlugin.Core {
public abstract class AbstractDestination : IDestination { public abstract class AbstractDestination : IDestination {
private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination)); private static readonly ILog Log = LogManager.GetLogger(typeof(AbstractDestination));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
public virtual int CompareTo(object obj) { public virtual int CompareTo(object obj) {
if (!(obj is IDestination other)) { if (!(obj is IDestination other)) {
return 1; return 1;
@ -150,7 +150,7 @@ namespace GreenshotPlugin.Core {
ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker")); ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker"));
var menu = new ContextMenuStrip var menu = new ContextMenuStrip
{ {
ImageScalingSize = CoreConfig.IconSize, ImageScalingSize = CoreConfig.ScaledIconSize,
Tag = null, Tag = null,
TopLevel = true TopLevel = true
}; };
@ -292,7 +292,7 @@ namespace GreenshotPlugin.Core {
}; };
AddTagEvents(basisMenuItem, menu, Description); AddTagEvents(basisMenuItem, menu, Description);
basisMenuItem.Click -= destinationClickHandler; basisMenuItem.Click -= destinationClickHandler;
basisMenuItem.Click += destinationClickHandler; basisMenuItem.Click += destinationClickHandler;
if (IsDynamic && addDynamics) { if (IsDynamic && addDynamics) {
basisMenuItem.DropDownOpening += delegate basisMenuItem.DropDownOpening += delegate
@ -330,6 +330,6 @@ namespace GreenshotPlugin.Core {
return basisMenuItem; return basisMenuItem;
} }
} }
} }

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -45,7 +45,7 @@ namespace GreenshotPlugin.Core {
RELEASE_CANDIDATE, RELEASE_CANDIDATE,
RELEASE RELEASE
} }
public enum ClickActions { public enum ClickActions {
DO_NOTHING, DO_NOTHING,
OPEN_LAST_IN_EXPLORER, OPEN_LAST_IN_EXPLORER,
@ -104,7 +104,7 @@ namespace GreenshotPlugin.Core {
public bool PlayCameraSound { get; set; } = false; public bool PlayCameraSound { get; set; } = false;
[IniProperty("ShowTrayNotification", LanguageKey="settings_shownotify",Description="Show a notification from the systray when a capture is taken.", DefaultValue="true")] [IniProperty("ShowTrayNotification", LanguageKey="settings_shownotify",Description="Show a notification from the systray when a capture is taken.", DefaultValue="true")]
public bool ShowTrayNotification { get; set; } = true; public bool ShowTrayNotification { get; set; } = true;
[IniProperty("OutputFilePath", Description="Output file path.")] [IniProperty("OutputFilePath", Description="Output file path.")]
public string OutputFilePath { get; set; } public string OutputFilePath { get; set; }
[IniProperty("OutputFileAllowOverwrite", Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")] [IniProperty("OutputFileAllowOverwrite", Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")]
@ -267,7 +267,7 @@ namespace GreenshotPlugin.Core {
public Size Win10BorderCrop { get; set; } public Size Win10BorderCrop { get; set; }
private Size _iconSize; private Size _iconSize;
[IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")] [IniProperty("BaseIconSize", Description = "Defines the base size of the icons (e.g. for the buttons in the editor), default value 16,16 and it's scaled to the current DPI", DefaultValue = "16,16")]
public Size IconSize { public Size IconSize {
get { get {
return _iconSize; return _iconSize;
@ -295,6 +295,8 @@ namespace GreenshotPlugin.Core {
} }
} }
public Size ScaledIconSize => DpiHelper.ScaleWithCurrentDpi(_iconSize);
[IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")] [IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")]
public int WebRequestTimeout { get; set; } public int WebRequestTimeout { get; set; }
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")] [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
@ -371,7 +373,7 @@ namespace GreenshotPlugin.Core {
} }
return null; return null;
} }
/// <summary> /// <summary>
/// This method will be called before converting the property, making to possible to correct a certain value /// This method will be called before converting the property, making to possible to correct a certain value
/// Can be used when migration is needed /// Can be used when migration is needed
@ -494,7 +496,7 @@ namespace GreenshotPlugin.Core {
NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower(); NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower();
} }
} }
if (AutoCropDifference < 0) { if (AutoCropDifference < 0) {
AutoCropDifference = 0; AutoCropDifference = 0;
} }

View file

@ -0,0 +1,711 @@
using GreenshotPlugin.Core.Enums;
using GreenshotPlugin.UnmanagedHelpers;
using log4net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace GreenshotPlugin.Core
{
/// <summary>
/// This handles DPI changes see
/// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266.aspx">Writing DPI-Aware Desktop and Win32 Applications</a>
/// </summary>
public static class DpiHelper
{
private static readonly ILog Log = LogManager.GetLogger(typeof(DpiHelper));
/// <summary>
/// This is the default DPI for the screen
/// </summary>
public const uint DefaultScreenDpi = 96;
/// <summary>
/// Retrieve the current DPI for the UI element which is related to this DpiHandler
/// </summary>
public static uint Dpi { get; private set; } = GetDpiForSystem();
/// <summary>
/// Calculate a DPI scale factor
/// </summary>
/// <param name="dpi">uint</param>
/// <returns>double</returns>
public static float DpiScaleFactor(uint dpi)
{
return (float)dpi / DefaultScreenDpi;
}
/// <summary>
/// Scale the supplied number according to the supplied dpi
/// </summary>
/// <param name="someNumber">double with e.g. the width 16 for 16x16 images</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>double with the scaled number</returns>
public static float ScaleWithDpi(float someNumber, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return dpiScaleFactor * someNumber;
}
/// <summary>
/// Scale the supplied number according to the supplied dpi
/// </summary>
/// <param name="number">int with e.g. 16 for 16x16 images</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>Scaled width</returns>
public static int ScaleWithDpi(int number, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return (int)(dpiScaleFactor * number);
}
/// <summary>
/// Scale the supplied Size according to the supplied dpi
/// </summary>
/// <param name="size">Size to resize</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativeSize scaled</returns>
public static Size ScaleWithDpi(Size size, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return new Size((int)(dpiScaleFactor * size.Width), (int)(dpiScaleFactor * size.Height));
}
/// <summary>
/// Scale the supplied NativePoint according to the supplied dpi
/// </summary>
/// <param name="size">NativePoint to resize</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativePoint scaled</returns>
public static Point ScaleWithDpi(Point size, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return new Point((int)(dpiScaleFactor * size.X), (int)(dpiScaleFactor * size.Y));
}
/// <summary>
/// Scale the supplied NativeSizeFloat according to the supplied dpi
/// </summary>
/// <param name="point">PointF</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>PointF</returns>
public static PointF ScaleWithDpi(PointF point, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return new PointF(dpiScaleFactor * point.X, dpiScaleFactor * point.Y);
}
/// <summary>
/// Scale the supplied NativeSizeFloat according to the supplied dpi
/// </summary>
/// <param name="size">NativeSizeFloat to resize</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativeSize scaled</returns>
public static SizeF ScaleWithDpi(SizeF size, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return new SizeF(dpiScaleFactor * size.Width, dpiScaleFactor * size.Height);
}
/// <summary>
/// Scale the supplied number to the current dpi
/// </summary>
/// <param name="someNumber">double with e.g. a width like 16 for 16x16 images</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>double with scaled number</returns>
public static float ScaleWithCurrentDpi(float someNumber, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(someNumber, Dpi, scaleModifier);
}
/// <summary>
/// Scale the supplied number to the current dpi
/// </summary>
/// <param name="someNumber">int with e.g. a width like 16 for 16x16 images</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>int with scaled number</returns>
public static int ScaleWithCurrentDpi(int someNumber, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(someNumber, Dpi, scaleModifier);
}
/// <summary>
/// Scale the supplied NativeSize to the current dpi
/// </summary>
/// <param name="size">NativeSize to scale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativeSize scaled</returns>
public static Size ScaleWithCurrentDpi(Size size, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(size, Dpi, scaleModifier);
}
/// <summary>
/// Scale the supplied NativeSizeFloat to the current dpi
/// </summary>
/// <param name="size">NativeSizeFloat to scale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativeSizeFloat scaled</returns>
public static SizeF ScaleWithCurrentDpi(SizeF size, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(size, Dpi, scaleModifier);
}
/// <summary>
/// Scale the supplied NativePoint to the current dpi
/// </summary>
/// <param name="point">NativePoint to scale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativePoint scaled</returns>
public static Point ScaleWithCurrentDpi(Point point, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(point, Dpi, scaleModifier);
}
/// <summary>
/// Scale the supplied PointF to the current dpi
/// </summary>
/// <param name="point">PointF to scale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>PointF scaled</returns>
public static PointF ScaleWithCurrentDpi(PointF point, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(point, Dpi, scaleModifier);
}
/// <summary>
/// Calculate a DPI unscale factor
/// </summary>
/// <param name="dpi">uint</param>
/// <returns>float</returns>
public static float DpiUnscaleFactor(uint dpi)
{
return (float)DefaultScreenDpi / dpi;
}
/// <summary>
/// Unscale the supplied number according to the supplied dpi
/// </summary>
/// <param name="someNumber">double with e.g. the scaled width</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>double with the unscaled number</returns>
public static float UnscaleWithDpi(float someNumber, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
if (scaleModifier != null)
{
dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
}
return dpiUnscaleFactor * someNumber;
}
/// <summary>
/// Unscale the supplied number according to the supplied dpi
/// </summary>
/// <param name="number">int with a scaled width</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>Unscaled width</returns>
public static int UnscaleWithDpi(int number, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
if (scaleModifier != null)
{
dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
}
return (int)(dpiUnscaleFactor * number);
}
/// <summary>
/// Unscale the supplied NativeSize according to the supplied dpi
/// </summary>
/// <param name="size">NativeSize to unscale</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>Size unscaled</returns>
public static Size UnscaleWithDpi(Size size, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
if (scaleModifier != null)
{
dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
}
return new Size((int)(dpiUnscaleFactor * size.Width), (int)(dpiUnscaleFactor * size.Height));
}
/// <summary>
/// Unscale the supplied Point according to the supplied dpi
/// </summary>
/// <param name="size">Point to unscale</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>Point unscaled</returns>
public static Point UnscaleWithDpi(Point point, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiUnscaleFactor = DpiUnscaleFactor(dpi);
if (scaleModifier != null)
{
dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
}
return new Point((int)(dpiUnscaleFactor * point.X), (int)(dpiUnscaleFactor * point.Y));
}
/// <summary>
/// unscale the supplied NativeSizeFloat according to the supplied dpi
/// </summary>
/// <param name="size">NativeSizeFloat to resize</param>
/// <param name="dpi">current dpi, normal is 96.</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>SizeF unscaled</returns>
public static SizeF UnscaleWithDpi(SizeF size, uint dpi, Func<float, float> scaleModifier = null)
{
float dpiUnscaleFactor = DpiUnscaleFactor(dpi);
if (scaleModifier != null)
{
dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor);
}
return new SizeF(dpiUnscaleFactor * size.Width, dpiUnscaleFactor * size.Height);
}
/// <summary>
/// Unscale the supplied number to the current dpi
/// </summary>
/// <param name="someNumber">double with e.g. a width like 16 for 16x16 images</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>double with unscaled number</returns>
public static float UnscaleWithCurrentDpi(float someNumber, Func<float, float> scaleModifier = null)
{
return UnscaleWithDpi(someNumber, Dpi, scaleModifier);
}
/// <summary>
/// Unscale the supplied number to the current dpi
/// </summary>
/// <param name="someNumber">int with e.g. a width like 16 for 16x16 images</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>int with unscaled number</returns>
public static int UnscaleWithCurrentDpi(int someNumber, Func<float, float> scaleModifier = null)
{
return UnscaleWithDpi(someNumber, Dpi, scaleModifier);
}
/// <summary>
/// Unscale the supplied NativeSize to the current dpi
/// </summary>
/// <param name="size">Size to unscale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>Size unscaled</returns>
public static Size UnscaleWithCurrentDpi(Size size, Func<float, float> scaleModifier = null)
{
return UnscaleWithDpi(size, Dpi, scaleModifier);
}
/// <summary>
/// Unscale the supplied NativeSizeFloat to the current dpi
/// </summary>
/// <param name="size">NativeSizeFloat to unscale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativeSizeFloat unscaled</returns>
public static SizeF UnscaleWithCurrentDpi(SizeF size, Func<float, float> scaleModifier = null)
{
return UnscaleWithDpi(size, Dpi, scaleModifier);
}
/// <summary>
/// Unscale the supplied NativePoint to the current dpi
/// </summary>
/// <param name="point">NativePoint to unscale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativePoint unscaled</returns>
public static Point UnscaleWithCurrentDpi(Point point, Func<float, float> scaleModifier = null)
{
return UnscaleWithDpi(point, Dpi, scaleModifier);
}
/// <summary>
/// Unscale the supplied NativePointFloat to the current dpi
/// </summary>
/// <param name="point">NativePointFloat to unscale</param>
/// <param name="scaleModifier">A function which can modify the scale factor</param>
/// <returns>NativePointFloat unscaled</returns>
public static PointF UnscaleWithCurrentDpi(PointF point, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(point, Dpi, scaleModifier);
}
/// <summary>
/// public wrapper for EnableNonClientDpiScaling, this also checks if the function is available.
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <returns>true if it worked</returns>
public static bool TryEnableNonClientDpiScaling(IntPtr hWnd)
{
// EnableNonClientDpiScaling is only available on Windows 10 and later
if (!WindowsVersion.IsWindows10OrLater)
{
return false;
}
var result = EnableNonClientDpiScaling(hWnd);
if (result.Succeeded())
{
return true;
}
var error = Win32.GetLastErrorCode();
if (Log.IsDebugEnabled)
{
Log.DebugFormat("Error enabling non client dpi scaling : {0}", Win32.GetMessage(error));
}
return false;
}
/// <summary>
/// Make the current process DPI Aware, this should be done via the manifest but sometimes this is not possible.
/// </summary>
/// <returns>bool true if it was possible to change the DPI awareness</returns>
public static bool EnableDpiAware()
{
// We can only test this for Windows 8.1 or later
if (!WindowsVersion.IsWindows81OrLater)
{
Log.Debug("An application can only be DPI aware starting with Window 8.1 and later.");
return false;
}
if (WindowsVersion.IsWindows10BuildOrLater(15063))
{
if (IsValidDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2))
{
SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2);
}
else
{
SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2);
}
return true;
}
return SetProcessDpiAwareness(DpiAwareness.PerMonitorAware).Succeeded();
}
/// <summary>
/// Check if the process is DPI Aware, an DpiHandler doesn't make sense if not.
/// </summary>
public static bool IsDpiAware
{
get
{
// We can only test this for Windows 8.1 or later
if (!WindowsVersion.IsWindows81OrLater)
{
Log.Debug("An application can only be DPI aware starting with Window 8.1 and later.");
return false;
}
using var process = Process.GetCurrentProcess();
GetProcessDpiAwareness(process.Handle, out var dpiAwareness);
if (Log.IsDebugEnabled)
{
Log.DebugFormat("Process {0} has a Dpi awareness {1}", process.ProcessName, dpiAwareness);
}
return dpiAwareness != DpiAwareness.Unaware && dpiAwareness != DpiAwareness.Invalid;
}
}
/// <summary>
/// Retrieve the DPI value for the supplied window handle
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <returns>dpi value</returns>
public static uint GetDpi(IntPtr hWnd)
{
if (!User32.IsWindow(hWnd))
{
return DefaultScreenDpi;
}
// Use the easiest method, but this only works for Windows 10
if (WindowsVersion.IsWindows10OrLater)
{
return GetDpiForWindow(hWnd);
}
// Use the second easiest method, but this only works for Windows 8.1 or later
if (WindowsVersion.IsWindows81OrLater)
{
var hMonitor = User32.MonitorFromWindow(hWnd, MonitorFrom.DefaultToNearest);
// ReSharper disable once UnusedVariable
if (GetDpiForMonitor(hMonitor, MonitorDpiType.EffectiveDpi, out var dpiX, out var dpiY))
{
return dpiX;
}
}
// Fallback to the global DPI settings
using var hdc = SafeWindowDcHandle.FromWindow(hWnd);
if (hdc == null)
{
return DefaultScreenDpi;
}
return (uint)GDI32.GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX);
}
/// <summary>
/// See details <a hef="https://msdn.microsoft.com/en-us/library/windows/desktop/dn302113(v=vs.85).aspx">GetProcessDpiAwareness function</a>
/// Retrieves the dots per inch (dpi) awareness of the specified process.
/// </summary>
/// <param name="processHandle">IntPtr with handle of the process that is being queried. If this parameter is NULL, the current process is queried.</param>
/// <param name="value">out DpiAwareness - The DPI awareness of the specified process. Possible values are from the PROCESS_DPI_AWARENESS enumeration.</param>
/// <returns>HResult</returns>
[DllImport("shcore")]
private static extern HResult GetProcessDpiAwareness(IntPtr processHandle, out DpiAwareness value);
/// <summary>
/// Sets the current process to a specified dots per inch (dpi) awareness level. The DPI awareness levels are from the PROCESS_DPI_AWARENESS enumeration.
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx">SetProcessDpiAwareness function</a>
/// </summary>
/// <param name="dpiAwareness">DpiAwareness</param>
/// <returns>HResult</returns>
[DllImport("shcore")]
private static extern HResult SetProcessDpiAwareness(DpiAwareness dpiAwareness);
/// <summary>
/// It is recommended that you set the process-default DPI awareness via application manifest. See Setting the default DPI awareness for a process for more information. Setting the process-default DPI awareness via API call can lead to unexpected application behavior.
///
/// Sets the current process to a specified dots per inch (dpi) awareness context. The DPI awareness contexts are from the DPI_AWARENESS_CONTEXT value.
/// Remarks:
/// This API is a more advanced version of the previously existing SetProcessDpiAwareness API, allowing for the process default to be set to the finer-grained DPI_AWARENESS_CONTEXT values. Most importantly, this allows you to programmatically set Per Monitor v2 as the process default value, which is not possible with the previous API.
///
/// This method sets the default DPI_AWARENESS_CONTEXT for all threads within an application. Individual threads can have their DPI awareness changed from the default with the SetThreadDpiAwarenessContext method.
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt807676(v=vs.85).aspx">SetProcessDpiAwarenessContext function</a>
/// </summary>
/// <param name="dpiAwarenessContext">DpiAwarenessContext</param>
/// <returns>bool</returns>
[DllImport("User32.dll", SetLastError = true)]
private static extern bool SetProcessDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
/// <summary>
/// See more at <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt748624(v=vs.85).aspx">GetDpiForWindow function</a>
/// Returns the dots per inch (dpi) value for the associated window.
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <returns>uint with dpi</returns>
[DllImport("User32.dll")]
private static extern uint GetDpiForWindow(IntPtr hWnd);
/// <summary>
/// See
/// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx">GetDpiForMonitor function</a>
/// Queries the dots per inch (dpi) of a display.
/// </summary>
/// <param name="hMonitor">IntPtr</param>
/// <param name="dpiType">MonitorDpiType</param>
/// <param name="dpiX">out int for the horizontal dpi</param>
/// <param name="dpiY">out int for the vertical dpi</param>
/// <returns>true if all okay</returns>
[DllImport("shcore")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetDpiForMonitor(IntPtr hMonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);
/// <summary>
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt748621(v=vs.85).aspx">EnableNonClientDpiScaling function</a>
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <returns>bool</returns>
[DllImport("User32.dll", SetLastError = true)]
private static extern HResult EnableNonClientDpiScaling(IntPtr hWnd);
/// <summary>
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt748623(v=vs.85).aspx">GetDpiForSystem function</a>
/// Returns the system DPI.
/// </summary>
/// <returns>uint with the system DPI</returns>
[DllImport("User32.dll")]
private static extern uint GetDpiForSystem();
/// <summary>
/// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS.
/// See more at <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn384110(v=vs.85).aspx">LogicalToPhysicalPointForPerMonitorDPI function</a>
/// </summary>
/// <param name="hWnd">IntPtr A handle to the window whose transform is used for the conversion.</param>
/// <param name="point">A pointer to a POINT structure that specifies the logical coordinates to be converted. The new physical coordinates are copied into this structure if the function succeeds.</param>
/// <returns>bool</returns>
[DllImport("User32.dll")]
private static extern bool LogicalToPhysicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point);
/// <summary>
/// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS.
/// See more at <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn384112(v=vs.85).aspx">PhysicalToLogicalPointForPerMonitorDPI function</a>
/// </summary>
/// <param name="hWnd">IntPtr A handle to the window whose transform is used for the conversion.</param>
/// <param name="point">NativePoint A pointer to a POINT structure that specifies the physical/screen coordinates to be converted. The new logical coordinates are copied into this structure if the function succeeds.</param>
/// <returns>bool</returns>
[DllImport("User32.dll")]
private static extern bool PhysicalToLogicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point);
/// <summary>
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx">SystemParametersInfo function</a>
/// Retrieves the value of one of the system-wide parameters, taking into account the provided DPI value.
/// </summary>
/// <param name="uiAction">
/// SystemParametersInfoActions The system-wide parameter to be retrieved.
/// This function is only intended for use with SPI_GETICONTITLELOGFONT, SPI_GETICONMETRICS, or SPI_GETNONCLIENTMETRICS. See SystemParametersInfo for more information on these values.
/// </param>
/// <param name="uiParam">
/// A parameter whose usage and format depends on the system parameter being queried or set. For more
/// information about system-wide parameters, see the uiAction parameter. If not otherwise indicated, you must specify
/// zero for this parameter.
/// </param>
/// <param name="pvParam">IntPtr</param>
/// <param name="fWinIni">SystemParametersInfoBehaviors</param>
/// <param name="dpi">uint with dpi value</param>
/// <returns>bool</returns>
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfoForDpi(SystemParametersInfoActions uiAction, uint uiParam, IntPtr pvParam, SystemParametersInfoBehaviors fWinIni, uint dpi);
/// <summary>
/// See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt748626(v=vs.85).aspx">GetThreadDpiAwarenessContext function</a>
/// Gets the DPI_AWARENESS_CONTEXT for the current thread.
///
/// This method will return the latest DPI_AWARENESS_CONTEXT sent to SetThreadDpiAwarenessContext. If SetThreadDpiAwarenessContext was never called for this thread, then the return value will equal the default DPI_AWARENESS_CONTEXT for the process.
/// </summary>
/// <returns>DpiAwarenessContext</returns>
[DllImport("User32.dll")]
private static extern DpiAwarenessContext GetThreadDpiAwarenessContext();
/// <summary>
/// Set the DPI awareness for the current thread to the provided value.
/// </summary>
/// <param name="dpiAwarenessContext">DpiAwarenessContext the new value for the current thread</param>
/// <returns>DpiAwarenessContext previous value</returns>
[DllImport("User32.dll")]
private static extern DpiAwarenessContext SetThreadDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
/// <summary>
/// Retrieves the DpiAwareness value from a DpiAwarenessContext.
/// </summary>
/// <param name="dpiAwarenessContext">DpiAwarenessContext</param>
/// <returns>DpiAwareness</returns>
[DllImport("User32.dll")]
private static extern DpiAwareness GetAwarenessFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
/// <summary>
/// Retrieves the DPI from a given DPI_AWARENESS_CONTEXT handle. This enables you to determine the DPI of a thread without needed to examine a window created within that thread.
/// </summary>
/// <param name="dpiAwarenessContext">DpiAwarenessContext</param>
/// <returns>uint with dpi value</returns>
[DllImport("User32.dll")]
private static extern uint GetDpiFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
/// <summary>
/// Determines if a specified DPI_AWARENESS_CONTEXT is valid and supported by the current system.
/// </summary>
/// <param name="dpiAwarenessContext">DpiAwarenessContext The context that you want to determine if it is supported.</param>
/// <returns>bool true if supported otherwise false</returns>
[DllImport("User32.dll")]
private static extern bool IsValidDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext);
/// <summary>
/// Returns the DPI_HOSTING_BEHAVIOR of the specified window.
///
/// This API allows you to examine the hosting behavior of a window after it has been created. A window's hosting behavior is the hosting behavior of the thread in which the window was created, as set by a call to SetThreadDpiHostingBehavior. This is a permanent value and cannot be changed after the window is created, even if the thread's hosting behavior is changed.
/// </summary>
/// <returns>DpiHostingBehavior</returns>
[DllImport("User32.dll")]
private static extern DpiHostingBehavior GetWindowDpiHostingBehavior();
/// <summary>
/// See more at <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/mt845775.aspx">SetThreadDpiHostingBehavior function</a>
/// Sets the thread's DPI_HOSTING_BEHAVIOR. This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT.
///
/// DPI_HOSTING_BEHAVIOR enables a mixed content hosting behavior, which allows parent windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT value. This property only effects new windows created within this thread while the mixed hosting behavior is active. A parent window with this hosting behavior is able to host child windows with different DPI_AWARENESS_CONTEXT values, regardless of whether the child windows have mixed hosting behavior enabled.
///
/// This hosting behavior does not allow for windows with per-monitor DPI_AWARENESS_CONTEXT values to be hosted until windows with DPI_AWARENESS_CONTEXT values of system or unaware.
///
/// To avoid unexpected outcomes, a thread's DPI_HOSTING_BEHAVIOR should be changed to support mixed hosting behaviors only when creating a new window which needs to support those behaviors. Once that window is created, the hosting behavior should be switched back to its default value.
///
/// This API is used to change the thread's DPI_HOSTING_BEHAVIOR from its default value. This is only necessary if your app needs to host child windows from plugins and third-party components that do not support per-monitor-aware context. This is most likely to occur if you are updating complex applications to support per-monitor DPI_AWARENESS_CONTEXT behaviors.
///
/// Enabling mixed hosting behavior will not automatically adjust the thread's DPI_AWARENESS_CONTEXT to be compatible with legacy content. The thread's awareness context must still be manually changed before new windows are created to host such content.
/// </summary>
/// <param name="dpiHostingBehavior">DpiHostingBehavior</param>
/// <returns>previous DpiHostingBehavior</returns>
[DllImport("User32.dll")]
private static extern DpiHostingBehavior SetThreadDpiHostingBehavior(DpiHostingBehavior dpiHostingBehavior);
/// <summary>
///Retrieves the DPI_HOSTING_BEHAVIOR from the current thread.
/// </summary>
/// <returns>DpiHostingBehavior</returns>
[DllImport("User32.dll")]
private static extern DpiHostingBehavior GetThreadDpiHostingBehavior();
/// <summary>
/// Overrides the default per-monitor DPI scaling behavior of a child window in a dialog.
/// This function returns TRUE if the operation was successful, and FALSE otherwise. To get extended error information, call GetLastError.
///
/// Possible errors are ERROR_INVALID_HANDLE if passed an invalid HWND, and ERROR_ACCESS_DENIED if the windows belongs to another process.
///
/// The behaviors are specified as values from the DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS enum. This function follows the typical two-parameter approach to setting flags, where a mask specifies the subset of the flags to be changed.
///
/// It is valid to set these behaviors on any window. It does not matter if the window is currently a child of a dialog at the point in time that SetDialogControlDpiChangeBehavior is called. The behaviors are retained and will take effect only when the window is an immediate child of a dialog that has per-monitor DPI scaling enabled.
///
/// This API influences individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior is controlled by SetDialogDpiChangeBehavior.
/// </summary>
/// <param name="hWnd">IntPtr A handle for the window whose behavior will be modified.</param>
/// <param name="mask">DialogScalingBehaviors A mask specifying the subset of flags to be changed.</param>
/// <param name="values">DialogScalingBehaviors The desired value to be set for the specified subset of flags.</param>
/// <returns>bool</returns>
[DllImport("User32.dll")]
private static extern bool SetDialogControlDpiChangeBehavior(IntPtr hWnd, DialogScalingBehaviors mask, DialogScalingBehaviors values);
/// <summary>
/// Retrieves and per-monitor DPI scaling behavior overrides of a child window in a dialog.
/// The flags set on the given window. If passed an invalid handle, this function will return zero, and set its last error to ERROR_INVALID_HANDLE.
/// </summary>
/// <param name="hWnd">IntPtr A handle for the window whose behavior will be modified.</param>
/// <returns>DialogScalingBehaviors</returns>
[DllImport("User32.dll")]
private static extern DialogScalingBehaviors GetDialogControlDpiChangeBehavior(IntPtr hWnd);
}
}

View file

@ -0,0 +1,34 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// In Per Monitor v2 contexts, dialogs will automatically respond to DPI changes by resizing themselves and re-computing the positions of their child windows (here referred to as re-layouting). This enum works in conjunction with SetDialogDpiChangeBehavior in order to override the default DPI scaling behavior for dialogs.
/// This does not affect DPI scaling behavior for the child windows of dialogs(beyond re-layouting), which is controlled by DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS.
/// </summary>
[Flags]
public enum DialogDpiChangeBehaviors
{
/// <summary>
/// The default behavior of the dialog manager. In response to a DPI change, the dialog manager will re-layout each control, update the font on each control, resize the dialog, and update the dialog's own font.
/// </summary>
Default = 0,
/// <summary>
/// Prevents the dialog manager from responding to WM_GETDPISCALEDSIZE and WM_DPICHANGED, disabling all default DPI scaling behavior.
/// </summary>
DisableAll = 1,
/// <summary>
/// Prevents the dialog manager from resizing the dialog in response to a DPI change.
/// </summary>
DisableResize = 2,
/// <summary>
/// Prevents the dialog manager from re-layouting all of the dialogue's immediate children HWNDs in response to a DPI change.
/// </summary>
DisableControlRelayout = 3
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// Describes per-monitor DPI scaling behavior overrides for child windows within dialogs. The values in this enumeration are bitfields and can be combined.
///
/// This enum is used with SetDialogControlDpiChangeBehavior in order to override the default per-monitor DPI scaling behavior for a child window within a dialog.
///
/// These settings only apply to individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior of a dialog is controlled by DIALOG_DPI_CHANGE_BEHAVIORS.
/// </summary>
[Flags]
public enum DialogScalingBehaviors
{
/// <summary>
/// The default behavior of the dialog manager. The dialog managed will update the font, size, and position of the child window on DPI changes.
/// </summary>
Default = 0,
/// <summary>
/// Prevents the dialog manager from sending an updated font to the child window via WM_SETFONT in response to a DPI change.
/// </summary>
DisableFontUpdate = 1,
/// <summary>
/// Prevents the dialog manager from resizing and repositioning the child window in response to a DPI change.
/// </summary>
DisableRelayout = 2
}
}

View file

@ -0,0 +1,40 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// Identifies the dots per inch (dpi) setting for a thread, process, or window.
/// Can be used everywhere ProcessDpiAwareness is passed.
/// </summary>
public enum DpiAwareness
{
/// <summary>
/// Invalid DPI awareness. This is an invalid DPI awareness value.
/// </summary>
Invalid = -1,
/// <summary>
/// DPI unaware.
/// This process does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI).
/// It will be automatically scaled by the system on any other DPI setting.
/// </summary>
Unaware = 0,
/// <summary>
/// System DPI aware.
/// This process does not scale for DPI changes.
/// It will query for the DPI once and use that value for the lifetime of the process.
/// If the DPI changes, the process will not adjust to the new DPI value.
/// It will be automatically scaled up or down by the system when the DPI changes from the system value.
/// </summary>
SystemAware = 1,
/// <summary>
/// Per monitor DPI aware.
/// This process checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes.
/// These processes are not automatically scaled by the system.
/// </summary>
PerMonitorAware = 2
}
}

View file

@ -0,0 +1,46 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// </summary>
public enum DpiAwarenessContext
{
/// <summary>
/// DPI unaware.
/// This window does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI).
/// It will be automatically scaled by the system on any other DPI setting.
/// </summary>
Unaware = -1,
/// <summary>
/// System DPI aware.
/// This window does not scale for DPI changes.
/// It will query for the DPI once and use that value for the lifetime of the process.
/// If the DPI changes, the process will not adjust to the new DPI value.
/// It will be automatically scaled up or down by the system when the DPI changes from the system value.
/// </summary>
SystemAware = -2,
/// <summary>
/// Per monitor DPI aware.
/// This window checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes.
/// These processes are not automatically scaled by the system.
/// </summary>
PerMonitorAware = -3,
/// <summary>
/// Also known as Per Monitor v2. An advancement over the original per-monitor DPI awareness mode, which enables applications to access new DPI-related scaling behaviors on a per top-level window basis.
/// Per Monitor v2 was made available in the Creators Update of Windows 10, and is not available on earlier versions of the operating system.
/// The additional behaviors introduced are as follows:
/// * Child window DPI change notifications - In Per Monitor v2 contexts, the entire window tree is notified of any DPI changes that occur.
/// * Scaling of non-client area - All windows will automatically have their non-client area drawn in a DPI sensitive fashion. Calls to EnableNonClientDpiScaling are unnecessary.
/// * Scaling of Win32 menus - All NTUSER menus created in Per Monitor v2 contexts will be scaling in a per-monitor fashion.
/// * Dialog Scaling - Win32 dialogs created in Per Monitor v2 contexts will automatically respond to DPI changes.
/// * Improved scaling of comctl32 controls - Various comctl32 controls have improved DPI scaling behavior in Per Monitor v2 contexts.
/// * Improved theming behavior - UxTheme handles opened in the context of a Per Monitor v2 window will operate in terms of the DPI associated with that window.
/// </summary>
PerMonitorAwareV2 = -4
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// Identifies the DPI hosting behavior for a window.
/// This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT
/// </summary>
public enum DpiHostingBehavior
{
/// <summary>
/// Invalid DPI hosting behavior. This usually occurs if the previous SetThreadDpiHostingBehavior call used an invalid parameter.
/// </summary>
Invalid = -1,
/// <summary>
/// Default DPI hosting behavior. The associated window behaves as normal, and cannot create or re-parent child windows with a different DPI_AWARENESS_CONTEXT.
/// </summary>
Default = 0,
/// <summary>
/// Mixed DPI hosting behavior. This enables the creation and re-parenting of child windows with different DPI_AWARENESS_CONTEXT. These child windows will be independently scaled by the OS.
/// </summary>
Mixed = 1
}
}

View file

@ -1,11 +1,25 @@
using System; // Greenshot - a free and open source screenshot tool
using System.Collections.Generic; // Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
using System.Diagnostics.CodeAnalysis; //
using System.Linq; // For more information see: http://getgreenshot.org/
using System.Text; // The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
using System.Threading.Tasks; //
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 1 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General 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 GreenshotWin10Plugin.Native using System.Diagnostics.CodeAnalysis;
namespace GreenshotPlugin.Core.Enums
{ {
/// <summary> /// <summary>
/// The HRESULT represents Windows error codes /// The HRESULT represents Windows error codes

View file

@ -0,0 +1,40 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// See
/// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511(v=vs.85).aspx">
/// MONITOR_DPI_TYPE
/// enumeration
/// </a>
/// </summary>
[Flags]
public enum MonitorDpiType
{
/// <summary>
/// The effective DPI.
/// This value should be used when determining the correct scale factor for scaling UI elements.
/// This incorporates the scale factor set by the user for this specific display.
/// </summary>
EffectiveDpi = 0,
/// <summary>
/// The angular DPI.
/// This DPI ensures rendering at a compliant angular resolution on the screen.
/// This does not include the scale factor set by the user for this specific display
/// </summary>
AngularDpi = 1,
/// <summary>
/// The raw DPI.
/// This value is the linear DPI of the screen as measured on the screen itself.
/// Use this value when you want to read the pixel density and not the recommended scaling setting.
/// This does not include the scale factor set by the user for this specific display and is not guaranteed to be a
/// supported DPI value.
/// </summary>
RawDpi = 2
}
}

View file

@ -0,0 +1,30 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// Flags for the MonitorFromRect / MonitorFromWindow "flags" field
/// see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd145063(v=vs.85).aspx">MonitorFromRect function</a>
/// or see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd145064(v=vs.85).aspx">MonitorFromWindow function</a>
/// </summary>
[Flags]
public enum MonitorFrom : uint
{
/// <summary>
/// Returns a handle to the display monitor that is nearest to the rectangle.
/// </summary>
DefaultToNearest = 0,
/// <summary>
/// Returns NULL. (why??)
/// </summary>
DefaultToNull = 1,
/// <summary>
/// Returns a handle to the primary display monitor.
/// </summary>
DefaultToPrimary = 2
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace GreenshotPlugin.Core.Enums
{
/// <summary>
/// If a system parameter is being set, specifies whether the user profile is to be updated, and if so, whether the
/// WM_SETTINGCHANGE message is to be broadcast to all top-level windows to notify them of the change.
/// This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message,
/// or it can be one or more of the following values.
/// </summary>
public enum SystemParametersInfoBehaviors : uint
{
/// <summary>
/// Do nothing
/// </summary>
None = 0x00,
/// <summary>Writes the new system-wide parameter setting to the user profile.</summary>
UpdateIniFile = 0x01,
/// <summary>Broadcasts the WM_SETTINGCHANGE message after updating the user profile.</summary>
SendChange = 0x02,
/// <summary>Same as SPIF_SENDCHANGE.</summary>
SendWinIniChange = SendChange
}
}

View file

@ -17,10 +17,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using GreenshotPlugin.Core.Enums;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace GreenshotWin10Plugin.Native namespace GreenshotPlugin.Core
{ {
/// <summary> /// <summary>
/// Extensions to handle the HResult /// Extensions to handle the HResult
@ -55,7 +56,7 @@ namespace GreenshotWin10Plugin.Native
/// <param name="hResult">HResult</param> /// <param name="hResult">HResult</param>
public static void ThrowOnFailure(this HResult hResult) public static void ThrowOnFailure(this HResult hResult)
{ {
if (Failed(hResult)) if (hResult.Failed())
{ {
throw Marshal.GetExceptionForHR((int)hResult); throw Marshal.GetExceptionForHR((int)hResult);
} }

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -1203,7 +1203,7 @@ namespace GreenshotPlugin.Core {
public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma) public static Image Adjust(Image sourceImage, float brightness, float contrast, float gamma)
{ {
//create a blank bitmap the same size as original //create a blank bitmap the same size as original
// If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format. // If using 8bpp than the following exception comes: A Graphics object cannot be created from an image that has an indexed pixel format.
Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); Bitmap newBitmap = CreateEmpty(sourceImage.Width, sourceImage.Height, PixelFormat.Format24bppRgb, Color.Empty, sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma)) using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma))
{ {
@ -1306,7 +1306,7 @@ namespace GreenshotPlugin.Core {
sourceRect.Intersect(bitmapRect); sourceRect.Intersect(bitmapRect);
} }
// If no pixelformat is supplied // If no pixelformat is supplied
if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat) if (PixelFormat.DontCare == targetFormat || PixelFormat.Undefined == targetFormat)
{ {
if (SupportsPixelFormat(sourceImage.PixelFormat)) if (SupportsPixelFormat(sourceImage.PixelFormat))

View file

@ -1,102 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub: https://github.com/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General 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
{
/// <summary>
/// Extensions to help with querying the Operating System
/// </summary>
public static class OperatingSystemExtensions
{
/// <summary>
/// Test if the current OS is Windows 10
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 10</returns>
public static bool IsWindows10(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major == 10;
}
/// <summary>
/// Test if the current OS is Windows 10 or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 10 or later</returns>
public static bool IsWindows10OrLater(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major >= 10;
}
/// <summary>
/// Test if the current OS is Windows 8(.1)
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 8(.1)</returns>
public static bool IsWindows8(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2;
}
/// <summary>
/// Test if the current OS is Windows 8 or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 8 or later</returns>
public static bool IsWindows8OrLater(this OperatingSystem operatingSystem)
{
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major > 6;
}
/// <summary>
/// Test if the current OS is Windows 7 or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows 7 or later</returns>
public static bool IsWindows7OrLater(this OperatingSystem operatingSystem)
{
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major > 6;
}
/// <summary>
/// Test if the current OS is Windows Vista or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows Vista or later</returns>
public static bool IsWindowsVistaOrLater(this OperatingSystem operatingSystem)
{
return operatingSystem.Version.Major >= 6;
}
/// <summary>
/// Test if the current OS is Windows XP or later
/// </summary>
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
/// <returns>true if we are running on Windows XP or later</returns>
public static bool IsWindowsXpOrLater(this OperatingSystem operatingSystem)
{
// Windows 2000 is Major 5 minor 0
return Environment.OSVersion.Version.Major > 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1);
}
}
}

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -145,7 +145,7 @@ namespace GreenshotPlugin.Core {
private static readonly IList<IntPtr> IgnoreHandles = new List<IntPtr>(); private static readonly IList<IntPtr> IgnoreHandles = new List<IntPtr>();
private static readonly IList<string> ExcludeProcessesFromFreeze = new List<string>(); private static readonly IList<string> ExcludeProcessesFromFreeze = new List<string>();
private static readonly IAppVisibility AppVisibility; private static readonly IAppVisibility AppVisibility;
static WindowDetails() { static WindowDetails() {
try try
{ {
@ -212,7 +212,7 @@ namespace GreenshotPlugin.Core {
public override int GetHashCode() { public override int GetHashCode() {
return Handle.ToInt32(); return Handle.ToInt32();
} }
public override bool Equals(object right) { public override bool Equals(object right) {
return Equals(right as WindowDetails); return Equals(right as WindowDetails);
} }
@ -226,11 +226,11 @@ namespace GreenshotPlugin.Core {
if (other is null) { if (other is null) {
return false; return false;
} }
if (ReferenceEquals(this, other)) { if (ReferenceEquals(this, other)) {
return true; return true;
} }
if (GetType() != other.GetType()){ if (GetType() != other.GetType()){
return false; return false;
} }
@ -377,7 +377,7 @@ namespace GreenshotPlugin.Core {
private static IEnumerable<WindowDetails> FindWindow(IList<WindowDetails> windows, string titlePattern, string classnamePattern) { private static IEnumerable<WindowDetails> FindWindow(IList<WindowDetails> windows, string titlePattern, string classnamePattern) {
Regex titleRegexp = null; Regex titleRegexp = null;
Regex classnameRegexp = null; Regex classnameRegexp = null;
if (titlePattern != null && titlePattern.Trim().Length > 0) { if (titlePattern != null && titlePattern.Trim().Length > 0) {
titleRegexp = new Regex(titlePattern); titleRegexp = new Regex(titlePattern);
} }
@ -393,7 +393,7 @@ namespace GreenshotPlugin.Core {
} }
} }
} }
/// <summary> /// <summary>
/// Retrieve the child with matching classname /// Retrieve the child with matching classname
/// </summary> /// </summary>
@ -486,7 +486,7 @@ namespace GreenshotPlugin.Core {
public IEnumerable<WindowDetails> FindChildren(string titlePattern, string classnamePattern) { public IEnumerable<WindowDetails> FindChildren(string titlePattern, string classnamePattern) {
return FindWindow(Children, titlePattern, classnamePattern); return FindWindow(Children, titlePattern, classnamePattern);
} }
/// <summary> /// <summary>
/// Recursing helper method for the FindPath /// Recursing helper method for the FindPath
/// </summary> /// </summary>
@ -620,7 +620,7 @@ namespace GreenshotPlugin.Core {
} }
} }
} }
/// <summary> /// <summary>
/// Gets/Sets whether the window is maximised or not. /// Gets/Sets whether the window is maximised or not.
/// </summary> /// </summary>
@ -650,14 +650,14 @@ namespace GreenshotPlugin.Core {
} }
} }
} }
/// <summary> /// <summary>
/// This doesn't work as good as is should, but does move the App out of the way... /// This doesn't work as good as is should, but does move the App out of the way...
/// </summary> /// </summary>
public void HideApp() { public void HideApp() {
User32.ShowWindow(Handle, ShowWindowCommand.Hide); User32.ShowWindow(Handle, ShowWindowCommand.Hide);
} }
/// <summary> /// <summary>
/// Gets whether the window is visible. /// Gets whether the window is visible.
/// </summary> /// </summary>
@ -697,7 +697,7 @@ namespace GreenshotPlugin.Core {
return User32.IsWindowVisible(Handle); return User32.IsWindowVisible(Handle);
} }
} }
public bool HasParent { public bool HasParent {
get { get {
GetParent(); GetParent();
@ -757,7 +757,7 @@ namespace GreenshotPlugin.Core {
_lastWindowRectangleRetrieveTime = now; _lastWindowRectangleRetrieveTime = now;
} }
} }
if (gotFrameBounds && Environment.OSVersion.IsWindows10() && !Maximised) if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised)
{ {
// Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture // Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture
// Remove this border, currently it's fixed but TODO: Make it depend on the OS? // Remove this border, currently it's fixed but TODO: Make it depend on the OS?
@ -775,7 +775,7 @@ namespace GreenshotPlugin.Core {
Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error));
} }
} }
// Correction for maximized windows, only if it's not an app // Correction for maximized windows, only if it's not an app
if (!HasParent && !IsApp && Maximised) { if (!HasParent && !IsApp && Maximised) {
// Only if the border size can be retrieved // Only if the border size can be retrieved
@ -816,7 +816,7 @@ namespace GreenshotPlugin.Core {
return new Size(tmpRectangle.Right - tmpRectangle.Left, tmpRectangle.Bottom - tmpRectangle.Top); return new Size(tmpRectangle.Right - tmpRectangle.Left, tmpRectangle.Bottom - tmpRectangle.Top);
} }
} }
/// <summary> /// <summary>
/// Get the client rectangle, this is the part of the window inside the borders (drawable area) /// Get the client rectangle, this is the part of the window inside the borders (drawable area)
/// </summary> /// </summary>
@ -841,7 +841,7 @@ namespace GreenshotPlugin.Core {
} }
/// <summary> /// <summary>
/// Restores and Brings the window to the front, /// Restores and Brings the window to the front,
/// assuming it is a visible application window. /// assuming it is a visible application window.
/// </summary> /// </summary>
public void Restore() { public void Restore() {
@ -969,7 +969,7 @@ namespace GreenshotPlugin.Core {
} else { } else {
doesCaptureFit = true; doesCaptureFit = true;
} }
} else if (!Environment.OSVersion.IsWindows8OrLater()) { } else if (!WindowsVersion.IsWindows8OrLater) {
//GetClientRect(out windowRectangle); //GetClientRect(out windowRectangle);
GetBorderSize(out borderSize); GetBorderSize(out borderSize);
formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height); formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height);
@ -986,7 +986,7 @@ namespace GreenshotPlugin.Core {
captureRectangle.Inflate(borderSize.Width, borderSize.Height); captureRectangle.Inflate(borderSize.Width, borderSize.Height);
} else { } else {
// TODO: Also 8.x? // TODO: Also 8.x?
if (Environment.OSVersion.IsWindows10()) if (WindowsVersion.IsWindows10OrLater)
{ {
captureRectangle.Inflate(Conf.Win10BorderCrop); captureRectangle.Inflate(Conf.Win10BorderCrop);
} }
@ -1017,7 +1017,7 @@ namespace GreenshotPlugin.Core {
// Intersect with screen // Intersect with screen
captureRectangle.Intersect(capture.ScreenBounds); captureRectangle.Intersect(capture.ScreenBounds);
// Destination bitmap for the capture // Destination bitmap for the capture
Bitmap capturedBitmap = null; Bitmap capturedBitmap = null;
bool frozen = false; bool frozen = false;
@ -1064,7 +1064,7 @@ namespace GreenshotPlugin.Core {
Color colorizationColor = DWM.ColorizationColor; Color colorizationColor = DWM.ColorizationColor;
// Modify by losing the transparency and increasing the intensity (as if the background color is white) // Modify by losing the transparency and increasing the intensity (as if the background color is white)
colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1);
tempForm.BackColor = colorizationColor; tempForm.BackColor = colorizationColor;
} }
// Make sure everything is visible // Make sure everything is visible
tempForm.Refresh(); tempForm.Refresh();
@ -1079,7 +1079,7 @@ namespace GreenshotPlugin.Core {
} }
if (capturedBitmap != null) { if (capturedBitmap != null) {
// Not needed for Windows 8 // Not needed for Windows 8
if (!Environment.OSVersion.IsWindows8OrLater()) { if (!WindowsVersion.IsWindows8OrLater) {
// Only if the Inivalue is set, not maximized and it's not a tool window. // Only if the Inivalue is set, not maximized and it's not a tool window.
if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) { if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) {
// Remove corners // Remove corners
@ -1099,7 +1099,7 @@ namespace GreenshotPlugin.Core {
UnfreezeWindow(); UnfreezeWindow();
} }
} }
capture.Image = capturedBitmap; capture.Image = capturedBitmap;
// Make sure the capture location is the location of the window, not the copy // Make sure the capture location is the location of the window, not the copy
capture.Location = Location; capture.Location = Location;
@ -1181,7 +1181,7 @@ namespace GreenshotPlugin.Core {
} }
return targetBuffer.UnlockAndReturnBitmap(); return targetBuffer.UnlockAndReturnBitmap();
} }
/// <summary> /// <summary>
/// Helper method to get the window size for DWM Windows /// Helper method to get the window size for DWM Windows
/// </summary> /// </summary>
@ -1201,7 +1201,7 @@ namespace GreenshotPlugin.Core {
/// Helper method to get the window size for GDI Windows /// Helper method to get the window size for GDI Windows
/// </summary> /// </summary>
/// <param name="rectangle">out Rectangle</param> /// <param name="rectangle">out Rectangle</param>
/// <returns>bool true if it worked</returns> /// <returns>bool true if it worked</returns>
private bool GetClientRect(out Rectangle rectangle) { private bool GetClientRect(out Rectangle rectangle) {
var windowInfo = new WindowInfo(); var windowInfo = new WindowInfo();
// Get the Window Info for this window // Get the Window Info for this window
@ -1209,12 +1209,12 @@ namespace GreenshotPlugin.Core {
rectangle = result ? windowInfo.rcClient.ToRectangle() : Rectangle.Empty; rectangle = result ? windowInfo.rcClient.ToRectangle() : Rectangle.Empty;
return result; return result;
} }
/// <summary> /// <summary>
/// Helper method to get the window size for GDI Windows /// Helper method to get the window size for GDI Windows
/// </summary> /// </summary>
/// <param name="rectangle">out Rectangle</param> /// <param name="rectangle">out Rectangle</param>
/// <returns>bool true if it worked</returns> /// <returns>bool true if it worked</returns>
private bool GetWindowRect(out Rectangle rectangle) { private bool GetWindowRect(out Rectangle rectangle) {
var windowInfo = new WindowInfo(); var windowInfo = new WindowInfo();
// Get the Window Info for this window // Get the Window Info for this window
@ -1227,7 +1227,7 @@ namespace GreenshotPlugin.Core {
/// Helper method to get the Border size for GDI Windows /// Helper method to get the Border size for GDI Windows
/// </summary> /// </summary>
/// <param name="size">out Size</param> /// <param name="size">out Size</param>
/// <returns>bool true if it worked</returns> /// <returns>bool true if it worked</returns>
private bool GetBorderSize(out Size size) { private bool GetBorderSize(out Size size) {
var windowInfo = new WindowInfo(); var windowInfo = new WindowInfo();
// Get the Window Info for this window // Get the Window Info for this window
@ -1280,7 +1280,7 @@ namespace GreenshotPlugin.Core {
public void ToForeground(bool workaround = true) { public void ToForeground(bool workaround = true) {
ToForeground(Handle, workaround); ToForeground(Handle, workaround);
} }
/// <summary> /// <summary>
/// Get the region for a window /// Get the region for a window
/// </summary> /// </summary>
@ -1295,7 +1295,7 @@ namespace GreenshotPlugin.Core {
} }
return null; return null;
} }
private bool CanFreezeOrUnfreeze(string titleOrProcessname) { private bool CanFreezeOrUnfreeze(string titleOrProcessname) {
if (string.IsNullOrEmpty(titleOrProcessname)) { if (string.IsNullOrEmpty(titleOrProcessname)) {
return false; return false;
@ -1397,13 +1397,13 @@ namespace GreenshotPlugin.Core {
exceptionOccured = User32.CreateWin32Exception("PrintWindow"); exceptionOccured = User32.CreateWin32Exception("PrintWindow");
} }
} }
// Apply the region "transparency" // Apply the region "transparency"
if (region != null && !region.IsEmpty(graphics)) { if (region != null && !region.IsEmpty(graphics)) {
graphics.ExcludeClip(region); graphics.ExcludeClip(region);
graphics.Clear(Color.Transparent); graphics.Clear(Color.Transparent);
} }
graphics.Flush(); graphics.Flush();
} }
@ -1421,7 +1421,7 @@ namespace GreenshotPlugin.Core {
} }
return returnImage; return returnImage;
} }
/// <summary> /// <summary>
/// Constructs a new instance of this class for /// Constructs a new instance of this class for
/// the specified Window Handle. /// the specified Window Handle.
@ -1430,7 +1430,7 @@ namespace GreenshotPlugin.Core {
public WindowDetails(IntPtr hWnd) { public WindowDetails(IntPtr hWnd) {
Handle = hWnd; Handle = hWnd;
} }
/// <summary> /// <summary>
/// Gets an instance of the current active foreground window /// Gets an instance of the current active foreground window
/// </summary> /// </summary>
@ -1451,7 +1451,7 @@ namespace GreenshotPlugin.Core {
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Check if this window is Greenshot /// Check if this window is Greenshot
/// </summary> /// </summary>
@ -1469,7 +1469,7 @@ namespace GreenshotPlugin.Core {
return false; return false;
} }
} }
/// <summary> /// <summary>
/// Gets the Desktop window /// Gets the Desktop window
/// </summary> /// </summary>
@ -1477,7 +1477,7 @@ namespace GreenshotPlugin.Core {
public static WindowDetails GetDesktopWindow() { public static WindowDetails GetDesktopWindow() {
return new WindowDetails(User32.GetDesktopWindow()); return new WindowDetails(User32.GetDesktopWindow());
} }
/// <summary> /// <summary>
/// Get all the top level windows /// Get all the top level windows
/// </summary> /// </summary>
@ -1715,7 +1715,7 @@ namespace GreenshotPlugin.Core {
if (window.Iconic) { if (window.Iconic) {
continue; continue;
} }
// Windows without size // Windows without size
Size windowSize = window.WindowRectangle.Size; Size windowSize = window.WindowRectangle.Size;
if (windowSize.Width == 0 || windowSize.Height == 0) { if (windowSize.Width == 0 || windowSize.Height == 0) {
@ -1744,7 +1744,7 @@ namespace GreenshotPlugin.Core {
} }
} }
} }
/// <summary> /// <summary>
/// Get the AppLauncher /// Get the AppLauncher
/// </summary> /// </summary>
@ -1760,7 +1760,7 @@ namespace GreenshotPlugin.Core {
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Return true if the metro-app-launcher is visible /// Return true if the metro-app-launcher is visible
/// </summary> /// </summary>

View file

@ -0,0 +1,107 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace GreenshotPlugin.Core
{
/// <summary>
/// Extension methods to test the windows version
/// </summary>
public static class WindowsVersion
{
/// <summary>
/// Get the current windows version
/// </summary>
public static Version WinVersion { get; } = Environment.OSVersion.Version;
/// <summary>
/// Test if the current OS is Windows 10
/// </summary>
/// <returns>true if we are running on Windows 10</returns>
public static bool IsWindows10 { get; } = WinVersion.Major == 10;
/// <summary>
/// Test if the current OS is Windows 10 or later
/// </summary>
/// <returns>true if we are running on Windows 10 or later</returns>
public static bool IsWindows10OrLater { get; } = WinVersion.Major >= 10;
/// <summary>
/// Test if the current OS is Windows 7 or later
/// </summary>
/// <returns>true if we are running on Windows 7 or later</returns>
public static bool IsWindows7OrLater { get; } = WinVersion.Major == 6 && WinVersion.Minor >= 1 || WinVersion.Major > 6;
/// <summary>
/// Test if the current OS is Windows 8.0
/// </summary>
/// <returns>true if we are running on Windows 8.0</returns>
public static bool IsWindows8 { get; } = WinVersion.Major == 6 && WinVersion.Minor == 2;
/// <summary>
/// Test if the current OS is Windows 8(.1)
/// </summary>
/// <returns>true if we are running on Windows 8(.1)</returns>
public static bool IsWindows81 { get; } = WinVersion.Major == 6 && WinVersion.Minor == 3;
/// <summary>
/// Test if the current OS is Windows 8.0 or 8.1
/// </summary>
/// <returns>true if we are running on Windows 8.1 or 8.0</returns>
public static bool IsWindows8X { get; } = IsWindows8 || IsWindows81;
/// <summary>
/// Test if the current OS is Windows 8.1 or later
/// </summary>
/// <returns>true if we are running on Windows 8.1 or later</returns>
public static bool IsWindows81OrLater { get; } = WinVersion.Major == 6 && WinVersion.Minor >= 3 || WinVersion.Major > 6;
/// <summary>
/// Test if the current OS is Windows 8 or later
/// </summary>
/// <returns>true if we are running on Windows 8 or later</returns>
public static bool IsWindows8OrLater { get; } = WinVersion.Major == 6 && WinVersion.Minor >= 2 || WinVersion.Major > 6;
/// <summary>
/// Test if the current OS is Windows Vista
/// </summary>
/// <returns>true if we are running on Windows Vista or later</returns>
public static bool IsWindowsVista { get; } = WinVersion.Major >= 6 && WinVersion.Minor == 0;
/// <summary>
/// Test if the current OS is Windows Vista or later
/// </summary>
/// <returns>true if we are running on Windows Vista or later</returns>
public static bool IsWindowsVistaOrLater { get; } = WinVersion.Major >= 6;
/// <summary>
/// Test if the current OS is from before Windows Vista (e.g. Windows XP)
/// </summary>
/// <returns>true if we are running on Windows from before Vista</returns>
public static bool IsWindowsBeforeVista { get; } = WinVersion.Major < 6;
/// <summary>
/// Test if the current OS is Windows XP
/// </summary>
/// <returns>true if we are running on Windows XP or later</returns>
public static bool IsWindowsXp { get; } = WinVersion.Major == 5 && WinVersion.Minor >= 1;
/// <summary>
/// Test if the current OS is Windows XP or later
/// </summary>
/// <returns>true if we are running on Windows XP or later</returns>
public static bool IsWindowsXpOrLater { get; } = WinVersion.Major >= 5 || WinVersion.Major == 5 && WinVersion.Minor >= 1;
/// <summary>
/// Test if the current Windows version is 10 and the build number or later
/// See the build numbers <a href="https://en.wikipedia.org/wiki/Windows_10_version_history">here</a>
/// </summary>
/// <param name="minimalBuildNumber">int</param>
/// <returns>bool</returns>
public static bool IsWindows10BuildOrLater(int minimalBuildNumber)
{
return IsWindows10 && WinVersion.Build >= minimalBuildNumber;
}
}
}

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -25,12 +25,12 @@ using System.Text;
namespace Greenshot.IniFile { namespace Greenshot.IniFile {
/// <summary> /// <summary>
/// /// The IniReader does exactly what it says, it reads the .ini file
/// </summary> /// </summary>
public static class IniReader { public static class IniReader {
private const string SectionStart = "["; private const char SectionStartToken = '[';
private const string SectionEnd = "]"; private const char SectionEndToken = ']';
private const string Comment = ";"; private const char CommentToken = ';';
private static readonly char[] Assignment = { '=' }; private static readonly char[] Assignment = { '=' };
/// <summary> /// <summary>
@ -52,11 +52,16 @@ namespace Greenshot.IniFile {
continue; continue;
} }
string cleanLine = line.Trim(); string cleanLine = line.Trim();
if (cleanLine.Length == 0 || cleanLine.StartsWith(Comment)) { if (cleanLine.Length == 0 || cleanLine[0] == CommentToken) {
continue; continue;
} }
if (cleanLine.StartsWith(SectionStart)) { if (cleanLine[0] == SectionStartToken) {
string section = line.Replace(SectionStart, string.Empty).Replace(SectionEnd, string.Empty).Trim(); var sectionEndIndex = line.IndexOf(SectionEndToken,1);
if (sectionEndIndex <0)
{
continue;
}
string section = line.Substring(1,sectionEndIndex-1).Trim();
if (!ini.TryGetValue(section, out nameValues)) if (!ini.TryGetValue(section, out nameValues))
{ {
nameValues = new Dictionary<string, string>(); nameValues = new Dictionary<string, string>();

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -155,7 +155,7 @@ namespace GreenshotPlugin.UnmanagedHelpers {
// Cleanup // Cleanup
User32.DestroyIcon(shfi.hIcon); User32.DestroyIcon(shfi.hIcon);
return icon; return icon;
} }
/// <summary> /// <summary>
/// Returns an icon representation of an image contained in the specified file. /// Returns an icon representation of an image contained in the specified file.

View file

@ -1,20 +1,20 @@
/* /*
* Greenshot - a free and open source screenshot tool * Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or * the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -30,6 +30,7 @@ using Microsoft.Win32.SafeHandles;
using System.Security; using System.Security;
using System.Security.Permissions; using System.Security.Permissions;
using log4net; using log4net;
using GreenshotPlugin.Core.Enums;
namespace GreenshotPlugin.UnmanagedHelpers { namespace GreenshotPlugin.UnmanagedHelpers {
/// <summary> /// <summary>
@ -53,7 +54,7 @@ namespace GreenshotPlugin.UnmanagedHelpers {
public const int PW_DEFAULT = 0x00; public const int PW_DEFAULT = 0x00;
public const int PW_CLIENTONLY = 0x01; public const int PW_CLIENTONLY = 0x01;
// For MonitorFromWindow // For MonitorFromWindow
public const int MONITOR_DEFAULTTONULL = 0; public const int MONITOR_DEFAULTTONULL = 0;
public const int MONITOR_DEFAULTTOPRIMARY = 1; public const int MONITOR_DEFAULTTOPRIMARY = 1;
@ -62,6 +63,19 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern bool keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); public static extern bool keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
/// <summary>
/// Determines whether the specified window handle identifies an existing window.
/// </summary>
/// <param name="hWnd">A handle to the window to be tested.</param>
/// <returns>
/// If the window handle identifies an existing window, the return value is true.
/// If the window handle does not identify an existing window, the return value is false.
/// </returns>
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd); public static extern bool IsWindowVisible(IntPtr hWnd);
@ -125,7 +139,7 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[DllImport("user32", SetLastError = true, EntryPoint = "SetWindowLongPtr")] [DllImport("user32", SetLastError = true, EntryPoint = "SetWindowLongPtr")]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int index, IntPtr styleFlags); public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int index, IntPtr styleFlags);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags); public static extern IntPtr MonitorFromWindow(IntPtr hwnd, MonitorFrom dwFlags);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags); public static extern IntPtr MonitorFromRect([In] ref RECT lprc, uint dwFlags);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
@ -224,8 +238,18 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern bool CloseDesktop(IntPtr hDesktop); public static extern bool CloseDesktop(IntPtr hDesktop);
/// <summary>
/// The GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. A window device context permits painting anywhere in a window, because the origin of the device context is the upper-left corner of the window instead of the client area.
/// GetWindowDC assigns default attributes to the window device context each time it retrieves the device context.Previous attributes are lost.
/// See <a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowdc">GetWindowDC function</a>
/// </summary>
/// <param name="hWnd">A handle to the window whose DC is to be retrieved. If this value is NULL, GetWindowDC retrieves the DC for the entire screen.</param>
/// <returns>If the function succeeds, the return value is a handle to a device context for the specified window.</returns>
[DllImport("user32", SetLastError = true)]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
/// <summary>
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7.
/// </summary> /// </summary>
/// <returns>Point with cursor location, relative to the origin of the monitor setup /// <returns>Point with cursor location, relative to the origin of the monitor setup
@ -407,6 +431,21 @@ namespace GreenshotPlugin.UnmanagedHelpers {
return returnValue; return returnValue;
} }
/// <summary>
/// Creates a DC as SafeWindowDcHandle for the whole of the specified hWnd
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <returns>SafeWindowDcHandle</returns>
public static SafeWindowDcHandle FromWindow(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
{
return null;
}
var hDcDesktop = GetWindowDC(hWnd);
return new SafeWindowDcHandle(hWnd, hDcDesktop);
}
public static SafeWindowDcHandle FromDesktop() { public static SafeWindowDcHandle FromDesktop() {
IntPtr hWndDesktop = User32.GetDesktopWindow(); IntPtr hWndDesktop = User32.GetDesktopWindow();
IntPtr hDCDesktop = GetWindowDC(hWndDesktop); IntPtr hDCDesktop = GetWindowDC(hWndDesktop);

View file

@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using GreenshotPlugin.Core;
using System; using System;
using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.DataTransfer;

View file

@ -17,18 +17,19 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using GreenshotPlugin.Core.Enums;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Windows.ApplicationModel.DataTransfer; using Windows.ApplicationModel.DataTransfer;
namespace GreenshotWin10Plugin.Native namespace GreenshotWin10Plugin.Native
{ {
/// <summary> /// <summary>
/// The IDataTransferManagerInterOp is documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/jj542488(v=vs.85).aspx. /// The IDataTransferManagerInterOp is documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/jj542488(v=vs.85).aspx.
/// This interface allows an app to tie the share context to a specific /// This interface allows an app to tie the share context to a specific
/// window using a window handle. Useful for Win32 apps. /// window using a window handle. Useful for Win32 apps.
/// </summary> /// </summary>
[ComImport, Guid("3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8")] [ComImport, Guid("3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDataTransferManagerInterOp public interface IDataTransferManagerInterOp
{ {

View file

@ -54,7 +54,7 @@ namespace GreenshotWin10Plugin
/// <returns>IEnumerable with the destinations</returns> /// <returns>IEnumerable with the destinations</returns>
public IEnumerable<IDestination> Destinations() public IEnumerable<IDestination> Destinations()
{ {
if (!Environment.OSVersion.IsWindows10OrLater()) if (!WindowsVersion.IsWindows10OrLater)
{ {
yield break; yield break;
} }