Small changes to make the code more generic, so it's better possible to migrate.

This commit is contained in:
Robin 2018-08-21 17:23:26 +02:00
commit d8b58b1538
17 changed files with 119 additions and 66 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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