39 Commits

Author SHA1 Message Date
3ae6e827a5 start implementation fo SimpleSorting 2023-08-09 09:25:06 +02:00
e142513083 add IUniquieIDHost 2023-08-02 08:47:53 +02:00
bc5aec6da8 remove obsulete UniquieID<TargetType> types 2023-08-02 08:19:29 +02:00
9100057ae2 more constructors for UniquieID 2023-08-02 08:09:12 +02:00
67be15157c depricate UniquieID<TargetType> and adjust json converters 2023-08-02 07:57:47 +02:00
dccd845a3d make base class not abstract 2023-08-02 07:13:31 +02:00
8fcb6a42d3 add UniquieID abstract base class 2023-08-02 06:39:56 +02:00
ef85aea1c5 fix highlight color 2023-06-12 09:48:34 +02:00
a42ea8d0f3 fix logical operator in HightlightPanel.GetColor 2023-06-12 09:40:08 +02:00
4393c59ab7 return an ICON 2023-01-02 15:06:54 +01:00
1b0b0e22c2 rename IconExtractor to FileTypeIcons 2023-01-02 14:45:46 +01:00
db6fb95dad make class instead of module 2023-01-02 14:42:52 +01:00
3c49701873 Mapped.IconExtractor 2023-01-02 14:35:59 +01:00
8dbd0a764e Get serial number only once 2022-12-02 10:43:29 +01:00
6aa00b360b Merge branch 'master' of https://gitlab.com/Pilzinsel64/pilz-framework 2022-12-02 10:04:46 +01:00
5002077d9a add Highlighter 2022-06-27 20:33:14 +02:00
e7e83b9597 add some more native functions for Highlighter 2022-06-27 20:33:12 +02:00
8c74ca9553 recursive SuspendDrawing and ResumeDrawing 2022-01-31 14:04:12 +00:00
schedpas
1f12af2a68 d 2021-11-30 11:46:59 +01:00
schedpas
a7de6c7bd6 prevent ReferenceNullException for equalizing UniquieID 2021-11-30 11:14:49 +01:00
schedpas
daf0e8f4a3 optimize equals for UniquieID 2021-10-27 10:34:25 +02:00
schedpas
4ca12b19da Euqlas for IUniquieID 2021-10-27 10:16:58 +02:00
schedpas
2415feaca3 public IUniquieID 2021-10-27 10:11:58 +02:00
schedpas
ad4e8b7e41 Merge branch 'master' of https://gitlab.com/Pilzinsel64/pilz-framework 2021-10-27 10:04:43 +02:00
schedpas
88524047ff Interface for UniquieID - IUniquieID 2021-10-27 10:04:34 +02:00
675dd6594a ignore PaintingObjectLayering._PaintingObject for Json serialization 2021-07-21 13:18:24 +02:00
756eb88d26 use alt instead ctrl for moving 2021-04-14 14:26:07 +02:00
fe2bb8efa1 add LocationDirect property to access the loaction fo a paintingobject without zoom 2021-03-25 13:30:58 +01:00
3376fecd12 fix return the wrong value 2021-03-25 13:24:04 +01:00
6871d6952f . 2021-03-17 10:24:34 +01:00
45696f2d19 use PaintEventArgs.ClipRectangle.Location if offset is not used 2021-02-25 10:44:19 +01:00
7d7cb0eee0 add extended line cap configuration 2021-02-23 09:21:12 +01:00
4480c00cb7 support for line start and end cap 2021-02-23 08:46:03 +01:00
f120e7a374 ignore "Selected" value 2021-02-17 08:50:53 +01:00
27b348d10a Merge branch 'master' of https://gitlab.com/Pilzinsel64/pilz-framework 2021-02-11 14:35:25 +01:00
ae76557adf add properties to get current past and future stack of HistoryStack 2021-02-11 14:35:19 +01:00
schedpas
6a65019bfa better json serializable PaintingObjects 2020-12-08 09:56:52 +01:00
8fd06a729c change to const 2020-12-04 11:10:57 +01:00
191b2fc319 update RealOSType check 2020-12-04 09:41:37 +01:00
43 changed files with 1901 additions and 121 deletions

View File

@@ -83,4 +83,7 @@
<ItemGroup>
<Compile Remove="SimpleHistory\Enums.vb" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz.Cryptography\Pilz.Cryptography.csproj" />
</ItemGroup>
</Project>

View File

@@ -17,6 +17,26 @@ Namespace SimpleHistory
End Get
End Property
''' <summary>
''' Gets the current stack of all past HistoryPoints that are used for the Undo function.
''' </summary>
''' <returns></returns>
Public ReadOnly Property PastHistoryPoints As HistoryPoint()
Get
Return stackPast.ToArray
End Get
End Property
''' <summary>
''' Gets the current stack of all future HistoryPoints that are used for the Redo function.
''' </summary>
''' <returns></returns>
Public ReadOnly Property FutureHistoryPoints As HistoryPoint()
Get
Return stackFuture.ToArray
End Get
End Property
''' <summary>
''' Checks if the History has past changes.
''' </summary>

View File

@@ -0,0 +1,8 @@
Namespace SimpleSorting
Public Enum ElementSortingPosition
Before
After
End Enum
End Namespace

View File

@@ -0,0 +1,10 @@
Namespace SimpleSorting
Public Interface ISimpleSortingHost
Inherits IList
Event OnInsert(sender As Object, e As SimpleSortingHostEventArgs)
Event OnRemove(sender As Object, e As SimpleSortingHostEventArgs)
End Interface
End Namespace

View File

@@ -0,0 +1,13 @@
Imports Pilz.Cryptography
Namespace SimpleSorting
Friend Class SimpleSortingEntry
Public Property Element As UniquieID
Public Property Position As ElementSortingPosition
Public Property ReferenceElement As UniquieID
End Class
End Namespace

View File

@@ -0,0 +1,18 @@
Imports Pilz.Cryptography
Namespace SimpleSorting
Public Class SimpleSortingHostEventArgs
Inherits EventArgs
Public ReadOnly Property ElementID As UniquieID
Public ReadOnly Property ElementIndex As Integer
Public Sub New(elementID As UniquieID, elementIndex As Integer)
Me.ElementID = elementID
Me.ElementIndex = elementIndex
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,121 @@
Imports System.Runtime.InteropServices.ComTypes
Imports Newtonsoft.Json
Imports Pilz.Cryptography
Namespace SimpleSorting
''' <summary>
''' Provides some management methods for sorting a list without changing the list itself.
''' Useful if the host list can not be changed or the sorting is indipendent from the required sorting.
''' </summary>
''' <typeparam name="T">The content of the host list to sort.</typeparam>
Public Class SimpleSortingList(Of T As IUniquieIDHost)
Private ReadOnly host As ISimpleSortingHost
<JsonProperty("SortingInfo")>
Private ReadOnly sortingList As New List(Of SimpleSortingEntry)
Public Sub New(parentList As ISimpleSortingHost)
host = parentList
AddHandler host.OnInsert, AddressOf Host_OnInsert
AddHandler host.OnRemove, AddressOf Host_OnRemove
End Sub
Protected Overrides Sub Finalize()
RemoveHandler host.OnInsert, AddressOf Host_OnInsert
RemoveHandler host.OnRemove, AddressOf Host_OnRemove
End Sub
Private Sub Host_OnInsert(sender As Object, e As SimpleSortingHostEventArgs)
'...
End Sub
Private Sub Host_OnRemove(sender As Object, e As SimpleSortingHostEventArgs)
'...
End Sub
''' <summary>
''' Stores positioning infos for the given element.
''' </summary>
''' <param name="elementID"></param>
''' <param name="position"></param>
''' <param name="referenceElementID"></param>
Public Sub SetElementPosition(elementID As UniquieID, position As ElementSortingPosition, referenceElementID As UniquieID)
'...
End Sub
''' <summary>
''' Removes the positioning infos for the given element if available.
''' </summary>
''' <param name="elementID"></param>
Public Sub RemoveElementPosition(elementID As UniquieID)
Dim infoToRemove = FindSortInfoByID(elementID)
If infoToRemove IsNot Nothing Then
sortingList.Remove(infoToRemove)
For Each info In sortingList
If info.ReferenceElement = elementID Then
info.ReferenceElement = infoToRemove.ReferenceElement
End If
Next
End If
End Sub
''' <summary>
''' Completely removes an element from all positioning infos. If possible, elements will be assigned to nearby reference or removed completely.
''' </summary>
''' <param name="elementID"></param>
Public Sub InvalidateElement(elementID As UniquieID)
'...
End Sub
''' <summary>
''' Creates a sorted list with all elements from the host list.
''' </summary>
''' <returns></returns>
Public Function GetSortedList() As List(Of T)
Dim list As New List(Of T)
list.AddRange(host)
For Each info In sortingList
Dim element As T = list.FirstOrDefault(Function(n) n.ID = info.Element)
Dim referenceElement As T = list.FirstOrDefault(Function(n) n.ID = info.ReferenceElement)
If element IsNot Nothing AndAlso referenceElement IsNot Nothing Then
list.Remove(element)
Dim referenceElementIndex As Integer = list.IndexOf(referenceElement)
If info.Position = ElementSortingPosition.After Then
referenceElementIndex += 1
End If
list.Insert(referenceElementIndex, element)
End If
Next
Return list
End Function
''' <summary>
''' Creates a sorted list with all elements from the host list.
''' </summary>
''' <returns></returns>
Public Function GetSortedArray() As T()
Return GetSortedList.ToArray
End Function
Private Function FindSortInfoByID(id As UniquieID) As SimpleSortingEntry
Return sortingList.FirstOrDefault(Function(n) n.Element = id)
End Function
Private Function FindSortInfoByReferenceID(id As UniquieID) As SimpleSortingEntry
Return sortingList.FirstOrDefault(Function(n) n.ReferenceElement = id)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Cryptography
{
public interface IUniquieID
{
bool HasID { get; }
string ID { get; }
void GenerateIfNull();
void Generate();
bool Equals(object obj);
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Cryptography
{
/// <summary>
/// Can be implemented on objects that provides an UniquieID.
/// </summary>
public interface IUniquieIDHost
{
UniquieID ID { get; }
}
}

View File

@@ -2,30 +2,28 @@
using Pilz.Cryptography;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Json.Converters
{
public class UniquiIDStringJsonConverter<TargetType> : JsonConverter
public class UniquieIDStringJsonConverter : JsonConverter
{
public static bool EnableCheckForDepricatedTypes { get; set; } = true;
public override bool CanConvert(Type objectType)
{
return typeof(UniquieID<TargetType>).IsAssignableFrom(objectType);
return typeof(UniquieID).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var idString = serializer.Deserialize<string>(reader);
UniquieID<TargetType> id;
UniquieID id;
if (existingValue is object)
id = (UniquieID<TargetType>)existingValue;
if (existingValue is UniquieID existingID && (!EnableCheckForDepricatedTypes || existingID.GetType() == typeof(UniquieID)))
id = existingID;
else
id = new UniquieID<TargetType>();
id = new UniquieID();
id.ID = idString;
@@ -34,7 +32,7 @@ namespace Pilz.Json.Converters
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((UniquieID<TargetType>)value).ID);
serializer.Serialize(writer, ((UniquieID)value).ID);
}
}
}

View File

@@ -11,20 +11,19 @@ namespace Pilz.Cryptography
public class SecureString
{
public static ICrypter DefaultCrypter { get; set; }
[JsonIgnore]
public ICrypter Crypter { get; set; }
[JsonProperty]
public string EncryptedValue { get; set; }
[JsonIgnore]
public string Value
{
get => GetCrypter().Decrypt(EncryptedValue);
get => GetCrypter()?.Decrypt(EncryptedValue);
set => EncryptedValue = GetCrypter().Encrypt(value);
}
[JsonConstructor]
private SecureString(JsonConstructorAttribute dummyAttribute)
{
}
public SecureString() :
this(string.Empty, true)
{
@@ -73,7 +72,7 @@ namespace Pilz.Cryptography
public static implicit operator string(SecureString value) => value?.Value;
public static implicit operator SecureString(string value) => new SecureString(value, false);
public static bool operator ==(SecureString left, SecureString right) => left.EncryptedValue == right.EncryptedValue;
public static bool operator !=(SecureString left, SecureString right) => left.EncryptedValue != right.EncryptedValue;
public static bool operator ==(SecureString left, SecureString right) => left?.EncryptedValue == right?.EncryptedValue;
public static bool operator !=(SecureString left, SecureString right) => left?.EncryptedValue != right?.EncryptedValue;
}
}

View File

@@ -22,12 +22,13 @@ namespace Pilz.Json.Converters
var idString = serializer.Deserialize<string>(reader);
SecureString id;
if (existingValue is object)
if (existingValue is SecureString)
{
id = (SecureString)existingValue;
id.EncryptedValue = idString;
}
else
id = new SecureString();
id.EncryptedValue = idString;
id = new SecureString(idString, true);
return id;
}

