mirror of
https://github.com/greenshot/greenshot
synced 2025-08-23 06:36:20 -07:00
Small changes to make the code more generic, so it's better possible to migrate.
This commit is contained in:
parent
ede22c7132
commit
d8b58b1538
17 changed files with 119 additions and 66 deletions
|
@ -31,13 +31,22 @@ using Greenshot.Core.Interfaces;
|
||||||
namespace Greenshot.Core
|
namespace Greenshot.Core
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class Capture : ICapture
|
public class Capture<TContent> : ICapture<TContent>
|
||||||
{
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var captureElement in CaptureElements)
|
||||||
|
{
|
||||||
|
captureElement?.Dispose();
|
||||||
|
}
|
||||||
|
CaptureElements.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public DateTimeOffset Taken { get; } = DateTimeOffset.Now;
|
public DateTimeOffset Taken { get; } = DateTimeOffset.Now;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IList<ICaptureElement> CaptureElements { get; } = new List<ICaptureElement>();
|
public IList<ICaptureElement<TContent>> CaptureElements { get; } = new List<ICaptureElement<TContent>>();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public NativeRect Bounds => CaptureElements.Select(element => element.Bounds).Aggregate((b1, b2) => b1.Union(b2));
|
public NativeRect Bounds => CaptureElements.Select(element => element.Bounds).Aggregate((b1, b2) => b1.Union(b2));
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Windows.Media;
|
using System.Drawing;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using Dapplo.Windows.Common.Structs;
|
using Dapplo.Windows.Common.Structs;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
using Greenshot.Core.Interfaces;
|
using Greenshot.Core.Interfaces;
|
||||||
|
@ -32,11 +34,25 @@ namespace Greenshot.Core
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The CaptureElement contains the information of an element in a capture, e.g the window and mouse
|
/// The CaptureElement contains the information of an element in a capture, e.g the window and mouse
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CaptureElement : ICaptureElement
|
public class CaptureElement<TContent> : ICaptureElement<TContent>
|
||||||
{
|
{
|
||||||
public CaptureElement(NativePoint location, ImageSource content)
|
public CaptureElement(NativePoint location, TContent content)
|
||||||
{
|
{
|
||||||
Bounds = new NativeRect(location, new NativeSize((int)content.Width, (int)content.Height));
|
NativeSize size;
|
||||||
|
if (content is BitmapSource bitmapSource)
|
||||||
|
{
|
||||||
|
size = new NativeSize((int)bitmapSource.Width, (int)bitmapSource.Height);
|
||||||
|
}
|
||||||
|
else if (content is Bitmap bitmap)
|
||||||
|
{
|
||||||
|
size = new NativeSize(bitmap.Width, bitmap.Height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(typeof(TContent).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Bounds = new NativeRect(location, size);
|
||||||
Content = content;
|
Content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,12 +60,20 @@ namespace Greenshot.Core
|
||||||
public NativeRect Bounds { get; set; }
|
public NativeRect Bounds { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ImageSource Content { get; set; }
|
public TContent Content { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public CaptureElementType ElementType { get; set; } = CaptureElementType.Unknown;
|
public CaptureElementType ElementType { get; set; } = CaptureElementType.Unknown;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IDictionary<string, string> MetaData { get; } = new Dictionary<string, string>();
|
public IDictionary<string, string> MetaData { get; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Content is IDisposable disposable)
|
||||||
|
{
|
||||||
|
disposable.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,40 +31,40 @@ namespace Greenshot.Core
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This describes a capture flow, from source via processor to destination
|
/// This describes a capture flow, from source via processor to destination
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CaptureFlow
|
public class CaptureFlow<TContent>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ISource this capture flow contains
|
/// The ISource this capture flow contains
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<ISource> Sources
|
public IList<ISource<TContent>> Sources
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
} = new List<ISource>();
|
} = new List<ISource<TContent>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The IProcessor this capture flow contains
|
/// The IProcessor this capture flow contains
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<IProcessor> Processors
|
public IList<IProcessor<TContent>> Processors
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
} = new List<IProcessor>();
|
} = new List<IProcessor<TContent>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The IDestination this capture flow contains
|
/// The IDestination this capture flow contains
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<IDestination> Destinations
|
public IList<IDestination<TContent>> Destinations
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
} = new List<IDestination>();
|
} = new List<IDestination<TContent>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Execute this capture flow, to create a capture
|
/// Execute this capture flow, to create a capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">CancellationToken</param>
|
/// <param name="cancellationToken">CancellationToken</param>
|
||||||
/// <returns>ICapture</returns>
|
/// <returns>ICapture</returns>
|
||||||
public async Task<ICapture> Execute(CancellationToken cancellationToken = default)
|
public async Task<ICapture<TContent>> Execute(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var capture = new Capture();
|
var capture = new Capture<TContent>();
|
||||||
|
|
||||||
// Import the capture from the sources
|
// Import the capture from the sources
|
||||||
foreach (var source in Sources)
|
foreach (var source in Sources)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using Dapplo.Windows.Common.Structs;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
|
|
||||||
namespace Greenshot.Core.Extensions
|
namespace Greenshot.Core.Extensions
|
||||||
|
@ -66,5 +67,15 @@ namespace Greenshot.Core.Extensions
|
||||||
|
|
||||||
return returnStream;
|
return returnStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a NativeSizeFloat object from a BitmapSource
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bitmapSource"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static NativeSizeFloat Size(this BitmapSource bitmapSource)
|
||||||
|
{
|
||||||
|
return new NativeSizeFloat(bitmapSource.Width, bitmapSource.Height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,10 @@ namespace Greenshot.Core.Extensions
|
||||||
/// <param name="interopWindow">InteropWindow</param>
|
/// <param name="interopWindow">InteropWindow</param>
|
||||||
/// <param name="clientBounds">true to use the client bounds</param>
|
/// <param name="clientBounds">true to use the client bounds</param>
|
||||||
/// <returns>ICaptureElement</returns>
|
/// <returns>ICaptureElement</returns>
|
||||||
public static ICaptureElement CaptureFromScreen(this IInteropWindow interopWindow, bool clientBounds = false)
|
public static ICaptureElement<BitmapSource> CaptureFromScreen(this IInteropWindow interopWindow, bool clientBounds = false)
|
||||||
{
|
{
|
||||||
var bounds = clientBounds ? interopWindow.GetInfo().ClientBounds: interopWindow.GetInfo().Bounds;
|
var bounds = clientBounds ? interopWindow.GetInfo().ClientBounds: interopWindow.GetInfo().Bounds;
|
||||||
ICaptureElement result = ScreenSource.CaptureRectangle(bounds);
|
ICaptureElement<BitmapSource> result = ScreenSource.CaptureRectangle(bounds);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,18 +84,18 @@ namespace Greenshot.Core.Extensions
|
||||||
/// TODO: If there is a parent, this could be removed with SetParent, and set back afterwards.
|
/// TODO: If there is a parent, this could be removed with SetParent, and set back afterwards.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>ICaptureElement</returns>
|
/// <returns>ICaptureElement</returns>
|
||||||
public static ICaptureElement PrintWindow(this IInteropWindow interopWindow)
|
public static ICaptureElement<BitmapSource> PrintWindow(this IInteropWindow interopWindow)
|
||||||
{
|
{
|
||||||
var returnBitmap = interopWindow.PrintWindow<BitmapSource>();
|
var returnBitmap = interopWindow.PrintWindow<BitmapSource>();
|
||||||
if (interopWindow.HasParent || !interopWindow.IsMaximized())
|
if (interopWindow.HasParent || !interopWindow.IsMaximized())
|
||||||
{
|
{
|
||||||
return new CaptureElement(interopWindow.GetInfo().Bounds.Location, returnBitmap);
|
return new CaptureElement<BitmapSource>(interopWindow.GetInfo().Bounds.Location, returnBitmap);
|
||||||
}
|
}
|
||||||
Log.Debug().WriteLine("Correcting for maximalization");
|
Log.Debug().WriteLine("Correcting for maximalization");
|
||||||
var borderSize = interopWindow.GetInfo().BorderSize;
|
var borderSize = interopWindow.GetInfo().BorderSize;
|
||||||
var bounds = interopWindow.GetInfo().Bounds;
|
var bounds = interopWindow.GetInfo().Bounds;
|
||||||
var borderRectangle = new NativeRect(borderSize.Width, borderSize.Height, bounds.Width - 2 * borderSize.Width, bounds.Height - 2 * borderSize.Height);
|
var borderRectangle = new NativeRect(borderSize.Width, borderSize.Height, bounds.Width - 2 * borderSize.Width, bounds.Height - 2 * borderSize.Height);
|
||||||
return new CaptureElement(interopWindow.GetInfo().Bounds.Location, new CroppedBitmap(returnBitmap, borderRectangle));
|
return new CaptureElement<BitmapSource>(interopWindow.GetInfo().Bounds.Location, new CroppedBitmap(returnBitmap, borderRectangle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ namespace Greenshot.Core.Extensions
|
||||||
/// Helper method to check if it is allowed to capture the process using GDI
|
/// Helper method to check if it is allowed to capture the process using GDI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="process">Process owning the window</param>
|
/// <param name="process">Process owning the window</param>
|
||||||
|
/// <param name="captureConfiguration">ICaptureConfiguration</param>
|
||||||
/// <returns>true if it's allowed</returns>
|
/// <returns>true if it's allowed</returns>
|
||||||
public static bool IsGdiAllowed(Process process, ICaptureConfiguration captureConfiguration)
|
public static bool IsGdiAllowed(Process process, ICaptureConfiguration captureConfiguration)
|
||||||
{
|
{
|
||||||
|
@ -137,10 +138,10 @@ namespace Greenshot.Core.Extensions
|
||||||
/// <param name="interopWindow">IInteropWindow</param>
|
/// <param name="interopWindow">IInteropWindow</param>
|
||||||
/// <param name="captureConfiguration">ICaptureConfiguration configuration for the settings</param>
|
/// <param name="captureConfiguration">ICaptureConfiguration configuration for the settings</param>
|
||||||
/// <returns>ICaptureElement with the capture</returns>
|
/// <returns>ICaptureElement with the capture</returns>
|
||||||
public static async ValueTask<ICaptureElement> CaptureDwmWindow(this IInteropWindow interopWindow, ICaptureConfiguration captureConfiguration)
|
public static async ValueTask<ICaptureElement<BitmapSource>> CaptureDwmWindow(this IInteropWindow interopWindow, ICaptureConfiguration captureConfiguration)
|
||||||
{
|
{
|
||||||
// The capture
|
// The capture
|
||||||
ICaptureElement capturedBitmap = null;
|
ICaptureElement<BitmapSource> capturedBitmap = null;
|
||||||
var thumbnailHandle = IntPtr.Zero;
|
var thumbnailHandle = IntPtr.Zero;
|
||||||
Form tempForm = null;
|
Form tempForm = null;
|
||||||
var tempFormShown = false;
|
var tempFormShown = false;
|
||||||
|
@ -387,12 +388,11 @@ namespace Greenshot.Core.Extensions
|
||||||
/// <param name="blackBitmap">ICaptureElement with the black image</param>
|
/// <param name="blackBitmap">ICaptureElement with the black image</param>
|
||||||
/// <param name="whiteBitmap">ICaptureElement with the white image</param>
|
/// <param name="whiteBitmap">ICaptureElement with the white image</param>
|
||||||
/// <returns>ICaptureElement with transparency</returns>
|
/// <returns>ICaptureElement with transparency</returns>
|
||||||
private static ICaptureElement ApplyTransparency(ICaptureElement blackBitmap, ICaptureElement whiteBitmap)
|
private static ICaptureElement<BitmapSource> ApplyTransparency(ICaptureElement<BitmapSource> blackBitmap, ICaptureElement<BitmapSource> whiteBitmap)
|
||||||
{
|
{
|
||||||
var blackBitmapSource = blackBitmap.Content as BitmapSource ?? throw new ArgumentException("Not a BitmapSource", nameof(blackBitmap));
|
var blackBuffer = new WriteableBitmap(blackBitmap.Content);
|
||||||
var whitkBitmapSource = whiteBitmap.Content as BitmapSource ?? throw new ArgumentException("Not a BitmapSource", nameof(whiteBitmap));
|
var whiteBuffer = new WriteableBitmap(whiteBitmap.Content);
|
||||||
var blackBuffer = new WriteableBitmap(blackBitmapSource);
|
var blackBitmapSource = blackBitmap.Content;
|
||||||
var whiteBuffer = new WriteableBitmap(whitkBitmapSource);
|
|
||||||
var result = new WriteableBitmap((int)blackBitmapSource.Width, (int)blackBitmapSource.Height, blackBitmapSource.DpiX, blackBitmapSource.DpiY, PixelFormats.Bgra32, null);
|
var result = new WriteableBitmap((int)blackBitmapSource.Width, (int)blackBitmapSource.Height, blackBitmapSource.DpiX, blackBitmapSource.DpiY, PixelFormats.Bgra32, null);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -458,7 +458,7 @@ namespace Greenshot.Core.Extensions
|
||||||
blackBuffer.Unlock();
|
blackBuffer.Unlock();
|
||||||
whiteBuffer.Unlock();
|
whiteBuffer.Unlock();
|
||||||
}
|
}
|
||||||
return new CaptureElement(blackBitmap.Bounds.Location, result);
|
return new CaptureElement<BitmapSource>(blackBitmap.Bounds.Location, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This contains all the capture information
|
/// This contains all the capture information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ICapture
|
public interface ICapture<TContent> : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The calculated bounds for this capture
|
/// The calculated bounds for this capture
|
||||||
|
@ -55,6 +55,6 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the actual capture elements, making up the capture
|
/// the actual capture elements, making up the capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IList<ICaptureElement> CaptureElements { get; }
|
IList<ICaptureElement<TContent>> CaptureElements { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Windows.Media;
|
|
||||||
using Dapplo.Windows.Common.Structs;
|
using Dapplo.Windows.Common.Structs;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This specifies a single element of a capture, making it possible to have a capture contain mouse, window, popup etc information
|
/// This specifies a single element of a capture, making it possible to have a capture contain mouse, window, popup etc information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ICaptureElement
|
public interface ICaptureElement<TContent> : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location or bounds of the content
|
/// The location or bounds of the content
|
||||||
|
@ -45,7 +45,7 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The actual content
|
/// The actual content
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ImageSource Content
|
TContent Content
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This IDestination describes things which can export a capture
|
/// This IDestination describes things which can export a capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDestination
|
public interface IDestination<TContent>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is called when the a capture needs to be exported
|
/// This is called when the a capture needs to be exported
|
||||||
|
@ -37,6 +37,6 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <param name="capture">ICapture</param>
|
/// <param name="capture">ICapture</param>
|
||||||
/// <param name="cancellationToken">CancellationToken</param>
|
/// <param name="cancellationToken">CancellationToken</param>
|
||||||
/// <returns>Task of bool</returns>
|
/// <returns>Task of bool</returns>
|
||||||
Task<bool> Export(ICapture capture, CancellationToken cancellationToken = default);
|
Task<bool> Export(ICapture<TContent> capture, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// This IProcessor describes things which can process a capture
|
/// This IProcessor describes things which can process a capture
|
||||||
/// An example would be to add a watermark to the capture
|
/// An example would be to add a watermark to the capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProcessor
|
public interface IProcessor<TContent>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Process the capture
|
/// Process the capture
|
||||||
|
@ -38,6 +38,6 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <param name="capture">ICapture</param>
|
/// <param name="capture">ICapture</param>
|
||||||
/// <param name="cancellationToken">CancellationToken</param>
|
/// <param name="cancellationToken">CancellationToken</param>
|
||||||
/// <returns>Task of bool</returns>
|
/// <returns>Task of bool</returns>
|
||||||
Task<bool> Process(ICapture capture, CancellationToken cancellationToken = default);
|
Task<bool> Process(ICapture<TContent> capture, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,13 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// This interface defines sources, which can be used to get information from.
|
/// This interface defines sources, which can be used to get information from.
|
||||||
/// For instance the screen, IE, a file etc.
|
/// For instance the screen, IE, a file etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISource
|
public interface ISource<TResult>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Import an ICaptureElement from the source
|
/// Import an ICaptureElement from the source
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken">CancellationToken</param>
|
/// <param name="cancellationToken">CancellationToken</param>
|
||||||
/// <returns>Task with ICaptureElement</returns>
|
/// <returns>Task with ICaptureElement</returns>
|
||||||
ValueTask<ICaptureElement> Import(CancellationToken cancellationToken = default);
|
ValueTask<ICaptureElement<TResult>> Import(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,13 @@ namespace Greenshot.Core.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This defines a template which is applied to a capture, so we can output it to the screen or to disk.
|
/// This defines a template which is applied to a capture, so we can output it to the screen or to disk.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITemplate
|
public interface ITemplate<TContent>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This applies a template, to generate a framework element
|
/// This applies a template, to generate a framework element
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capture">ICapture</param>
|
/// <param name="capture">ICapture</param>
|
||||||
/// <returns>FrameworkElement</returns>
|
/// <returns>FrameworkElement</returns>
|
||||||
FrameworkElement Apply(ICapture capture);
|
FrameworkElement Apply(ICapture<TContent> capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using Dapplo.Windows.Desktop;
|
using Dapplo.Windows.Desktop;
|
||||||
using Greenshot.Core.Configuration;
|
using Greenshot.Core.Configuration;
|
||||||
using Greenshot.Core.Extensions;
|
using Greenshot.Core.Extensions;
|
||||||
|
@ -34,7 +35,7 @@ namespace Greenshot.Core.Sources
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This does the screen capture of a Window via DWM
|
/// This does the screen capture of a Window via DWM
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DwmWindowSource : ISource
|
public class DwmWindowSource : ISource<BitmapSource>
|
||||||
{
|
{
|
||||||
private readonly ICaptureConfiguration _captureConfiguration;
|
private readonly ICaptureConfiguration _captureConfiguration;
|
||||||
private readonly Func<IInteropWindow> _retrieveWindowFunc;
|
private readonly Func<IInteropWindow> _retrieveWindowFunc;
|
||||||
|
@ -45,7 +46,7 @@ namespace Greenshot.Core.Sources
|
||||||
_retrieveWindowFunc = retrieveWindowFunc ?? InteropWindowQuery.GetActiveWindow;
|
_retrieveWindowFunc = retrieveWindowFunc ?? InteropWindowQuery.GetActiveWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<ICaptureElement> Import(CancellationToken cancellationToken = default)
|
public ValueTask<ICaptureElement<BitmapSource>> Import(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var window = _retrieveWindowFunc();
|
var window = _retrieveWindowFunc();
|
||||||
return window.CaptureDwmWindow(_captureConfiguration);
|
return window.CaptureDwmWindow(_captureConfiguration);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using Dapplo.Windows.Icons;
|
using Dapplo.Windows.Icons;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
using Greenshot.Core.Interfaces;
|
using Greenshot.Core.Interfaces;
|
||||||
|
@ -32,21 +33,21 @@ namespace Greenshot.Core.Sources
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A source to capture the mouse cursor
|
/// A source to capture the mouse cursor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MouseSource : ISource
|
public class MouseSource : ISource<BitmapSource>
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ValueTask<ICaptureElement> Import(CancellationToken cancellationToken = default)
|
public ValueTask<ICaptureElement<BitmapSource>> Import(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
ICaptureElement result = null;
|
ICaptureElement<BitmapSource> result = null;
|
||||||
if (CursorHelper.TryGetCurrentCursor(out var bitmapSource, out var location))
|
if (CursorHelper.TryGetCurrentCursor(out var bitmapSource, out var location))
|
||||||
{
|
{
|
||||||
result = new CaptureElement(location, bitmapSource)
|
result = new CaptureElement<BitmapSource>(location, bitmapSource)
|
||||||
{
|
{
|
||||||
ElementType = CaptureElementType.Mouse
|
ElementType = CaptureElementType.Mouse
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ValueTask<ICaptureElement>(result);
|
return new ValueTask<ICaptureElement<BitmapSource>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ using System.Windows;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Dapplo.Log;
|
|
||||||
using Dapplo.Windows.Common;
|
using Dapplo.Windows.Common;
|
||||||
using Dapplo.Windows.Common.Extensions;
|
using Dapplo.Windows.Common.Extensions;
|
||||||
using Dapplo.Windows.Common.Structs;
|
using Dapplo.Windows.Common.Structs;
|
||||||
|
@ -49,14 +48,13 @@ namespace Greenshot.Core.Sources
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This does the screen capture
|
/// This does the screen capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ScreenSource : ISource
|
public class ScreenSource : ISource<BitmapSource>
|
||||||
{
|
{
|
||||||
private static readonly LogSource Log = new LogSource();
|
public ValueTask<ICaptureElement<BitmapSource>> Import(CancellationToken cancellationToken = default)
|
||||||
public ValueTask<ICaptureElement> Import(CancellationToken cancellationToken = default)
|
|
||||||
{
|
{
|
||||||
var screenbounds = DisplayInfo.GetAllScreenBounds();
|
var screenbounds = DisplayInfo.GetAllScreenBounds();
|
||||||
var result = CaptureRectangle(screenbounds);
|
var result = CaptureRectangle(screenbounds);
|
||||||
return new ValueTask<ICaptureElement>(result);
|
return new ValueTask<ICaptureElement<BitmapSource>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -83,9 +81,9 @@ namespace Greenshot.Core.Sources
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="captureBounds">NativeRect</param>
|
/// <param name="captureBounds">NativeRect</param>
|
||||||
/// <returns>ICaptureElement</returns>
|
/// <returns>ICaptureElement</returns>
|
||||||
internal static ICaptureElement CaptureRectangle(NativeRect captureBounds)
|
internal static ICaptureElement<BitmapSource> CaptureRectangle(NativeRect captureBounds)
|
||||||
{
|
{
|
||||||
BitmapSource capturedBitmapSource = null;
|
BitmapSource capturedBitmapSource;
|
||||||
if (captureBounds.IsEmpty)
|
if (captureBounds.IsEmpty)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -183,7 +181,7 @@ namespace Greenshot.Core.Sources
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ICaptureElement result = new CaptureElement(captureBounds.Location, capturedBitmapSource)
|
var result = new CaptureElement<BitmapSource>(captureBounds.Location, capturedBitmapSource)
|
||||||
{
|
{
|
||||||
ElementType = CaptureElementType.Screen
|
ElementType = CaptureElementType.Screen
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
using Greenshot.Core.Interfaces;
|
using Greenshot.Core.Interfaces;
|
||||||
|
@ -33,10 +34,10 @@ namespace Greenshot.Core.Templates
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A template to create a FrameworkElement from a capture, with a crop applied
|
/// A template to create a FrameworkElement from a capture, with a crop applied
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CroppedTemplate : ITemplate
|
public class CroppedTemplate : ITemplate<BitmapSource>
|
||||||
{
|
{
|
||||||
public bool DisplayMouse { get; set; } = true;
|
public bool DisplayMouse { get; set; } = true;
|
||||||
public FrameworkElement Apply(ICapture capture)
|
public FrameworkElement Apply(ICapture<BitmapSource> capture)
|
||||||
{
|
{
|
||||||
var width = (int)(capture.CropRect.Width + 0.5);
|
var width = (int)(capture.CropRect.Width + 0.5);
|
||||||
var height = (int)(capture.CropRect.Height + 0.5);
|
var height = (int)(capture.CropRect.Height + 0.5);
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using Greenshot.Core.Enums;
|
using Greenshot.Core.Enums;
|
||||||
using Greenshot.Core.Interfaces;
|
using Greenshot.Core.Interfaces;
|
||||||
|
|
||||||
|
@ -31,10 +33,10 @@ namespace Greenshot.Core.Templates
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A template to create a FrameworkElement from a capture
|
/// A template to create a FrameworkElement from a capture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimpleTemplate : ITemplate
|
public class SimpleTemplate : ITemplate<BitmapSource>
|
||||||
{
|
{
|
||||||
public bool DisplayMouse { get; set; } = true;
|
public bool DisplayMouse { get; set; } = true;
|
||||||
public FrameworkElement Apply(ICapture capture)
|
public FrameworkElement Apply(ICapture<BitmapSource> capture)
|
||||||
{
|
{
|
||||||
var canvas = new Canvas
|
var canvas = new Canvas
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using Dapplo.CaliburnMicro.Extensions;
|
using Dapplo.CaliburnMicro.Extensions;
|
||||||
using Dapplo.Ini;
|
using Dapplo.Ini;
|
||||||
using Dapplo.Windows.Desktop;
|
using Dapplo.Windows.Desktop;
|
||||||
|
@ -48,7 +49,7 @@ namespace Greenshot.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Test_CaptureFlow_ScreenSource()
|
public async Task Test_CaptureFlow_ScreenSource()
|
||||||
{
|
{
|
||||||
var captureFlow = new CaptureFlow
|
var captureFlow = new CaptureFlow<BitmapSource>
|
||||||
{
|
{
|
||||||
Sources = {new ScreenSource()}
|
Sources = {new ScreenSource()}
|
||||||
};
|
};
|
||||||
|
@ -64,7 +65,7 @@ namespace Greenshot.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Test_CaptureFlow_ScreenSource_MouseSource()
|
public async Task Test_CaptureFlow_ScreenSource_MouseSource()
|
||||||
{
|
{
|
||||||
var captureFlow = new CaptureFlow
|
var captureFlow = new CaptureFlow<BitmapSource>
|
||||||
{
|
{
|
||||||
Sources = { new ScreenSource() , new MouseSource()}
|
Sources = { new ScreenSource() , new MouseSource()}
|
||||||
};
|
};
|
||||||
|
@ -82,16 +83,21 @@ namespace Greenshot.Tests
|
||||||
{
|
{
|
||||||
var iniConfig = new IniConfig("Greenshot.Tests", "Greenshot.Tests");
|
var iniConfig = new IniConfig("Greenshot.Tests", "Greenshot.Tests");
|
||||||
var config = iniConfig.Get<ICoreConfiguration>();
|
var config = iniConfig.Get<ICoreConfiguration>();
|
||||||
var captureFlow = new CaptureFlow
|
|
||||||
|
var windowToCapture = InteropWindowQuery.GetTopLevelWindows().First(window => window.GetCaption().Contains("Notepad"));
|
||||||
|
var bounds = windowToCapture.GetInfo().Bounds;
|
||||||
|
var captureFlow = new CaptureFlow<BitmapSource>
|
||||||
{
|
{
|
||||||
Sources = { new DwmWindowSource(config, () => InteropWindowQuery.GetTopLevelWindows().First(window => window.GetCaption().Contains("Notepad"))) }
|
Sources = { new DwmWindowSource(config, () => windowToCapture) }
|
||||||
};
|
};
|
||||||
var capture = await captureFlow.Execute();
|
var capture = await captureFlow.Execute();
|
||||||
Assert.NotNull(capture);
|
Assert.NotNull(capture);
|
||||||
Assert.NotNull(capture.CaptureElements);
|
Assert.NotNull(capture.CaptureElements);
|
||||||
|
|
||||||
var template = new SimpleTemplate();
|
var template = new SimpleTemplate();
|
||||||
using (var outputStream = template.Apply(capture).ToBitmapSource().ToStream(OutputFormats.png))
|
var bitmapSource = template.Apply(capture).ToBitmapSource();
|
||||||
|
Assert.Equal(bounds.Size, bitmapSource.Size());
|
||||||
|
using (var outputStream = bitmapSource.ToStream(OutputFormats.png))
|
||||||
using (var fileStream = File.Create("Test_CaptureFlow_DwmWindowSource.png"))
|
using (var fileStream = File.Create("Test_CaptureFlow_DwmWindowSource.png"))
|
||||||
{
|
{
|
||||||
outputStream.Seek(0, SeekOrigin.Begin);
|
outputStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue