diff --git a/Pilz.Cryptography/IUniquieID.cs b/Pilz.Cryptography/IUniquieID.cs new file mode 100644 index 0000000..34bc49e --- /dev/null +++ b/Pilz.Cryptography/IUniquieID.cs @@ -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); + } +} diff --git a/Pilz.Cryptography/UniquieID.cs b/Pilz.Cryptography/UniquieID.cs index 16efa58..dad0034 100644 --- a/Pilz.Cryptography/UniquieID.cs +++ b/Pilz.Cryptography/UniquieID.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Pilz.Cryptography { - public class UniquieID + public class UniquieID : IUniquieID { private static int currentSimpleID = 0; @@ -72,27 +72,60 @@ 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; - return sn; + 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 Win32_PhysicalMedia_SerialNumber; } public override string ToString() => ID; public override bool Equals(object obj) { + var res = false; var iD = obj as UniquieID; - return iD != null && - _iD == iD._iD; + + if (iD is object) + { + if (ReferenceEquals(res, iD)) + res = 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) + res = _iD.Equals(iD._iD); + } + } + + return res; } public override int GetHashCode() @@ -104,7 +137,7 @@ namespace Pilz.Cryptography 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 static bool operator ==(UniquieID left, UniquieID right) => left.ID == right.ID; - public static bool operator !=(UniquieID left, UniquieID 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); } } diff --git a/Pilz.UI/Utilities/DrawingControl.vb b/Pilz.UI/Utilities/DrawingControl.vb index 02b44a8..9dd45a4 100644 --- a/Pilz.UI/Utilities/DrawingControl.vb +++ b/Pilz.UI/Utilities/DrawingControl.vb @@ -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) 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 @@ -19,8 +28,19 @@ Namespace Utils 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 diff --git a/Pilz.Win32/Internals/IconExtractor.vb b/Pilz.Win32/Internals/IconExtractor.vb index d6487b9..1411abe 100644 --- a/Pilz.Win32/Internals/IconExtractor.vb +++ b/Pilz.Win32/Internals/IconExtractor.vb @@ -1,5 +1,7 @@ Imports System.Drawing Imports System.Runtime.InteropServices + +Imports Pilz.Win32.Mapped Imports Pilz.Win32.Native Namespace Internals @@ -10,10 +12,11 @@ Namespace Internals ''' Extrahiert das Icon aus einer Datei oder aus einem Ordner. ''' ''' Hier übergeben Sie den Pfad der Datei von dem das Icon extrahiert werden soll. - ''' Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben. - Public Shared Function ExtractIcon(FilePath As String, Small As Boolean) As Icon + ''' Bei übergabe von true wird ein kleines und bei false ein großes Icon zurück gegeben. + 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)) diff --git a/Pilz.Win32/Internals/IconFactory.vb b/Pilz.Win32/Internals/IconFactory.vb new file mode 100644 index 0000000..26ff50f --- /dev/null +++ b/Pilz.Win32/Internals/IconFactory.vb @@ -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 + + + ''' + ''' Get the number of icons in the specified file. + ''' + ''' Full path of the file to look for. + ''' + 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, ByRef largeIcon As Icon, 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 + + ''' + ''' Parse strings in registry who contains the name of the icon and + ''' the index of the icon an return both parts. + ''' + ''' The full string in the form "path,index" as found in registry. + ''' The "path" part of the string. + ''' The "index" part of the string. + Public Shared Sub ExtractInformationsFromRegistryString(ByVal regString As String, ByRef fileName As String, 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 diff --git a/Pilz.Win32/Mapped/IconExtractor.vb b/Pilz.Win32/Mapped/IconExtractor.vb new file mode 100644 index 0000000..c244ec4 --- /dev/null +++ b/Pilz.Win32/Mapped/IconExtractor.vb @@ -0,0 +1,17 @@ +Imports System.Drawing + +Namespace Mapped + + Public Module IconExtractor + + 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) + Return Internals.IconFactory.IconFromExtensionShell(fileExtension, size) + End Function + + End Module + +End Namespace diff --git a/Pilz.Win32/Mapped/SystemIconSize.vb b/Pilz.Win32/Mapped/SystemIconSize.vb new file mode 100644 index 0000000..99bd177 --- /dev/null +++ b/Pilz.Win32/Mapped/SystemIconSize.vb @@ -0,0 +1,12 @@ +Namespace Mapped + + ''' + ''' Two constants extracted from the FileInfoFlags, the only that are + ''' meaningfull for the user of this class. + ''' + Public Enum SystemIconSize As Integer + Large + Small + End Enum + +End Namespace diff --git a/Pilz.Win32/Native/FileInfoFlags.vb b/Pilz.Win32/Native/FileInfoFlags.vb new file mode 100644 index 0000000..120f982 --- /dev/null +++ b/Pilz.Win32/Native/FileInfoFlags.vb @@ -0,0 +1,20 @@ +Namespace Native + + + Public Enum FileInfoFlags As Integer + ''' + ''' 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. + ''' + SHGFI_ICON = &H100 + ''' + ''' 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. + ''' + SHGFI_USEFILEATTRIBUTES = &H10 + End Enum + +End Namespace \ No newline at end of file diff --git a/Pilz.Win32/Native/SHFILEINFO.vb b/Pilz.Win32/Native/SHFILEINFO.vb index 2cd55f8..3717b55 100644 --- a/Pilz.Win32/Native/SHFILEINFO.vb +++ b/Pilz.Win32/Native/SHFILEINFO.vb @@ -2,18 +2,43 @@ Namespace Native - + ''' + ''' Contains information about a file object. + ''' Public Structure SHFILEINFO Public Const SHGFI_ICON As UInteger = &H100 Public Const SHGFI_LARGEICON As UInteger = &H0 Public Const SHGFI_SMALLICON As UInteger = &H1 - + ''' + ''' Handle to the icon that represents the file. You are responsible for + ''' destroying this handle with DestroyIcon when you no longer need it. + ''' Public hIcon As IntPtr + + ''' + ''' Index of the icon image within the system image list. + ''' Public iIcon As IntPtr + + ''' + ''' Array of values that indicates the attributes of the file object. + ''' For information about these values, see the IShellFolder::GetAttributesOf + ''' method. + ''' Public dwAttributes As UInteger + + ''' + ''' 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. + ''' Public szDisplayName As String + + ''' + ''' String that describes the type of file. + ''' Public szTypeName As String End Structure diff --git a/Pilz.Win32/Native/Shell32.vb b/Pilz.Win32/Native/Shell32.vb new file mode 100644 index 0000000..f6595e1 --- /dev/null +++ b/Pilz.Win32/Native/Shell32.vb @@ -0,0 +1,70 @@ +Imports System.Runtime.InteropServices + +Namespace Native + + Public Class Shell32 + + ''' + ''' Creates an array of handles to large or small icons extracted from + ''' the specified executable file, dynamic-link library (DLL), or icon + ''' file. + ''' + ''' + ''' Name of an executable file, DLL, or icon file from which icons will + ''' be extracted. + ''' + ''' + ''' + ''' 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. + ''' + ''' + ''' If this value is �1 and and + ''' 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. + ''' + ''' + ''' Windows 95/98/Me, Windows NT 4.0 and later: If this value is a + ''' negative number and either or + ''' is not NULL, the function begins by + ''' extracting the icon whose resource identifier is equal to the + ''' absolute value of . For example, use -3 + ''' to extract the icon whose resource identifier is 3. + ''' + ''' + ''' + ''' 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. + ''' + ''' + ''' 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. + ''' + ''' + ''' Specifies the number of icons to extract from the file. + ''' + ''' + ''' If the parameter is -1, the + ''' parameter is NULL, and the + ''' 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. + ''' + + Public Shared Function ExtractIconEx( 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 Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As Integer, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As Integer, ByVal uFlags As FileInfoFlags) As IntPtr + End Function + + End Class + +End Namespace