View File

@@ -35,10 +35,13 @@ namespace Pilz.Cryptography
byte[] bytes = TextEncoding.GetBytes(key);
byte[] array = sha1CryptoServiceProvider.ComputeHash(bytes);
var output = new byte[checked(length - 1 + 1)];
array.CopyTo(output, 0);
var output = new byte[length];
var lowerLength = Math.Min(array.Length, output.Length);
for (int i = 0; i < lowerLength; i++)
output[i] = array[i];
return array;
return output;
}
private string EncryptData(string plaintext)
@@ -63,7 +66,7 @@ namespace Pilz.Cryptography
public string Encrypt(string plainValue)
{
return EncryptData(plainValue);
return EncryptData(plainValue ?? string.Empty);
}
public string Decrypt(string encryptedValue)

View File

@@ -1,23 +1,31 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Cryptography
{
public class UniquieID<TargetType>
[JsonConverter(typeof(Json.Converters.UniquieIDStringJsonConverter))]
public class UniquieID : IUniquieID
{
private static int currentSimpleID = 0;
protected static ulong currentSimpleID = 0;
[JsonProperty(nameof(ID))]
private string _iD;
protected string _iD;
[JsonIgnore]
public string ID
public virtual bool SimpleMode { get; }
[JsonIgnore]
public virtual bool GenerateOnGet { get; }
[JsonIgnore]
public virtual bool HasID => !string.IsNullOrEmpty(_iD);
[JsonIgnore]
public virtual string ID
{
get
{
@@ -29,36 +37,96 @@ namespace Pilz.Cryptography
=> _iD = value;
}
[JsonIgnore]
public bool HasID { get => !string.IsNullOrEmpty(_iD); }
[JsonIgnore]
public bool SimpleMode { get; set; } = false;
[JsonIgnore]
public bool GenerateOnGet { get; set; } = false;
public UniquieID() : this(false)
public UniquieID() : this(UniquieIDGenerationMode.None)
{
}
public UniquieID(bool autoGenerate)
public UniquieID(UniquieIDGenerationMode mode) : this(mode, false)
{
if (autoGenerate)
}
public UniquieID(UniquieIDGenerationMode mode, bool simpleMode)
{
SimpleMode = simpleMode;
if (mode == UniquieIDGenerationMode.GenerateOnInit)
GenerateIfNull();
else if (mode == UniquieIDGenerationMode.GenerateOnGet)
GenerateOnGet = true;
}
public void Generate()
[Obsolete]
public UniquieID(bool autoGenerate) : this(autoGenerate ? UniquieIDGenerationMode.GenerateOnInit : UniquieIDGenerationMode.None)
{
}
public virtual void Generate()
{
if (SimpleMode)
ID = typeof(TargetType).ToString() + currentSimpleID++.ToString();
ID = GenerateSimple();
else
ID = GenerateUniquieID<TargetType>(string.Empty);
ID = GenerateDefault();
}
public void GenerateIfNull()
protected virtual string GenerateSimple()
{
return new Random().Next().ToString() + DateTime.Now.ToString("yyyyMMddHHmmssfffffff") + currentSimpleID++.ToString();
}
protected virtual string GenerateDefault()
{
return GenerateUniquieID<UniquieID>(currentSimpleID++.ToString());
}
public virtual void GenerateIfNull()
{
if (!HasID) Generate();
}
private static string GenerateUniquieID<T>(string var)
public override string ToString()
{
return ID;
}
public override int GetHashCode()
{
return -1430039477 + EqualityComparer<string>.Default.GetHashCode(_iD);
}
public override bool Equals(object obj)
{
if (obj is UniquieID iD)
{
if (ReferenceEquals(obj, iD))
return true;
else
{
var leftHasID = iD.HasID;
var rightHasID = HasID;
if (!leftHasID && iD.GenerateOnGet)
{
iD.Generate();
leftHasID = iD.HasID;
}
if (!rightHasID && GenerateOnGet)
{
Generate();
rightHasID = HasID;
}
if (leftHasID && rightHasID)
return _iD.Equals(iD._iD);
}
}
return base.Equals(obj);
}
#region Statics for Generation
protected static string GenerateUniquieID<T>(string var)
{
var sn = TryGetSerialNumberOfFirstHardDrive();
var dateTime = DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff");
@@ -72,39 +140,33 @@ namespace Pilz.Cryptography
return hash;
}
private static string Win32_PhysicalMedia_SerialNumber = null;
private static string TryGetSerialNumberOfFirstHardDrive()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
var sn = string.Empty;
foreach (ManagementObject wmi_HD in searcher.Get())
if (Win32_PhysicalMedia_SerialNumber == null)
{
if (string.IsNullOrEmpty(sn) && wmi_HD["SerialNumber"] != null)
sn = wmi_HD["SerialNumber"].ToString().Trim();
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
var sn = string.Empty;
foreach (ManagementObject wmi_HD in searcher.Get())
{
if (string.IsNullOrEmpty(sn) && wmi_HD["SerialNumber"] != null)
sn = wmi_HD["SerialNumber"].ToString().Trim();
}
Win32_PhysicalMedia_SerialNumber = sn;
}
return sn;
return Win32_PhysicalMedia_SerialNumber;
}
public override string ToString() => ID;
#endregion
public override bool Equals(object obj)
{
var iD = obj as UniquieID<TargetType>;
return iD != null &&
_iD == iD._iD;
}
public static implicit operator string(UniquieID id) => id.ID;
public static implicit operator UniquieID(string id) => new UniquieID() { ID = id };
public static implicit operator UniquieID(int id) => new UniquieID() { ID = Convert.ToString(id) };
public override int GetHashCode()
{
return -1430039477 + EqualityComparer<string>.Default.GetHashCode(_iD);
}
public static implicit operator string(UniquieID<TargetType> id) => id.ID;
public static implicit operator UniquieID<TargetType>(string id) => new UniquieID<TargetType>() { ID = id };
public static implicit operator UniquieID<TargetType>(int id) => new UniquieID<TargetType>() { ID = Convert.ToString(id) };
public static bool operator ==(UniquieID<TargetType> left, UniquieID<TargetType> right) => left.ID == right.ID;
public static bool operator !=(UniquieID<TargetType> left, UniquieID<TargetType> right) => left.ID != right.ID;
public static bool operator ==(UniquieID left, UniquieID right) => left.ID.Equals(right.ID);
public static bool operator !=(UniquieID left, UniquieID right) => !left.ID.Equals(right.ID);
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Pilz.Cryptography
{
public enum UniquieIDGenerationMode
{
None,
GenerateOnGet,
GenerateOnInit
}
}

View File

@@ -2,6 +2,12 @@
Public Class PluginManager
''' <summary>
''' Gets or sets an indicator if an exception should throw on error while loading a plugin.
''' </summary>
''' <returns></returns>
Public Property ThrowOnError As Boolean = False
''' <summary>
''' The name of the type where to search for Methods when loading a new Plugin.
''' </summary>
@@ -79,7 +85,11 @@ Public Class PluginManager
If addToList Then Plugins.Add(filePath, plugin)
Return plugin
Catch ex As Exception
Return Nothing
If ThrowOnError Then
Throw
Else
Return Nothing
End If
End Try
End Function

163
Pilz.UI/DisplayHelp.vb Normal file
View File

@@ -0,0 +1,163 @@
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class DisplayHelp
Public Shared Sub FillRectangle(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal color1 As Color)
FillRectangle(g, bounds, color1, Color.Empty, 90)
End Sub
Public Shared Sub FillRectangle(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal color1 As Color, ByVal color2 As Color)
FillRectangle(g, bounds, color1, color2, 90)
End Sub
Public Shared Sub FillRectangle(ByVal g As Graphics, ByVal r As Rectangle, ByVal color1 As Color, ByVal color2 As Color, ByVal gradientAngle As Integer)
If r.Width = 0 OrElse r.Height = 0 Then Return
If color2.IsEmpty Then
If Not color1.IsEmpty Then
Dim sm As SmoothingMode = g.SmoothingMode
g.SmoothingMode = SmoothingMode.None
Using brush As SolidBrush = New SolidBrush(color1)
g.FillRectangle(brush, r)
End Using
g.SmoothingMode = sm
End If
Else
Using brush As LinearGradientBrush = CreateLinearGradientBrush(r, color1, color2, gradientAngle)
g.FillRectangle(brush, r)
End Using
End If
End Sub
Public Shared Sub FillRectangle(ByVal g As Graphics, ByVal r As Rectangle, ByVal color1 As Color, ByVal color2 As Color, ByVal gradientAngle As Integer, ByVal factors As Single(), ByVal positions As Single())
If r.Width = 0 OrElse r.Height = 0 Then Return
If color2.IsEmpty Then
If Not color1.IsEmpty Then
Dim sm As SmoothingMode = g.SmoothingMode
g.SmoothingMode = SmoothingMode.None
Using brush As SolidBrush = New SolidBrush(color1)
g.FillRectangle(brush, r)
End Using
g.SmoothingMode = sm
End If
Else
Using brush As LinearGradientBrush = CreateLinearGradientBrush(r, color1, color2, gradientAngle)
Dim blend As Blend = New Blend(factors.Length)
blend.Factors = factors
blend.Positions = positions
brush.Blend = blend
g.FillRectangle(brush, r)
End Using
End If
End Sub
Public Shared Sub FillRoundedRectangle(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal cornerSize As Integer, ByVal color1 As Color, ByVal color2 As Color, ByVal gradientAngle As Integer)
If color2.IsEmpty Then
If Not color1.IsEmpty Then
Using brush As SolidBrush = New SolidBrush(color1)
FillRoundedRectangle(g, brush, bounds, cornerSize)
End Using
End If
Else
Using brush As LinearGradientBrush = CreateLinearGradientBrush(bounds, color1, color2, gradientAngle)
FillRoundedRectangle(g, brush, bounds, cornerSize)
End Using
End If
End Sub
Public Shared Sub FillRoundedRectangle(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal cornerSize As Integer, ByVal color1 As Color, ByVal color2 As Color)
FillRoundedRectangle(g, bounds, cornerSize, color1, color2, 90)
End Sub
Public Shared Sub FillRoundedRectangle(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal cornerSize As Integer, ByVal color1 As Color)
Using brush As SolidBrush = New SolidBrush(color1)
FillRoundedRectangle(g, brush, bounds, cornerSize)
End Using
End Sub
Public Shared Sub FillRoundedRectangle(ByVal g As Graphics, ByVal brush As Brush, ByVal bounds As Rectangle, ByVal cornerSize As Integer)
If cornerSize <= 0 Then
Dim sm As SmoothingMode = g.SmoothingMode
g.SmoothingMode = SmoothingMode.None
g.FillRectangle(brush, bounds)
g.SmoothingMode = sm
Else
bounds.Width -= 1
bounds.Height -= 1
Using path As GraphicsPath = GetRoundedRectanglePath(bounds, cornerSize)
g.FillPath(brush, path)
End Using
End If
End Sub
Public Shared Sub DrawRectangle(ByVal g As System.Drawing.Graphics, ByVal color As Color, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer)
Using pen As Pen = New Pen(color, 1)
DrawRectangle(g, pen, x, y, width, height)
End Using
End Sub
Public Shared Sub DrawRectangle(ByVal g As System.Drawing.Graphics, ByVal color As Color, ByVal r As System.Drawing.Rectangle)
DrawRectangle(g, color, r.X, r.Y, r.Width, r.Height)
End Sub
Public Shared Sub DrawRectangle(ByVal g As System.Drawing.Graphics, ByVal pen As System.Drawing.Pen, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer)
width -= 1
height -= 1
g.DrawRectangle(pen, x, y, width, height)
End Sub
Public Shared Sub DrawRoundedRectangle(ByVal g As System.Drawing.Graphics, ByVal color As Color, ByVal bounds As Rectangle, ByVal cornerSize As Integer)
If Not color.IsEmpty Then
Using pen As Pen = New Pen(color)
DrawRoundedRectangle(g, pen, bounds.X, bounds.Y, bounds.Width, bounds.Height, cornerSize)
End Using
End If
End Sub
Public Shared Sub DrawRoundedRectangle(ByVal g As System.Drawing.Graphics, ByVal pen As System.Drawing.Pen, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal cornerSize As Integer)
DrawRoundedRectangle(g, pen, Nothing, x, y, width, height, cornerSize)
End Sub
Public Shared Sub DrawRoundedRectangle(ByVal g As System.Drawing.Graphics, ByVal pen As System.Drawing.Pen, ByVal fill As Brush, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal cornerSize As Integer)
width -= 1
height -= 1
Dim r As Rectangle = New Rectangle(x, y, width, height)
Using path As GraphicsPath = GetRoundedRectanglePath(r, cornerSize)
If fill IsNot Nothing Then g.FillPath(fill, path)
g.DrawPath(pen, path)
End Using
End Sub
Public Shared Function GetRoundedRectanglePath(ByVal r As Rectangle, ByVal cornerSize As Integer) As GraphicsPath
Dim path As GraphicsPath = New GraphicsPath()
If cornerSize = 0 Then
path.AddRectangle(r)
End If
Return path
End Function
Public Shared Function CreateLinearGradientBrush(ByVal r As Rectangle, ByVal color1 As Color, ByVal color2 As Color, ByVal gradientAngle As Single) As LinearGradientBrush
If r.Width <= 0 Then r.Width = 1
If r.Height <= 0 Then r.Height = 1
Return New LinearGradientBrush(New Rectangle(r.X, r.Y - 1, r.Width, r.Height + 1), color1, color2, gradientAngle)
End Function
End Class

261
Pilz.UI/HighlightPanel.vb Normal file
View File

@@ -0,0 +1,261 @@
Imports System.Drawing
Imports System.Windows.Forms
Imports Pilz.Win32
Friend Class HighlightPanel
Inherits Control
Private _Highlights As Dictionary(Of Control, eHighlightColor) = Nothing
Private _HighlightRegions As List(Of HighlightRegion) = New List(Of HighlightRegion)()
Public Sub New(ByVal highlights As Dictionary(Of Control, eHighlightColor))
_Highlights = highlights
Me.SetStyle(ControlStyles.UserPaint, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.Selectable, False)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim g As Graphics = e.Graphics
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
For Each highlightRegion As HighlightRegion In _HighlightRegions
Dim colors As Color() = GetHighlightColors(highlightRegion.HighlightColor)
Dim r As Rectangle = highlightRegion.Bounds
Dim back As Color = highlightRegion.BackColor
r.Inflate(1, 1)
DisplayHelp.FillRectangle(g, r, back)
r.Inflate(-1, -1)
DisplayHelp.FillRoundedRectangle(g, r, 2, colors(0))
r.Inflate(-2, -2)
DisplayHelp.DrawRectangle(g, colors(2), r)
r.Inflate(1, 1)
DisplayHelp.DrawRoundedRectangle(g, colors(1), r, 2)
Next
MyBase.OnPaint(e)
End Sub
Private Function GetHighlightColors(ByVal color As eHighlightColor) As Color()
Dim colors As Color() = New Color(2) {}
If color = eHighlightColor.Blue Then
colors(0) = GetColor(172, &H6A9CD4)
colors(1) = GetColor(&H6A9CD4)
colors(2) = GetColor(&H5D7EA4)
ElseIf color = eHighlightColor.Orange Then
colors(0) = GetColor(172, &HFF9C00)
colors(1) = GetColor(&HFF9C00)
colors(2) = GetColor(&HCC6600)
ElseIf color = eHighlightColor.Green Then
colors(0) = GetColor(172, &H71B171)
colors(1) = GetColor(&H71B171)
colors(2) = GetColor(&H339933)
ElseIf color = eHighlightColor.Custom Then
If _CustomHighlightColors Is Nothing OrElse _CustomHighlightColors.Length < 3 Then
colors(0) = System.Drawing.Color.Red
colors(1) = System.Drawing.Color.Red
colors(2) = System.Drawing.Color.Red
Else
colors(0) = _CustomHighlightColors(0)
colors(1) = _CustomHighlightColors(1)
colors(2) = _CustomHighlightColors(2)
End If
Else
colors(0) = GetColor(172, &HC63030)
colors(1) = GetColor(&HC63030)
colors(2) = GetColor(&H990000)
End If
Return colors
End Function
Protected Overrides Sub OnVisibleChanged(ByVal e As EventArgs)
If Me.Visible AndAlso Not _UpdatingRegion Then UpdateRegion()
MyBase.OnVisibleChanged(e)
End Sub
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
If Not _RegionInitialized Then UpdateRegion()
MyBase.OnHandleCreated(e)
End Sub
Private _RegionInitialized As Boolean = False
Private _UpdatingRegion As Boolean = False
Friend Sub UpdateRegion()
If _UpdatingRegion OrElse Not Me.IsHandleCreated Then Return
Try
_UpdatingRegion = True
Me.Region = Nothing
_HighlightRegions.Clear()
If _Highlights Is Nothing Then Return
If _Highlights.Count = 0 AndAlso _FocusHighlightControl Is Nothing Then
Me.Visible = False
Return
End If
Dim processFocusControl As Boolean = True
Dim region As Region = Nothing
For Each item As KeyValuePair(Of Control, eHighlightColor) In _Highlights
If item.Value = eHighlightColor.None OrElse Not GetIsVisible(item.Key) Then Continue For
If item.Key Is _FocusHighlightControl Then processFocusControl = False
Dim r As Rectangle = GetControlRect(item.Key)
If r.IsEmpty Then Continue For
r.Inflate(2, 2)
_HighlightRegions.Add(New HighlightRegion(r, GetBackColor(item.Key.Parent), item.Value))
If region Is Nothing Then
region = New Region(r)
Else
region.Union(r)
End If
r.Inflate(-3, -3)
region.Exclude(r)
Next
If processFocusControl AndAlso _FocusHighlightControl IsNot Nothing AndAlso _FocusHighlightControl.Visible Then
Dim r As Rectangle = GetControlRect(_FocusHighlightControl)
If Not r.IsEmpty Then
r.Inflate(2, 2)
_HighlightRegions.Add(New HighlightRegion(r, GetBackColor(_FocusHighlightControl.Parent), _FocusHighlightColor))
If region Is Nothing Then
region = New Region(r)
Else
region.Union(r)
End If
r.Inflate(-3, -3)
region.Exclude(r)
End If
End If
Me.Region = region
If region Is Nothing Then
Me.Visible = False
ElseIf Not Me.Visible Then
Me.Visible = True
Me.BringToFront()
End If
Me.Invalidate()
Finally
_UpdatingRegion = False
_RegionInitialized = True
End Try
End Sub
Private Shared Function GetColor(rgb As Integer) As Color
If rgb = -1 Then
Return Color.Empty
Else
Return Color.FromArgb((rgb And &HFF0000) >> 16, (rgb And &HFF00) >> 8, rgb And &HFF)
End If
End Function
Private Shared Function GetColor(alpha As Integer, rgb As Integer) As Color
If rgb = -1 Then
Return Color.Empty
Else
Return Color.FromArgb(alpha, (rgb And &HFF0000) >> 16, (rgb And &HFF00) >> 8, rgb And &HFF)
End If
End Function
Private Function GetIsVisible(ByVal control As Control) As Boolean
If Not control.Visible Then Return False
If control.Parent Is Nothing OrElse Not control.IsHandleCreated Then Return control.Visible
Dim rect As New Native.RECT
Native.User32.GetWindowRect(control.Handle, rect)
Dim pp As Point = control.Parent.PointToClient(New Point(rect.Left + 3, rect.Top + 3))
Dim handle As IntPtr = Native.User32.ChildWindowFromPointEx(control.Parent.Handle, New Native.POINT(pp.X, pp.Y), CUInt(Native.WindowFromPointFlags.CWP_SKIPINVISIBLE))
If handle = IntPtr.Zero Then Return control.Visible
Dim c As Control = Control.FromHandle(handle)
If c IsNot Nothing AndAlso c IsNot control AndAlso c IsNot Me AndAlso c IsNot control.Parent Then
Return False
End If
Return control.Visible
End Function
Private Function GetBackColor(ByVal control As Control) As Color
Dim backColor As Color = control.BackColor
If backColor.IsEmpty OrElse backColor = Color.Transparent Then
backColor = SystemColors.Control
ElseIf backColor.A < 255 Then
backColor = Color.FromArgb(255, backColor)
End If
Return backColor
End Function
Protected Overrides Sub OnResize(ByVal e As EventArgs)
UpdateRegion()
MyBase.OnResize(e)
End Sub
Private Function GetControlRect(ByVal c As Control) As Rectangle
If Not c.IsHandleCreated Then Return Rectangle.Empty
Dim rect As Native.RECT
Native.User32.GetWindowRect(c.Handle, rect)
Dim p As Point = Me.PointToClient(rect.Location)
Return New Rectangle(p, rect.Size)
End Function
Private Structure HighlightRegion
Public Bounds As Rectangle
Public BackColor As Color
Public HighlightColor As eHighlightColor
Public Sub New(ByVal bounds As Rectangle, ByVal backColor As Color, ByVal highlightColor As eHighlightColor)
Me.Bounds = bounds
Me.BackColor = backColor
Me.HighlightColor = highlightColor
End Sub
End Structure
Private _FocusHighlightControl As Control
Public Property FocusHighlightControl As Control
Get
Return _FocusHighlightControl
End Get
Set(ByVal value As Control)
_FocusHighlightControl = value
End Set
End Property
Private _FocusHighlightColor As eHighlightColor = eHighlightColor.Blue
Public Property FocusHighlightColor As eHighlightColor
Get
Return _FocusHighlightColor
End Get
Set(ByVal value As eHighlightColor)
_FocusHighlightColor = value
End Set
End Property
Private _CustomHighlightColors As Color() = Nothing
Public Property CustomHighlightColors As Color()
Get
Return _CustomHighlightColors
End Get
Set(ByVal value As Color())
_CustomHighlightColors = value
End Set
End Property
End Class

409
Pilz.UI/Highlighter.vb Normal file
View File

@@ -0,0 +1,409 @@
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Drawing
Public Class Highlighter
Inherits Component
Private _Highlights As Dictionary(Of Control, eHighlightColor) = New Dictionary(Of Control, eHighlightColor)()
Private _HighlightOnFocus As Dictionary(Of Control, Boolean) = New Dictionary(Of Control, Boolean)()
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If _ContainerControl IsNot Nothing Then
RemoveHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
RemoveHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
End If
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.Parent Is Nothing AndAlso Not _HighlightPanel.IsDisposed Then
_HighlightPanel.Dispose()
_HighlightPanel = Nothing
Else
_HighlightPanel = Nothing
End If
MyBase.Dispose(disposing)
End Sub
<DefaultValue(False), Localizable(True), Description("Indicates whether control is highlighted when it receives input focus.")>
Public Function GetHighlightOnFocus(ByVal c As Control) As Boolean
If _HighlightOnFocus.ContainsKey(c) Then
Return _HighlightOnFocus(c)
End If
Return False
End Function
Public Sub SetHighlightOnFocus(ByVal c As Control, ByVal highlight As Boolean)
If c Is Nothing Then Throw New NullReferenceException()
If _HighlightOnFocus.ContainsKey(c) Then
If Not highlight Then
RemoveHighlightOnFocus(_HighlightOnFocus, c)
End If
Return
End If
If highlight Then AddHighlightOnFocus(_HighlightOnFocus, c)
End Sub
Private Sub AddHighlightOnFocus(ByVal highlightOnFocus As Dictionary(Of Control, Boolean), ByVal c As Control)
AddHandler c.Enter, AddressOf ControlHighlightEnter
AddHandler c.Leave, AddressOf ControlHighlightLeave
AddHandler c.VisibleChanged, AddressOf ControlHighlightVisibleChanged
highlightOnFocus.Add(c, True)
End Sub
Private Sub ControlHighlightVisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.FocusHighlightControl = sender Then UpdateHighlighterRegion()
End Sub
Private Sub ControlHighlightLeave(ByVal sender As Object, ByVal e As EventArgs)
If _HighlightPanel IsNot Nothing Then _HighlightPanel.FocusHighlightControl = Nothing
UpdateHighlighterRegion()
End Sub
Private Sub ControlHighlightEnter(ByVal sender As Object, ByVal e As EventArgs)
If _HighlightPanel IsNot Nothing Then
If Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
_HighlightPanel.BringToFront()
_HighlightPanel.FocusHighlightControl = CType(sender, Control)
End If
UpdateHighlighterRegion()
End Sub
Private Sub RemoveHighlightOnFocus(ByVal highlightOnFocus As Dictionary(Of Control, Boolean), ByVal c As Control)
RemoveHandler c.Enter, AddressOf ControlHighlightEnter
RemoveHandler c.Leave, AddressOf ControlHighlightLeave
RemoveHandler c.VisibleChanged, AddressOf ControlHighlightVisibleChanged
highlightOnFocus.Remove(c)
End Sub
<DefaultValue(eHighlightColor.None), Localizable(True), Description("Indicates the highlight color that is applied to the control.")>
Public Function GetHighlightColor(ByVal c As Control) As eHighlightColor
If _Highlights.ContainsKey(c) Then
Return _Highlights(c)
End If
Return eHighlightColor.None
End Function
Public Sub SetHighlightColor(ByVal c As Control, ByVal highlightColor As eHighlightColor)
If _Highlights.ContainsKey(c) Then
If highlightColor = eHighlightColor.None Then
RemoveHighlight(_Highlights, c)
Else
Dim color As eHighlightColor = _Highlights(c)
RemoveHighlight(_Highlights, c)
AddHighlight(_Highlights, c, highlightColor)
End If
ElseIf highlightColor <> eHighlightColor.None Then
AddHighlight(_Highlights, c, highlightColor)
End If
End Sub
Private _TabControl2 As Dictionary(Of System.Windows.Forms.TabControl, Integer) = New Dictionary(Of System.Windows.Forms.TabControl, Integer)()
Private _ParentPanel As Dictionary(Of Panel, Integer) = New Dictionary(Of Panel, Integer)()
Private Sub AddHighlight(ByVal highlights As Dictionary(Of Control, eHighlightColor), ByVal c As Control, ByVal highlightColor As eHighlightColor)
highlights.Add(c, highlightColor)
AddHandler c.LocationChanged, New EventHandler(AddressOf ControlLocationChanged)
AddHandler c.SizeChanged, New EventHandler(AddressOf ControlSizeChanged)
AddHandler c.VisibleChanged, New EventHandler(AddressOf ControlVisibleChanged)
If _HighlightPanel IsNot Nothing Then
If Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
_HighlightPanel.BringToFront()
End If
If c.Parent Is Nothing Then
AddHandler c.ParentChanged, AddressOf ControlParentChanged
Else
AddTabControlHandlers(c)
End If
UpdateHighlighterRegion()
End Sub
Private Sub ControlParentChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim c As Control = CType(sender, Control)
RemoveHandler c.ParentChanged, AddressOf ControlParentChanged
AddTabControlHandlers(c)
End Sub
Private Sub AddTabControlHandlers(ByVal c As Control)
Dim tab2 As System.Windows.Forms.TabControl = TryCast(GetParentControl(c, GetType(System.Windows.Forms.TabControl)), System.Windows.Forms.TabControl)
If tab2 IsNot Nothing Then
If _TabControl2.ContainsKey(tab2) Then
_TabControl2(tab2) = _TabControl2(tab2) + 1
Else
_TabControl2.Add(tab2, 1)
AddHandler tab2.SelectedIndexChanged, AddressOf WinFormsTabSelectedIndexChanged
End If
Else
Dim parentPanel As Panel = TryCast(GetParentControl(c, GetType(Panel)), Panel)
If parentPanel IsNot Nothing Then
If _ParentPanel.ContainsKey(parentPanel) Then
_ParentPanel(parentPanel) = _ParentPanel(parentPanel) + 1
Else
_ParentPanel.Add(parentPanel, 1)
AddHandler parentPanel.Resize, AddressOf ParentPanelResized
AddHandler parentPanel.LocationChanged, AddressOf ParentPanelLocationChanged
End If
End If
End If
End Sub
Private Sub ParentPanelLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlights()
End Sub
Private Sub ParentPanelResized(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlights()
End Sub
Private Sub WinFormsTabSelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlighterRegion()
End Sub
Private Function GetParentControl(ByVal c As Control, ByVal parentType As Type) As Control
Dim parent As Control = c.Parent
While parent IsNot Nothing
If parentType.IsAssignableFrom(parent.[GetType]()) Then Return parent
parent = parent.Parent
End While
Return Nothing
End Function
Private Sub ControlVisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlighterRegion()
End Sub
Private Sub ControlSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlighterRegion()
End Sub
Private Sub ControlLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
UpdateHighlighterRegion()
End Sub
Private Sub UpdateHighlighterRegion()
If _HighlightPanel IsNot Nothing Then _HighlightPanel.UpdateRegion()
End Sub
Public Sub UpdateHighlights()
UpdateHighlighterRegion()
End Sub
Private Sub RemoveHighlight(ByVal highlights As Dictionary(Of Control, eHighlightColor), ByVal c As Control)
highlights.Remove(c)
RemoveHandler c.LocationChanged, New EventHandler(AddressOf ControlLocationChanged)
RemoveHandler c.SizeChanged, New EventHandler(AddressOf ControlSizeChanged)
RemoveHandler c.VisibleChanged, New EventHandler(AddressOf ControlVisibleChanged)
Dim tab2 As System.Windows.Forms.TabControl = TryCast(GetParentControl(c, GetType(System.Windows.Forms.TabControl)), System.Windows.Forms.TabControl)
If tab2 IsNot Nothing Then
If _TabControl2.ContainsKey(tab2) Then
If _TabControl2(tab2) = 1 Then
_TabControl2.Remove(tab2)
RemoveHandler tab2.SelectedIndexChanged, AddressOf WinFormsTabSelectedIndexChanged
Else
_TabControl2(tab2) = _TabControl2(tab2) - 1
End If
End If
Else
Dim parentPanel As Panel = TryCast(GetParentControl(c, GetType(Panel)), Panel)
If parentPanel IsNot Nothing Then
If _ParentPanel.ContainsKey(parentPanel) Then
If _ParentPanel(parentPanel) = 1 Then
_ParentPanel.Remove(parentPanel)
RemoveHandler parentPanel.LocationChanged, AddressOf ParentPanelLocationChanged
RemoveHandler parentPanel.SizeChanged, AddressOf ParentPanelResized
Else
_ParentPanel(parentPanel) = _ParentPanel(parentPanel) - 1
End If
End If
End If
End If
UpdateHighlighterRegion()
End Sub
Friend ReadOnly Property Highlights As Dictionary(Of Control, eHighlightColor)
Get
Return _Highlights
End Get
End Property
Private _FocusHighlightColor As eHighlightColor = eHighlightColor.Blue
<DefaultValue(eHighlightColor.Blue), Category("Appearance"), Description("Indicates the highlight focus color."), Localizable(True)>
Public Property FocusHighlightColor As eHighlightColor
Get
Return _FocusHighlightColor
End Get
Set(ByVal value As eHighlightColor)
_FocusHighlightColor = value
If _HighlightPanel IsNot Nothing Then
_HighlightPanel.FocusHighlightColor = value
UpdateHighlighterRegion()
End If
End Set
End Property
Private _HighlightPanel As HighlightPanel = Nothing
Private _ContainerControl As Control = Nothing
<Description("Indicates container control highlighter is bound to. Should be set to parent form."), Category("Behavior")>
Public Property ContainerControl As Control
Get
Return _ContainerControl
End Get
Set(ByVal value As Control)
If Me.DesignMode Then
_ContainerControl = value
Return
End If
If _ContainerControl IsNot value Then
If _ContainerControl IsNot Nothing Then
RemoveHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
RemoveHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.Parent Is _ContainerControl Then _ContainerControl.Controls.Remove(_HighlightPanel)
End If
_ContainerControl = value
If _ContainerControl IsNot Nothing Then
If _HighlightPanel Is Nothing Then
_HighlightPanel = New HighlightPanel(_Highlights)
_HighlightPanel.FocusHighlightColor = _FocusHighlightColor
_HighlightPanel.Margin = New System.Windows.Forms.Padding(0)
_HighlightPanel.Padding = New System.Windows.Forms.Padding(0)
_HighlightPanel.CustomHighlightColors = _CustomHighlightColors
_HighlightPanel.Visible = False
End If
AddHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
AddHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
_ContainerControl.Controls.Add(_HighlightPanel)
UpdateHighlightPanelBounds()
End If
End If
End Set
End Property
Private Sub ContainerControlHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
If _Highlights.Count > 0 AndAlso _HighlightPanel IsNot Nothing AndAlso Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
End Sub
Private Sub UpdateHighlightPanelBounds()
Dim bounds As Rectangle = New Rectangle(0, 0, _ContainerControl.ClientRectangle.Width, _ContainerControl.ClientRectangle.Height)
If TypeOf _HighlightPanel.Parent Is Form Then
Dim form As Form = TryCast(_HighlightPanel.Parent, Form)
If form.AutoSize Then
bounds.X += form.Padding.Left
bounds.Y += form.Padding.Top
bounds.Width -= form.Padding.Horizontal
bounds.Height -= form.Padding.Vertical
End If
End If
If _HighlightPanel.Bounds.Equals(bounds) Then
_HighlightPanel.UpdateRegion()
Else
_HighlightPanel.Bounds = bounds
End If
_HighlightPanel.BringToFront()
End Sub
Private _DelayTimer As Timer = Nothing
Private Sub ContainerControlSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim form As Form = TryCast(sender, Form)
If form IsNot Nothing Then
If _DelayTimer Is Nothing Then
_DelayTimer = New Timer()
_DelayTimer.Interval = 100
AddHandler _DelayTimer.Tick, New EventHandler(AddressOf DelayTimerTick)
_DelayTimer.Start()
End If
Return
End If
UpdateHighlightPanelBounds()
End Sub
Private Sub DelayTimerTick(ByVal sender As Object, ByVal e As EventArgs)
Dim timer As Timer = _DelayTimer
_DelayTimer = Nothing
RemoveHandler timer.Tick, New EventHandler(AddressOf DelayTimerTick)
timer.[Stop]()
timer.Dispose()
UpdateHighlightPanelBounds()
End Sub
Private _CustomHighlightColors As Color() = Nothing
<Category("Appearance"), Description("Array of colors used to render custom highlight color. Control expects 3 colors in array to be specified which define the highlight border.")>
Public Property CustomHighlightColors As Color()
Get
Return _CustomHighlightColors
End Get
Set(ByVal value As Color())
_CustomHighlightColors = value
If _HighlightPanel IsNot Nothing Then
_HighlightPanel.CustomHighlightColors = _CustomHighlightColors
_HighlightPanel.Invalidate()
End If
End Set
End Property
Public Function CanExtend(ByVal extendee As Object) As Boolean
Return (TypeOf extendee Is Control)
End Function
Private Sub SetError(ByVal control As Control, ByVal value As String)
Me.SetHighlightColor(control, eHighlightColor.Red)
End Sub
Private Sub ClearError(ByVal control As Control)
Me.SetHighlightColor(control, eHighlightColor.None)
End Sub
End Class
Public Enum eHighlightColor
None
Red
Blue
Green
Orange
Custom
End Enum

View File

@@ -0,0 +1,15 @@
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class ArrowLineCapProps
Inherits LineCapProps
Public Property Size As New Size(10, 10)
Public Property IsFilles As Boolean = True
Friend Overrides Function Configure() As LineCapConfigurationArgs
Dim cap As New AdjustableArrowCap(Size.Width, Size.Height, IsFilles)
Return New LineCapConfigurationArgs(cap)
End Function
End Class

View File

@@ -112,7 +112,22 @@ Public Class DefaultDrawMethodes
Public Shared Sub DrawLine(e As PaintingObjectPaintEventArgs)
Dim obj As PaintingObject = e.PaintingObject
Dim p2 As New Pen(obj.OutlineColor, obj.OutlineThicknes) With {.DashStyle = obj.OutlineDashStyle}
Dim p2 As New Pen(obj.OutlineColor, obj.OutlineThicknes) With {
.DashStyle = obj.OutlineDashStyle
}
If obj.LineEndCap IsNot Nothing Then
Dim args As LineCapConfigurationArgs = obj.LineEndCap.Configure
p2.StartCap = args.LineCap
p2.CustomStartCap = args.CustomLineCap
End If
If obj.LineStartCap IsNot Nothing Then
Dim args As LineCapConfigurationArgs = obj.LineStartCap.Configure
p2.EndCap = args.LineCap
p2.CustomEndCap = args.CustomLineCap
End If
p2.Alignment = PenAlignment.Center
Dim no As PointF = New PointF(e.X, e.Y)
e.Graphics.DrawLine(p2, no, no + obj.Size)

View File

@@ -0,0 +1,13 @@
Imports System.Drawing.Drawing2D
Public Class DefaultLineCapProps
Inherits LineCapProps
Public Property LineCap As LineCap = LineCap.Flat
Public Property CustomLineCap As CustomLineCap = Nothing
Friend Overrides Function Configure() As LineCapConfigurationArgs
Return New LineCapConfigurationArgs(LineCap, CustomLineCap)
End Function
End Class

View File

@@ -0,0 +1,21 @@
Imports System.Drawing.Drawing2D
Public Class LineCapConfigurationArgs
Public ReadOnly Property LineCap As LineCap
Public ReadOnly Property CustomLineCap As CustomLineCap
Public Sub New(lineCap As LineCap)
Me.New(lineCap, Nothing)
End Sub
Public Sub New(customLineCap As CustomLineCap)
Me.New(Nothing, customLineCap)
End Sub
Public Sub New(lineCap As LineCap, customLineCap As CustomLineCap)
Me.LineCap = lineCap
Me.CustomLineCap = customLineCap
End Sub
End Class

View File

@@ -0,0 +1,7 @@
Imports System.Drawing
Public MustInherit Class LineCapProps
Friend MustOverride Function Configure() As LineCapConfigurationArgs
End Class

View File

@@ -196,7 +196,7 @@ Public Class PaintingControl
End If
End If
If pressedControl Then
If pressedAlt Then
calcOffset_MouseOnTab = New Point(e.X, e.Y)
calcOffset_LastOffset = Offset
@@ -281,7 +281,7 @@ Public Class PaintingControl
End If
If calcOffset_IsActive Then
If pressedControl Then
If pressedAlt Then
CalcNewOffset(e.Location)
Else
calcOffset_IsActive = False
@@ -314,7 +314,7 @@ Public Class PaintingControl
Private Sub SaveObjectPositions(e As MouseEventArgs, objs As IList)
For Each obj As PaintingObject In objs
If Not savedPos.ContainsKey(obj) Then
If Not obj.HardcodedLocation AndAlso Not savedPos.ContainsKey(obj) Then
savedPos.Add(obj, New PointF(e.X - obj.Location.X + Offset.X, e.Y - obj.Location.Y + Offset.Y))
SaveObjectPositions(e, obj.PinnedObjects)
End If

View File

@@ -19,35 +19,48 @@ Imports Newtonsoft.Json
Public Property OutlineColor As Color = Color.DarkBlue
Public Property OutlineThicknes As Single = 1
Public Property OutlineDashStyle As DashStyle = DashStyle.Solid
Public Property LineStartCap As LineCapProps = Nothing
Public Property LineEndCap As LineCapProps = Nothing
<JsonProperty>
Private _Text As String = ""
Public Property TextPosition As TextPosition = TextPosition.FullCenter
Public Property VerticalTextAlignment As StringAlignment = StringAlignment.Center
Public Property HorizontalTextAlignment As StringAlignment = StringAlignment.Center
Public Property TextFont As New Font(FontFamily.GenericSansSerif, 8.25)
Public Property TextColor As Color = Color.Black
<JsonProperty>
Private _Location As New PointF(50, 50)
<JsonProperty>
Private _Size As New SizeF(50, 80)
Public Property EnableFill As Boolean = True
Public Property EnableOutline As Boolean = True
Public Property SelectionColor As Color = Color.CornflowerBlue
Public Property SelectionDashStyle As DashStyle = DashStyle.Dot
<JsonProperty>
Private _EnableSelection As Boolean = True
Public Property Image As Image = Nothing
<JsonIgnore> Public Property BufferedImage As Image = Nothing
Public Property ImageSizeMode As ImageSizeMode
Public Property ImageProperties As New PaintingObjectImageProperties
Public Property Tag As String = Nothing
<JsonIgnore>
Public Property Tag As Object = Nothing
Public Property Name As String = ""
Public ReadOnly Property PinnedObjects As New List(Of PaintingObject)
<JsonIgnore>
Public ReadOnly Property DrawMethodes As New List(Of DelegateDrawPaintingObjectMethode)
<JsonIgnore>
Public ReadOnly Property DrawSelectionMethode As DelegateDrawPaintingObjectMethode = AddressOf DefaultDrawMethodes.DrawSelection
Public Property Cursor As Cursor = Cursors.Default
Public Property HardcodedSize As Boolean = False
Public Property HardcodedLocation As Boolean = False
<JsonProperty>
Private _Visible As Boolean = True
<JsonProperty>
Private _AutoAlignToGrid As Boolean = False
Public Property MouseTransparency As Boolean = False
Public ReadOnly Property Layering As New PaintingObjectLayering(Me)
Public ReadOnly Property PaintingObjects As New PaintingObjectList(_Parent) With {.EnableRaisingEvents = False}
<JsonIgnore>
Public ReadOnly Property ErrorsAtDrawing As ULong = 0
Public Event MouseClick(sender As PaintingObject, e As MouseEventArgs)
@@ -172,6 +185,15 @@ Imports Newtonsoft.Json
End Set
End Property
<JsonIgnore> Public Property LocationDirect As PointF
Get
Return _Location
End Get
Set(value As PointF)
_Location = value
End Set
End Property
<JsonIgnore> Public Property Size As SizeF
Get
If Parent IsNot Nothing Then
@@ -246,6 +268,7 @@ Imports Newtonsoft.Json
End Set
End Property
<JsonIgnore>
Public Property Selected As Boolean
Get
Return _Selected
@@ -321,6 +344,7 @@ Imports Newtonsoft.Json
End Set
End Property
<JsonIgnore>
Public Property Rectangle As RectangleF
Get
Return New RectangleF(Location, Size)
@@ -408,6 +432,20 @@ Imports Newtonsoft.Json
End Set
End Property
<JsonProperty(NameOf(Tag))>
Public Property TagString As String
Get
If TypeOf Tag Is String Then
Return Tag
Else
Return String.Empty
End If
End Get
Set(value As String)
Tag = value
End Set
End Property
Public Property EnableResize As Boolean
Get
If resizeEngine Is Nothing Then
@@ -443,7 +481,7 @@ Imports Newtonsoft.Json
End Sub
Public Sub Draw(e As PaintEventArgs)
Draw(e, PointF.Empty)
Draw(e, e.ClipRectangle.Location)
End Sub
Public Sub Draw(e As PaintEventArgs, offset As PointF)
@@ -528,8 +566,10 @@ End Class
Public Class PaintingObjectList
Inherits List(Of PaintingObject)
<JsonIgnore>
Friend ReadOnly Property MyParent As PaintingControl
Friend Property EnableRaisingEvents As Boolean = True
<JsonIgnore>
Public ReadOnly Property Layering As New PaintingObjectListLayering(Me)
Public Sub New()

View File

@@ -0,0 +1,3 @@
Public Class PaintingObjectJsonSerializer
End Class

View File

@@ -1,11 +1,22 @@
Public Class PaintingObjectLayering
Imports Newtonsoft.Json
Public Class PaintingObjectLayering
'<JsonProperty(NameOf(PaintingObject))>
Private ReadOnly _PaintingObject As PaintingObject
<JsonIgnore>
Public ReadOnly Property PaintingObject As PaintingObject
Get
Return _PaintingObject
End Get
End Property
''' <summary>
''' Get the current object list from the painting object.
''' </summary>
''' <returns>Returns the current object list from the painting object.</returns>
<JsonIgnore>
Public ReadOnly Property ObjectList As PaintingObjectList
Get
Return PaintingObject.Parent.PaintingObjects
@@ -17,7 +28,7 @@
''' </summary>
''' <param name="obj"></param>
Public Sub New(obj As PaintingObject)
PaintingObject = obj
_PaintingObject = obj
End Sub
''' <summary>

View File

@@ -100,5 +100,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pilz.Drawing\Pilz.Drawing.vbproj" />
<ProjectReference Include="..\Pilz.Win32\Pilz.Win32.vbproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
Imports System.Runtime.CompilerServices
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms
Namespace Utils
@@ -6,10 +6,19 @@ Namespace Utils
Public Module DrawingControl
Private Const WM_SETREDRAW = 11
Private ReadOnly dicSuspendCount As New Dictionary(Of IntPtr, Integer)
<Extension>
Public Sub SuspendDrawing(control As Control)
SendMessage(control.Handle, WM_SETREDRAW, False, 0)
If Not dicSuspendCount.ContainsKey(control.Handle) Then
dicSuspendCount.Add(control.Handle, 1)
Else
dicSuspendCount(control.Handle) += 1
End If
If dicSuspendCount(control.Handle) = 1 Then
SendMessage(control.Handle, WM_SETREDRAW, False, 0)
End If
End Sub
<Extension>
@@ -19,8 +28,19 @@ Namespace Utils
<Extension>
Public Sub ResumeDrawing(control As Control, redraw As Boolean)
SendMessage(control.Handle, WM_SETREDRAW, True, 0)
If redraw Then control.Refresh()
Dim doRedraw As Boolean = True
If dicSuspendCount.ContainsKey(control.Handle) Then
dicSuspendCount(control.Handle) -= 1
If dicSuspendCount(control.Handle) >= 1 Then
doRedraw = False
End If
End If
If doRedraw Then
SendMessage(control.Handle, WM_SETREDRAW, True, 0)
If redraw Then control.Refresh()
End If
End Sub
End Module

View File

@@ -1,5 +1,7 @@
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports Pilz.Win32.Mapped
Imports Pilz.Win32.Native
Namespace Internals
@@ -10,12 +12,13 @@ Namespace Internals
''' Extrahiert das Icon aus einer Datei oder aus einem Ordner.
''' </summary>
''' <param name="FilePath">Hier übergeben Sie den Pfad der Datei von dem das Icon extrahiert werden soll.</param>
''' <param name="Small">Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben.</param>
Public Shared Function ExtractIcon(FilePath As String, Small As Boolean) As Icon
''' <param name="size">Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben.</param>
Public Shared Function ExtractIcon(FilePath As String, size As SystemIconSize) As Icon
Dim icon As Icon
Dim shinfo As New SHFILEINFO
Dim small As Boolean = size = SystemIconSize.Small
LibShell32.SHGetFileInfo(FilePath, 0, shinfo, Math.Truncate(Marshal.SizeOf(shinfo)), SHFILEINFO.SHGFI_ICON Or If(Small, SHFILEINFO.SHGFI_SMALLICON, SHFILEINFO.SHGFI_LARGEICON))
Shell32.SHGetFileInfo(FilePath, 0, shinfo, Math.Truncate(Marshal.SizeOf(shinfo)), SHFILEINFO.SHGFI_ICON Or If(small, SHFILEINFO.SHGFI_SMALLICON, SHFILEINFO.SHGFI_LARGEICON))
Try
icon = Icon.FromHandle(shinfo.hIcon)

View File

@@ -0,0 +1,208 @@
Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.Reflection
Imports System.Collections.Generic
Imports System.Drawing
Imports Pilz.Win32.Native
Imports Pilz.Win32.Native.Shell32
Imports Pilz.Win32.Mapped
Namespace Internals
Public Class IconFactory
#Region "Custom exceptions class"
Public Class IconNotFoundException
Inherits Exception
Public Sub New(ByVal fileName As String, ByVal index As Integer)
MyBase.New(String.Format("Icon with Id = {0} wasn't found in file {1}", index, fileName))
End Sub
End Class
Public Class UnableToExtractIconsException
Inherits Exception
Public Sub New(ByVal fileName As String, ByVal firstIconIndex As Integer, ByVal iconCount As Integer)
MyBase.New(String.Format("Tryed to extract {2} icons starting from the one with id {1} from the ""{0}"" file but failed", fileName, firstIconIndex, iconCount))
End Sub
End Class
#End Region
''' <summary>
''' Get the number of icons in the specified file.
''' </summary>
''' <param name="fileName">Full path of the file to look for.</param>
''' <returns></returns>
Private Shared Function GetIconsCountInFile(fileName As String) As Integer
Return ExtractIconEx(fileName, -1, Nothing, Nothing, 0)
End Function
#Region "ExtractIcon-like functions"
Public Shared Sub ExtractEx(ByVal fileName As String, ByVal largeIcons As List(Of Icon), ByVal smallIcons As List(Of Icon), ByVal firstIconIndex As Integer, ByVal iconCount As Integer)
'
' Memory allocations
'
Dim smallIconsPtrs As IntPtr() = Nothing
Dim largeIconsPtrs As IntPtr() = Nothing
If smallIcons IsNot Nothing Then
smallIconsPtrs = New IntPtr(iconCount - 1) {}
End If
If largeIcons IsNot Nothing Then
largeIconsPtrs = New IntPtr(iconCount - 1) {}
End If
'
' Call to native Win32 API
'
Dim apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount)
If apiResult <> iconCount Then
Throw New UnableToExtractIconsException(fileName, firstIconIndex, iconCount)
End If
'
' Fill lists
'
If smallIcons IsNot Nothing Then
smallIcons.Clear()
For Each actualIconPtr In smallIconsPtrs
smallIcons.Add(Icon.FromHandle(actualIconPtr))
Next
End If
If largeIcons IsNot Nothing Then
largeIcons.Clear()
For Each actualIconPtr In largeIconsPtrs
largeIcons.Add(Icon.FromHandle(actualIconPtr))
Next
End If
End Sub
Public Shared Function ExtractEx(ByVal fileName As String, ByVal size As SystemIconSize, ByVal firstIconIndex As Integer, ByVal iconCount As Integer) As List(Of Icon)
Dim iconList As New List(Of Icon)()
Select Case size
Case SystemIconSize.Large
ExtractEx(fileName, iconList, Nothing, firstIconIndex, iconCount)
Case SystemIconSize.Small
ExtractEx(fileName, Nothing, iconList, firstIconIndex, iconCount)
Case Else
Throw New ArgumentOutOfRangeException("size")
End Select
Return iconList
End Function
Public Shared Sub Extract(ByVal fileName As String, ByVal largeIcons As List(Of Icon), ByVal smallIcons As List(Of Icon))
Dim iconCount = GetIconsCountInFile(fileName)
ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount)
End Sub
Public Shared Function Extract(ByVal fileName As String, ByVal size As SystemIconSize) As List(Of Icon)
Dim iconCount = GetIconsCountInFile(fileName)
Return ExtractEx(fileName, size, 0, iconCount)
End Function
Public Shared Function ExtractOne(ByVal fileName As String, ByVal index As Integer, ByVal size As SystemIconSize) As Icon
Try
Dim iconList = ExtractEx(fileName, size, index, 1)
Return iconList(0)
Catch __unusedUnableToExtractIconsException1__ As UnableToExtractIconsException
Throw New IconNotFoundException(fileName, index)
End Try
End Function
Public shared Sub ExtractOne(ByVal fileName As String, ByVal index As Integer, <Out> ByRef largeIcon As Icon, <Out> ByRef smallIcon As Icon)
Dim smallIconList As List(Of Icon) = New List(Of Icon)()
Dim largeIconList As List(Of Icon) = New List(Of Icon)()
Try
ExtractEx(fileName, largeIconList, smallIconList, index, 1)
largeIcon = largeIconList(0)
smallIcon = smallIconList(0)
Catch __unusedUnableToExtractIconsException1__ As UnableToExtractIconsException
Throw New IconNotFoundException(fileName, index)
End Try
End Sub
#End Region
'this will look throw the registry
'to find if the Extension have an icon.
Public Shared Function IconFromExtension(ByVal extension As String, ByVal size As SystemIconSize) As Icon
' Add the '.' to the extension if needed
If extension(0) <> "."c Then extension = "."c & extension
'opens the registry for the wanted key.
Dim Root = Registry.ClassesRoot
Dim ExtensionKey = Root.OpenSubKey(extension)
ExtensionKey.GetValueNames()
Dim ApplicationKey As RegistryKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString())
'gets the name of the file that have the icon.
Dim IconLocation As String = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString()
Dim IconPath = IconLocation.Split(","c)
If Equals(IconPath(1), Nothing) Then IconPath(1) = "0"
Dim Large = New IntPtr(0) {}, Small = New IntPtr(0) {}
'extracts the icon from the file.
ExtractIconEx(IconPath(0), Convert.ToInt16(IconPath(1)), Large, Small, 1)
Return If(size = SystemIconSize.Large, Icon.FromHandle(Large(0)), Icon.FromHandle(Small(0)))
End Function
Public Shared Function IconFromExtensionShell(ByVal extension As String, ByVal size As SystemIconSize) As Icon
'add '.' if nessesry
If extension(0) <> "."c Then extension = "."c & extension
'temp struct for getting file shell info
Dim fileInfo As SHFILEINFO = New SHFILEINFO()
SHGetFileInfo(extension, 0, fileInfo, Marshal.SizeOf(fileInfo), FileInfoFlags.SHGFI_ICON Or FileInfoFlags.SHGFI_USEFILEATTRIBUTES Or CType(size, FileInfoFlags))
Return Icon.FromHandle(fileInfo.hIcon)
End Function
Public Shared Function IconFromResource(ByVal resourceName As String) As Icon
Dim assembly As Assembly = Assembly.GetCallingAssembly()
Return New Icon(assembly.GetManifestResourceStream(resourceName))
End Function
''' <summary>
''' Parse strings in registry who contains the name of the icon and
''' the index of the icon an return both parts.
''' </summary>
''' <param name="regString">The full string in the form "path,index" as found in registry.</param>
''' <param name="fileName">The "path" part of the string.</param>
''' <param name="index">The "index" part of the string.</param>
Public Shared Sub ExtractInformationsFromRegistryString(ByVal regString As String, <Out> ByRef fileName As String, <Out> ByRef index As Integer)
If Equals(regString, Nothing) Then
Throw New ArgumentNullException("regString")
End If
If regString.Length = 0 Then
Throw New ArgumentException("The string should not be empty.", "regString")
End If
index = 0
Dim strArr = regString.Replace("""", "").Split(","c)
fileName = strArr(0).Trim()
If strArr.Length > 1 Then
Call Integer.TryParse(strArr(1).Trim(), index)
End If
End Sub
Public Shared Function ExtractFromRegistryString(ByVal regString As String, ByVal size As SystemIconSize) As Icon
Dim fileName As String
Dim index As Integer
ExtractInformationsFromRegistryString(regString, fileName, index)
Return ExtractOne(fileName, index, size)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,17 @@
Imports System.Drawing
Namespace Mapped
Public Module FileTypeIcons
Public Function ExtractIconFromFilePath(filePath As String, size As SystemIconSize) As Icon
Return Internals.IconExtractor.ExtractIcon(filePath, size)
End Function
Public Function ExtractIconFromFileExtension(fileExtension As String, size As SystemIconSize) As Icon
Return Internals.IconFactory.IconFromExtensionShell(fileExtension, size)
End Function
End Module
End Namespace

View File

@@ -0,0 +1,12 @@
Namespace Mapped
''' <summary>
''' Two constants extracted from the FileInfoFlags, the only that are
''' meaningfull for the user of this class.
''' </summary>
Public Enum SystemIconSize As Integer
Large
Small
End Enum
End Namespace

View File

@@ -0,0 +1,20 @@
Namespace Native
<Flags>
Public Enum FileInfoFlags As Integer
''' <summary>
''' Retrieve the handle to the icon that represents the file and the index
''' of the icon within the system image list. The handle is copied to the
''' hIcon member of the structure specified by psfi, and the index is copied
''' to the iIcon member.
''' </summary>
SHGFI_ICON = &H100
''' <summary>
''' Indicates that the function should not attempt to access the file
''' specified by pszPath. Rather, it should act as if the file specified by
''' pszPath exists with the file attributes passed in dwFileAttributes.
''' </summary>
SHGFI_USEFILEATTRIBUTES = &H10
End Enum
End Namespace

