WIP fixed some DPI issues, still missing some icons

This commit is contained in:
Robin Krom 2022-04-05 23:51:48 +02:00
commit f3c986e3f4
No known key found for this signature in database
GPG key ID: BCC01364F1371490
52 changed files with 135 additions and 1130 deletions

View file

@ -102,6 +102,20 @@ namespace Greenshot.Base.Controls
/// </summary>
protected bool ToFront { get; set; }
protected GreenshotForm()
{
DpiChanged += (sender, dpiChangedEventArgs) => DpiChangedHandler(dpiChangedEventArgs.DeviceDpiOld, dpiChangedEventArgs.DeviceDpiNew);
}
/// <summary>
/// This is the basic DpiChangedHandler responsible for all the DPI relative changes
/// </summary>
/// <param name="oldDpi"></param>
/// <param name="newDpi"></param>
protected virtual void DpiChangedHandler(int oldDpi, int newDpi)
{
}
#if DEBUG
/// <summary>
/// Code to initialize the language etc during design time
@ -530,7 +544,7 @@ namespace Greenshot.Base.Controls
/// <summary>
/// Fill all GreenshotControls with the values from the configuration
/// </summary>
protected void FillFields()
private void FillFields()
{
foreach (FieldInfo field in GetCachedFields(GetType()))
{

View file

@ -26,6 +26,7 @@ using System.Threading;
using System.Windows.Forms;
using Dapplo.Windows.Common.Extensions;
using Dapplo.Windows.Common.Structs;
using Dapplo.Windows.Dpi;
using Dapplo.Windows.User32;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
@ -34,7 +35,7 @@ using log4net;
namespace Greenshot.Base.Core
{
/// <summary>
/// Description of AbstractDestination.
/// The AbstractDestination is a default implementation of IDestination
/// </summary>
public abstract class AbstractDestination : IDestination
{
@ -178,7 +179,7 @@ namespace Greenshot.Base.Core
ExportInformation exportInformation = new ExportInformation(Designation, Language.GetString("settings_destination_picker"));
var menu = new ContextMenuStrip
{
ImageScalingSize = CoreConfig.ScaledIconSize,
ImageScalingSize = CoreConfig.IconSize,
Tag = null,
TopLevel = true
};
@ -186,10 +187,10 @@ namespace Greenshot.Base.Core
menu.Opening += (sender, args) =>
{
// find the DPI settings for the screen where this is going to land
var screenDpi = DpiHelper.GetDpi(menu.Location);
var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, screenDpi);
var screenDpi = NativeDpiMethods.GetDpi(menu.Location);
var scaledIconSize = DpiCalculator.ScaleWithDpi(CoreConfig.IconSize, screenDpi);
menu.SuspendLayout();
var fontSize = DpiHelper.ScaleWithDpi(12f, screenDpi);
var fontSize = DpiCalculator.ScaleWithDpi(12f, screenDpi);
menu.Font = new Font(FontFamily.GenericSansSerif, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
menu.ImageScalingSize = scaledIconSize;
menu.ResumeLayout();
@ -306,7 +307,7 @@ namespace Greenshot.Base.Core
ShowMenuAtCursor(menu);
return exportInformation;
}
/// <summary>
/// This method will show the supplied context menu at the mouse cursor, also makes sure it has focus and it's not visible in the taskbar.
/// </summary>

View file

@ -24,7 +24,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Dapplo.Windows.Common.Structs;
@ -370,13 +369,11 @@ namespace Greenshot.Base.Core
}
}
}
public NativeSize 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 web requests, these are seconds", DefaultValue = "100")]
public int WebRequestTimeout { get; set; }
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for web requests, these are seconds", DefaultValue = "100")]
public int WebRequestReadWriteTimeout { get; set; }
public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32;

View file

@ -1,207 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
using Dapplo.Windows.Common.Enums;
using Dapplo.Windows.Common.Extensions;
using Dapplo.Windows.Common.Structs;
using Dapplo.Windows.Gdi32;
using Dapplo.Windows.Gdi32.Enums;
using Dapplo.Windows.Gdi32.SafeHandles;
using Dapplo.Windows.User32;
using Dapplo.Windows.User32.Enums;
using Greenshot.Base.Core.Enums;
namespace Greenshot.Base.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
{
/// <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; } = WindowsVersion.IsWindows10OrLater ? GetDpiForSystem() : DefaultScreenDpi;
/// <summary>
/// Calculate a DPI scale factor
/// </summary>
/// <param name="dpi">uint</param>
/// <returns>double</returns>
public static float DpiScaleFactor(uint dpi)
{
if (dpi == 0)
{
dpi = 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 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 NativeSize ScaleWithDpi(NativeSize size, uint dpi, Func<float, float> scaleModifier = null)
{
var dpiScaleFactor = DpiScaleFactor(dpi);
if (scaleModifier != null)
{
dpiScaleFactor = scaleModifier(dpiScaleFactor);
}
return new NativeSize((int) (dpiScaleFactor * size.Width), (int) (dpiScaleFactor * size.Height));
}
/// <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 NativeSize ScaleWithCurrentDpi(NativeSize size, Func<float, float> scaleModifier = null)
{
return ScaleWithDpi(size, Dpi, scaleModifier);
}
/// <summary>
/// Return the DPI for the screen which the location is located on
/// </summary>
/// <param name="location">NativePoint</param>
/// <returns>uint</returns>
public static uint GetDpi(NativePoint location)
{
if (!WindowsVersion.IsWindows81OrLater)
{
return DefaultScreenDpi;
}
NativeRect rect = new NativeRect(location.X, location.Y, 1, 1);
IntPtr hMonitor = User32Api.MonitorFromRect(ref rect, MonitorFrom.DefaultToNearest);
var result = GetDpiForMonitor(hMonitor, MonitorDpiType.EffectiveDpi, out var dpiX, out var dpiY);
if (result.Succeeded())
{
return dpiX;
}
return DefaultScreenDpi;
}
/// <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 (!User32Api.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 = User32Api.MonitorFromWindow(hWnd, MonitorFrom.DefaultToNearest);
// ReSharper disable once UnusedVariable
var result = GetDpiForMonitor(hMonitor, MonitorDpiType.EffectiveDpi, out var dpiX, out var dpiY);
if (result.Succeeded())
{
return dpiX;
}
}
// Fallback to the global DPI settings
using var hdc = SafeWindowDcHandle.FromWindow(hWnd);
if (hdc == null)
{
return DefaultScreenDpi;
}
return (uint) Gdi32Api.GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX);
}
/// <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.dll", SetLastError = true)]
private static extern HResult GetDpiForMonitor(IntPtr hMonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);
/// <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();
}
}

