mirror of
https://github.com/greenshot/greenshot
synced 2025-08-21 14:03:23 -07:00
Improved the support for dragging and dropping images from a website, now also parsing HTML img src information, to be able to download that image. For this we need the HtmlAgilityPack.dll (#294)
Removed a lot of dead code, and remove the old OCR code as we don't even know if it still works.
This commit is contained in:
parent
90cab1e8a3
commit
26fe579d31
151 changed files with 1138 additions and 8174 deletions
|
@ -91,35 +91,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
public void ActivateIETab(string tabCaptionToActivate) {
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
foreach (var tab in child.Children) {
|
||||
if (tab.Name == tabCaptionToActivate) {
|
||||
tab.Activate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CloseIETab(string tabCaptionToClose) {
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
foreach (var tab in child.Children) {
|
||||
if (tab.Name == tabCaptionToClose) {
|
||||
foreach (var CloseTab in tab.Children) {
|
||||
CloseTab.Activate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ActivateIETab(int tabIndexToActivate) {
|
||||
public void ActivateIETab(int tabIndexToActivate) {
|
||||
var index = 0;
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
|
@ -138,50 +110,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
public string IEActiveTabUrl {
|
||||
get {
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
foreach (var tab in child.Children) {
|
||||
object tabIndex = tab.accessible.get_accState(CHILDID_SELF);
|
||||
|
||||
if ((int)tabIndex == IE_ACTIVE_TAB) {
|
||||
var description = tab.accessible.get_accDescription(CHILDID_SELF);
|
||||
|
||||
if (!string.IsNullOrEmpty(description)) {
|
||||
if (description.Contains(Environment.NewLine)) {
|
||||
var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim();
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public int IEActiveTabIndex {
|
||||
get {
|
||||
var index = 0;
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
foreach (var tab in child.Children) {
|
||||
object tabIndex = tab.accessible.get_accState(0);
|
||||
|
||||
if ((int)tabIndex == IE_ACTIVE_TAB) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public string IEActiveTabCaption {
|
||||
public string IEActiveTabCaption {
|
||||
get {
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
|
@ -238,21 +167,8 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int IETabCount {
|
||||
get {
|
||||
foreach (Accessible accessor in Children) {
|
||||
foreach (var child in accessor.Children) {
|
||||
foreach (var tab in child.Children) {
|
||||
return child.ChildCount - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private Accessible(IAccessible acc) {
|
||||
private Accessible(IAccessible acc) {
|
||||
accessible = acc ?? throw new Exception();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
@ -14,7 +34,6 @@ namespace GreenshotPlugin.Core
|
|||
/// </summary>
|
||||
public class Capture : ICapture {
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Capture));
|
||||
private List<ICaptureElement> _elements = new List<ICaptureElement>();
|
||||
|
||||
private Rectangle _screenBounds;
|
||||
/// <summary>
|
||||
|
@ -178,15 +197,6 @@ namespace GreenshotPlugin.Core
|
|||
// TODO: Remove invisible lines/words?
|
||||
CaptureDetails.OcrInformation?.Offset(-cropRectangle.Location.X, -cropRectangle.Location.Y);
|
||||
|
||||
// Remove invisible elements
|
||||
var visibleElements = new List<ICaptureElement>();
|
||||
foreach(var captureElement in _elements) {
|
||||
if (captureElement.Bounds.IntersectsWith(cropRectangle)) {
|
||||
visibleElements.Add(captureElement);
|
||||
}
|
||||
}
|
||||
_elements = visibleElements;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A class representing an element in the capture
|
||||
/// </summary>
|
||||
public class CaptureElement : ICaptureElement {
|
||||
public CaptureElement(Rectangle bounds) {
|
||||
Bounds = bounds;
|
||||
}
|
||||
public CaptureElement(string name) {
|
||||
Name = name;
|
||||
}
|
||||
public CaptureElement(string name, Rectangle bounds) {
|
||||
Name = name;
|
||||
Bounds = bounds;
|
||||
}
|
||||
|
||||
public List<ICaptureElement> Children { get; set; } = new List<ICaptureElement>();
|
||||
|
||||
public string Name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public Rectangle Bounds {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
// CaptureElements are regarded equal if their bounds are equal. this should be sufficient.
|
||||
public override bool Equals(object obj) {
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return obj is CaptureElement other && Bounds.Equals(other.Bounds);
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
// TODO: Fix this, this is not right...
|
||||
return Bounds.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,7 +34,9 @@ using System.Runtime.InteropServices;
|
|||
using GreenshotPlugin.IniFile;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
using GreenshotPlugin.Interop;
|
||||
using log4net;
|
||||
using HtmlDocument = HtmlAgilityPack.HtmlDocument;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
|
@ -45,7 +47,8 @@ namespace GreenshotPlugin.Core {
|
|||
private static readonly object ClipboardLockObject = new object();
|
||||
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
private static readonly string FORMAT_FILECONTENTS = "FileContents";
|
||||
private static readonly string FORMAT_PNG = "PNG";
|
||||
private static readonly string FORMAT_HTML = "text/html";
|
||||
private static readonly string FORMAT_PNG = "PNG";
|
||||
private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art";
|
||||
private static readonly string FORMAT_17 = "Format17";
|
||||
private static readonly string FORMAT_JPG = "JPG";
|
||||
|
@ -207,17 +210,8 @@ EndSelection:<<<<<<<4
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for Clipboard.ContainsText, Created for Bug #3432313
|
||||
/// </summary>
|
||||
/// <returns>boolean if there is text on the clipboard</returns>
|
||||
public static bool ContainsText() {
|
||||
IDataObject clipboardData = GetDataObject();
|
||||
return ContainsText(clipboardData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Test if the IDataObject contains Text
|
||||
/// </summary>
|
||||
/// <param name="dataObject"></param>
|
||||
|
@ -246,41 +240,124 @@ EndSelection:<<<<<<<4
|
|||
/// <param name="dataObject"></param>
|
||||
/// <returns>true if an image is there</returns>
|
||||
public static bool ContainsImage(IDataObject dataObject) {
|
||||
if (dataObject != null) {
|
||||
if (dataObject.GetDataPresent(DataFormats.Bitmap)
|
||||
|| dataObject.GetDataPresent(DataFormats.Dib)
|
||||
|| dataObject.GetDataPresent(DataFormats.Tiff)
|
||||
|| dataObject.GetDataPresent(DataFormats.EnhancedMetafile)
|
||||
|| dataObject.GetDataPresent(FORMAT_PNG)
|
||||
|| dataObject.GetDataPresent(FORMAT_17)
|
||||
|| dataObject.GetDataPresent(FORMAT_JPG)
|
||||
|| dataObject.GetDataPresent(FORMAT_JFIF)
|
||||
|| dataObject.GetDataPresent(FORMAT_JPEG)
|
||||
|| dataObject.GetDataPresent(FORMAT_GIF)) {
|
||||
return true;
|
||||
}
|
||||
var imageFiles = GetImageFilenames(dataObject);
|
||||
if (imageFiles.Any()) {
|
||||
return true;
|
||||
}
|
||||
if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) {
|
||||
try {
|
||||
MemoryStream imageStream = dataObject.GetData(FORMAT_FILECONTENTS) as MemoryStream;
|
||||
if (IsValidStream(imageStream)) {
|
||||
using (ImageHelper.FromStream(imageStream))
|
||||
{
|
||||
// If we get here, there is an image
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (dataObject == null) return false;
|
||||
|
||||
if (dataObject.GetDataPresent(DataFormats.Bitmap)
|
||||
|| dataObject.GetDataPresent(DataFormats.Dib)
|
||||
|| dataObject.GetDataPresent(DataFormats.Tiff)
|
||||
|| dataObject.GetDataPresent(DataFormats.EnhancedMetafile)
|
||||
|| dataObject.GetDataPresent(FORMAT_PNG)
|
||||
|| dataObject.GetDataPresent(FORMAT_17)
|
||||
|| dataObject.GetDataPresent(FORMAT_JPG)
|
||||
|| dataObject.GetDataPresent(FORMAT_JFIF)
|
||||
|| dataObject.GetDataPresent(FORMAT_JPEG)
|
||||
|| dataObject.GetDataPresent(FORMAT_GIF)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var imageFiles = GetImageFilenames(dataObject);
|
||||
if (imageFiles.Any()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var fileDescriptor = (MemoryStream)dataObject.GetData("FileGroupDescriptorW");
|
||||
var files = FileDescriptorReader.Read(fileDescriptor);
|
||||
var fileIndex = 0;
|
||||
foreach (var fileContentFile in files)
|
||||
{
|
||||
if ((fileContentFile.FileAttributes & FileAttributes.Directory) != 0)
|
||||
{
|
||||
//Do something with directories?
|
||||
//Note that directories do not have FileContents
|
||||
//And will throw if we try to read them
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex);
|
||||
try
|
||||
{
|
||||
//Do something with the fileContent Stream
|
||||
if (IsValidStream(fileData))
|
||||
{
|
||||
fileData.Position = 0;
|
||||
using (ImageHelper.FromStream(fileData))
|
||||
{
|
||||
// If we get here, there is an image
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
fileData?.Dispose();
|
||||
}
|
||||
fileIndex++;
|
||||
}
|
||||
|
||||
if (dataObject.GetDataPresent(FORMAT_FILECONTENTS))
|
||||
{
|
||||
try
|
||||
{
|
||||
var clipboardContent = dataObject.GetData(FORMAT_FILECONTENTS, true);
|
||||
var imageStream = clipboardContent as MemoryStream;
|
||||
if (IsValidStream(imageStream))
|
||||
{
|
||||
using (ImageHelper.FromStream(imageStream))
|
||||
{
|
||||
// If we get here, there is an image
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get the image from the HTML code
|
||||
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
|
||||
if (textObject != null)
|
||||
{
|
||||
var doc = new HtmlDocument();
|
||||
doc.LoadHtml(textObject);
|
||||
var imgNodes = doc.DocumentNode.SelectNodes("//img");
|
||||
if (imgNodes != null)
|
||||
{
|
||||
foreach (var imgNode in imgNodes)
|
||||
{
|
||||
var srcAttribute = imgNode.Attributes["src"];
|
||||
var imageUrl = srcAttribute.Value;
|
||||
if (!string.IsNullOrEmpty(imageUrl))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the specified IDataObject format as a string
|
||||
/// </summary>
|
||||
/// <param name="dataObject">IDataObject</param>
|
||||
/// <param name="format">string</param>
|
||||
/// <param name="encoding">Encoding</param>
|
||||
/// <returns>sting</returns>
|
||||
private static string ContentAsString(IDataObject dataObject, string format, Encoding encoding = null)
|
||||
{
|
||||
encoding ??= Encoding.Unicode;
|
||||
var objectAsFormat = dataObject.GetData(format);
|
||||
return objectAsFormat switch
|
||||
{
|
||||
null => null,
|
||||
string text => text,
|
||||
MemoryStream ms => encoding.GetString(ms.ToArray()),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple helper to check the stream
|
||||
/// </summary>
|
||||
|
@ -348,9 +425,9 @@ EndSelection:<<<<<<<4
|
|||
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib)) {
|
||||
// Outlook ??
|
||||
Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
|
||||
retrieveFormats = new[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
|
||||
retrieveFormats = new[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML };
|
||||
} else {
|
||||
retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF };
|
||||
retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML };
|
||||
}
|
||||
foreach (string currentFormat in retrieveFormats) {
|
||||
if (formats != null && formats.Contains(currentFormat)) {
|
||||
|
@ -376,8 +453,32 @@ EndSelection:<<<<<<<4
|
|||
/// <param name="dataObject">IDataObject</param>
|
||||
/// <returns>Image or null</returns>
|
||||
private static Image GetImageForFormat(string format, IDataObject dataObject) {
|
||||
if (format == FORMAT_HTML)
|
||||
{
|
||||
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
|
||||
if (textObject != null)
|
||||
{
|
||||
var doc = new HtmlDocument();
|
||||
doc.LoadHtml(textObject);
|
||||
var imgNodes = doc.DocumentNode.SelectNodes("//img");
|
||||
if (imgNodes != null)
|
||||
{
|
||||
foreach (var imgNode in imgNodes)
|
||||
{
|
||||
var srcAttribute = imgNode.Attributes["src"];
|
||||
var imageUrl = srcAttribute.Value;
|
||||
Log.Debug(imageUrl);
|
||||
var image = NetworkHelper.DownloadImage(imageUrl);
|
||||
if (image != null)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
object clipboardObject = GetFromDataObject(dataObject, format);
|
||||
MemoryStream imageStream = clipboardObject as MemoryStream;
|
||||
var imageStream = clipboardObject as MemoryStream;
|
||||
if (!IsValidStream(imageStream)) {
|
||||
// TODO: add "HTML Format" support here...
|
||||
return clipboardObject as Image;
|
||||
|
@ -390,14 +491,14 @@ EndSelection:<<<<<<<4
|
|||
{
|
||||
byte[] dibBuffer = new byte[imageStream.Length];
|
||||
imageStream.Read(dibBuffer, 0, dibBuffer.Length);
|
||||
BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADER>(dibBuffer);
|
||||
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADER>(dibBuffer);
|
||||
if (!infoHeader.IsDibV5) {
|
||||
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
|
||||
int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
|
||||
uint infoHeaderSize = infoHeader.biSize;
|
||||
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
|
||||
|
||||
BITMAPFILEHEADER fileHeader = new BITMAPFILEHEADER
|
||||
var fileHeader = new BITMAPFILEHEADER
|
||||
{
|
||||
bfType = BITMAPFILEHEADER.BM,
|
||||
bfSize = fileSize,
|
||||
|
@ -408,7 +509,7 @@ EndSelection:<<<<<<<4
|
|||
|
||||
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
|
||||
|
||||
using MemoryStream bitmapStream = new MemoryStream();
|
||||
using var bitmapStream = new MemoryStream();
|
||||
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
||||
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
||||
bitmapStream.Seek(0, SeekOrigin.Begin);
|
||||
|
@ -459,6 +560,7 @@ EndSelection:<<<<<<<4
|
|||
} catch (Exception streamImageEx) {
|
||||
Log.Error($"Problem retrieving {format} from clipboard.", streamImageEx);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -706,16 +808,8 @@ EndSelection:<<<<<<<4
|
|||
// Use false to make the object disappear when the application stops.
|
||||
SetDataObject(dataObj, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a list of all formats currently on the clipboard
|
||||
/// </summary>
|
||||
/// <returns>List of strings with the current formats</returns>
|
||||
public static List<string> GetFormats() {
|
||||
return GetFormats(GetDataObject());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Retrieve a list of all formats currently in the IDataObject
|
||||
/// </summary>
|
||||
/// <returns>List of string with the current formats</returns>
|
||||
|
@ -732,16 +826,7 @@ EndSelection:<<<<<<<4
|
|||
return new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if there is currently something in the dataObject which has the supplied format
|
||||
/// </summary>
|
||||
/// <param name="format">string with format</param>
|
||||
/// <returns>true if one the format is found</returns>
|
||||
public static bool ContainsFormat(string format) {
|
||||
return ContainsFormat(GetDataObject(), new[]{format});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Check if there is currently something on the clipboard which has the supplied format
|
||||
/// </summary>
|
||||
/// <param name="dataObject">IDataObject</param>
|
||||
|
@ -781,17 +866,7 @@ EndSelection:<<<<<<<4
|
|||
return formatFound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Object of type Type from the clipboard
|
||||
/// </summary>
|
||||
/// <param name="type">Type to get</param>
|
||||
/// <returns>object from clipboard</returns>
|
||||
public static object GetClipboardData(Type type) {
|
||||
string format = type.FullName;
|
||||
return GetClipboardData(format);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Get Object for format from IDataObject
|
||||
/// </summary>
|
||||
/// <param name="dataObj">IDataObject</param>
|
||||
|
@ -837,14 +912,5 @@ EndSelection:<<<<<<<4
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Object for format from the clipboard
|
||||
/// </summary>
|
||||
/// <param name="format">format to get</param>
|
||||
/// <returns>object from clipboard</returns>
|
||||
public static object GetClipboardData(string format) {
|
||||
return GetFromDataObject(GetDataObject(), format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,25 +305,7 @@ namespace GreenshotPlugin.Core {
|
|||
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||
public int WebRequestReadWriteTimeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what THIS build is
|
||||
/// </summary>
|
||||
public BuildStates BuildState {
|
||||
get {
|
||||
string informationalVersion = Application.ProductVersion;
|
||||
if (informationalVersion != null) {
|
||||
if (informationalVersion.ToLowerInvariant().Contains("-rc")) {
|
||||
return BuildStates.RELEASE_CANDIDATE;
|
||||
}
|
||||
if (informationalVersion.ToLowerInvariant().Contains("-unstable")) {
|
||||
return BuildStates.UNSTABLE;
|
||||
}
|
||||
}
|
||||
return BuildStates.RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32;
|
||||
public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32;
|
||||
|
||||
/// <summary>
|
||||
/// A helper method which returns true if the supplied experimental feature is enabled
|
||||
|
|
|
@ -242,68 +242,14 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog.</summary>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show() {
|
||||
return Show(null, Name, Password, SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified save checkbox status.</summary>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(bool saveChecked) {
|
||||
return Show(null, Name, Password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name.</summary>
|
||||
/// <summary>Shows the credentials dialog with the specified name.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name) {
|
||||
return Show(null, name, Password, SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name and password.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name, string password) {
|
||||
return Show(null, name, password, SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified name, password and save checkbox status.</summary>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(string name, string password, bool saveChecked) {
|
||||
return Show(null, name, password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner) {
|
||||
return Show(owner, Name, Password, SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner and save checkbox status.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="saveChecked">True if the save checkbox is checked.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner, bool saveChecked) {
|
||||
return Show(owner, Name, Password, saveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner, name and password.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
/// <returns>Returns a DialogResult indicating the user action.</returns>
|
||||
public DialogResult Show(IWin32Window owner, string name, string password) {
|
||||
return Show(owner, name, password, SaveChecked);
|
||||
}
|
||||
|
||||
/// <summary>Shows the credentials dialog with the specified owner, name, password and save checkbox status.</summary>
|
||||
/// <summary>Shows the credentials dialog with the specified owner, name, password and save checkbox status.</summary>
|
||||
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
|
||||
/// <param name="name">The name for the credentials.</param>
|
||||
/// <param name="password">The password for the credentials.</param>
|
||||
|
@ -450,7 +396,6 @@ namespace GreenshotPlugin.Core {
|
|||
public const int MAX_MESSAGE_LENGTH = 100;
|
||||
public const int MAX_CAPTION_LENGTH = 100;
|
||||
public const int MAX_GENERIC_TARGET_LENGTH = 100;
|
||||
public const int MAX_DOMAIN_TARGET_LENGTH = 100;
|
||||
public const int MAX_USERNAME_LENGTH = 100;
|
||||
public const int MAX_PASSWORD_LENGTH = 100;
|
||||
|
||||
|
@ -463,20 +408,12 @@ namespace GreenshotPlugin.Core {
|
|||
public enum CredFlags {
|
||||
INCORRECT_PASSWORD = 0x1,
|
||||
DO_NOT_PERSIST = 0x2,
|
||||
REQUEST_ADMINISTRATOR = 0x4,
|
||||
EXCLUDE_CERTIFICATES = 0x8,
|
||||
REQUIRE_CERTIFICATE = 0x10,
|
||||
SHOW_SAVE_CHECK_BOX = 0x40,
|
||||
ALWAYS_SHOW_UI = 0x80,
|
||||
REQUIRE_SMARTCARD = 0x100,
|
||||
PASSWORD_ONLY_OK = 0x200,
|
||||
VALIDATE_USERNAME = 0x400,
|
||||
COMPLETE_USERNAME = 0x800,
|
||||
PERSIST = 0x1000,
|
||||
SERVER_CREDENTIAL = 0x4000,
|
||||
EXPECT_CONFIRMATION = 0x20000,
|
||||
GENERIC_CREDENTIALS = 0x40000,
|
||||
USERNAME_TARGET_CREDENTIALS = 0x80000,
|
||||
KEEP_USERNAME = 0x100000,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,28 @@
|
|||
using GreenshotPlugin.Core.Enums;
|
||||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.Core.Enums;
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using GreenshotPlugin.UnmanagedHelpers.Enums;
|
||||
|
@ -59,23 +79,6 @@ namespace GreenshotPlugin.Core
|
|||
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>
|
||||
|
@ -93,79 +96,6 @@ namespace GreenshotPlugin.Core
|
|||
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>
|
||||
|
@ -177,282 +107,6 @@ namespace GreenshotPlugin.Core
|
|||
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>
|
||||
/// Return the DPI for the screen which the location is located on
|
||||
/// </summary>
|
||||
|
@ -510,40 +164,6 @@ namespace GreenshotPlugin.Core
|
|||
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.
|
||||
|
@ -566,14 +186,6 @@ namespace GreenshotPlugin.Core
|
|||
[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/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.
|
||||
|
@ -581,151 +193,5 @@ namespace GreenshotPlugin.Core
|
|||
/// <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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
namespace GreenshotPlugin.Core {
|
||||
public static class EnumerationExtensions {
|
||||
public static bool Has<T>(this Enum type, T value) {
|
||||
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
try {
|
||||
if (underlyingType == typeof(int)) {
|
||||
return (((int)(object)type & (int)(object)value) == (int)(object)value);
|
||||
} else if (underlyingType == typeof(uint)) {
|
||||
return (((uint)(object)type & (uint)(object)value) == (uint)(object)value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool Is<T>(this Enum type, T value) {
|
||||
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
try
|
||||
{
|
||||
if (underlyingType == typeof(int)) {
|
||||
return (int)(object)type == (int)(object)value;
|
||||
}
|
||||
if (underlyingType == typeof(uint)) {
|
||||
return (uint)(object)type == (uint)(object)value;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a flag to an enum
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static T Add<T>(this Enum type, T value) {
|
||||
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
try
|
||||
{
|
||||
if (underlyingType == typeof(int)) {
|
||||
return (T)(object)(((int)(object)type | (int)(object)value));
|
||||
}
|
||||
if (underlyingType == typeof(uint)) {
|
||||
return (T)(object)(((uint)(object)type | (uint)(object)value));
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'.", ex);
|
||||
}
|
||||
throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a flag from an enum type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static T Remove<T>(this Enum type, T value) {
|
||||
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
try
|
||||
{
|
||||
if (underlyingType == typeof(int)) {
|
||||
return (T)(object)(((int)(object)type & ~(int)(object)value));
|
||||
}
|
||||
if (underlyingType == typeof(uint)) {
|
||||
return (T)(object)(((uint)(object)type & ~(uint)(object)value));
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'.", ex);
|
||||
}
|
||||
throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +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 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
|
||||
}
|
||||
}
|
|
@ -1,32 +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 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
|
||||
}
|
||||
}
|
|
@ -1,40 +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.
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -1,46 +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.
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -1,28 +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.
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,28 +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.
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -355,16 +355,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating a FastBitmap as a destination for the source
|
||||
/// </summary>
|
||||
/// <param name="source">Bitmap to clone</param>
|
||||
/// <returns>IFastBitmap</returns>
|
||||
public static IFastBitmap CreateCloneOf(Image source) {
|
||||
return CreateCloneOf(source, source.PixelFormat, Rectangle.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Factory for creating a FastBitmap as a destination for the source
|
||||
/// </summary>
|
||||
/// <param name="source">Bitmap to clone</param>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
using GreenshotPlugin.Core.Enums;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
|
@ -29,7 +28,7 @@ namespace GreenshotPlugin.Core
|
|||
public static class HResultExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Test if the HResult respresents a fail
|
||||
/// Test if the HResult represents a fail
|
||||
/// </summary>
|
||||
/// <param name="hResult">HResult</param>
|
||||
/// <returns>bool</returns>
|
||||
|
@ -40,7 +39,7 @@ namespace GreenshotPlugin.Core
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the HResult respresents a success
|
||||
/// Test if the HResult represents a success
|
||||
/// </summary>
|
||||
/// <param name="hResult">HResult</param>
|
||||
/// <returns>bool</returns>
|
||||
|
@ -49,17 +48,5 @@ namespace GreenshotPlugin.Core
|
|||
{
|
||||
return hResult >= HResult.S_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception on Failure
|
||||
/// </summary>
|
||||
/// <param name="hResult">HResult</param>
|
||||
public static void ThrowOnFailure(this HResult hResult)
|
||||
{
|
||||
if (hResult.Failed())
|
||||
{
|
||||
throw Marshal.GetExceptionForHR((int)hResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,16 +12,6 @@ namespace GreenshotPlugin.Core
|
|||
private readonly Image _image;
|
||||
private Image _imageClone;
|
||||
|
||||
/// <summary>
|
||||
/// Factory method
|
||||
/// </summary>
|
||||
/// <param name="image">Image</param>
|
||||
/// <returns>IImage</returns>
|
||||
public static IImage FromImage(Image image)
|
||||
{
|
||||
return image == null ? null : new ImageWrapper(image);
|
||||
}
|
||||
|
||||
public ImageWrapper(Image image)
|
||||
{
|
||||
// Make sure the orientation is set correctly so Greenshot can process the image correctly
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
using log4net;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
|
@ -33,42 +31,28 @@ namespace GreenshotPlugin.Core {
|
|||
private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils));
|
||||
|
||||
public static List<Type> GetSubclassesOf(Type type, bool excludeSystemTypes) {
|
||||
List<Type> list = new List<Type>();
|
||||
foreach(Assembly currentAssembly in Thread.GetDomain().GetAssemblies()) {
|
||||
var list = new List<Type>();
|
||||
foreach(var currentAssembly in Thread.GetDomain().GetAssemblies()) {
|
||||
try {
|
||||
Type[] types = currentAssembly.GetTypes();
|
||||
if (!excludeSystemTypes || (excludeSystemTypes && !currentAssembly.FullName.StartsWith("System."))) {
|
||||
foreach(Type currentType in types) {
|
||||
if (type.IsInterface) {
|
||||
if (currentType.GetInterface(type.FullName) != null) {
|
||||
list.Add(currentType);
|
||||
}
|
||||
} else if (currentType.IsSubclassOf(type)) {
|
||||
list.Add(currentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (excludeSystemTypes && (!excludeSystemTypes || currentAssembly.FullName.StartsWith("System.")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach(var currentType in types) {
|
||||
if (type.IsInterface) {
|
||||
if (currentType.GetInterface(type.FullName) != null) {
|
||||
list.Add(currentType);
|
||||
}
|
||||
} else if (currentType.IsSubclassOf(type)) {
|
||||
list.Add(currentType);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.WarnFormat("Problem getting subclasses of type: {0}, message: {1}", type.FullName, ex.Message);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<IProcessor> GetProcessors() {
|
||||
List<IProcessor> processors = new List<IProcessor>();
|
||||
foreach(Type processorType in GetSubclassesOf(typeof(IProcessor), true)) {
|
||||
if (!processorType.IsAbstract) {
|
||||
IProcessor processor = (IProcessor)Activator.CreateInstance(processorType);
|
||||
if (processor.isActive) {
|
||||
LOG.DebugFormat("Found processor {0} with designation {1}", processorType.Name, processor.Designation);
|
||||
processors.Add(processor);
|
||||
} else {
|
||||
LOG.DebugFormat("Ignoring processor {0} with designation {1}", processorType.Name, processor.Designation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return processors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -476,32 +476,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a resource with prefix.key exists
|
||||
/// </summary>
|
||||
/// <param name="prefix"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>true if available</returns>
|
||||
public static bool HasKey(string prefix, Enum key) {
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
return HasKey(prefix + "." + key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a resource with key exists
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>true if available</returns>
|
||||
public static bool HasKey(Enum key) {
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
return HasKey(key.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Check if a resource with prefix.key exists
|
||||
/// </summary>
|
||||
/// <param name="prefix"></param>
|
||||
|
|
|
@ -40,9 +40,8 @@ namespace GreenshotPlugin.Core {
|
|||
GET,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
HEAD
|
||||
};
|
||||
DELETE
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Description of NetworkHelper.
|
||||
|
@ -61,54 +60,21 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn("An error has occured while allowing self-signed certificates:", ex);
|
||||
Log.Warn("An error has occurred while allowing self-signed certificates:", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a uri response as string
|
||||
/// </summary>
|
||||
/// <param name="uri">An Uri to specify the download location</param>
|
||||
/// <returns>string with the file content</returns>
|
||||
public static string GetAsString(Uri uri) {
|
||||
return GetResponseAsString(CreateWebRequest(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the FavIcon as a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="baseUri"></param>
|
||||
/// <returns>Bitmap with the FavIcon</returns>
|
||||
public static Bitmap DownloadFavIcon(Uri baseUri) {
|
||||
Uri url = new Uri(baseUri, new Uri("favicon.ico"));
|
||||
try {
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (request.HaveResponse)
|
||||
{
|
||||
using Stream responseStream = response.GetResponseStream();
|
||||
if (responseStream != null)
|
||||
{
|
||||
using Image image = ImageHelper.FromStream(responseStream);
|
||||
return image.Height > 16 && image.Width > 16 ? new Bitmap(image, 16, 16) : new Bitmap(image);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.Error("Problem downloading the FavIcon from: " + baseUri, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Download the uri into a memory stream, without catching exceptions
|
||||
/// </summary>
|
||||
/// <param name="url">Of an image</param>
|
||||
/// <returns>MemoryStream which is already seek-ed to 0</returns>
|
||||
public static MemoryStream GetAsMemoryStream(string url) {
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
using (Stream responseStream = response.GetResponseStream()) {
|
||||
var request = CreateWebRequest(url);
|
||||
using var response = (HttpWebResponse)request.GetResponse();
|
||||
var memoryStream = new MemoryStream();
|
||||
using (var responseStream = response.GetResponseStream()) {
|
||||
responseStream?.CopyTo(memoryStream);
|
||||
// Make sure it can be used directly
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
@ -123,7 +89,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <returns>Bitmap</returns>
|
||||
public static Image DownloadImage(string url)
|
||||
{
|
||||
StringBuilder extensions = new StringBuilder();
|
||||
var extensions = new StringBuilder();
|
||||
foreach (var extension in ImageHelper.StreamConverters.Keys)
|
||||
{
|
||||
if (string.IsNullOrEmpty(extension))
|
||||
|
@ -147,7 +113,7 @@ namespace GreenshotPlugin.Core {
|
|||
{
|
||||
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
|
||||
string content;
|
||||
using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
|
||||
using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
|
||||
{
|
||||
content = streamReader.ReadLine();
|
||||
}
|
||||
|
@ -198,7 +164,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="method">Method to use</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) {
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
var webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = method.ToString();
|
||||
return webRequest;
|
||||
}
|
||||
|
@ -209,7 +175,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="uri">Uri with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(Uri uri) {
|
||||
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
|
||||
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
|
||||
webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null;
|
||||
// Make sure the default credentials are available
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
|
@ -231,28 +197,32 @@ namespace GreenshotPlugin.Core {
|
|||
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
|
||||
public static IWebProxy CreateProxy(Uri uri) {
|
||||
IWebProxy proxyToUse = null;
|
||||
if (Config.UseProxy) {
|
||||
proxyToUse = WebRequest.DefaultWebProxy;
|
||||
if (proxyToUse != null) {
|
||||
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
|
||||
if (Log.IsDebugEnabled) {
|
||||
// check the proxy for the Uri
|
||||
if (!proxyToUse.IsBypassed(uri)) {
|
||||
Uri proxyUri = proxyToUse.GetProxy(uri);
|
||||
if (proxyUri != null) {
|
||||
Log.Debug("Using proxy: " + proxyUri + " for " + uri);
|
||||
} else {
|
||||
Log.Debug("No proxy found!");
|
||||
}
|
||||
} else {
|
||||
Log.Debug("Proxy bypass for: " + uri);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.Debug("No proxy found!");
|
||||
}
|
||||
}
|
||||
return proxyToUse;
|
||||
if (!Config.UseProxy)
|
||||
{
|
||||
return proxyToUse;
|
||||
}
|
||||
proxyToUse = WebRequest.DefaultWebProxy;
|
||||
if (proxyToUse != null) {
|
||||
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
|
||||
if (!Log.IsDebugEnabled)
|
||||
{
|
||||
return proxyToUse;
|
||||
}
|
||||
// check the proxy for the Uri
|
||||
if (!proxyToUse.IsBypassed(uri)) {
|
||||
var proxyUri = proxyToUse.GetProxy(uri);
|
||||
if (proxyUri != null) {
|
||||
Log.Debug("Using proxy: " + proxyUri + " for " + uri);
|
||||
} else {
|
||||
Log.Debug("No proxy found!");
|
||||
}
|
||||
} else {
|
||||
Log.Debug("Proxy bypass for: " + uri);
|
||||
}
|
||||
} else {
|
||||
Log.Debug("No proxy found!");
|
||||
}
|
||||
return proxyToUse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -263,7 +233,7 @@ namespace GreenshotPlugin.Core {
|
|||
// [Obsolete("Use System.Uri.EscapeDataString instead")]
|
||||
public static string UrlEncode(string text) {
|
||||
if (!string.IsNullOrEmpty(text)) {
|
||||
// Sytem.Uri provides reliable parsing, but doesn't encode spaces.
|
||||
// System.Uri provides reliable parsing, but doesn't encode spaces.
|
||||
return Uri.EscapeDataString(text).Replace("%20", "+");
|
||||
}
|
||||
return null;
|
||||
|
@ -277,7 +247,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <returns>escaped data string</returns>
|
||||
public static string EscapeDataString(string text) {
|
||||
if (!string.IsNullOrEmpty(text)) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
var result = new StringBuilder();
|
||||
int currentLocation = 0;
|
||||
while (currentLocation < text.Length) {
|
||||
string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
|
||||
|
@ -326,7 +296,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the query paramters
|
||||
/// Generate the query parameters
|
||||
/// </summary>
|
||||
/// <param name="queryParameters">the list of query parameters</param>
|
||||
/// <returns>a string with the query parameters</returns>
|
||||
|
@ -337,7 +307,7 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
queryParameters = new SortedDictionary<string, object>(queryParameters);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
foreach(string key in queryParameters.Keys) {
|
||||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}"));
|
||||
}
|
||||
|
@ -358,18 +328,8 @@ namespace GreenshotPlugin.Core {
|
|||
WriteMultipartFormData(formDataStream, boundary, postParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data to the HttpListenerResponse
|
||||
/// </summary>
|
||||
/// <param name="response">HttpListenerResponse</param>
|
||||
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
||||
public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary<string, object> postParameters) {
|
||||
string boundary = $"----------{Guid.NewGuid():N}";
|
||||
response.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||
WriteMultipartFormData(response.OutputStream, boundary, postParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data to a Stream, content-type should be set before this!
|
||||
/// </summary>
|
||||
/// <param name="formDataStream">Stream to write the multipart form data to</param>
|
||||
|
@ -519,27 +479,7 @@ namespace GreenshotPlugin.Core {
|
|||
}
|
||||
return responseData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get LastModified for a URI
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri</param>
|
||||
/// <returns>DateTime</returns>
|
||||
public static DateTime GetLastModified(Uri uri) {
|
||||
try {
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = HTTPMethod.HEAD.ToString();
|
||||
using HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||
Log.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
|
||||
return webResponse.LastModified;
|
||||
} catch (Exception wE) {
|
||||
Log.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri);
|
||||
Log.Warn(wE.Message);
|
||||
// Pretend it is old
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface can be used to pass binary information around, like byte[] or Image
|
||||
|
@ -555,158 +495,7 @@ namespace GreenshotPlugin.Core {
|
|||
string Filename { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container to supply files to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class ByteContainer : IBinaryContainer {
|
||||
private readonly byte[] _file;
|
||||
private readonly string _contentType;
|
||||
private readonly int _fileSize;
|
||||
public ByteContainer(byte[] file) : this(file, null) {
|
||||
}
|
||||
public ByteContainer(byte[] file, string filename) : this(file, filename, null) {
|
||||
}
|
||||
public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) {
|
||||
}
|
||||
public ByteContainer(byte[] file, string filename, string contenttype, int filesize) {
|
||||
_file = file;
|
||||
Filename = filename;
|
||||
_contentType = contenttype;
|
||||
_fileSize = filesize == 0 ? file.Length : filesize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Base64String from the byte[]
|
||||
/// </summary>
|
||||
/// <returns>string</returns>
|
||||
public string ToBase64String(Base64FormattingOptions formattingOptions) {
|
||||
return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the initial byte-array which was supplied when creating the FileParameter
|
||||
/// </summary>
|
||||
/// <returns>byte[]</returns>
|
||||
public byte[] ToByteArray() {
|
||||
return _file;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
||||
/// </summary>
|
||||
/// <param name="boundary">Separator</param>
|
||||
/// <param name="name">name</param>
|
||||
/// <param name="formDataStream">Stream to write to</param>
|
||||
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) {
|
||||
// Add just the first part of this param, since we will write the file data directly to the Stream
|
||||
string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {_contentType ?? "application/octet-stream"}\r\n\r\n";
|
||||
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
formDataStream.Write(_file, 0, _fileSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A plain "write data to stream"
|
||||
/// </summary>
|
||||
/// <param name="dataStream">Stream to write to</param>
|
||||
public void WriteToStream(Stream dataStream) {
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
dataStream.Write(_file, 0, _fileSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload the file to the webrequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public void Upload(HttpWebRequest webRequest) {
|
||||
webRequest.ContentType = _contentType;
|
||||
webRequest.ContentLength = _fileSize;
|
||||
using var requestStream = webRequest.GetRequestStream();
|
||||
WriteToStream(requestStream);
|
||||
}
|
||||
|
||||
public string ContentType => _contentType;
|
||||
public string Filename { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container to supply images to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class BitmapContainer : IBinaryContainer {
|
||||
private readonly Bitmap _bitmap;
|
||||
private readonly SurfaceOutputSettings _outputSettings;
|
||||
|
||||
public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) {
|
||||
_bitmap = bitmap;
|
||||
_outputSettings = outputSettings;
|
||||
Filename = filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Base64String from the image by saving it to a memory stream and converting it.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>string</returns>
|
||||
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
||||
{
|
||||
using MemoryStream stream = new MemoryStream();
|
||||
ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
|
||||
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a byte[] from the image by saving it to a memory stream.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>byte[]</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
using MemoryStream stream = new MemoryStream();
|
||||
ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
||||
/// </summary>
|
||||
/// <param name="boundary">Separator</param>
|
||||
/// <param name="name">Name of the thing/file</param>
|
||||
/// <param name="formDataStream">Stream to write to</param>
|
||||
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) {
|
||||
// Add just the first part of this param, since we will write the file data directly to the Stream
|
||||
string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
|
||||
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||
ImageOutput.SaveToStream(_bitmap, null, formDataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A plain "write data to stream"
|
||||
/// </summary>
|
||||
/// <param name="dataStream"></param>
|
||||
public void WriteToStream(Stream dataStream) {
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
ImageOutput.SaveToStream(_bitmap, null, dataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload the image to the webrequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public void Upload(HttpWebRequest webRequest) {
|
||||
webRequest.ContentType = "image/" + _outputSettings.Format;
|
||||
using var requestStream = webRequest.GetRequestStream();
|
||||
WriteToStream(requestStream);
|
||||
}
|
||||
|
||||
public string ContentType => "image/" + _outputSettings.Format;
|
||||
|
||||
public string Filename { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// A container to supply surfaces to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class SurfaceContainer : IBinaryContainer {
|
||||
|
|
|
@ -549,21 +549,7 @@ namespace GreenshotPlugin.Core {
|
|||
return MakeOAuthRequest(method, requestUrl, requestUrl, null, parametersToSign, additionalParameters, postData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submit a web request using oAuth.
|
||||
/// </summary>
|
||||
/// <param name="method">GET or POST</param>
|
||||
/// <param name="requestUrl">The full url, including the querystring for the signing/request</param>
|
||||
/// <param name="headers">Header values</param>
|
||||
/// <param name="parametersToSign">Parameters for the request, which need to be signed</param>
|
||||
/// <param name="additionalParameters">Parameters for the request, which do not need to be signed</param>
|
||||
/// <param name="postData">Data to post (MemoryStream)</param>
|
||||
/// <returns>The web server response.</returns>
|
||||
public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary<string, string> headers, IDictionary<string, object> parametersToSign, IDictionary<string, object> additionalParameters, IBinaryContainer postData) {
|
||||
return MakeOAuthRequest(method, requestUrl, requestUrl, headers, parametersToSign, additionalParameters, postData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Submit a web request using oAuth.
|
||||
/// </summary>
|
||||
/// <param name="method">GET or POST</param>
|
||||
|
|
|
@ -29,7 +29,6 @@ using System.Drawing;
|
|||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using GreenshotPlugin.IniFile;
|
||||
using GreenshotPlugin.Interfaces.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
|
@ -52,7 +51,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="e"></param>
|
||||
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) {
|
||||
if (e.PropertyName != "IconSize") return;
|
||||
List<Image> cachedImages = new List<Image>();
|
||||
var cachedImages = new List<Image>();
|
||||
lock (ExeIconCache) {
|
||||
foreach (string key in ExeIconCache.Keys) {
|
||||
cachedImages.Add(ExeIconCache[key]);
|
||||
|
@ -71,7 +70,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <param name="exeName">e.g. cmd.exe</param>
|
||||
/// <returns>Path to file</returns>
|
||||
public static string GetExePath(string exeName) {
|
||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) {
|
||||
using (var key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) {
|
||||
if (key != null) {
|
||||
// "" is the default key, which should point to the requested location
|
||||
return (string)key.GetValue(string.Empty);
|
||||
|
@ -147,69 +146,7 @@ namespace GreenshotPlugin.Core {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="image">Image to display in the menu</param>
|
||||
/// <param name="text">Text to display in the menu</param>
|
||||
/// <param name="tag">The TAG value</param>
|
||||
/// <param name="shortcutKeys">Keys which can be used as shortcut</param>
|
||||
/// <param name="handler">The onclick handler</param>
|
||||
public static void AddToFileMenu(IImageEditor imageEditor, Image image, string text, object tag, Keys? shortcutKeys, EventHandler handler) {
|
||||
var item = new ToolStripMenuItem
|
||||
{
|
||||
Image = image,
|
||||
Text = text,
|
||||
Tag = tag
|
||||
};
|
||||
if (shortcutKeys.HasValue) {
|
||||
item.ShortcutKeys = shortcutKeys.Value;
|
||||
}
|
||||
item.Click += handler;
|
||||
AddToFileMenu(imageEditor, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item) {
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem();
|
||||
bool added = false;
|
||||
for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) {
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) {
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item) {
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem();
|
||||
bool added = false;
|
||||
for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) {
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) {
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Helper method to add a plugin MenuItem to the Greenshot context menu
|
||||
/// </summary>
|
||||
/// <param name="item">ToolStripMenuItem</param>
|
||||
|
|
|
@ -137,19 +137,5 @@ namespace GreenshotPlugin.Core {
|
|||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read "streamextensions" :)
|
||||
/// </summary>
|
||||
/// <param name="input">Stream</param>
|
||||
/// <param name="output">Stream</param>
|
||||
public static void CopyTo(this Stream input, Stream output) {
|
||||
byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) {
|
||||
output.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,17 +298,6 @@ namespace GreenshotPlugin.Core
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the children with matching classname
|
||||
/// </summary>
|
||||
public IEnumerable<WindowDetails> GetChilden(string childClassname) {
|
||||
foreach (var child in Children) {
|
||||
if (childClassname.Equals(child.ClassName)) {
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IntPtr ParentHandle {
|
||||
get {
|
||||
if (_parentHandle == IntPtr.Zero) {
|
||||
|
@ -379,92 +368,6 @@ namespace GreenshotPlugin.Core
|
|||
return FindWindow(Children, titlePattern, classnamePattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recurse-ing helper method for the FindPath
|
||||
/// </summary>
|
||||
/// <param name="classNames">List string with classNames</param>
|
||||
/// <param name="index">The index in the list to look for</param>
|
||||
/// <returns>WindowDetails if a match was found</returns>
|
||||
private WindowDetails FindPath(IList<string> classNames, int index) {
|
||||
if (index == classNames.Count - 1) {
|
||||
foreach (var foundWindow in FindChildren(null, classNames[index]))
|
||||
{
|
||||
return foundWindow;
|
||||
}
|
||||
} else {
|
||||
foreach(var foundWindow in FindChildren(null, classNames[index]))
|
||||
{
|
||||
var resultWindow = foundWindow.FindPath(classNames, index+1);
|
||||
if (resultWindow != null)
|
||||
{
|
||||
return resultWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will find the child window according to a path of classNames.
|
||||
/// Usually used for finding a certain "content" window like for the IE Browser
|
||||
/// </summary>
|
||||
/// <param name="classNames">List of string with classname "path"</param>
|
||||
/// <param name="allowSkip">true allows the search to skip a classname of the path</param>
|
||||
/// <returns>WindowDetails if found</returns>
|
||||
public WindowDetails FindPath(IList<string> classNames, bool allowSkip) {
|
||||
int index = 0;
|
||||
var resultWindow = FindPath(classNames, index++);
|
||||
if (resultWindow == null && allowSkip) {
|
||||
while(resultWindow == null && index < classNames.Count) {
|
||||
resultWindow = FindPath(classNames, index);
|
||||
}
|
||||
}
|
||||
return resultWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deep scan for a certain classname pattern
|
||||
/// </summary>
|
||||
/// <param name="windowDetails">Window to scan into</param>
|
||||
/// <param name="classnamePattern">Classname regexp pattern</param>
|
||||
/// <returns>The first WindowDetails found</returns>
|
||||
public static WindowDetails DeepScan(WindowDetails windowDetails, Regex classnamePattern) {
|
||||
if (classnamePattern.IsMatch(windowDetails.ClassName)) {
|
||||
return windowDetails;
|
||||
}
|
||||
// First loop through this level
|
||||
foreach(var child in windowDetails.Children) {
|
||||
if (classnamePattern.IsMatch(child.ClassName)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
// Go into all children
|
||||
foreach(var child in windowDetails.Children) {
|
||||
var deepWindow = DeepScan(child, classnamePattern);
|
||||
if (deepWindow != null) {
|
||||
return deepWindow;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetWindow
|
||||
/// </summary>
|
||||
/// <param name="gwCommand">The GetWindowCommand to use</param>
|
||||
/// <returns>null if nothing found, otherwise the WindowDetails instance of the "child"</returns>
|
||||
public WindowDetails GetWindow(GetWindowCommand gwCommand) {
|
||||
var tmphWnd = User32.GetWindow(Handle, gwCommand);
|
||||
if (IntPtr.Zero == tmphWnd) {
|
||||
return null;
|
||||
}
|
||||
var windowDetails = new WindowDetails(tmphWnd)
|
||||
{
|
||||
_parent = this
|
||||
};
|
||||
return windowDetails;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the window's handle
|
||||
/// </summary>
|
||||
|
@ -512,7 +415,7 @@ namespace GreenshotPlugin.Core
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets whether the window is maximised or not.
|
||||
/// Gets/Sets whether the window is maximized or not.
|
||||
/// </summary>
|
||||
public bool Maximised {
|
||||
get {
|
||||
|
@ -541,13 +444,6 @@ namespace GreenshotPlugin.Core
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This doesn't work as good as is should, but does move the App out of the way...
|
||||
/// </summary>
|
||||
public void HideApp() {
|
||||
User32.ShowWindow(Handle, ShowWindowCommand.Hide);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this window is cloaked
|
||||
/// </summary>
|
||||
|
@ -627,13 +523,6 @@ namespace GreenshotPlugin.Core
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the next call of a cached value is guaranteed the real value
|
||||
/// </summary>
|
||||
public void Reset() {
|
||||
_previousWindowRectangle = Rectangle.Empty;
|
||||
}
|
||||
|
||||
private Rectangle _previousWindowRectangle = Rectangle.Empty;
|
||||
private long _lastWindowRectangleRetrieveTime;
|
||||
private const long CacheTime = TimeSpan.TicksPerSecond * 2;
|
||||
|
@ -1354,24 +1243,6 @@ namespace GreenshotPlugin.Core
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if this window is Greenshot
|
||||
/// </summary>
|
||||
public bool IsGreenshot {
|
||||
get {
|
||||
try {
|
||||
if (!IsMetroApp)
|
||||
{
|
||||
using Process thisWindowProcess = Process;
|
||||
return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.Warn(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Desktop window
|
||||
/// </summary>
|
||||
|
|
|
@ -34,25 +34,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// </summary>
|
||||
public IList<WindowDetails> Items { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all top level windows on the system.
|
||||
/// </summary>
|
||||
public WindowsEnumerator GetWindows() {
|
||||
GetWindows(IntPtr.Zero, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all child windows of the specified window
|
||||
/// </summary>
|
||||
/// <param name="parent">Window Handle to get children for</param>
|
||||
public WindowsEnumerator GetWindows(WindowDetails parent)
|
||||
{
|
||||
GetWindows(parent?.Handle ?? IntPtr.Zero, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Gets all child windows of the specified window
|
||||
/// </summary>
|
||||
/// <param name="hWndParent">Window Handle to get children for</param>
|
||||
|
@ -69,7 +51,7 @@ namespace GreenshotPlugin.Core {
|
|||
parentText = title.ToString();
|
||||
}
|
||||
|
||||
List<WindowDetails> windows = new List<WindowDetails>();
|
||||
var windows = new List<WindowDetails>();
|
||||
foreach (var window in Items) {
|
||||
if (hasParent) {
|
||||
window.Text = parentText;
|
||||
|
|
|
@ -15,51 +15,18 @@ namespace GreenshotPlugin.Core
|
|||
/// </summary>
|
||||
public static Version WinVersion { get; } = Environment.OSVersion.Version;
|
||||
|
||||
public static double WinVersionTotal = WinVersion.Major + (double)WinVersion.Minor / 10;
|
||||
/// <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 before Windows 10
|
||||
/// </summary>
|
||||
/// <returns>true if we are running on Windows before 10</returns>
|
||||
public static bool IsBeforeWindows10 { 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;
|
||||
|
||||
public static bool IsWindows7OrLower { get; } = WinVersionTotal <= 6.1;
|
||||
|
||||
/// <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>
|
||||
|
@ -72,36 +39,12 @@ namespace GreenshotPlugin.Core
|
|||
/// <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>
|
||||
/// Returns the windows build number
|
||||
/// </summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue