2017-11-27 12:18:01 -05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.ComponentModel.Design.Serialization;
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Runtime.InteropServices;
|
2022-01-05 12:53:54 -05:00
|
|
|
|
#pragma warning disable IDE1006 // Naming Styles
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
namespace Vanara.PInvoke
|
|
|
|
|
{
|
|
|
|
|
/// <summary>Defines the coordinates of the upper-left and lower-right corners of a rectangle.</summary>
|
|
|
|
|
/// <remarks>
|
2018-11-19 23:18:50 -05:00
|
|
|
|
/// By convention, the right and bottom edges of the rectangle are normally considered exclusive. In other words, the pixel whose
|
|
|
|
|
/// coordinates are ( right, bottom ) lies immediately outside of the rectangle. For example, when RECT is passed to the FillRect
|
|
|
|
|
/// function, the rectangle is filled up to, but not including, the right column and bottom row of pixels. This structure is identical to
|
|
|
|
|
/// the RECT structure.
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// </remarks>
|
|
|
|
|
[StructLayout(LayoutKind.Sequential), TypeConverter(typeof(RECTConverter))]
|
|
|
|
|
public struct RECT : IEquatable<PRECT>, IEquatable<RECT>, IEquatable<Rectangle>
|
|
|
|
|
{
|
|
|
|
|
/// <summary>The x-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int left;
|
|
|
|
|
|
|
|
|
|
/// <summary>The y-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int top;
|
|
|
|
|
|
2022-01-14 09:32:51 -05:00
|
|
|
|
/// <summary>The x-coordinate of the lower-right corner of the rectangle.</summary>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
public int right;
|
|
|
|
|
|
2022-01-14 09:32:51 -05:00
|
|
|
|
/// <summary>The y-coordinate of the lower-right corner of the rectangle.</summary>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
public int bottom;
|
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="RECT"/> struct.</summary>
|
|
|
|
|
/// <param name="left">The left.</param>
|
|
|
|
|
/// <param name="top">The top.</param>
|
|
|
|
|
/// <param name="right">The right.</param>
|
|
|
|
|
/// <param name="bottom">The bottom.</param>
|
|
|
|
|
public RECT(int left, int top, int right, int bottom)
|
|
|
|
|
{
|
|
|
|
|
this.left = left;
|
|
|
|
|
this.top = top;
|
|
|
|
|
this.right = right;
|
|
|
|
|
this.bottom = bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="RECT"/> struct.</summary>
|
|
|
|
|
/// <param name="r">The rectangle.</param>
|
|
|
|
|
public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-14 09:32:51 -05:00
|
|
|
|
/// <summary>The x-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int Left { get => left; set => left = value; }
|
|
|
|
|
|
|
|
|
|
/// <summary>The x-coordinate of the lower-right corner of the rectangle.</summary>
|
|
|
|
|
public int Right { get => right; set => right = value; }
|
|
|
|
|
|
|
|
|
|
/// <summary>The y-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int Top { get => top; set => top = value; }
|
|
|
|
|
|
|
|
|
|
/// <summary>The y-coordinate of the lower-right corner of the rectangle.</summary>
|
|
|
|
|
public int Bottom { get => bottom; set => bottom = value; }
|
|
|
|
|
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <summary>Gets or sets the x-coordinate of the upper-left corner of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>The x-coordinate of the upper-left corner of this <see cref="RECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int X
|
|
|
|
|
{
|
|
|
|
|
get => left;
|
|
|
|
|
set
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
right -= left - value;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
left = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the y-coordinate of the upper-left corner of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>The y-coordinate of the upper-left corner of this <see cref="RECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Y
|
|
|
|
|
{
|
|
|
|
|
get => top;
|
|
|
|
|
set
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
bottom -= top - value;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
top = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the height of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>The height of this <see cref="RECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Height
|
|
|
|
|
{
|
|
|
|
|
get => bottom - top;
|
|
|
|
|
set => bottom = value + top;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the width of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>The width of this <see cref="RECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Width
|
|
|
|
|
{
|
|
|
|
|
get => right - left;
|
|
|
|
|
set => right = value + left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the coordinates of the upper-left corner of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>A Point that represents the upper-left corner of this <see cref="RECT"/> structure.</value>
|
2022-01-06 20:15:15 -05:00
|
|
|
|
public POINT Location
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
get => new(left, top);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
X = value.X;
|
|
|
|
|
Y = value.Y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the size of this <see cref="RECT"/> structure.</summary>
|
|
|
|
|
/// <value>A Size that represents the width and height of this <see cref="RECT"/> structure.</value>
|
2023-01-16 14:13:58 -05:00
|
|
|
|
public SIZE Size
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
get => new(Width, Height);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
Width = value.Width;
|
|
|
|
|
Height = value.Height;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Tests whether all numeric properties of this <see cref="RECT"/> have values of zero.</summary>
|
|
|
|
|
/// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
|
|
|
|
|
public bool IsEmpty => left == 0 && top == 0 && right == 0 && bottom == 0;
|
|
|
|
|
|
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="RECT"/> to <see cref="Rectangle"/>.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="RECT"/> structure.</param>
|
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
public static implicit operator Rectangle(RECT r) => new(r.left, r.top, r.Width, r.Height);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="Rectangle"/> to <see cref="RECT"/>.</summary>
|
|
|
|
|
/// <param name="r">The Rectangle structure.</param>
|
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
public static implicit operator RECT(Rectangle r) => new(r);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Tests whether two <see cref="RECT"/> structures have equal values.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r1">The first <see cref="RECT"/> structure.</param>
|
|
|
|
|
/// <param name="r2">The second <see cref="RECT"/> structure.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the operator.</returns>
|
|
|
|
|
public static bool operator ==(RECT r1, RECT r2) => r1.Equals(r2);
|
|
|
|
|
|
|
|
|
|
/// <summary>Tests whether two <see cref="RECT"/> structures have different values.</summary>
|
|
|
|
|
/// <param name="r1">The first <see cref="RECT"/> structure.</param>
|
|
|
|
|
/// <param name="r2">The second <see cref="RECT"/> structure.</param>
|
|
|
|
|
/// <returns>The result of the operator.</returns>
|
|
|
|
|
public static bool operator !=(RECT r1, RECT r2) => !r1.Equals(r2);
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="RECT"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="RECT"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="RECT"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public bool Equals(RECT r) => r.left == left && r.top == top && r.right == right && r.bottom == bottom;
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="PRECT"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="PRECT"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="PRECT"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
public bool Equals(PRECT r) => r is not null && Equals(r.rect);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="Rectangle"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="Rectangle"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="Rectangle"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public bool Equals(Rectangle r) => r.Left == left && r.Top == top && r.Right == right && r.Bottom == bottom;
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="object"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
public override bool Equals(object obj) => obj switch
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
null => false,
|
|
|
|
|
RECT r => Equals(r),
|
|
|
|
|
PRECT r => Equals(r),
|
|
|
|
|
Rectangle r => Equals(r),
|
|
|
|
|
_ => false,
|
|
|
|
|
};
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Returns a hash code for this instance.</summary>
|
|
|
|
|
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
|
|
|
|
public override int GetHashCode() => ((Rectangle)this).GetHashCode();
|
|
|
|
|
|
|
|
|
|
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
|
|
|
|
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
|
|
|
|
public override string ToString() => $"{{left={left},top={top},right={right},bottom={bottom}}}";
|
2019-10-01 19:51:05 -04:00
|
|
|
|
|
|
|
|
|
/// <summary>Represents an empty instance where all values are set to 0.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
public static readonly RECT Empty = new();
|
2017-11-27 12:18:01 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Defines the coordinates of the upper-left and lower-right corners of a rectangle.</summary>
|
|
|
|
|
/// <remarks>
|
2018-11-19 23:18:50 -05:00
|
|
|
|
/// By convention, the right and bottom edges of the rectangle are normally considered exclusive. In other words, the pixel whose
|
|
|
|
|
/// coordinates are ( right, bottom ) lies immediately outside of the rectangle. For example, when RECT is passed to the FillRect
|
|
|
|
|
/// function, the rectangle is filled up to, but not including, the right column and bottom row of pixels. This structure is identical to
|
|
|
|
|
/// the RECT structure.
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// </remarks>
|
|
|
|
|
[StructLayout(LayoutKind.Sequential), TypeConverter(typeof(PRECTConverter))]
|
|
|
|
|
public class PRECT : IEquatable<PRECT>, IEquatable<RECT>, IEquatable<Rectangle>
|
|
|
|
|
{
|
|
|
|
|
internal RECT rect;
|
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PRECT"/> class with all values set to 0.</summary>
|
|
|
|
|
public PRECT()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PRECT"/> class.</summary>
|
|
|
|
|
/// <param name="left">The left.</param>
|
|
|
|
|
/// <param name="top">The top.</param>
|
|
|
|
|
/// <param name="right">The right.</param>
|
|
|
|
|
/// <param name="bottom">The bottom.</param>
|
2018-11-19 23:18:50 -05:00
|
|
|
|
public PRECT(int left, int top, int right, int bottom) => rect = new RECT(left, top, right, bottom);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PRECT"/> class.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="Rectangle"/> structure.</param>
|
2018-11-19 23:18:50 -05:00
|
|
|
|
public PRECT(Rectangle r) => rect = new RECT(r);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="PRECT"/> class.</summary>
|
|
|
|
|
/// <param name="r">The r.</param>
|
|
|
|
|
[ExcludeFromCodeCoverage]
|
2018-11-19 23:18:50 -05:00
|
|
|
|
private PRECT(RECT r) => rect = r;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>The x-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int left
|
|
|
|
|
{
|
|
|
|
|
get => rect.left;
|
|
|
|
|
set => rect.left = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>The y-coordinate of the upper-left corner of the rectangle.</summary>
|
|
|
|
|
public int top
|
|
|
|
|
{
|
|
|
|
|
get => rect.top;
|
|
|
|
|
set => rect.top = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>he x-coordinate of the lower-right corner of the rectangle.</summary>
|
|
|
|
|
public int right
|
|
|
|
|
{
|
|
|
|
|
get => rect.right;
|
|
|
|
|
set => rect.right = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>he y-coordinate of the lower-right corner of the rectangle.</summary>
|
|
|
|
|
public int bottom
|
|
|
|
|
{
|
|
|
|
|
get => rect.bottom;
|
|
|
|
|
set => rect.bottom = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the x-coordinate of the upper-left corner of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>The x-coordinate of the upper-left corner of this <see cref="PRECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int X
|
|
|
|
|
{
|
|
|
|
|
get => rect.X;
|
|
|
|
|
set => rect.X = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the y-coordinate of the upper-left corner of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>The y-coordinate of the upper-left corner of this <see cref="PRECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Y
|
|
|
|
|
{
|
|
|
|
|
get => rect.Y;
|
|
|
|
|
set => rect.Y = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the height of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>The height of this <see cref="PRECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Height
|
|
|
|
|
{
|
|
|
|
|
get => rect.Height;
|
|
|
|
|
set => rect.Height = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the width of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>The width of this <see cref="PRECT"/> structure. The default is 0.</value>
|
|
|
|
|
public int Width
|
|
|
|
|
{
|
|
|
|
|
get => rect.Width;
|
|
|
|
|
set => rect.Width = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the coordinates of the upper-left corner of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>A Point that represents the upper-left corner of this <see cref="PRECT"/> structure.</value>
|
2022-01-06 20:15:15 -05:00
|
|
|
|
public POINT Location
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
|
|
|
|
get => rect.Location;
|
|
|
|
|
set => rect.Location = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets or sets the size of this <see cref="PRECT"/> structure.</summary>
|
|
|
|
|
/// <value>A Size that represents the width and height of this <see cref="PRECT"/> structure.</value>
|
2023-01-16 14:13:58 -05:00
|
|
|
|
public SIZE Size
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
|
|
|
|
get => rect.Size;
|
|
|
|
|
set => rect.Size = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Tests whether all numeric properties of this <see cref="RECT"/> have values of zero.</summary>
|
|
|
|
|
/// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
|
|
|
|
|
public bool IsEmpty => rect.IsEmpty;
|
|
|
|
|
|
2023-01-16 14:13:58 -05:00
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="PRECT"/> to <see cref="RECT"/>.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="PRECT"/> to convert.</param>
|
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
|
|
|
|
public static implicit operator RECT?(PRECT r) => r?.rect;
|
|
|
|
|
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="PRECT"/> to <see cref="Rectangle"/>.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r">The <see cref="PRECT"/> to convert.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
2023-01-16 14:13:58 -05:00
|
|
|
|
public static implicit operator Rectangle?(PRECT r) => r?.rect;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="System.Nullable{Rectangle}"/> to <see cref="PRECT"/>.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r">The <see cref="Rectangle"/> to convert.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
|
|
|
|
public static implicit operator PRECT(Rectangle? r) => r.HasValue ? new PRECT(r.Value) : null;
|
|
|
|
|
|
2023-01-16 14:13:58 -05:00
|
|
|
|
/// <summary>Performs an implicit conversion from <see cref="System.Nullable{RECT}"/> to <see cref="PRECT"/>.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r">The <see cref="RECT"/> to convert.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the conversion.</returns>
|
2023-01-16 14:13:58 -05:00
|
|
|
|
public static implicit operator PRECT(RECT? r) => r.HasValue ? new PRECT(r.Value) : null;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>Implements the operator ==.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r1">The first <see cref="PRECT"/> structure.</param>
|
|
|
|
|
/// <param name="r2">The second <see cref="PRECT"/> structure.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the operator.</returns>
|
|
|
|
|
public static bool operator ==(PRECT r1, PRECT r2)
|
|
|
|
|
{
|
|
|
|
|
if (ReferenceEquals(r1, r2))
|
|
|
|
|
return true;
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (r1 is null || r2 is null)
|
2017-11-27 12:18:01 -05:00
|
|
|
|
return false;
|
|
|
|
|
return r1.Equals(r2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Implements the operator !=.</summary>
|
2022-01-05 12:53:54 -05:00
|
|
|
|
/// <param name="r1">The first <see cref="PRECT"/> structure.</param>
|
|
|
|
|
/// <param name="r2">The second <see cref="PRECT"/> structure.</param>
|
2017-11-27 12:18:01 -05:00
|
|
|
|
/// <returns>The result of the operator.</returns>
|
|
|
|
|
public static bool operator !=(PRECT r1, PRECT r2) => !(r1 == r2);
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="PRECT"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="PRECT"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="PRECT"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public bool Equals(PRECT r) => rect == r?.rect;
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="RECT"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="RECT"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="RECT"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public bool Equals(RECT r) => rect.Equals(r);
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="Rectangle"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="r">The <see cref="Rectangle"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="Rectangle"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public bool Equals(Rectangle r) => rect.Equals(r);
|
|
|
|
|
|
|
|
|
|
/// <summary>Determines whether the specified <see cref="object"/>, is equal to this instance.</summary>
|
|
|
|
|
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
|
|
|
|
|
/// <returns><c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
|
|
|
|
public override bool Equals(object obj) => rect.Equals(obj);
|
|
|
|
|
|
|
|
|
|
/// <summary>Returns a hash code for this instance.</summary>
|
|
|
|
|
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
|
|
|
|
public override int GetHashCode() => rect.GetHashCode();
|
|
|
|
|
|
|
|
|
|
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
|
|
|
|
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
|
|
|
|
public override string ToString() => rect.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-19 23:18:50 -05:00
|
|
|
|
internal class PRECTConverter : RECTConverter
|
|
|
|
|
{
|
|
|
|
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
|
|
|
|
{
|
|
|
|
|
var b = base.ConvertFrom(context, culture, value);
|
2022-01-05 12:53:54 -05:00
|
|
|
|
return b is RECT r ? new PRECT(r) : b;
|
2018-11-19 23:18:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (value is PRECT prect && destinationType == typeof(InstanceDescriptor))
|
2018-11-19 23:18:50 -05:00
|
|
|
|
{
|
|
|
|
|
var ctor = typeof(PRECT).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int) });
|
|
|
|
|
return new InstanceDescriptor(ctor, new object[] { prect.left, prect.top, prect.right, prect.bottom });
|
|
|
|
|
}
|
2022-01-05 12:53:54 -05:00
|
|
|
|
return base.ConvertTo(context, culture, value, destinationType);
|
2018-11-19 23:18:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (propertyValues is null)
|
2018-11-19 23:18:50 -05:00
|
|
|
|
throw new ArgumentNullException(nameof(propertyValues));
|
|
|
|
|
|
|
|
|
|
var left = propertyValues["left"] ?? 0;
|
|
|
|
|
var top = propertyValues["top"] ?? 0;
|
|
|
|
|
var right = propertyValues["right"] ?? 0;
|
|
|
|
|
var bottom = propertyValues["bottom"] ?? 0;
|
|
|
|
|
|
2022-01-05 12:53:54 -05:00
|
|
|
|
return left is int l && top is int t && right is int r && bottom is int b ? new PRECT(l, t, r, b) :
|
2018-11-19 23:18:50 -05:00
|
|
|
|
throw new ArgumentException(@"Invalid property value.");
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 11:06:09 -04:00
|
|
|
|
#if NET6_0_OR_GREATER
|
|
|
|
|
[RequiresUnreferencedCode(null)]
|
|
|
|
|
#endif
|
2018-11-19 23:18:50 -05:00
|
|
|
|
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
|
|
|
|
|
{
|
|
|
|
|
var props = TypeDescriptor.GetProperties(typeof(PRECT), attributes);
|
|
|
|
|
return props.Sort(new[] { "left", "top", "right", "bottom" });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-27 12:18:01 -05:00
|
|
|
|
internal class RECTConverter : TypeConverter
|
|
|
|
|
{
|
|
|
|
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) =>
|
|
|
|
|
sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
|
|
|
|
|
|
|
|
|
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) =>
|
|
|
|
|
destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
|
|
|
|
|
|
|
|
|
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (value is string strValue)
|
|
|
|
|
{
|
|
|
|
|
var text = strValue.Trim();
|
|
|
|
|
if (text.Length == 0)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
culture ??= CultureInfo.CurrentCulture;
|
|
|
|
|
var tokens = text.Split(culture.TextInfo.ListSeparator[0]);
|
|
|
|
|
if (tokens.Length == 4)
|
|
|
|
|
{
|
|
|
|
|
var intConverter = TypeDescriptor.GetConverter(typeof(int));
|
|
|
|
|
var values = Array.ConvertAll(tokens, i => (int)intConverter.ConvertFromString(context, culture, i));
|
|
|
|
|
return new RECT(values[0], values[1], values[2], values[3]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-27 12:18:01 -05:00
|
|
|
|
return base.ConvertFrom(context, culture, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (destinationType is null)
|
2017-11-27 12:18:01 -05:00
|
|
|
|
throw new ArgumentNullException(nameof(destinationType));
|
|
|
|
|
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (value is not RECT rect)
|
2017-11-27 12:18:01 -05:00
|
|
|
|
return base.ConvertTo(context, culture, value, destinationType);
|
|
|
|
|
|
2022-01-05 12:53:54 -05:00
|
|
|
|
culture ??= CultureInfo.CurrentCulture;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
|
|
|
|
if (destinationType == typeof(string))
|
|
|
|
|
return IntConvertToString(context, culture, rect);
|
|
|
|
|
|
|
|
|
|
if (destinationType == typeof(InstanceDescriptor))
|
|
|
|
|
{
|
|
|
|
|
var ctor = typeof(RECT).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int) });
|
2022-01-05 12:53:54 -05:00
|
|
|
|
return new InstanceDescriptor(ctor, new[] { rect.left, rect.top, rect.right, rect.bottom });
|
2017-11-27 12:18:01 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return base.ConvertTo(context, culture, value, destinationType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
|
|
|
|
|
{
|
2022-01-05 12:53:54 -05:00
|
|
|
|
if (propertyValues is null)
|
2017-11-27 12:18:01 -05:00
|
|
|
|
throw new ArgumentNullException(nameof(propertyValues));
|
|
|
|
|
|
2022-01-05 12:53:54 -05:00
|
|
|
|
var left = propertyValues["left"];
|
|
|
|
|
var top = propertyValues["top"];
|
|
|
|
|
var right = propertyValues["right"];
|
|
|
|
|
var bottom = propertyValues["bottom"];
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
2022-01-05 12:53:54 -05:00
|
|
|
|
return left is int l && top is int t && right is int r && bottom is int b ? new RECT(l, t, r, b) :
|
2017-11-27 12:18:01 -05:00
|
|
|
|
throw new ArgumentException(@"Invalid property value.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) => true;
|
|
|
|
|
|
2022-10-04 11:06:09 -04:00
|
|
|
|
#if NET6_0_OR_GREATER
|
|
|
|
|
[RequiresUnreferencedCode(null)]
|
|
|
|
|
#endif
|
2017-11-27 12:18:01 -05:00
|
|
|
|
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
|
|
|
|
|
{
|
|
|
|
|
var props = TypeDescriptor.GetProperties(typeof(RECT), attributes);
|
|
|
|
|
return props.Sort(new[] { "left", "top", "right", "bottom" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool GetPropertiesSupported(ITypeDescriptorContext context) => true;
|
|
|
|
|
|
2018-11-19 23:18:50 -05:00
|
|
|
|
protected static string IntConvertToString(ITypeDescriptorContext context, CultureInfo culture, RECT rect)
|
2017-11-27 12:18:01 -05:00
|
|
|
|
{
|
2018-11-19 23:18:50 -05:00
|
|
|
|
var intConverter = TypeDescriptor.GetConverter(typeof(int));
|
|
|
|
|
var args = new string[4];
|
|
|
|
|
var nArg = 0;
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
2018-11-19 23:18:50 -05:00
|
|
|
|
args[nArg++] = intConverter.ConvertToString(context, culture, rect.left);
|
|
|
|
|
args[nArg++] = intConverter.ConvertToString(context, culture, rect.top);
|
|
|
|
|
args[nArg++] = intConverter.ConvertToString(context, culture, rect.right);
|
|
|
|
|
args[nArg++] = intConverter.ConvertToString(context, culture, rect.bottom);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
|
2018-11-19 23:18:50 -05:00
|
|
|
|
return string.Join(culture.TextInfo.ListSeparator + " ", args);
|
2017-11-27 12:18:01 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|