Added doc comments

This commit is contained in:
Darth Affe 2021-05-24 23:38:06 +02:00
parent e6202d88b5
commit 9bdb07fdc5
11 changed files with 346 additions and 15 deletions

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using ScreenCapture.Events;
using SharpGen.Runtime; using SharpGen.Runtime;
using Vortice.Direct3D; using Vortice.Direct3D;
using Vortice.Direct3D11; using Vortice.Direct3D11;
@ -15,6 +14,10 @@ using Usage = Vortice.Direct3D11.Usage;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
/// Represents a ScreenCapture using DirectX 11 desktop duplicaton.
/// https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/desktop-dup-api
/// </summary>
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public sealed class DX11ScreenCapture : IScreenCapture public sealed class DX11ScreenCapture : IScreenCapture
{ {
@ -36,8 +39,14 @@ namespace ScreenCapture
private int _indexCounter = 0; private int _indexCounter = 0;
/// <inheritdoc />
public Display Display { get; } public Display Display { get; }
/// <summary>
/// Gets or sets the timeout in ms used for screen-capturing. (default 1000ms)
/// This is used in <see cref="CaptureScreen"/> https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgioutputduplication-acquirenextframe
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public int Timeout { get; set; } = 1000; public int Timeout { get; set; } = 1000;
private readonly IDXGIFactory1 _factory; private readonly IDXGIFactory1 _factory;
@ -54,12 +63,18 @@ namespace ScreenCapture
#region Events #region Events
/// <inheritdoc />
public event EventHandler<ScreenCaptureUpdatedEventArgs>? Updated; public event EventHandler<ScreenCaptureUpdatedEventArgs>? Updated;
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="DX11ScreenCapture"/> class.
/// </summary>
/// <param name="factory">The <see cref="IDXGIFactory1"/> used to create underlying objects.</param>
/// <param name="display">The <see cref="Display"/> to duplicate.</param>
public DX11ScreenCapture(IDXGIFactory1 factory, Display display) public DX11ScreenCapture(IDXGIFactory1 factory, Display display)
{ {
this._factory = factory; this._factory = factory;
@ -72,6 +87,7 @@ namespace ScreenCapture
#region Methods #region Methods
/// <inheritdoc />
public bool CaptureScreen() public bool CaptureScreen()
{ {
bool result = false; bool result = false;
@ -171,6 +187,7 @@ namespace ScreenCapture
} }
} }
/// <inheritdoc />
public CaptureZone RegisterCaptureZone(int x, int y, int width, int height, int downscaleLevel = 0) public CaptureZone RegisterCaptureZone(int x, int y, int width, int height, int downscaleLevel = 0)
{ {
if (_device == null) throw new ApplicationException("ScreenCapture isn't initialized."); if (_device == null) throw new ApplicationException("ScreenCapture isn't initialized.");
@ -209,6 +226,7 @@ namespace ScreenCapture
return captureZone; return captureZone;
} }
/// <inheritdoc />
public bool UnregisterCaptureZone(CaptureZone captureZone) public bool UnregisterCaptureZone(CaptureZone captureZone)
{ {
lock (_captureZones) lock (_captureZones)
@ -268,6 +286,7 @@ namespace ScreenCapture
_captureZones[captureZone] = (stagingTexture, scalingTexture, scalingTextureView); _captureZones[captureZone] = (stagingTexture, scalingTexture, scalingTextureView);
} }
/// <inheritdoc />
public void Restart() public void Restart()
{ {
lock (_captureLock) lock (_captureLock)
@ -312,6 +331,7 @@ namespace ScreenCapture
} }
} }
/// <inheritdoc />
public void Dispose() => Dispose(true); public void Dispose() => Dispose(true);
private void Dispose(bool removeCaptureZones) private void Dispose(bool removeCaptureZones)

View File