View File

@@ -1,9 +0,0 @@
Namespace Native
Public Class LibShell32
Public Declare Function SHGetFileInfo Lib "shell32.dll" (ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbSizeFileInfo As UInteger, ByVal uFlags As UInteger) As IntPtr
End Class
End Namespace

View File

@@ -0,0 +1,21 @@
Imports System.Runtime.InteropServices
Namespace Native
<StructLayout(LayoutKind.Sequential)>
Public Structure POINT
Public Sub New(ByVal p As System.Drawing.Point)
Me.x = p.X
Me.y = p.Y
End Sub
Public Sub New(ByVal x As Integer, ByVal y As Integer)
Me.x = x
Me.y = y
End Sub
Public x As Integer
Public y As Integer
End Structure
End Namespace

82
Pilz.Win32/Native/RECT.vb Normal file
View File

@@ -0,0 +1,82 @@
Imports System.Drawing
Imports System.Runtime.InteropServices
Namespace Native
<Serializable, StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
Public Sub New(ByVal left_ As Integer, ByVal top_ As Integer, ByVal right_ As Integer, ByVal bottom_ As Integer)
Left = left_
Top = top_
Right = right_
Bottom = bottom_
End Sub
Public Sub New(ByVal r As Rectangle)
Left = r.Left
Top = r.Top
Right = r.Right
Bottom = r.Bottom
End Sub
Public ReadOnly Property Height As Integer
Get
Return Bottom - Top
End Get
End Property
Public ReadOnly Property Width As Integer
Get
Return Right - Left
End Get
End Property
Public ReadOnly Property Size As System.Drawing.Size
Get
Return New System.Drawing.Size(Width, Height)
End Get
End Property
Public ReadOnly Property Location As System.Drawing.Point
Get
Return New System.Drawing.Point(Left, Top)
End Get
End Property
Public Function ToRectangle() As Rectangle
Return Rectangle.FromLTRB(Left, Top, Right, Bottom)
End Function
Public Shared Function FromRectangle(ByVal rectangle As Rectangle) As RECT
Return New RECT(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom)
End Function
Public Overrides Function GetHashCode() As Integer
Return Left ^ ((Top << 13) Or (Top >> &H13)) _
^ ((Width << &H1A) Or (Width >> 6)) _
^ ((Height << 7) Or (Height >> &H19))
End Function
Public Shared Function FromXYWH(ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer) As RECT
Return New RECT(x, y, x + width, y + height)
End Function
Public Shared Widening Operator CType(ByVal rect As RECT) As Rectangle
Return Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom)
End Operator
Public Shared Widening Operator CType(ByVal rect As Rectangle) As RECT
Return New RECT(rect.Left, rect.Top, rect.Right, rect.Bottom)
End Operator
Public Overrides Function ToString() As String
Return "Left=" & Me.Left & ", Top=" & Me.Top & ", Right=" & Me.Right & ", Bottom=" & Me.Bottom
End Function
End Structure
End Namespace