View file

@ -1,41 +0,0 @@
// 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 Greenshot.Base.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

@ -1020,7 +1020,7 @@ namespace Greenshot.Base.Core
{
var colorizationColor = DwmApi.ColorizationColor;
// Modify by losing the transparency and increasing the intensity (as if the background color is white)
tempForm.BackColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); ;
tempForm.BackColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1);
}
// Make sure everything is visible
@ -1451,7 +1451,7 @@ namespace Greenshot.Base.Core
if (!HasParent && Maximised)
{
Log.Debug("Correcting for maximalization");
Log.Debug("Correcting for maximized window");
GetBorderSize(out var borderSize);
NativeRect borderRectangle = new NativeRect(borderSize.Width, borderSize.Height, windowRect.Width - (2 * borderSize.Width), windowRect.Height - (2 * borderSize.Height));
ImageHelper.Crop(ref returnImage, ref borderRectangle);

View file

@ -6,11 +6,12 @@
<ItemGroup>
<PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="1.0.18" />
<PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.13" />
<PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.13" />
<PackageReference Include="Dapplo.Windows.Icons" Version="1.0.13" />
<PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.13" />
<PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.13" />
<PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.19" />
<PackageReference Include="Dapplo.Windows.Dpi" Version="1.0.19" />
<PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.19" />
<PackageReference Include="Dapplo.Windows.Icons" Version="1.0.19" />
<PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.19" />
<PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.19" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.42" />
<PackageReference Include="log4net" version="2.0.14" />
<PackageReference Include="Svg" Version="3.4.1" />

View file

@ -1,151 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Greenshot.Base.UnmanagedHelpers.Enums;
namespace Greenshot.Base.Hooking
{
/// <summary>
/// The WinEventHook can register handlers to become important windows events
/// This makes it possible to know a.o. when a window is created, moved, updated and closed.
/// </summary>
public class WindowsEventHook : IDisposable
{
private readonly WinEventDelegate _winEventHandler;
private GCHandle _gcHandle;
/// <summary>
/// Used with Register hook
/// </summary>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
public delegate void WinEventHandler(WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
/// <summary>
/// Create a WindowsEventHook object
/// </summary>
public WindowsEventHook()
{
_winEventHandler = WinEventDelegateHandler;
_gcHandle = GCHandle.Alloc(_winEventHandler);
}
[DllImport("user32", SetLastError = true)]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32", SetLastError = true)]
private static extern IntPtr SetWinEventHook(WinEvent eventMin, WinEvent eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, int idProcess, int idThread,
WinEventHookFlags dwFlags);
/// <summary>
/// Used with SetWinEventHook
/// </summary>
/// <param name="hWinEventHook"></param>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
private delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
private readonly IDictionary<IntPtr, WinEventHandler> _winEventHandlers = new Dictionary<IntPtr, WinEventHandler>();
/// <summary>
/// Are hooks active?
/// </summary>
public bool IsHooked => _winEventHandlers.Count > 0;
/// <summary>
/// Hook a WinEvent
/// </summary>
/// <param name="winEvent"></param>
/// <param name="winEventHandler"></param>
/// <returns>true if success</returns>
public void Hook(WinEvent winEvent, WinEventHandler winEventHandler)
{
Hook(winEvent, winEvent, winEventHandler);
}
/// <summary>
/// Hook a WinEvent
/// </summary>
/// <param name="winEventStart"></param>
/// <param name="winEventEnd"></param>
/// <param name="winEventHandler"></param>
public void Hook(WinEvent winEventStart, WinEvent winEventEnd, WinEventHandler winEventHandler)
{
var hookPtr = SetWinEventHook(winEventStart, winEventEnd, IntPtr.Zero, _winEventHandler, 0, 0,
WinEventHookFlags.WINEVENT_SKIPOWNPROCESS | WinEventHookFlags.WINEVENT_OUTOFCONTEXT);
_winEventHandlers.Add(hookPtr, winEventHandler);
}
/// <summary>
/// Remove all hooks
/// </summary>
private void Unhook()
{
foreach (var hookPtr in _winEventHandlers.Keys)
{
if (hookPtr != IntPtr.Zero)
{
UnhookWinEvent(hookPtr);
}
}
_winEventHandlers.Clear();
_gcHandle.Free();
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Unhook();
}
/// <summary>
/// Call the WinEventHandler for this event
/// </summary>
/// <param name="hWinEventHook"></param>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
private void WinEventDelegateHandler(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (_winEventHandlers.TryGetValue(hWinEventHook, out var handler))
{
handler(eventType, hWnd, idObject, idChild, dwEventThread, dwmsEventTime);
}
}
}
}

View file

@ -1,180 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using Greenshot.Base.Core;
using Greenshot.Base.UnmanagedHelpers.Enums;
namespace Greenshot.Base.Hooking
{
/// <summary>
/// Event arguments for the WindowOpenCloseEvent
/// </summary>
public class WindowOpenCloseEventArgs : EventArgs
{
public bool IsOpen { get; set; }
/// <summary>
/// HWnd of the window which has a changed title
/// </summary>
public IntPtr HWnd { get; set; }
/// <summary>
/// Title which is changed
/// </summary>
public string Title { get; set; }
public string ClassName { get; set; }
}
/// <summary>
/// Delegate for the window open close event
/// </summary>
/// <param name="eventArgs"></param>
public delegate void WindowOpenCloseEventDelegate(WindowOpenCloseEventArgs eventArgs);
/// <summary>
/// Monitor all new and destroyed windows
/// </summary>
public sealed class WindowsOpenCloseMonitor : IDisposable
{
private WindowsEventHook _hook;
private readonly object _lockObject = new object();
// ReSharper disable once InconsistentNaming
private event WindowOpenCloseEventDelegate _windowOpenCloseEvent;
/// <summary>
/// Add / remove event handler to the title monitor
/// </summary>
public event WindowOpenCloseEventDelegate WindowOpenCloseChangeEvent
{
add
{
lock (_lockObject)
{
if (_hook == null)
{
_hook = new WindowsEventHook();
_hook.Hook(WinEvent.EVENT_OBJECT_CREATE, WinEvent.EVENT_OBJECT_DESTROY, WinEventHandler);
}
_windowOpenCloseEvent += value;
}
}
remove
{
lock (_lockObject)
{
_windowOpenCloseEvent -= value;
if (_windowOpenCloseEvent == null || _windowOpenCloseEvent.GetInvocationList().Length == 0)
{
if (_hook != null)
{
_hook.Dispose();
_hook = null;
}
}
}
}
}
/// <summary>
/// WinEventDelegate for the creation and destruction
/// </summary>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
private void WinEventHandler(WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (hWnd == IntPtr.Zero || idObject != EventObjects.OBJID_WINDOW)
{
return;
}
if (eventType == WinEvent.EVENT_OBJECT_CREATE)
{
if (_windowOpenCloseEvent != null)
{
var windowsDetails = new WindowDetails(hWnd);
_windowOpenCloseEvent(new WindowOpenCloseEventArgs
{
HWnd = hWnd,
IsOpen = true,
Title = windowsDetails.Text,
ClassName = windowsDetails.ClassName
});
}
}
if (eventType == WinEvent.EVENT_OBJECT_DESTROY)
{
_windowOpenCloseEvent?.Invoke(new WindowOpenCloseEventArgs
{
HWnd = hWnd,
IsOpen = false
});
}
}
private bool _disposedValue; // To detect redundant calls
/// <summary>
/// Dispose the underlying hook
/// </summary>
public void Dispose(bool disposing)
{
if (_disposedValue)
{
return;
}
lock (_lockObject)
{
_hook?.Dispose();
}
_disposedValue = true;
}
/// <summary>
/// Make sure the finalizer disposes the underlying hook
/// </summary>
~WindowsOpenCloseMonitor()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
/// <summary>
/// Dispose the underlying hook
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View file

@ -1,165 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using Greenshot.Base.Core;
using Greenshot.Base.UnmanagedHelpers.Enums;
namespace Greenshot.Base.Hooking
{
/// <summary>
/// Event arguments for the TitleChangeEvent
/// </summary>
public class TitleChangeEventArgs : EventArgs
{
/// <summary>
/// HWnd of the window which has a changed title
/// </summary>
public IntPtr HWnd { get; set; }
/// <summary>
/// Title which is changed
/// </summary>
public string Title { get; set; }
}
/// <summary>
/// Delegate for the title change event
/// </summary>
/// <param name="eventArgs"></param>
public delegate void TitleChangeEventDelegate(TitleChangeEventArgs eventArgs);
/// <summary>
/// Monitor all title changes
/// </summary>
public sealed class WindowsTitleMonitor : IDisposable
{
private WindowsEventHook _hook;
private readonly object _lockObject = new object();
// ReSharper disable once InconsistentNaming
private event TitleChangeEventDelegate _titleChangeEvent;
/// <summary>
/// Add / remove event handler to the title monitor
/// </summary>
public event TitleChangeEventDelegate TitleChangeEvent
{
add
{
lock (_lockObject)
{
if (_hook == null)
{
_hook = new WindowsEventHook();
_hook.Hook(WinEvent.EVENT_OBJECT_NAMECHANGE, WinEventHandler);
}
_titleChangeEvent += value;
}
}
remove
{
lock (_lockObject)
{
_titleChangeEvent -= value;
if (_titleChangeEvent == null || _titleChangeEvent.GetInvocationList().Length == 0)
{
if (_hook != null)
{
_hook.Dispose();
_hook = null;
}
}
}
}
}
/// <summary>
/// WinEventDelegate for the creation & destruction
/// </summary>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
private void WinEventHandler(WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (hWnd == IntPtr.Zero || idObject != EventObjects.OBJID_WINDOW)
{
return;
}
if (eventType == WinEvent.EVENT_OBJECT_NAMECHANGE)
{
if (_titleChangeEvent != null)
{
string newTitle = new WindowDetails(hWnd).Text;
_titleChangeEvent(new TitleChangeEventArgs
{
HWnd = hWnd,
Title = newTitle
});
}
}
}
private bool _disposedValue; // To detect redundant calls
/// <summary>
/// Dispose the underlying hook
/// </summary>
public void Dispose(bool disposing)
{
if (_disposedValue)
{
return;
}
lock (_lockObject)
{
_hook?.Dispose();
}
_disposedValue = true;
}
/// <summary>
/// Make sure the finalizer disposes the underlying hook
/// </summary>
~WindowsTitleMonitor()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
/// <summary>
/// Dispose the underlying hook
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View file

@ -98,7 +98,7 @@ namespace Greenshot.Base.Interfaces.Drawing.Adorners
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi"></param>
void AdjustToDpi(uint dpi);
void AdjustToDpi(int dpi);
/// <summary>
/// The color of the lines around the adorner

View file

@ -97,8 +97,8 @@ namespace Greenshot.Base.Interfaces.Drawing
/// <summary>
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi">uint</param>
void AdjustToDpi(uint dpi);
/// <param name="dpi">int</param>
void AdjustToDpi(int dpi);
/// <summary>
/// Enable a way for elements to add a context menu entry

View file

@ -59,6 +59,6 @@ namespace Greenshot.Base.Interfaces.Drawing
void PushElementsToBottom(IDrawableContainerList elements);
void ShowContextMenu(MouseEventArgs e, ISurface surface);
void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e);
void AdjustToDpi(uint dpi);
void AdjustToDpi(int dpi);
}
}

View file

@ -1,4 +1,4 @@
/*
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
@ -19,15 +19,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Base.UnmanagedHelpers
namespace Greenshot.Base.Interfaces
{
/// <summary>
/// Used with EnumWindows or EnumChildWindows
/// IProvideDeviceDpi can provide the current DPI for a component
/// </summary>
/// <param name="hWnd">IntPtr</param>
/// <param name="lParam">int</param>
/// <returns>int</returns>
public delegate int EnumWindowsProc(IntPtr hWnd, int lParam);
public interface IProvideDeviceDpi
{
/// <summary>
/// A simple getter for the current DPI
/// </summary>
int DeviceDpi { get; }
}
}

View file

@ -20,7 +20,6 @@
*/
using System;
using System.Drawing;
namespace Greenshot.Base.Interfaces
{

View file

@ -20,7 +20,6 @@
*/
using System;
using System.Drawing;
namespace Greenshot.Base.Interfaces
{

View file

@ -1,45 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Diagnostics.CodeAnalysis;
namespace Greenshot.Base.UnmanagedHelpers.Enums
{
[Flags]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum DesktopAccessRight : uint
{
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
GENERIC_ALL = (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU |
DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK |
DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP)
};
}

View file

@ -1,34 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System.Diagnostics.CodeAnalysis;
namespace Greenshot.Base.UnmanagedHelpers.Enums
{
/// <summary>
/// See <a href="https://docs.microsoft.com/en-gb/windows/win32/winauto/object-identifiers">Object Identifiers</a>
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum EventObjects
{
OBJID_WINDOW = 0
}
}

View file

@ -1,34 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Diagnostics.CodeAnalysis;
namespace Greenshot.Base.UnmanagedHelpers.Enums
{
[Flags]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ProcessAccessFlags : uint
{
VMRead = 0x00000010,
QueryInformation = 0x00000400,
}
}

View file

@ -1,37 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System.Diagnostics.CodeAnalysis;
namespace Greenshot.Base.UnmanagedHelpers.Enums
{
/// <summary>
/// Used for User32.SetWinEventHook
/// See MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066%28v=vs.85%29.aspx
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum WinEvent : uint
{
EVENT_OBJECT_CREATE = 32768,
EVENT_OBJECT_DESTROY = 32769,
EVENT_OBJECT_NAMECHANGE = 32780,
}
}

View file

@ -1,18 +0,0 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace Greenshot.Base.UnmanagedHelpers.Enums
{
/// <summary>
/// Used for User32.SetWinEventHook
/// See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming"), Flags]
public enum WinEventHookFlags
{
WINEVENT_SKIPOWNTHREAD = 1,
WINEVENT_SKIPOWNPROCESS = 2,
WINEVENT_OUTOFCONTEXT = 0,
WINEVENT_INCONTEXT = 4
}
}

View file

@ -1,36 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
namespace Greenshot.Base.UnmanagedHelpers.Structs
{
[StructLayout(LayoutKind.Sequential)]
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
}

View file

@ -1,38 +0,0 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
namespace Greenshot.Base.UnmanagedHelpers.Structs
{
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct SCROLLINFO
{
public int cbSize;
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
}

View file

@ -1,17 +0,0 @@
using System;
using Greenshot.Base.UnmanagedHelpers.Enums;
namespace Greenshot.Base.UnmanagedHelpers
{
/// <summary>
/// Used with SetWinEventHook
/// </summary>
/// <param name="hWinEventHook"></param>
/// <param name="eventType"></param>
/// <param name="hWnd"></param>
/// <param name="idObject"></param>
/// <param name="idChild"></param>
/// <param name="dwEventThread"></param>
/// <param name="dwmsEventTime"></param>
public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
}

View file

@ -24,7 +24,7 @@ using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Dapplo.Windows.Common.Extensions;
using Dapplo.Windows.Common.Structs;
using Greenshot.Base.Core;
using Dapplo.Windows.Dpi;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Base.Interfaces.Drawing.Adorners;
@ -39,7 +39,7 @@ namespace Greenshot.Editor.Drawing.Adorners
public AbstractAdorner(IDrawableContainer owner)
{
_size = DpiHelper.ScaleWithDpi(DefaultSize, 0);
_size = DpiCalculator.ScaleWithDpi(DefaultSize, 0);
Owner = owner;
}
@ -133,9 +133,9 @@ namespace Greenshot.Editor.Drawing.Adorners
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi">uint</param>
public void AdjustToDpi(uint dpi)
public void AdjustToDpi(int dpi)
{
_size = DpiHelper.ScaleWithDpi(DefaultSize, dpi);
_size = DpiCalculator.ScaleWithDpi(DefaultSize, dpi);
}
public Color OutlineColor { get; set; } = Color.White;

View file

@ -20,7 +20,6 @@
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Helpers;

View file

@ -20,7 +20,6 @@
*/
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Helpers;

View file

@ -442,7 +442,7 @@ namespace Greenshot.Editor.Drawing
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi">uint with dpi value</param>
public void AdjustToDpi(uint dpi)
public void AdjustToDpi(int dpi)
{
foreach (var adorner in Adorners)
{

View file

@ -772,8 +772,8 @@ namespace Greenshot.Editor.Drawing
/// <summary>
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi"></param>
public void AdjustToDpi(uint dpi)
/// <param name="dpi">int</param>
public void AdjustToDpi(int dpi)
{
foreach (var drawableContainer in this)
{

View file

@ -25,7 +25,6 @@ using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using Greenshot.Base.Core;
using Greenshot.Base.Interfaces;
using Svg;
namespace Greenshot.Editor.Drawing
{

View file

@ -454,7 +454,7 @@ namespace Greenshot.Editor.Drawing
/// Adjust UI elements to the supplied DPI settings
/// </summary>
/// <param name="dpi"></param>
public void AdjustToDpi(uint dpi)
public void AdjustToDpi(int dpi)
{
foreach (var element in this._elements)
{

View file

@ -21,7 +21,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Threading;

View file

@ -38,7 +38,6 @@ namespace Greenshot.Editor.Forms {
protected override void Dispose(bool disposing)
{
if (disposing) {
DpiChanged -= AdjustToDpi;
if (components != null) {
components.Dispose();
}
@ -322,7 +321,7 @@ namespace Greenshot.Editor.Forms {
// toolsToolStrip
//
this.toolsToolStrip.ClickThrough = true;
this.toolsToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.toolsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
this.toolsToolStrip.Dock = System.Windows.Forms.DockStyle.None;
this.toolsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.toolsToolStrip.Renderer = new CustomToolStripProfessionalRenderer();
@ -558,7 +557,7 @@ namespace Greenshot.Editor.Forms {
// menuStrip1
//
this.menuStrip1.ClickThrough = true;
this.menuStrip1.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.menuStrip1.ImageScalingSize = coreConfiguration.IconSize;
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.Fill;
this.menuStrip1.Stretch = true;
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -876,7 +875,7 @@ namespace Greenshot.Editor.Forms {
// destinationsToolStrip
//
this.destinationsToolStrip.ClickThrough = true;
this.destinationsToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.destinationsToolStrip.ImageScalingSize = coreConfiguration.IconSize;
this.destinationsToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
this.destinationsToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.destinationsToolStrip.Name = "toolStrip1";
@ -1031,10 +1030,10 @@ namespace Greenshot.Editor.Forms {
// propertiesToolStrip
//
this.propertiesToolStrip.ClickThrough = true;
this.propertiesToolStrip.ImageScalingSize = coreConfiguration.ScaledIconSize;
this.propertiesToolStrip.ImageScalingSize = coreConfiguration.IconSize;
this.propertiesToolStrip.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertiesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.ScaledIconSize.Height + 10);
this.propertiesToolStrip.MinimumSize = new System.Drawing.Size(150, coreConfiguration.IconSize.Height + 10);
this.propertiesToolStrip.Name = "propertiesToolStrip";
this.propertiesToolStrip.Stretch = true;
this.propertiesToolStrip.TabIndex = 2;

View file

@ -30,6 +30,7 @@ using System.Threading;
using System.Windows.Forms;
using Dapplo.Windows.Common.Extensions;
using Dapplo.Windows.Common.Structs;
using Dapplo.Windows.Dpi;
using Dapplo.Windows.Kernel32;
using Dapplo.Windows.User32.Structs;
using Greenshot.Base;
@ -41,8 +42,6 @@ using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Base.Interfaces.Forms;
using Greenshot.Base.UnmanagedHelpers;
using Greenshot.Base.UnmanagedHelpers.Structs;
using Greenshot.Editor.Configuration;
using Greenshot.Editor.Destinations;
using Greenshot.Editor.Drawing;
@ -114,19 +113,17 @@ namespace Greenshot.Editor.Forms
/// <summary>
/// Adjust the icons etc to the supplied DPI settings
/// </summary>
/// <param name="sender"></param>
/// <param name="dpiChangedEventArgs">DpiChangedEventArgs</param>
private void AdjustToDpi(object sender, DpiChangedEventArgs dpiChangedEventArgs)
/// <param name="oldDpi"></param>
/// <param name="newDpi"></param>
protected override void DpiChangedHandler(int oldDpi, int newDpi)
{
var dpi = DpiHelper.GetDpi(Handle);
var newSize = DpiHelper.ScaleWithDpi(coreConfiguration.IconSize, dpi);
var newSize = DpiCalculator.ScaleWithDpi(coreConfiguration.IconSize, newDpi);
toolsToolStrip.ImageScalingSize = newSize;
menuStrip1.ImageScalingSize = newSize;
destinationsToolStrip.ImageScalingSize = newSize;
propertiesToolStrip.ImageScalingSize = newSize;
propertiesToolStrip.MinimumSize = new Size(150, newSize.Height + 10);
_surface?.AdjustToDpi(dpi);
_surface?.AdjustToDpi(newDpi);
UpdateUi();
}
@ -152,7 +149,6 @@ namespace Greenshot.Editor.Forms
ManualLanguageApply = true;
InitializeComponent();
// Make sure we change the icon size depending on the scaling
DpiChanged += AdjustToDpi;
Load += delegate
{
var thread = new Thread(AddDestinations)
@ -161,7 +157,7 @@ namespace Greenshot.Editor.Forms
};
thread.Start();
AdjustToDpi(null, null);
DpiChangedHandler(96, DeviceDpi);
};
// Make sure the editor is placed on the same location as the last editor was on close
@ -174,7 +170,7 @@ namespace Greenshot.Editor.Forms
}
// ReSharper disable once UnusedVariable
WindowDetails thisForm = new WindowDetails(Handle)
WindowDetails thisForm = new(Handle)
{
WindowPlacement = EditorConfiguration.GetEditorPlacement()
};
@ -317,9 +313,8 @@ namespace Greenshot.Editor.Forms
// Loop over all items in the propertiesToolStrip
foreach (ToolStripItem item in propertiesToolStrip.Items)
{
var cb = item as ToolStripComboBox;
// Only ToolStripComboBox that are visible
if (cb == null || !cb.Visible)
if (item is not ToolStripComboBox { Visible: true } cb)
{
continue;
}
@ -376,7 +371,7 @@ namespace Greenshot.Editor.Forms
{
if (toolstripDestination.IsDynamic)
{
ToolStripSplitButton destinationButton = new ToolStripSplitButton
ToolStripSplitButton destinationButton = new()
{
DisplayStyle = ToolStripItemDisplayStyle.Image,
Size = new Size(23, 22),
@ -1960,8 +1955,7 @@ namespace Greenshot.Editor.Forms
private void ZoomSetValue(Fraction value)
{
var surface = Surface as Surface;
var panel = surface?.Parent as Panel;
if (panel == null)
if (surface?.Parent is not Panel panel)
{
return;
}

View file

@ -21,7 +21,6 @@
using System;
using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;
using Greenshot.Plugin.Box.Forms;

View file

@ -20,7 +20,6 @@
*/
using System;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;

View file

@ -20,7 +20,6 @@
*/
using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;
using Greenshot.Plugin.Flickr.Forms;

View file

@ -30,7 +30,6 @@ using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Plugin;
using log4net;
using log4net.Config;
namespace Greenshot.Plugin.Flickr
{

View file

@ -20,7 +20,6 @@
using System;
using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;
using Greenshot.Plugin.GooglePhotos.Forms;

View file

@ -22,7 +22,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;
using Greenshot.Plugin.Imgur.Forms;

View file

@ -26,6 +26,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Dapplo.Jira.Entities;
using Dapplo.Windows.Dpi;
using Greenshot.Base.Controls;
using Greenshot.Base.Core;
using Greenshot.Base.IniFile;
@ -173,7 +174,7 @@ namespace Greenshot.Plugin.Jira.Forms
jiraListView.Columns.Add(translation);
}
var scaledIconSize = DpiHelper.ScaleWithDpi(CoreConfig.IconSize, DpiHelper.GetDpi(Handle));
var scaledIconSize = DpiCalculator.ScaleWithDpi(CoreConfig.IconSize, NativeDpiMethods.GetDpi(Handle));
var imageList = new ImageList
{
ImageSize = scaledIconSize

View file

@ -19,7 +19,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile;

View file

@ -63,8 +63,8 @@ namespace Greenshot.Plugin.Jira
var jiraConnector = SimpleServiceProvider.Current.GetInstance<JiraConnector>();
jiraConnector._jiraClient?.Behaviour.SetConfig(new SvgConfiguration
{
Width = CoreConfig.ScaledIconSize.Width,
Height = CoreConfig.ScaledIconSize.Height
Width = CoreConfig.IconSize.Width,
Height = CoreConfig.IconSize.Height
});
}
};
@ -112,8 +112,8 @@ namespace Greenshot.Plugin.Jira
_jiraClient = JiraClient.Create(new Uri(JiraConfig.Url));
_jiraClient.Behaviour.SetConfig(new SvgConfiguration
{
Width = CoreConfig.ScaledIconSize.Width,
Height = CoreConfig.ScaledIconSize.Height
Width = CoreConfig.IconSize.Width,
Height = CoreConfig.IconSize.Height
});
_jiraClient.SetBasicAuthentication(user, password);

View file

@ -27,7 +27,9 @@ using System.Threading;
using System.Threading.Tasks;
using Dapplo.Jira;
using Dapplo.Log;
using Greenshot.Base.Hooking;
using Dapplo.Windows.Desktop;
using Dapplo.Windows.Structs;
using Dapplo.Windows.User32;
namespace Greenshot.Plugin.Jira
{
@ -40,7 +42,7 @@ namespace Greenshot.Plugin.Jira
{
private static readonly LogSource Log = new LogSource();
private readonly Regex _jiraKeyPattern = new Regex(@"[A-Z][A-Z0-9]+\-[0-9]+");
private readonly WindowsTitleMonitor _monitor;
private readonly IDisposable _monitor;
private readonly IList<IJiraClient> _jiraInstances = new List<IJiraClient>();
private readonly IDictionary<string, IJiraClient> _projectJiraClientMap = new Dictionary<string, IJiraClient>();
@ -56,9 +58,8 @@ namespace Greenshot.Plugin.Jira
public JiraMonitor(int maxEntries = 40)
{
_monitor = WinEventHook.WindowTitleChangeObservable().Subscribe(wei => MonitorTitleChangeEvent(wei));
_maxEntries = maxEntries;
_monitor = new WindowsTitleMonitor();
_monitor.TitleChangeEvent += MonitorTitleChangeEvent;
}
/// <summary>
@ -82,7 +83,6 @@ namespace Greenshot.Plugin.Jira
}
// free managed resources
_monitor.TitleChangeEvent -= MonitorTitleChangeEvent;
_monitor.Dispose();
// free native resources if there are any.
}
@ -162,10 +162,10 @@ namespace Greenshot.Plugin.Jira
/// <summary>
/// Handle title changes, check for JIRA
/// </summary>
/// <param name="eventArgs"></param>
private void MonitorTitleChangeEvent(TitleChangeEventArgs eventArgs)
/// <param name="winEventInfo">WinEventInfo</param>
private void MonitorTitleChangeEvent(WinEventInfo winEventInfo)
{
string windowTitle = eventArgs.Title;
string windowTitle = User32Api.GetText(winEventInfo.Handle);
if (string.IsNullOrEmpty(windowTitle))
{
return;

View file

@ -29,9 +29,11 @@ using System.Windows.Interop;
using System.Windows.Media;
using Windows.Storage;
using Windows.Storage.Streams;
using Dapplo.Windows.Desktop;
using Dapplo.Windows.Enums;
using Dapplo.Windows.User32;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums;
using Greenshot.Base.Hooking;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Plugin;
using Greenshot.Plugin.Win10.Internal;
@ -82,24 +84,22 @@ namespace Greenshot.Plugin.Win10.Destinations
triggerWindow.Show();
var focusMonitor = new WindowsOpenCloseMonitor();
var windowHandle = new WindowInteropHelper(triggerWindow).Handle;
// This is a bad trick, but don't know how else to do it.
// Wait for the focus to return, and depending on the state close the window!
focusMonitor.WindowOpenCloseChangeEvent += e =>
var createDestroyMonitor = WinEventHook.WindowTitleChangeObservable().Subscribe(wei =>
{
if (e.IsOpen)
if (wei.WinEvent == WinEvents.EVENT_OBJECT_CREATE)
{
if ("Windows Shell Experience Host" == e.Title)
var windowTitle = User32Api.GetText(wei.Handle);
if ("Windows Shell Experience Host" == windowTitle)
{
shareInfo.SharingHwnd = e.HWnd;
shareInfo.SharingHwnd = wei.Handle;
}
return;
}
if (e.HWnd == shareInfo.SharingHwnd)
if (wei.Handle == shareInfo.SharingHwnd)
{
if (shareInfo.ApplicationName != null)
{
@ -108,12 +108,12 @@ namespace Greenshot.Plugin.Win10.Destinations
shareInfo.ShareTask.TrySetResult(false);
}
};
});
Share(shareInfo, windowHandle, surface, captureDetails).GetAwaiter().GetResult();
Log.Debug("Sharing finished, closing window.");
triggerWindow.Close();
focusMonitor.Dispose();
createDestroyMonitor.Dispose();
if (string.IsNullOrWhiteSpace(shareInfo.ApplicationName))
{
exportInformation.ExportMade = false;

View file

@ -23,7 +23,6 @@ using System;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel.DataTransfer;
using Dapplo.Windows.Common.Extensions;
using Greenshot.Base.Core;
namespace Greenshot.Plugin.Win10.Native
{

View file

@ -21,7 +21,6 @@ using System;
using System.Runtime.InteropServices;
using Windows.ApplicationModel.DataTransfer;
using Dapplo.Windows.Common.Enums;
using Greenshot.Base.Core.Enums;
namespace Greenshot.Plugin.Win10.Native
{

View file

@ -22,8 +22,10 @@
using System.Drawing;
using System.Windows.Forms;
using Dapplo.Windows.Common.Structs;
using Dapplo.Windows.Dpi;
using Greenshot.Base.Core;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
namespace Greenshot.Controls
{
@ -32,15 +34,21 @@ namespace Greenshot.Controls
/// </summary>
public class ContextMenuToolStripProfessionalRenderer : ToolStripProfessionalRenderer
{
private readonly IProvideDeviceDpi _provideDeviceDpi;
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private static Image _scaledCheckbox;
public ContextMenuToolStripProfessionalRenderer(IProvideDeviceDpi provideDeviceDpi)
{
_provideDeviceDpi = provideDeviceDpi;
}
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{
if (_scaledCheckbox == null || _scaledCheckbox.Size != CoreConfig.ScaledIconSize)
var newSize = DpiCalculator.ScaleWithDpi(CoreConfig.IconSize, _provideDeviceDpi.DeviceDpi);
if (_scaledCheckbox == null || _scaledCheckbox.Size != newSize)
{
_scaledCheckbox?.Dispose();
_scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, CoreConfig.ScaledIconSize.Width, CoreConfig.ScaledIconSize.Height, null);
_scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, newSize.Width, newSize.Height, null);
}
NativeRect old = e.ImageRectangle;

View file

@ -106,7 +106,7 @@ namespace Greenshot.Forms {
this.contextMenu.Name = "contextMenu";
this.contextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.ContextMenuClosing);
this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ContextMenuOpening);
this.contextMenu.Renderer = new Greenshot.Controls.ContextMenuToolStripProfessionalRenderer();
this.contextMenu.Renderer = new Greenshot.Controls.ContextMenuToolStripProfessionalRenderer(this);
//
// contextmenu_capturearea
//
@ -204,7 +204,7 @@ namespace Greenshot.Forms {
// contextmenu_quicksettings
//
this.contextmenu_quicksettings.Name = "contextmenu_quicksettings";
this.contextmenu_quicksettings.Size = new System.Drawing.Size(170, coreConfiguration.ScaledIconSize.Height + 8);
this.contextmenu_quicksettings.Size = new System.Drawing.Size(170, coreConfiguration.IconSize.Height + 8);
//
// contextmenu_settings
//

View file

@ -33,6 +33,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using Dapplo.Windows.DesktopWindowsManager;
using Dapplo.Windows.Dpi;
using Dapplo.Windows.Kernel32;
using Greenshot.Base;
using Greenshot.Base.Controls;
@ -43,7 +44,6 @@ using Greenshot.Base.Help;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Plugin;
using Greenshot.Base.UnmanagedHelpers;
using Greenshot.Configuration;
using Greenshot.Destinations;
using Greenshot.Editor;
@ -60,7 +60,7 @@ namespace Greenshot.Forms
/// <summary>
/// This is the MainForm, the shell of Greenshot
/// </summary>
public partial class MainForm : BaseForm, IGreenshotMainForm, ICaptureHelper
public partial class MainForm : BaseForm, IGreenshotMainForm, ICaptureHelper, IProvideDeviceDpi
{
private static ILog LOG;
private static ResourceMutex _applicationMutex;
@ -380,8 +380,7 @@ namespace Greenshot.Forms
{
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
SimpleServiceProvider.Current.AddService(uiContext);
DpiChanged += (e, o) => ApplyDpiScaling();
// The most important form is this
SimpleServiceProvider.Current.AddService<Form>(this);
// Also as itself
@ -746,7 +745,7 @@ namespace Greenshot.Forms
return;
}
ApplyDpiScaling();
DpiChangedHandler(96, DeviceDpi);
string ieExePath = PluginUtils.GetExePath("iexplore.exe");
if (!string.IsNullOrEmpty(ieExePath))
{
@ -757,10 +756,10 @@ namespace Greenshot.Forms
/// <summary>
/// Modify the DPI settings depending in the current value
/// </summary>
private void ApplyDpiScaling()
protected override void DpiChangedHandler(int oldDpi, int newDpi)
{
var scaledIconSize = DpiHelper.ScaleWithDpi(coreConfiguration.IconSize, DpiHelper.GetDpi(Handle));
contextMenu.ImageScalingSize = scaledIconSize;
var newSize = DpiCalculator.ScaleWithDpi(coreConfiguration.IconSize, newDpi);
contextMenu.ImageScalingSize = newSize;
}
/// <summary>
@ -1501,7 +1500,7 @@ namespace Greenshot.Forms
if (!_conf.Values["Destinations"].IsFixed)
{
// screenshot destination
selectList = new ToolStripMenuSelectList("destinations", true)
selectList = new ToolStripMenuSelectList("destinations", true, this)
{
Text = Language.GetString(LangKey.settings_destination)
};
@ -1518,7 +1517,7 @@ namespace Greenshot.Forms
if (!_conf.Values["WindowCaptureMode"].IsFixed)
{
// Capture Modes
selectList = new ToolStripMenuSelectList("capturemodes", false)
selectList = new ToolStripMenuSelectList("capturemodes", false, this)
{
Text = Language.GetString(LangKey.settings_window_capture_mode)
};
@ -1533,7 +1532,7 @@ namespace Greenshot.Forms
}
// print options
selectList = new ToolStripMenuSelectList("printoptions", true)
selectList = new ToolStripMenuSelectList("printoptions", true, this)
{
Text = Language.GetString(LangKey.settings_printoptions)
};
@ -1558,7 +1557,7 @@ namespace Greenshot.Forms
}
// effects
selectList = new ToolStripMenuSelectList("effects", true)
selectList = new ToolStripMenuSelectList("effects", true, this)
{
Text = Language.GetString(LangKey.settings_visualization)
};

View file

@ -29,6 +29,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Dapplo.Windows.DesktopWindowsManager;
using Dapplo.Windows.Dpi;
using Greenshot.Base;
using Greenshot.Base.Controls;
using Greenshot.Base.Core;
@ -420,7 +421,7 @@ namespace Greenshot.Forms
checkbox_picker.Checked = false;
listview_destinations.Items.Clear();
var scaledIconSize = DpiHelper.ScaleWithDpi(coreConfiguration.IconSize, DpiHelper.GetDpi(Handle));
var scaledIconSize = DpiCalculator.ScaleWithDpi(coreConfiguration.IconSize, NativeDpiMethods.GetDpi(Handle));
listview_destinations.ListViewItemSorter = new ListviewWithDestinationComparer();
ImageList imageList = new ImageList
{

View file

@ -23,8 +23,10 @@ using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using Dapplo.Windows.Dpi;
using Greenshot.Base.Core;
using Greenshot.Base.IniFile;
using Greenshot.Base.Interfaces;
namespace Greenshot.Forms
{
@ -35,6 +37,7 @@ namespace Greenshot.Forms
{
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private readonly bool _multiCheckAllowed;
private readonly IProvideDeviceDpi _provideDeviceDpi;
private bool _updateInProgress;
private static Image _defaultImage;
@ -45,25 +48,29 @@ namespace Greenshot.Forms
public object Identifier { get; private set; }
public ToolStripMenuSelectList(object identifier, bool allowMultiCheck)
public ToolStripMenuSelectList(object identifier, bool allowMultiCheck, IProvideDeviceDpi provideDeviceDpi)
{
Identifier = identifier;
CheckOnClick = false;
_multiCheckAllowed = allowMultiCheck;
if (_defaultImage == null || _defaultImage.Size != CoreConfig.ScaledIconSize)
_provideDeviceDpi = provideDeviceDpi;
UpdateImage();
}
private void UpdateImage()
{
var newSize = DpiCalculator.ScaleWithDpi(CoreConfig.IconSize, _provideDeviceDpi.DeviceDpi);
if (_defaultImage == null || _defaultImage.Size != newSize)
{
_defaultImage?.Dispose();
_defaultImage = ImageHelper.CreateEmpty(CoreConfig.ScaledIconSize.Width, CoreConfig.ScaledIconSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb,
_defaultImage = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb,
Color.Transparent, 96f, 96f);
}
Image = _defaultImage;
}
public ToolStripMenuSelectList() : this(null, false)
{
}
private void ItemCheckStateChanged(object sender, EventArgs e)
{
if (_updateInProgress)