@ -1,8 +1,12 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using Vortice.DXGI; using Vortice.DXGI;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
///
/// </summary>
public class DX11ScreenCaptureService : IScreenCaptureService public class DX11ScreenCaptureService : IScreenCaptureService
{ {
#region Properties & Fields #region Properties & Fields
@ -15,6 +19,9 @@ namespace ScreenCapture
#region Constructors #region Constructors
/// <summary>
///
/// </summary>
public DX11ScreenCaptureService() public DX11ScreenCaptureService()
{ {
DXGI.CreateDXGIFactory1(out _factory).CheckError(); DXGI.CreateDXGIFactory1(out _factory).CheckError();
@ -24,6 +31,7 @@ namespace ScreenCapture
#region Methods #region Methods
/// <inheritdoc />
public IEnumerable<GraphicsCard> GetGraphicsCards() public IEnumerable<GraphicsCard> GetGraphicsCards()
{ {
int i = 0; int i = 0;
@ -35,6 +43,7 @@ namespace ScreenCapture
} }
} }
/// <inheritdoc />
public IEnumerable<Display> GetDisplays(GraphicsCard graphicsCard) public IEnumerable<Display> GetDisplays(GraphicsCard graphicsCard)
{ {
using IDXGIAdapter1? adapter = _factory.GetAdapter1(graphicsCard.Index); using IDXGIAdapter1? adapter = _factory.GetAdapter1(graphicsCard.Index);
@ -50,6 +59,7 @@ namespace ScreenCapture
} }
} }
/// <inheritdoc />
public IScreenCapture GetScreenCapture(Display display) public IScreenCapture GetScreenCapture(Display display)
{ {
if (!_screenCaptures.TryGetValue(display, out DX11ScreenCapture? screenCapture)) if (!_screenCaptures.TryGetValue(display, out DX11ScreenCapture? screenCapture))
@ -57,6 +67,7 @@ namespace ScreenCapture
return screenCapture; return screenCapture;
} }
/// <inheritdoc />
public void Dispose() public void Dispose()
{ {
foreach (DX11ScreenCapture screenCapture in _screenCaptures.Values) foreach (DX11ScreenCapture screenCapture in _screenCaptures.Values)
@ -64,6 +75,8 @@ namespace ScreenCapture
_screenCaptures.Clear(); _screenCaptures.Clear();
_factory.Dispose(); _factory.Dispose();
GC.SuppressFinalize(this);
} }
#endregion #endregion

View File

@ -1,17 +1,29 @@
using System; // ReSharper disable MemberCanBePrivate.Global
using System;
namespace ScreenCapture.Events namespace ScreenCapture
{ {
/// <inheritdoc />
/// <summary>
/// Represents the information supplied with an <see cref="E:ScreenCapture.IDX11ScreenCapture.Updated" />-event.
/// </summary>
public class ScreenCaptureUpdatedEventArgs : EventArgs public class ScreenCaptureUpdatedEventArgs : EventArgs
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// <c>true</c> if the update was successful; otherwise, <c>false</c>.
/// </summary>
public bool IsSuccessful { get; set; } public bool IsSuccessful { get; set; }
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ScreenCaptureUpdatedEventArgs"/> class.
/// </summary>
/// <param name="isSuccessful">Indicates if the last update was successful.</param>
public ScreenCaptureUpdatedEventArgs(bool isSuccessful) public ScreenCaptureUpdatedEventArgs(bool isSuccessful)
{ {
this.IsSuccessful = isSuccessful; this.IsSuccessful = isSuccessful;

View File

@ -1,8 +1,12 @@
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
// ReSharper disable MemberCanBePrivate.Global
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
/// Helper-class for DPI-related WIN-API calls.
/// </summary>
public static class DPIAwareness public static class DPIAwareness
{ {
[DllImport("user32.dll", SetLastError = true)] [DllImport("user32.dll", SetLastError = true)]
@ -29,9 +33,9 @@ namespace ScreenCapture
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 34 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 34
} }
public static void Initalize() /// <summary>
{ /// Sets the DPI-Awareness-Context to V2. This is needed to prevent issues when using desktop duplication.
SetProcessDpiAwarenessContext((int)DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); /// </summary>
} public static void Initalize() => SetProcessDpiAwarenessContext((int)DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
} }
} }

View File

@ -2,13 +2,48 @@
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
/// Represents the duplication of a single display.
/// </summary>
public interface IScreenCapture : IDisposable public interface IScreenCapture : IDisposable
{ {
/// <summary>
/// Gets the <see cref="Display"/> this capture is duplicating.
/// </summary>
Display Display { get; } Display Display { get; }
/// <summary>
/// Occurs when the <see cref="IScreenCapture"/> is updated.
/// </summary>
event EventHandler<ScreenCaptureUpdatedEventArgs>? Updated;
/// <summary>
/// Attemts to capture the current frame showed on the <see cref="Display"/>.
/// </summary>
/// <returns><c>true</c> if the current frame was captures successfully; otherwise, <c>false</c>.</returns>
bool CaptureScreen(); bool CaptureScreen();
/// <summary>
/// Creates a new <see cref="CaptureScreen"/> for this <see cref="IScreenCapture"/>.
/// </summary>
/// <param name="x">The x-location of the region to capture (must be &gt;= 0 and &lt; screen-width).</param>
/// <param name="y">The x-location of the region to capture (must be &gt;= 0 and &lt; screen-height).</param>
/// <param name="width">The width of the region to capture (must be &gt;= 0 and this + x must be &lt;= screen-width).</param>
/// <param name="height">The height of the region to capture (must be &gt;= 0 and this + y must be &lt;= screen-height).</param>
/// <param name="downscaleLevel">The level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel.</param>
/// <returns>The new <see cref="CaptureScreen"/>.</returns>
CaptureZone RegisterCaptureZone(int x, int y, int width, int height, int downscaleLevel = 0); CaptureZone RegisterCaptureZone(int x, int y, int width, int height, int downscaleLevel = 0);
/// <summary>
/// Removes the given <see cref="CaptureScreen"/> from the <see cref="IScreenCapture"/>.
/// </summary>
/// <param name="captureZone">The previosly registered <see cref="CaptureScreen"/>.</param>
/// <returns><c>true</c> if the <see cref="CaptureScreen"/> was successfully removed; otherwise, <c>false</c>.</returns>
bool UnregisterCaptureZone(CaptureZone captureZone); bool UnregisterCaptureZone(CaptureZone captureZone);
/// <summary>
/// Restarts the <see cref="IScreenCapture"/>.
/// </summary>
void Restart(); void Restart();
} }
} }