View File

@@ -2,18 +2,43 @@
Namespace Native
''' <summary>
''' Contains information about a file object.
''' </summary>
<StructLayout(LayoutKind.Sequential)>
Public Structure SHFILEINFO
Public Const SHGFI_ICON As UInteger = &H100
Public Const SHGFI_LARGEICON As UInteger = &H0
Public Const SHGFI_SMALLICON As UInteger = &H1
''' <summary>
''' Handle to the icon that represents the file. You are responsible for
''' destroying this handle with DestroyIcon when you no longer need it.
''' </summary>
Public hIcon As IntPtr
''' <summary>
''' Index of the icon image within the system image list.
''' </summary>
Public iIcon As IntPtr
''' <summary>
''' Array of values that indicates the attributes of the file object.
''' For information about these values, see the IShellFolder::GetAttributesOf
''' method.
''' </summary>
Public dwAttributes As UInteger
''' <summary>
''' String that contains the name of the file as it appears in the Microsoft
''' Windows Shell, or the path and file name of the file that contains the
''' icon representing the file.
''' </summary>
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)>
Public szDisplayName As String
''' <summary>
''' String that describes the type of file.
''' </summary>
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)>
Public szTypeName As String
End Structure

View File

@@ -0,0 +1,68 @@
Imports System.Runtime.InteropServices
Namespace Native
Public Class Shell32
''' <summary>
''' Creates an array of handles to large or small icons extracted from
''' the specified executable file, dynamic-link library (DLL), or icon
''' file.
''' </summary>
''' <param name="lpszFile">
''' Name of an executable file, DLL, or icon file from which icons will
''' be extracted.
''' </param>
''' <param name="nIconIndex">
''' <para>
''' Specifies the zero-based index of the first icon to extract. For
''' example, if this value is zero, the function extracts the first
''' icon in the specified file.
''' </para>
''' <para>
''' If this value is <20>1 and <paramrefname="phiconLarge"/> and
''' <paramrefname="phiconSmall"/> are both NULL, the function returns
''' the total number of icons in the specified file. If the file is an
''' executable file or DLL, the return value is the number of
''' RT_GROUP_ICON resources. If the file is an .ico file, the return
''' value is 1.
''' </para>
''' <para>
''' Windows 95/98/Me, Windows NT 4.0 and later: If this value is a
''' negative number and either <paramrefname="phiconLarge"/> or
''' <paramrefname="phiconSmall"/> is not NULL, the function begins by
''' extracting the icon whose resource identifier is equal to the
''' absolute value of <paramrefname="nIconIndex"/>. For example, use -3
''' to extract the icon whose resource identifier is 3.
''' </para>
''' </param>
''' <param name="phIconLarge">
''' An array of icon handles that receives handles to the large icons
''' extracted from the file. If this parameter is NULL, no large icons
''' are extracted from the file.
''' </param>
''' <param name="phIconSmall">
''' An array of icon handles that receives handles to the small icons
''' extracted from the file. If this parameter is NULL, no small icons
''' are extracted from the file.
''' </param>
''' <param name="nIcons">
''' Specifies the number of icons to extract from the file.
''' </param>
''' <returns>
''' If the <paramrefname="nIconIndex"/> parameter is -1, the
''' <paramrefname="phIconLarge"/> parameter is NULL, and the
''' <paramrefname="phiconSmall"/> parameter is NULL, then the return
''' value is the number of icons contained in the specified file.
''' Otherwise, the return value is the number of icons successfully
''' extracted from the file.
''' </returns>
<DllImport("Shell32", CharSet:=CharSet.Auto)>
Public Shared Function ExtractIconEx(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpszFile As String, ByVal nIconIndex As Integer, ByVal phIconLarge As IntPtr(), ByVal phIconSmall As IntPtr(), ByVal nIcons As Integer) As Integer
End Function
Public Declare Function SHGetFileInfo Lib "shell32.dll" (ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbSizeFileInfo As UInteger, ByVal uFlags As UInteger) As IntPtr
End Class
End Namespace

View File

@@ -0,0 +1,17 @@
Imports System.Runtime.InteropServices
Namespace Native
Public Class User32
<DllImport("user32")>
Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef r As RECT) As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function ChildWindowFromPointEx(ByVal hWndParent As IntPtr, ByVal pt As POINT, ByVal uFlags As UInteger) As IntPtr
End Function
End Class
End Namespace

View File

@@ -0,0 +1,11 @@
Namespace Native
<Flags>
Public Enum WindowFromPointFlags
CWP_ALL = &H0
CWP_SKIPINVISIBLE = &H1
CWP_SKIPDISABLED = &H2
CWP_SKIPTRANSPARENT = &H4
End Enum
End Namespace

View File

@@ -30,28 +30,45 @@ Namespace Runtime
Get
Static t As OSType? = Nothing
If t Is Nothing Then
Dim windir As String = Environment.GetEnvironmentVariable("windir")
If t Is Nothing Then
If Not String.IsNullOrEmpty(windir) AndAlso windir.Contains("\") AndAlso Directory.Exists(windir) Then
t = OSType.Windows
ElseIf File.Exists("/proc/sys/kernel/ostype") Then
Dim osTypeString As String = File.ReadAllText("/proc/sys/kernel/ostype")
If osTypeString.StartsWith("Linux", StringComparison.OrdinalIgnoreCase) Then
' Note: Android gets here too
t = OSType.Linux
Else
t = OSType.Unknown
End If
ElseIf File.Exists("/System/Library/CoreServices/SystemVersion.plist") Then
' Note: iOS gets here too
t = OSType.OSX
Else
t = OSType.Unknown
End If
End If
Dim windir = Environment.GetEnvironmentVariable("windir")
Const ostypeDirWine = "Z:\proc\sys\kernel\ostype"
Const ostypeDirNative = "/proc/sys/kernel/ostype"
Const systemVersionWine = "Z:\System\Library\CoreServices\SystemVersion.plist"
Const systemVersionNative = "/System/Library/CoreServices/SystemVersion.plist"
Return t
If File.Exists(ostypeDirWine) Then ' Linux using wine
Dim osTypeString As String = File.ReadAllText(ostypeDirWine)
If osTypeString.StartsWith("Linux", StringComparison.OrdinalIgnoreCase) Then
' Note: Android gets here too
t = OSType.Linux
Else
t = OSType.Unknown
End If
ElseIf File.Exists(ostypeDirNative) Then ' Linux native
Dim osTypeString As String = File.ReadAllText(ostypeDirNative)
If osTypeString.StartsWith("Linux", StringComparison.OrdinalIgnoreCase) Then
' Note: Android gets here too
t = OSType.Linux
Else
t = OSType.Unknown
End If
ElseIf File.Exists(systemVersionWine) Then ' OSX using wine
' Note: iOS gets here too
t = OSType.OSX
ElseIf File.Exists(systemVersionNative) Then ' OSX native
' Note: iOS gets here too
t = OSType.OSX
ElseIf Not String.IsNullOrEmpty(windir) AndAlso Directory.Exists(windir) AndAlso Path.DirectorySeparatorChar = "\"c Then ' Windows
t = OSType.Windows
Else
t = OSType.Unknown
End If
End If
Return t
End Get
End Property