View File

@ -3,10 +3,29 @@ using System.Collections.Generic;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
///
/// </summary>
public interface IScreenCaptureService : IDisposable public interface IScreenCaptureService : IDisposable
{ {
/// <summary>
/// Gets a enumerable of all available graphics-cards.
/// </summary>
/// <returns>A enumerable of all available graphics-cards.</returns>
IEnumerable<GraphicsCard> GetGraphicsCards(); IEnumerable<GraphicsCard> GetGraphicsCards();
/// <summary>
/// Gets a enumerable of all display connected to the given graphics-cards.
/// </summary>
/// <param name="graphicsCard">The graphics-card to get the displays from.</param>
/// <returns>A enumerable of all display connected to the given graphics-cards.</returns>
IEnumerable<Display> GetDisplays(GraphicsCard graphicsCard); IEnumerable<Display> GetDisplays(GraphicsCard graphicsCard);
/// <summary>
/// Creates a <see cref="IScreenCapture"/> for the given display.
/// </summary>
/// <param name="display">The display to duplicate.</param>
/// <returns>The <see cref="IScreenCapture"/> for the give display.</returns>
IScreenCapture GetScreenCapture(Display display); IScreenCapture GetScreenCapture(Display display);
} }
} }

View File

@ -1,7 +1,11 @@
using System; // ReSharper disable MemberCanBePrivate.Global
using System;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
/// Represents the configuration for the detection and removal of black bars around the screen image.
/// </summary>
public sealed class BlackBarDetection public sealed class BlackBarDetection
{ {
#region Properties & Fields #region Properties & Fields
@ -9,18 +13,33 @@ namespace ScreenCapture
private readonly CaptureZone _captureZone; private readonly CaptureZone _captureZone;
private int? _top; private int? _top;
/// <summary>
/// Gets the size of the detected black bar at the top of the image.
/// </summary>
public int Top => _top ??= CalculateTop(); public int Top => _top ??= CalculateTop();
private int? _bottom; private int? _bottom;
/// <summary>
/// Gets the size of the detected black bar at the bottom of the image.
/// </summary>
public int Bottom => _bottom ??= CalculateBottom(); public int Bottom => _bottom ??= CalculateBottom();
private int? _left; private int? _left;
/// <summary>
/// Gets the size of the detected black bar at the left of the image.
/// </summary>
public int Left => _left ??= CalculateLeft(); public int Left => _left ??= CalculateLeft();
private int? _right; private int? _right;
/// <summary>
/// Gets the size of the detected black bar at the right of the image.
/// </summary>
public int Right => _right ??= CalculateRight(); public int Right => _right ??= CalculateRight();
private int _theshold = 0; private int _theshold = 0;
/// <summary>
/// Gets or sets the threshold of "blackness" used to detect black bars. (e. g. Threshold 5 will consider a pixel of color [5,5,5] as black.) (default 0)
/// </summary>
public int Threshold public int Threshold
{ {
get => _theshold; get => _theshold;
@ -35,7 +54,7 @@ namespace ScreenCapture
#region Constructors #region Constructors
public BlackBarDetection(CaptureZone captureZone) internal BlackBarDetection(CaptureZone captureZone)
{ {
this._captureZone = captureZone; this._captureZone = captureZone;
} }
@ -44,6 +63,9 @@ namespace ScreenCapture
#region Methods #region Methods
/// <summary>
/// Invalidates the cached values and recalculates <see cref="Top"/>, <see cref="Bottom"/>, <see cref="Left"/> and <see cref="Right"/>.
/// </summary>
public void InvalidateCache() public void InvalidateCache()
{ {
_top = null; _top = null;

View File

@ -1,45 +1,126 @@
using System; // ReSharper disable MemberCanBePrivate.Global
using System;
namespace ScreenCapture namespace ScreenCapture
{ {
/// <summary>
/// Represents a duplicated region on the screen.
/// </summary>
public sealed class CaptureZone public sealed class CaptureZone
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the unique id of this <see cref="CaptureZone"/>.
/// </summary>
public int Id { get; } public int Id { get; }
/// <summary>
/// Gets the x-location of the region on the screen.
/// </summary>
public int X { get; } public int X { get; }
/// <summary>
/// Gets the y-location of the region on the screen.
/// </summary>
public int Y { get; } public int Y { get; }
/// <summary>
/// Gets the width of the region on the screen.
/// </summary>
public int Width { get; } public int Width { get; }
/// <summary>
/// Gets the height of the region on the screen.
/// </summary>
public int Height { get; } public int Height { get; }
/// <summary>
/// Gets the level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel.
/// </summary>
public int DownscaleLevel { get; } public int DownscaleLevel { get; }
/// <summary>
/// Gets the original width of the region (this equals <see cref="Width"/> if <see cref="DownscaleLevel"/> is 0).
/// </summary>
public int UnscaledWidth { get; } public int UnscaledWidth { get; }
/// <summary>
/// Gets the original height of the region (this equals <see cref="Height"/> if <see cref="DownscaleLevel"/> is 0).
/// </summary>
public int UnscaledHeight { get; } public int UnscaledHeight { get; }
/// <summary>
/// Gets the actually captured width of the region (this can be greated than <see cref="Width"/> due to size-constraints on the GPU).
/// </summary>
public int CaptureWidth { get; } public int CaptureWidth { get; }
/// <summary>
/// Gets the actually captured height of the region (this can be greated than <see cref="Height"/> due to size-constraints on the GPU).
/// </summary>
public int CaptureHeight { get; } public int CaptureHeight { get; }
/// <summary>
/// Gets the width of the buffer the capture is saved to.
/// Equals <see cref="CaptureWidth"/> most of the time but can be bigger.
/// </summary>
public int BufferWidth { get; } public int BufferWidth { get; }
/// <summary>
/// Gets the height of the buffer the capture is saved to.
/// Equals <see cref="CaptureHeight"/> most of the time but can be bigger.
/// </summary>
public int BufferHeight { get; } public int BufferHeight { get; }
/// <summary>
/// Gets the buffer containing the image data. Format depends on the specific capture but is most likely BGRA32.
/// </summary>
public byte[] Buffer { get; } public byte[] Buffer { get; }
/// <summary>
/// Gets the config for black-bar detection.
/// </summary>
public BlackBarDetection BlackBars { get; } public BlackBarDetection BlackBars { get; }
/// <summary>
/// Gets or sets if the <see cref="CaptureZone"/> should be automatically updated on every captured frame.
/// </summary>
public bool AutoUpdate { get; set; } = true; public bool AutoUpdate { get; set; } = true;
/// <summary>
/// Gets if an update for the <see cref="CaptureZone"/> is requested on the next captured frame.
/// </summary>
public bool IsUpdateRequested { get; private set; } public bool IsUpdateRequested { get; private set; }
#endregion #endregion
#region Events #region Events
/// <summary>
/// Occurs when the <see cref="CaptureZone"/> is updated.
/// </summary>
public event EventHandler? Updated; public event EventHandler? Updated;
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="CaptureZone"/> class.
/// </summary>
/// <param name="id">The unique id of this <see cref="CaptureZone"/>.</param>
/// <param name="x">The x-location of the region on the screen.</param>
/// <param name="y">The y-location of the region on the screen.</param>
/// <param name="width">The width of the region on the screen.</param>
/// <param name="height">The height of the region on the screen.</param>
/// <param name="downscaleLevel">The level of downscaling applied to the image of this region before copying to local memory.</param>
/// <param name="unscaledWidth">The original width of the region.</param>
/// <param name="unscaledHeight">The original height of the region</param>
/// <param name="captureWidth">The actually captured width of the region.</param>
/// <param name="captureHeight">The actually captured height of the region.</param>
/// <param name="bufferWidth">The width of the buffer the capture is saved to.</param>
/// <param name="bufferHeight">The height of the buffer the capture is saved to.</param>
/// <param name="buffer">The buffer containing the image data.</param>
public CaptureZone(int id, int x, int y, int width, int height, int downscaleLevel, int unscaledWidth, int unscaledHeight, int captureWidth, int captureHeight, int bufferWidth, int bufferHeight, byte[] buffer) public CaptureZone(int id, int x, int y, int width, int height, int downscaleLevel, int unscaledWidth, int unscaledHeight, int captureWidth, int captureHeight, int bufferWidth, int bufferHeight, byte[] buffer)
{ {
this.Id = id; this.Id = id;
@ -63,8 +144,16 @@ namespace ScreenCapture
#region Methods #region Methods
/// <summary>
/// Requests to update this <see cref="CaptureZone"/> when the next frame is captured.
/// Only necessary if <see cref="AutoUpdate"/> is set to <c>false</c>.
/// </summary>
public void RequestUpdate() => IsUpdateRequested = true; public void RequestUpdate() => IsUpdateRequested = true;
/// <summary>
/// Marks the <see cref="CaptureZone"/> as updated.
/// WARNING: This should not be called outside of an <see cref="IScreenCapture"/>!
/// </summary>
public void SetUpdated() public void SetUpdated()
{ {
IsUpdateRequested = false; IsUpdateRequested = false;
@ -73,10 +162,19 @@ namespace ScreenCapture
Updated?.Invoke(this, new EventArgs()); Updated?.Invoke(this, new EventArgs());
} }
public override int GetHashCode() => Id; /// <summary>
/// Determines whether this <see cref="CaptureZone"/> equals the given one.
/// </summary>
/// <param name="other">The <see cref="CaptureZone"/> to compare.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
public bool Equals(CaptureZone other) => Id == other.Id; public bool Equals(CaptureZone other) => Id == other.Id;
/// <inheritdoc />
public override bool Equals(object? obj) => obj is CaptureZone other && Equals(other); public override bool Equals(object? obj) => obj is CaptureZone other && Equals(other);
/// <inheritdoc />
public override int GetHashCode() => Id;
#endregion #endregion
} }
} }

View File

@ -1,21 +1,51 @@
namespace ScreenCapture // ReSharper disable MemberCanBePrivate.Global
namespace ScreenCapture
{ {
/// <summary>
/// Represents a display connected to graphics-card.
/// </summary>
public readonly struct Display public readonly struct Display
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the index of the <see cref="Display"/>.
/// </summary>
public int Index { get; } public int Index { get; }
/// <summary>
/// Gets the name of the <see cref="Display"/>.
/// </summary>
public string DeviceName { get; } public string DeviceName { get; }
/// <summary>
/// Gets the with of the <see cref="Display"/>.
/// </summary>
public int Width { get; } public int Width { get; }
/// <summary>
/// Gets the height of the <see cref="Display"/>.
/// </summary>
public int Height { get; } public int Height { get; }
/// <summary>
/// Gets the <see cref="GraphicsCard"/> this <see cref="Display"/> is connected to.
/// </summary>
public GraphicsCard GraphicsCard { get; } public GraphicsCard GraphicsCard { get; }
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Display"/> struct.
/// </summary>
/// <param name="index">The index of the <see cref="Display"/>.</param>
/// <param name="deviceName">The name of the <see cref="Display"/>.</param>
/// <param name="width">The with of the <see cref="Display"/>.</param>
/// <param name="height">The height of the <see cref="Display"/>.</param>
/// <param name="graphicsCard">The <see cref="GraphicsCard"/> this <see cref="Display"/> is connected to.</param>
public Display(int index, string deviceName, int width, int height, GraphicsCard graphicsCard) public Display(int index, string deviceName, int width, int height, GraphicsCard graphicsCard)
{ {
this.Index = index; this.Index = index;
@ -28,11 +58,36 @@
#endregion #endregion
#region Methods #region Methods
/// <summary>
/// Determines whether this <see cref="Display"/> equals the given one.
/// </summary>
/// <param name="other">The <see cref="Display"/> to compare.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
public bool Equals(Display other) => Index == other.Index; public bool Equals(Display other) => Index == other.Index;
/// <inheritdoc />
public override bool Equals(object? obj) => obj is Display other && Equals(other); public override bool Equals(object? obj) => obj is Display other && Equals(other);
/// <inheritdoc />
public override int GetHashCode() => Index; public override int GetHashCode() => Index;
/// <summary>
/// Determines whether two <see cref="Display"/> are equal.
/// </summary>
/// <param name="left">The first value.</param>
/// <param name="right">The second value.</param>
/// <returns><c>true</c> if the two specified displays are equal; otherwise, <c>false</c>.</returns>
public static bool operator ==(Display left, Display right) => left.Equals(right);
/// <summary>
/// Determines whether two <see cref="Display"/> are not equal.
/// </summary>
/// <param name="left">The first value.</param>
/// <param name="right">The second value.</param>
/// <returns><c>true</c> if the two specified displays are not equal; otherwise, <c>false</c>.</returns>
public static bool operator !=(Display left, Display right) => !(left == right);
#endregion #endregion
} }
} }

View File

@ -1,18 +1,45 @@
namespace ScreenCapture // ReSharper disable MemberCanBePrivate.Global
namespace ScreenCapture
{ {
/// <summary>
/// Represents a graphics-card.
/// </summary>
public readonly struct GraphicsCard public readonly struct GraphicsCard
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the index of the <see cref="GraphicsCard"/>.
/// </summary>
public int Index { get; } public int Index { get; }
/// <summary>
/// Gets the name of the <see cref="GraphicsCard"/>.
/// </summary>
public string Name { get; } public string Name { get; }
/// <summary>
/// Gets the vendor-id of the <see cref="GraphicsCard"/>.
/// </summary>
public int VendorId { get; } public int VendorId { get; }
/// <summary>
/// Gets the device-id of the <see cref="GraphicsCard"/>.
/// </summary>
public int DeviceId { get; } public int DeviceId { get; }
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="GraphicsCard"/> struct.
/// </summary>
/// <param name="index">The index of the <see cref="GraphicsCard"/>.</param>
/// <param name="name">The name of the <see cref="GraphicsCard"/>.</param>
/// <param name="vendorId">The vendor-id of the <see cref="GraphicsCard"/>.</param>
/// <param name="deviceId">The device-id of the <see cref="GraphicsCard"/>.</param>
public GraphicsCard(int index, string name, int vendorId, int deviceId) public GraphicsCard(int index, string name, int vendorId, int deviceId)
{ {
this.Index = index; this.Index = index;
@ -25,10 +52,35 @@
#region Methods #region Methods
/// <summary>
/// Determines whether this <see cref="Display"/> equals the given one.
/// </summary>
/// <param name="other">The <see cref="Display"/> to compare.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, <c>false</c>.</returns>
public bool Equals(GraphicsCard other) => Index == other.Index; public bool Equals(GraphicsCard other) => Index == other.Index;
/// <inheritdoc />
public override bool Equals(object? obj) => obj is GraphicsCard other && Equals(other); public override bool Equals(object? obj) => obj is GraphicsCard other && Equals(other);
/// <inheritdoc />
public override int GetHashCode() => Index; public override int GetHashCode() => Index;
/// <summary>
/// Determines whether two <see cref="GraphicsCard"/> are equal.
/// </summary>
/// <param name="left">The first value.</param>
/// <param name="right">The second value.</param>
/// <returns><c>true</c> if the two specified graphics-cards are equal; otherwise, <c>false</c>.</returns>
public static bool operator ==(GraphicsCard left, GraphicsCard right) => left.Equals(right);
/// <summary>
/// Determines whether two <see cref="GraphicsCard"/> are not equal.
/// </summary>
/// <param name="left">The first value.</param>
/// <param name="right">The second value.</param>
/// <returns><c>true</c> if the two specified graphics-cards are not equal; otherwise, <c>false</c>.</returns>
public static bool operator !=(GraphicsCard left, GraphicsCard right) => !(left == right);
#endregion #endregion
} }
} }

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=directx/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=directx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=model/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=model/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>