Autor
|
Tema: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets) (Leído 556,862 veces)
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Comparto una forma que he ideado para automatizar la traducción, al idioma actual de la aplicación, los valores booleanos en un propertygrid (por ejemplo), mediante el uso clases de atributos.  
El modo de empleo es muy sencillo: public class TestClass <LocalizableBoolean> <TypeConverter(GetType(LocalizableBooleanConverter))> Public Property FeatureEnabled As Boolean = True end class
Me.PropertyGrid1.SelectedObject = new TestClass()
También se puede utilizar de esta forma alternativa para una representación arbitraria en los idiomas que se especifiquen mediante un string separado por comas (en este ejemplo, el español y el francés): <LocalizableBoolean("es, fr", "ssssí!!, Oui!", "nope!, Non!")> <TypeConverter(GetType(LocalizableBooleanConverter))> Public Property FeatureEnabled As Boolean = True
 El código:LocalizedBoolean.vb ''' <summary> ''' Represents localized strings for <see langword="True"/> and <see langword="False"/> <see cref="Boolean"/> values. ''' </summary> <DebuggerStepThrough> Public NotInheritable Class LocalizedBoolean ''' <summary> ''' The <see cref="CultureInfo"/> that represents the region for ''' the localized strings in <see cref="LocalizedBoolean.True"/> ''' and <see cref="LocalizedBoolean.False"/> properties. ''' </summary> Public ReadOnly Property Culture As CultureInfo ''' <summary> ''' The localized string representation for <see langword="True"/> <see cref="Boolean"/> value. ''' </summary> Public ReadOnly Property [True] As String ''' <summary> ''' The localized string representation for <see langword="False"/> <see cref="Boolean"/> value. ''' </summary> Public ReadOnly Property [False] As String ''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> that represents the region for the localized strings. ''' </param> ''' ''' <param name="trueString"> ''' The localized string representation for <see langword="True"/> <see cref="Boolean"/> value. ''' </param> ''' ''' <param name="falseString"> ''' The localized string representation for <see langword="False"/> <see cref="Boolean"/> value. ''' </param> Public Sub New(culture As CultureInfo, trueString As String, falseString As String) If culture Is Nothing Then Throw New ArgumentNullException(paramName:=NameOf(culture)) End If If String.IsNullOrWhiteSpace(trueString) Then Throw New ArgumentNullException(paramName:=NameOf(trueString)) End If If String.IsNullOrWhiteSpace(falseString) Then Throw New ArgumentNullException(paramName:=NameOf(falseString)) End If Me.Culture = culture Me.True = trueString Me.False = falseString End Sub ''' <summary> ''' Prevents a default instance of the <see cref="LocalizedBoolean"/> class from being created. ''' </summary> Private Sub New() End Sub End Class
LocalizableBooleanAttribute.vb ''' <summary> ''' Specifies that a <see cref="Boolean"/> property can display localized string representations ''' for <see langword="True"/> and <see langword="False"/> values. ''' </summary> <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=True)> <DebuggerStepThrough> Public NotInheritable Class LocalizableBooleanAttribute : Inherits Attribute
''' <summary> ''' Gets the localized boolean representations. ''' <para></para> ''' The dictionary Key is the ISO 639-1 two-letter code for the language. ''' </summary> Public ReadOnly Property Localizations As Dictionary(Of String, LocalizedBoolean)
''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> Public Sub New() Me.Localizations = New Dictionary(Of String, LocalizedBoolean)(StringComparison.OrdinalIgnoreCase) From { {"af", New LocalizedBoolean(CultureInfo.GetCultureInfo("af"), "Ja", "Nee")}, ' Afrikaans {"am", New LocalizedBoolean(CultureInfo.GetCultureInfo("am"), "እወዳለሁ", "አይደለሁ")}, ' Amharic {"ar", New LocalizedBoolean(CultureInfo.GetCultureInfo("ar"), "نعم", "لا")}, ' Arabic {"az", New LocalizedBoolean(CultureInfo.GetCultureInfo("az"), "Bəli", "Xeyr")}, ' Azerbaijani {"be", New LocalizedBoolean(CultureInfo.GetCultureInfo("be"), "Так", "Не")}, ' Belarusian {"bg", New LocalizedBoolean(CultureInfo.GetCultureInfo("bg"), "Да", "Не")}, ' Bulgarian {"bn", New LocalizedBoolean(CultureInfo.GetCultureInfo("bn"), "হ্যাঁ", "না")}, ' Bengali {"ca", New LocalizedBoolean(CultureInfo.GetCultureInfo("ca"), "Sí", "No")}, ' Catalan {"cs", New LocalizedBoolean(CultureInfo.GetCultureInfo("cs"), "Ano", "Ne")}, ' Czech {"cy", New LocalizedBoolean(CultureInfo.GetCultureInfo("cy"), "Ie", "Na")}, ' Welsh {"da", New LocalizedBoolean(CultureInfo.GetCultureInfo("da"), "Ja", "Nej")}, ' Danish {"de", New LocalizedBoolean(CultureInfo.GetCultureInfo("de"), "Ja", "Nein")}, ' German {"el", New LocalizedBoolean(CultureInfo.GetCultureInfo("el"), "Ναι", "Όχι")}, ' Greek {"en", New LocalizedBoolean(CultureInfo.GetCultureInfo("en"), "Yes", "No")}, ' English {"es", New LocalizedBoolean(CultureInfo.GetCultureInfo("es"), "Sí", "No")}, ' Spanish {"et", New LocalizedBoolean(CultureInfo.GetCultureInfo("et"), "Jah", "Ei")}, ' Estonian {"eu", New LocalizedBoolean(CultureInfo.GetCultureInfo("eu"), "Bai", "Ez")}, ' Basque {"fa", New LocalizedBoolean(CultureInfo.GetCultureInfo("fa"), "بله", "خیر")}, ' Persian {"fi", New LocalizedBoolean(CultureInfo.GetCultureInfo("fi"), "Kyllä", "Ei")}, ' Finnish {"fr", New LocalizedBoolean(CultureInfo.GetCultureInfo("fr"), "Oui", "Non")}, ' French {"ga", New LocalizedBoolean(CultureInfo.GetCultureInfo("ga"), "Tá", "Níl")}, ' Irish {"gd", New LocalizedBoolean(CultureInfo.GetCultureInfo("gd"), "Tha", "Chan eil")}, ' Scottish Gaelic {"gl", New LocalizedBoolean(CultureInfo.GetCultureInfo("gl"), "Si", "Non")}, ' Galician {"gu", New LocalizedBoolean(CultureInfo.GetCultureInfo("gu"), "હા", "ના")}, ' Gujarati {"hi", New LocalizedBoolean(CultureInfo.GetCultureInfo("hi"), "हाँ", "नहीं")}, ' Hindi {"hr", New LocalizedBoolean(CultureInfo.GetCultureInfo("hr"), "Da", "Ne")}, ' Croatian {"ht", New LocalizedBoolean(CultureInfo.GetCultureInfo("ht"), "Wi", "Pa")}, ' Haitian Creole {"hu", New LocalizedBoolean(CultureInfo.GetCultureInfo("hu"), "Igen", "Nem")}, ' Hungarian {"id", New LocalizedBoolean(CultureInfo.GetCultureInfo("id"), "Ya", "Tidak")}, ' Indonesian {"ig", New LocalizedBoolean(CultureInfo.GetCultureInfo("ig"), "Ee", "Mba")}, ' Igbo {"is", New LocalizedBoolean(CultureInfo.GetCultureInfo("is"), "Já", "Nei")}, ' Icelandic {"it", New LocalizedBoolean(CultureInfo.GetCultureInfo("it"), "Sì", "No")}, ' Italian {"ja", New LocalizedBoolean(CultureInfo.GetCultureInfo("ja"), "はい", "いいえ")}, ' Japanese {"jv", New LocalizedBoolean(CultureInfo.GetCultureInfo("jv"), "Iya", "Ora")}, ' Javanese {"kk", New LocalizedBoolean(CultureInfo.GetCultureInfo("kk"), "Иә", "Жоқ")}, ' Kazakh {"km", New LocalizedBoolean(CultureInfo.GetCultureInfo("km"), "បាទ/ចាស", "ទេ")}, ' Khmer {"kn", New LocalizedBoolean(CultureInfo.GetCultureInfo("kn"), "ಹೌದು", "ಇಲ್ಲ")}, ' Kannada {"ko", New LocalizedBoolean(CultureInfo.GetCultureInfo("ko"), "예", "아니오")}, ' Korean {"ku", New LocalizedBoolean(CultureInfo.GetCultureInfo("ku"), "Belê", "Na")}, ' Kurdish (Kurmanji) {"ky", New LocalizedBoolean(CultureInfo.GetCultureInfo("ky"), "Ооба", "Жок")}, ' Kyrgyz {"la", New LocalizedBoolean(CultureInfo.GetCultureInfo("la"), "Ita", "Non")}, ' Latin {"lg", New LocalizedBoolean(CultureInfo.GetCultureInfo("lg"), "Yee", "Nedda")}, ' Luganda {"lt", New LocalizedBoolean(CultureInfo.GetCultureInfo("lt"), "Taip", "Ne")}, ' Lithuanian {"lv", New LocalizedBoolean(CultureInfo.GetCultureInfo("lv"), "Jā", "Nē")}, ' Latvian {"mg", New LocalizedBoolean(CultureInfo.GetCultureInfo("mg"), "Eny", "Tsia")}, ' Malagasy {"mi", New LocalizedBoolean(CultureInfo.GetCultureInfo("mi"), "Āe", "Kāo")}, ' Maori {"mk", New LocalizedBoolean(CultureInfo.GetCultureInfo("mk"), "Да", "Не")}, ' Macedonian {"ml", New LocalizedBoolean(CultureInfo.GetCultureInfo("ml"), "അതെ", "ഇല്ല")}, ' Malayalam {"mn", New LocalizedBoolean(CultureInfo.GetCultureInfo("mn"), "Тийм", "Үгүй")}, ' Mongolian {"mr", New LocalizedBoolean(CultureInfo.GetCultureInfo("mr"), "होय", "नाही")}, ' Marathi {"ms", New LocalizedBoolean(CultureInfo.GetCultureInfo("ms"), "Ya", "Tidak")}, ' Malay {"mt", New LocalizedBoolean(CultureInfo.GetCultureInfo("mt"), "Iva", "Le")}, ' Maltese {"my", New LocalizedBoolean(CultureInfo.GetCultureInfo("my"), "ဟုတ်ကဲ့", "မဟုတ်ဘူး")}, ' Burmese {"ne", New LocalizedBoolean(CultureInfo.GetCultureInfo("ne"), "हो", "होइन")}, ' Nepali {"nl", New LocalizedBoolean(CultureInfo.GetCultureInfo("nl"), "Ja", "Nee")}, ' Dutch {"no", New LocalizedBoolean(CultureInfo.GetCultureInfo("no"), "Ja", "Nei")}, ' Norwegian {"ny", New LocalizedBoolean(CultureInfo.GetCultureInfo("ny"), "Yewo", "Ayawo")}, ' Chichewa {"pa", New LocalizedBoolean(CultureInfo.GetCultureInfo("pa"), "ਹਾਂ", "ਨਹੀਂ")}, ' Punjabi {"pl", New LocalizedBoolean(CultureInfo.GetCultureInfo("pl"), "Tak", "Nie")}, ' Polish {"ps", New LocalizedBoolean(CultureInfo.GetCultureInfo("ps"), "هو", "نه")}, ' Pashto {"pt", New LocalizedBoolean(CultureInfo.GetCultureInfo("pt"), "Sim", "Não")}, ' Portuguese {"rm", New LocalizedBoolean(CultureInfo.GetCultureInfo("rm"), "Gia", "Betg")}, ' Romansh {"ro", New LocalizedBoolean(CultureInfo.GetCultureInfo("ro"), "Da", "Nu")}, ' Romanian {"ru", New LocalizedBoolean(CultureInfo.GetCultureInfo("ru"), "Да", "Нет")}, ' Russian {"sd", New LocalizedBoolean(CultureInfo.GetCultureInfo("sd"), "هاڻي", "نه")}, ' Sindhi {"si", New LocalizedBoolean(CultureInfo.GetCultureInfo("si"), "ඔව්", "නැත")}, ' Sinhala {"sk", New LocalizedBoolean(CultureInfo.GetCultureInfo("sk"), "Áno", "Nie")}, ' Slovak {"sl", New LocalizedBoolean(CultureInfo.GetCultureInfo("sl"), "Da", "Ne")}, ' Slovenian {"sm", New LocalizedBoolean(CultureInfo.GetCultureInfo("sm"), "Ioe", "Leai")}, ' Samoan {"sn", New LocalizedBoolean(CultureInfo.GetCultureInfo("sn"), "Yebo", "Cha")}, ' Shona {"so", New LocalizedBoolean(CultureInfo.GetCultureInfo("so"), "Haa", "Maya")}, ' Somali {"sq", New LocalizedBoolean(CultureInfo.GetCultureInfo("sq"), "Po", "Jo")}, ' Albanian {"sr", New LocalizedBoolean(CultureInfo.GetCultureInfo("sr"), "Да", "Не")}, ' Serbian (Cyrillic) {"su", New LocalizedBoolean(CultureInfo.GetCultureInfo("su"), "Iya", "Teu")}, ' Sundanese {"sv", New LocalizedBoolean(CultureInfo.GetCultureInfo("sv"), "Ja", "Nej")}, ' Swedish {"sw", New LocalizedBoolean(CultureInfo.GetCultureInfo("sw"), "Ndiyo", "Hapana")}, ' Swahili {"ta", New LocalizedBoolean(CultureInfo.GetCultureInfo("ta"), "ஆம்", "இல்லை")}, ' Tamil {"te", New LocalizedBoolean(CultureInfo.GetCultureInfo("te"), "అవును", "కాదు")}, ' Telugu {"tg", New LocalizedBoolean(CultureInfo.GetCultureInfo("tg"), "Ҳа", "Не")}, ' Tajik {"th", New LocalizedBoolean(CultureInfo.GetCultureInfo("th"), "ใช่", "ไม่")}, ' Thai {"ti", New LocalizedBoolean(CultureInfo.GetCultureInfo("ti"), "እወ", "አይወ")}, ' Tigrinya {"tk", New LocalizedBoolean(CultureInfo.GetCultureInfo("tk"), "Hawa", "Ýok")}, ' Turkmen {"to", New LocalizedBoolean(CultureInfo.GetCultureInfo("to"), "ʻIo", "ʻEa")}, ' Tongan {"tr", New LocalizedBoolean(CultureInfo.GetCultureInfo("tr"), "Evet", "Hayır")}, ' Turkish {"tt", New LocalizedBoolean(CultureInfo.GetCultureInfo("tt"), "Әйе", "Юк")}, ' Tatar {"ug", New LocalizedBoolean(CultureInfo.GetCultureInfo("ug"), "ھەئە", "ياق")}, ' Uighur {"uk", New LocalizedBoolean(CultureInfo.GetCultureInfo("uk"), "Так", "Ні")}, ' Ukrainian {"ur", New LocalizedBoolean(CultureInfo.GetCultureInfo("ur"), "جی ہاں", "نہیں")}, ' Urdu {"uz", New LocalizedBoolean(CultureInfo.GetCultureInfo("uz"), "Ha", "Yo'q")}, ' Uzbek {"vi", New LocalizedBoolean(CultureInfo.GetCultureInfo("vi"), "Có", "Không")}, ' Vietnamese {"xh", New LocalizedBoolean(CultureInfo.GetCultureInfo("xh"), "Ewe", "Hayi")}, ' Xhosa {"yi", New LocalizedBoolean(CultureInfo.GetCultureInfo("yi"), "יאָ", "ניי")}, ' Yiddish {"yo", New LocalizedBoolean(CultureInfo.GetCultureInfo("yo"), "Bẹẹni", "Bẹẹkoo")}, ' Yoruba {"zh", New LocalizedBoolean(CultureInfo.GetCultureInfo("zh"), "是", "不")}, ' Chinese (Simplified) {"zu", New LocalizedBoolean(CultureInfo.GetCultureInfo("zu"), "Yebo", "Cha")} ' Zulu } End Sub
''' <summary> ''' Initializes a new instance of the <see cref="LocalizedBoolean"/> class. ''' </summary> ''' ''' <param name="cultureNames"> ''' A comma-separated value of the ISO 639-1 two-letter code languages (e.g.: "en,es,fr"). ''' </param> ''' ''' <param name="trueStrings"> ''' A comma-separated value of the localized string representation for "True" boolean value (e.g.: "Yes,Sí,Oui"). ''' </param> ''' ''' <param name="falseStrings"> ''' A comma-separated value of the localized string representation for "False" boolean value (e.g.: "No,No,Non"). ''' </param> Public Sub New(cultureNames As String, trueStrings As String, falseStrings As String) Me.New()
If String.IsNullOrWhiteSpace(cultureNames) Then Throw New ArgumentNullException(paramName:=NameOf(cultureNames)) End If If String.IsNullOrWhiteSpace(trueStrings) Then Throw New ArgumentNullException(paramName:=NameOf(trueStrings)) End If If String.IsNullOrWhiteSpace(falseStrings) Then Throw New ArgumentNullException(paramName:=NameOf(falseStrings)) End If
Dim cultureNamesArray As String() = cultureNames.Split({","c}, StringSplitOptions.RemoveEmptyEntries) Dim trueStringsArray As String() = trueStrings.Split({","c}, StringSplitOptions.RemoveEmptyEntries) Dim falseStringsArray As String() = falseStrings.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
If cultureNamesArray.Length <> trueStringsArray.Length OrElse cultureNamesArray.Length <> falseStringsArray.Length Then Throw New InvalidOperationException("The comma-separated values must have the same amount of tokens.") End If
For i As Integer = 0 To cultureNamesArray.Length - 1 Dim cultureName As String = cultureNamesArray(i).Trim() Dim trueString As String = trueStringsArray(i).Trim() Dim falseString As String = falseStringsArray(i).Trim()
If cultureName.Length <> 2 Then Throw New InvalidOperationException("The culture name must be a ISO 639-1 two-letter code.") End If
Dim localizedBoolean As New LocalizedBoolean(CultureInfo.GetCultureInfo(cultureName), trueString, falseString) If Me.Localizations.ContainsKey(cultureName) Then Me.Localizations(cultureName) = localizedBoolean Else Me.Localizations.Add(cultureName, localizedBoolean) End If Next End Sub
End Class LocalizableBooleanConverter.vb ''' <summary> ''' Provides conversion functionality between Boolean values and localized strings representing "True" and "False" boolean values. ''' </summary> Public Class LocalizableBooleanConverter : Inherits TypeConverter ''' <summary> ''' The localized string representation for "True" boolean value. ''' </summary> Private trueString As String = "Yes" ''' <summary> ''' The localized string representation for "False" boolean value. ''' </summary> Private falseString As String = "No" ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType = GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType = GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepperBoundary> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As Globalization.CultureInfo, value As Object) As Object If TypeOf value Is String Then Dim stringValue As String = DirectCast(value, String) If String.Equals(stringValue, Me.trueString, StringComparison.OrdinalIgnoreCase) Then Return True ElseIf String.Equals(stringValue, Me.FalseString, StringComparison.OrdinalIgnoreCase) Then Return False End If End If Return MyBase.ConvertFrom(context, culture, value) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepperBoundary> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As Globalization.CultureInfo, value As Object, destinationType As Type) As Object If context IsNot Nothing Then Dim attributes As IEnumerable(Of LocalizableBooleanAttribute) = context.PropertyDescriptor.Attributes.OfType(Of LocalizableBooleanAttribute) For Each attr As LocalizableBooleanAttribute In attributes Dim uiCulture As CultureInfo = My.Application.UICulture Dim localizedBoolean As LocalizedBoolean = Nothing If attr.Localizations.ContainsKey(uiCulture.TwoLetterISOLanguageName) Then localizedBoolean = attr.Localizations(uiCulture.TwoLetterISOLanguageName) End If If localizedBoolean IsNot Nothing Then Me.trueString = localizedBoolean.True Me.falseString = localizedBoolean.False End If Next End If If destinationType = GetType(String) Then If TypeOf value Is Boolean Then Dim boolValue As Boolean = value Return If(boolValue, Me.trueString, Me.falseString) End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function ''' <summary> ''' Returns a collection of standard values for the data type this type converter is designed for when provided with a format context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context that can be used to ''' extract additional information about the environment from which this converter is invoked. ''' <para></para> ''' This parameter or properties of this parameter can be null. ''' </param> ''' ''' <returns> ''' A <see cref="StandardValuesCollection"/> that holds a standard set of valid values, ''' or <see langword="null" /> if the data type does not support a standard set of values. ''' </returns> Public Overrides Function GetStandardValues(context As ITypeDescriptorContext) As StandardValuesCollection Return New StandardValuesCollection(New Boolean() {True, False}) End Function ''' <summary> ''' Returns whether this object supports a standard set of values that can be picked from a list, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext" /> that provides a format context. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if <see cref="TypeConverter.GetStandardValues"/> should be called to ''' find a common set of values the object supports; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function GetStandardValuesSupported(context As ITypeDescriptorContext) As Boolean Return True End Function End Class
NOTA: El diccionario con los idiomas y sus equivalentes para "Sí" y "No", lo ha generado ChatGPT. Puede haber fallos en las traducciones, o en los códigos ISO 639-1 de dos letras. Además, faltaría añadir muchos más idiomas: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
|
|
« Última modificación: 26 Abril 2024, 21:30 pm por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Comparto otro type converter, para convertir los nombres de los valores de una Enum, a una representación amistosa para mostrarlos, por ejemplo, en un propertygrid. Este convertidor está optimizado para nombres de enumeración escritos en upper/lower snake case y upper/lower camel case. Las palabras se separan con un espacio en blanco convencional, y los guiones bajos se reemplazan por un espacio en blanco unicode. Ejemplo de uso: <TypeConverter(GetType(EnumNameFormatterConverter))> Public Enum TestEnum MyUpperCamelCaseName myLowerCamelCaseName My_Upper_Snake_Case_Name my_lower_snake_case_name MyMixed_value123_WTF456wtf_ ___rare_case_STRANGE_Name___________123_aZ_Az_4_5_6_ End Enum
<DefaultValue(TestEnum.MyUpperCamelCaseName)> Public Property Test As TestEnum = TestEnum.MyUpperCamelCaseName
Sin formato:  Con formato:  El código:EnumNameFormatterConverter.vb Imports System.ComponentModel Imports System.Globalization Imports System.Runtime.InteropServices Imports System.Text ''' <summary> ''' Provides conversion functionality between the value names of an <see cref="[Enum]"/> to a friendly string representation. ''' <para></para> ''' This converter is optimized for enum names written in either upper/lower snake case or upper/lower camel case: ''' <list type="bullet"> ''' <item><description>Snake case: Each word is separated by underscores (e.g.: "My_Value").</description></item> ''' <item><description>Camel case: Each word is separated by a capitalized letter (e.g.: "MyValue").</description></item> ''' </list> ''' </summary> Public NotInheritable Class EnumNameFormatterConverter : Inherits EnumConverter ''' <summary> ''' Initializes a new instance of the <see cref="EnumNameFormatterConverter"/> class. ''' </summary> ''' <param name="type">A <see cref="T:System.Type" /> that represents the type of enumeration to associate with this enumeration converter.</param> Public Sub New(type As Type) MyBase.New(type) End Sub ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType Is GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType Is GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object If TypeOf value Is String Then value = DirectCast(value, String).Replace(" ", "").Replace(Convert.ToChar(&H205F), "_"c) Return [Enum].Parse(Me.EnumType, value, ignoreCase:=True) End If Return MyBase.ConvertFrom(context, culture, value) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object If destinationType = GetType(String) Then Dim name As String = [Enum].GetName(value.GetType(), value) If Not String.IsNullOrEmpty(name) Then Return Me.FormatName(name) End If End If Return MyBase.ConvertTo(context, culture, value, destinationType) End Function ''' <summary> ''' Formats the name of a <see cref="[Enum]"/> value to a friendly name. ''' </summary> ''' ''' <param name="name"> ''' <see cref="[Enum]"/> value name. ''' </param> ''' ''' <returns> ''' The resulting friendly name. ''' </returns> <DebuggerStepThrough> Private Function FormatName(name As String) As String Dim sb As New StringBuilder() Dim previousChar As Char Dim previousCharIsWhiteSpace As Boolean Dim previousCharIsUpperLetter As Boolean Dim previousCharIsDigit As Boolean Dim lastParsedCharIsUnderscore As Boolean Dim firstCapitalizedLetterIsAdded As Boolean For i As Integer = 0 To name.Length - 1 Dim c As Char = name(i) If i = 0 Then If c.Equals("_"c) Then sb.Append(Convert.ToChar(Convert.ToChar(&H205F))) lastParsedCharIsUnderscore = True Else sb.Append(Char.ToUpper(c)) firstCapitalizedLetterIsAdded = True End If Continue For End If previousChar = sb.Chars(sb.Length - 1) previousCharIsWhiteSpace = previousChar.Equals(" "c) OrElse previousChar.Equals(Convert.ToChar(&H205F)) previousCharIsUpperLetter = Char.IsUpper(previousChar) previousCharIsDigit = Char.IsDigit(previousChar) If Char.IsLetter(c) Then If previousCharIsDigit AndAlso Not previousCharIsWhiteSpace Then sb.Append(" "c) End If If Char.IsUpper(c) Then If previousCharIsUpperLetter Then sb.Append(c) ElseIf Not previousCharIsWhiteSpace Then sb.Append(" "c) sb.Append(c) Else sb.Append(c) End If firstCapitalizedLetterIsAdded = True Else If Not firstCapitalizedLetterIsAdded Then sb.Append(Char.ToUpper(c)) firstCapitalizedLetterIsAdded = True Else sb.Append(c) End If End If ElseIf Char.IsDigit(c) Then If Not previousCharIsDigit AndAlso Not previousCharIsWhiteSpace Then sb.Append(" "c) End If sb.Append(c) ElseIf c.Equals("_"c) Then If lastParsedCharIsUnderscore OrElse Not previousCharIsWhiteSpace Then sb.Append(Convert.ToChar(&H205F)) ' Unicode white-space: " " lastParsedCharIsUnderscore = True End If Else sb.Append(c) lastParsedCharIsUnderscore = False End If Next i Return sb.ToString() End Function End Class
|
|
« Última modificación: 27 Abril 2024, 03:05 am por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Comparto un enfoque y uso alternativo al código que he publicado arriba. Este enfoque nos permite atribuir nombres específicos a una enumeración para mostrarlos en un property grid. Modo de empleo: Imports System.Componentmodel <TypeConverter(GetType(EnumDescriptionConverter))> Public Enum TestEnum <Description("My Upper Camel Case Name")> MyUpperCamelCaseName = 1 <Description("My Lower Camel Case Name")> myLowerCamelCaseName = 2 <Description("My Upper Snake Case Name")> My_Upper_Snake_Case_Name = 3 <Description("My lower snake case Name")> my_lower_snake_case_Name = 4 <Description("My Mixed value 123 QWERTY 456 wtf_")> MyMixed_value123_QWERTY456wtf_ = 5 <Description("Rare case STRANGE Name 123 aZ Az 456")> ___rare_case_STRANGE_Name___________123_aZ_Az_4_5_6_ = 6 End Enum
<DefaultValue(TestEnum.MyUpperCamelCaseName)> Public Property Test As TestEnum = TestEnum.MyUpperCamelCaseName
El código: Imports System.ComponentModel Imports System.Globalization Imports System.Reflection Public NotInheritable Class EnumDescriptionConverter : Inherits EnumConverter ''' <summary> ''' Initializes a new instance of the <see cref="EnumDescriptionConverter"/> class. ''' </summary> ''' <param name="type">A <see cref="T:System.Type" /> that represents the type of enumeration to associate with this enumeration converter.</param> Public Sub New(type As Type) MyBase.New(type) End Sub ''' <summary> ''' Returns whether this converter can convert the object to the specified type, using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="destinationType"> ''' A <see cref="Type"/> that represents the type you want to convert to. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean Return destinationType Is GetType(String) OrElse MyBase.CanConvertTo(context, destinationType) End Function ''' <summary> ''' Returns whether this converter can convert an object of the given type to the type of this converter, ''' using the specified context. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="sourceType"> ''' A <see cref="Type" /> that represents the type you want to convert from. ''' </param> ''' ''' <returns> ''' <see langword="True"/> if this converter can perform the conversion; otherwise, <see langword="False"/>. ''' </returns> Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean Return sourceType Is GetType(String) OrElse MyBase.CanConvertFrom(context, sourceType) End Function ''' <summary> ''' Converts the given value object to the specified type, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' A <see cref="CultureInfo"/>. If null is passed, the current culture is assumed. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <param name="destinationType"> ''' The <see cref="Type"/> to convert the <paramref name="value"/> parameter to. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object Dim fi As FieldInfo = Me.EnumType.GetField([Enum].GetName(Me.EnumType, value)) Dim dna As DescriptionAttribute = CType(Attribute.GetCustomAttribute(fi, GetType(DescriptionAttribute)), DescriptionAttribute) Return If(dna IsNot Nothing, dna.Description, value.ToString()) End Function ''' <summary> ''' Converts the given object to the type of this converter, using the specified context and culture information. ''' </summary> ''' ''' <param name="context"> ''' An <see cref="ITypeDescriptorContext"/> that provides a format context. ''' </param> ''' ''' <param name="culture"> ''' The <see cref="CultureInfo"/> to use as the current culture. ''' </param> ''' ''' <param name="value"> ''' The <see cref="Object"/> to convert. ''' </param> ''' ''' <returns> ''' An <see cref="Object"/> that represents the converted value. ''' </returns> <DebuggerStepThrough> Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object For Each fi As FieldInfo In Me.EnumType.GetFields() Dim dna As DescriptionAttribute = CType(Attribute.GetCustomAttribute(fi, GetType(DescriptionAttribute)), DescriptionAttribute) If (dna IsNot Nothing) AndAlso DirectCast(value, String) = dna.Description Then Return [Enum].Parse(Me.EnumType, fi.Name, ignoreCase:=False) End If Next fi Return [Enum].Parse(Me.EnumType, DirectCast(value, String)) End Function End Class
|
|
« Última modificación: 27 Abril 2024, 03:05 am por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Clase DllExportAttributeLa clase DllExportAttribute indica que un método puede ser exportado como una función de C, desde una biblioteca de enlace dinámico (DLL) de .NET, lo que hace que el método sea invocable desde código no administrado. La clase DllExportAttribute está destinada únicamente a replicar y mejorar la clase de atributo DllExportAttribute de plugins como: Permitiendo que un programador pueda utilizar esta clase de atributo sin necesidad de tener el plugin instalado en sus proyectos de Visual Studio. Sigue siendo estrictamente necesario utilizar alguno de los proyectos mencionados para habilitar la exportación de funciones .NET. Capturas de pantalla de la documentación interactiva:     El código fuente:' *********************************************************************** ' Author : ElektroStudios ' Modified : 16-January-2025 ' *********************************************************************** #Region " Option Statements " Option Strict On Option Explicit On Option Infer Off #End Region #Region " Usage Examples " ' VB.NET ' <DllExport(NameOf(MyStringFunction), CallingConvention.StdCall)> ' Public Shared Function MyStringFunction() As <MarshalAs(UnmanagedType.BStr)> String ' Return "Hello World!" ' End Function ' C# ' [DllExport(nameof(MyStringFunction), CallingConvention.StdCall)] ' [return: MarshalAs(UnmanagedType.BStr)] ' public static string MyStringFunction() { ' return "Hello World!"; ' } #End Region #Region " Imports " Imports System.Runtime.InteropServices #End Region ' ReSharper disable once CheckNamespace #Region " DllExportAttribute " Namespace DevCase.Runtime.Attributes ''' <summary> ''' The <see cref="DllExportAttribute"/> class indicates that a method can be ''' exported as a C function from a .NET dynamic-link library (DLL) file, ''' making the method callable from unmanaged code. ''' <para></para> ''' The <see cref="DllExportAttribute"/> class is solely intended to replicate and improve the ''' <b>DllExportAttribute</b> attribute class from plugins like: ''' <list type="bullet"> ''' <item><b>DllExport</b> by 3F ''' <para></para> ''' <see href="https://github.com/3F/DllExport"/> ''' </item> ''' ''' <item><b>UnmanagedExports</b> by Huajitech ''' <para></para> ''' <see href="https://github.com/huajitech/UnmanagedExports"/> ''' </item> ''' ''' <item><b>UnmanagedExports.Repack.Upgrade</b> by StevenEngland ''' <para></para> ''' <see href="https://github.com/stevenengland/UnmanagedExports.Repack.Upgrade"/> ''' </item> ''' </list> ''' Allowing a programmer to use this attribute class without having the plugin installed in their Visual Studio projects. ''' <para></para> ''' Be aware that it is still necessary to use one of the mentioned projects to enable .NET functions export. ''' </summary> <AttributeUsage(AttributeTargets.Method, AllowMultiple:=False, Inherited:=False)> Public NotInheritable Class DllExportAttribute : Inherits Attribute #Region " Properties " ''' <summary> ''' Gets or sets the calling convention required to call this C-exported function from unmanaged code. ''' <para></para> ''' Default value is <see cref="System.Runtime.InteropServices.CallingConvention.Cdecl"/>, ''' like for other C/C++ programs (Microsoft Specific). ''' <para></para> ''' Value <see cref="System.Runtime.InteropServices.CallingConvention.StdCall"/> is mostly used with Windows API. ''' <para></para> ''' </summary> Public Property CallingConvention As CallingConvention = CallingConvention.Cdecl ''' <summary> ''' Gets or sets the optional name for this C-exported function. ''' </summary> ''' <remarks> ''' See also: ''' <seealso href="https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC"> ''' Format of a C decorated name. ''' </seealso> ''' </remarks> Public Property ExportName As String #End Region #Region " Constructors " ''' <summary> ''' Initializes a new instance of the <see cref="DllExportAttribute"/> class. ''' <para></para> ''' Use this constructor only if you plan to use <b>DllExport</b> by 3F (<see href="https://github.com/3F/DllExport"/>), ''' <para></para> ''' otherwise, use <see cref="DllExportAttribute.New(String, CallingConvention)"/> ''' to specify the export name and calling convention. ''' </summary> ''' ''' <param name="convention"> ''' The calling convention required to call this C-exported function. ''' <para></para> ''' Default value is <see cref="System.Runtime.InteropServices.CallingConvention.Cdecl"/>, ''' like for other C/C++ programs (Microsoft Specific). ''' <para></para> ''' Value <see cref="System.Runtime.InteropServices.CallingConvention.StdCall"/> is mostly used with Windows API. ''' <para></para> ''' </param> ''' ''' <param name="exportName"> ''' The optional name for this C-exported function. ''' See also: ''' <seealso href="https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC"> ''' Format of a C decorated name. ''' </seealso> ''' </param> Public Sub New(convention As CallingConvention, exportName As String) Me.CallingConvention = convention Me.ExportName = exportName End Sub ''' <summary> ''' Initializes a new instance of the <see cref="DllExportAttribute"/> class. ''' <para></para> ''' Do not use this constructor if you plan to use <b>DllExport</b> by 3F (<see href="https://github.com/3F/DllExport"/>), ''' <para></para> ''' in that case use <see cref="DllExportAttribute.New(CallingConvention, String)"/> ''' to specify the export name and calling convention. ''' </summary> ''' ''' <param name="exportName"> ''' The optional name for this C-exported function. ''' See also: ''' <seealso href="https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC"> ''' Format of a C decorated name. ''' </seealso> ''' </param> ''' ''' <param name="convention"> ''' The calling convention required to call this C-exported function. ''' <para></para> ''' Default value is <see cref="System.Runtime.InteropServices.CallingConvention.Cdecl"/>, ''' like for other C/C++ programs (Microsoft Specific). ''' <para></para> ''' Value <see cref="System.Runtime.InteropServices.CallingConvention.StdCall"/> is mostly used with Windows API. ''' <para></para> ''' </param> Public Sub New(exportName As String, convention As CallingConvention) Me.ExportName = exportName Me.CallingConvention = convention End Sub ''' <summary> ''' Initializes a new instance of the <see cref="DllExportAttribute"/> class. ''' </summary> ''' ''' <param name="exportName"> ''' The optional name for this C-exported function. ''' See also: ''' <seealso href="https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC"> ''' Format of a C decorated name. ''' </seealso> ''' </param> Public Sub New(exportName As String) Me.New(exportName, CallingConvention.Cdecl) End Sub ''' <summary> ''' Initializes a new instance of the <see cref="DllExportAttribute"/> class. ''' </summary> ''' ''' <param name="convention"> ''' The calling convention required to call this C-exported function. ''' <para></para> ''' Default value is <see cref="System.Runtime.InteropServices.CallingConvention.Cdecl"/>, ''' like for other C/C++ programs (Microsoft Specific). ''' <para></para> ''' Value <see cref="System.Runtime.InteropServices.CallingConvention.StdCall"/> is mostly used with Windows API. ''' <para></para> ''' </param> Public Sub New(convention As CallingConvention) Me.New(String.Empty, convention) End Sub ''' <summary> ''' Initializes a new instance of the <see cref="DllExportAttribute"/> class. ''' </summary> Public Sub New() End Sub #End Region End Class #End Region End Namespace
Ejemplos de modo de exportación:VB.NET: <DllExport(NameOf(MyStringFunction), CallingConvention.StdCall)> Public Shared Function MyStringFunction() As <MarshalAs(UnmanagedType.BStr)> String Return "Hello World!" End Function
C#: [DllExport(nameof(MyStringFunction), CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.BStr)] public static string MyStringFunction() { return "Hello World!"; }
Ejemplos de modo de importación:Pascal Script: function MyStringFunction(): Cardinal; external 'MyStringFunction@files:MyNetAPI.dll stdcall';
|
|
« Última modificación: 16 Enero 2025, 16:23 pm por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Le he dado un lavado de cara moderno a esta impresentable clase del año 2013: • Una nueva versión de mi Listview, que tiene muchas cosas interesantes como poder dibujar una barra de progreso en una celda...He aislado prácticamente toda la lógica de la "barra" de progreso para poder utilizarlo por separado en cualquier tipo de herencia de la clase ListView, en lugar de depender exclusivamente de ese control personalizado ListView que publiqué. Les presento la clase ListViewProgressBarSubItem que implementa por sí misma (la parte esencial de) el dibujado de la celda y la "barra" de progreso del subitem, proporcionando propiedades de personalización que lo vuelven un elemento flexible y versátil: 💡 Con un poco de mano e ingenio se podría adaptar relativamente fácil dicha clase para dibujar estrellitas (un ranking o puntuación) u otros menesteres varios.Para ello primero necesitaremos esta simple interfaz: ISelfDrawableListViewSubItem''' <summary> ''' Provides a contract for a <see cref="ListViewItem.ListViewSubItem"/> that is capable of drawing itself. ''' </summary> ''' ''' <remarks> ''' For this interface to take effect, the owning <see cref="ListView"/> must have its ''' <see cref="ListView.OwnerDraw"/> property set to <see langword="True"/>, and the ''' <see cref="ListView.OnDrawSubItem"/> method must be properly overridden to delegate ''' the drawing logic by calling the <see cref="ISelfDrawableListViewSubItem.Draw(Graphics, Rectangle)"/> method. ''' <para></para> ''' See the attached code example for a practical implementation of this functionality. ''' </remarks> ''' ''' <example> This is a code example. ''' <code language="VB"> ''' Public Class CustomListView : Inherits ListView ''' ''' Public Sub New() ''' ''' MyBase.New() ''' ''' Me.DoubleBuffered = True ''' Me.OwnerDraw = True ''' End Sub ''' ''' Protected Overrides Sub OnDrawColumnHeader(e As DrawListViewColumnHeaderEventArgs) ''' ''' e.DrawDefault = True ''' MyBase.OnDrawColumnHeader(e) ''' End Sub ''' ''' Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs) ''' ''' e.DrawDefault = False ''' MyBase.OnDrawItem(e) ''' End Sub ''' ''' Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs) ''' ''' Dim selfDrawableSubItem As ISelfDrawableListViewSubItem = TryCast(e.SubItem, ISelfDrawableListViewSubItem) ''' If selfDrawableSubItem IsNot Nothing Then ''' selfDrawableSubItem.Draw(e.Graphics, e.Bounds) ''' Else ''' e.DrawDefault = True ''' End If ''' ''' MyBase.OnDrawSubItem(e) ''' End Sub ''' ''' End Class ''' </code> ''' </example> Public Interface ISelfDrawableListViewSubItem ''' <summary> ''' Draws the subitem within the specified bounds using the provided <see cref="Graphics"/> surface. ''' <para></para> ''' This method must be called from the <see cref="ListView.OnDrawSubItem"/> method of the owning <see cref="ListView"/>. ''' </summary> ''' ''' <param name="g"> ''' The <see cref="Graphics"/> surface on which to render the subitem. ''' </param> ''' ''' <param name="bounds"> ''' The <see cref="Rectangle"/> that defines the drawing area for the subitem. ''' </param> Sub Draw(g As Graphics, bounds As Rectangle) End Interface
Y por último, la clase: ListViewProgressBarSubItem''' <summary> ''' Represents a custom <see cref="ListViewItem.ListViewSubItem"/> that visually ''' simulates a progress bar with personalizable text and appearance. ''' </summary> ''' ''' <remarks> ''' For this class to take effect, the owning <see cref="ListView"/> must have its ''' <see cref="ListView.OwnerDraw"/> property set to <see langword="True"/>, and the ''' <see cref="ListView.OnDrawSubItem"/> method must be properly overridden to delegate ''' the drawing logic by calling the <see cref="ListViewProgressBarSubItem.Draw(Graphics, Rectangle)"/> method. ''' <para></para> ''' See the attached code example for a practical implementation of this functionality. ''' </remarks> ''' ''' <example> This is a code example. ''' <code language="VB"> ''' Public Class Form1 ''' ''' Private WithEvents CustomListView1 As New CustomListView() ''' ''' Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ''' ''' Dim lv As ListView = Me.CustomListView1 ''' Dim item As New ListViewItem("My item") ''' Dim subItem As New ListViewProgressBarSubItem(item) With { ''' .DecimalPlaces = 2, ''' .TextSuffix = Nothing, ''' .BorderColor = Color.Empty, ''' .BackColor = Color.Empty, ''' .ForeColor = Color.Red, ''' .FillGradientColorLeft = SystemColors.Highlight, ''' .FillGradientColorRight = SystemColors.Highlight, ''' .FillGradientAngle = 0 ''' } ''' ''' item.SubItems.Add(subItem) ''' lv.Items.Add(item) ''' End Sub ''' ''' End Class ''' ''' Public Class CustomListView : Inherits ListView ''' ''' Public Sub New() ''' ''' MyBase.New() ''' ''' Me.DoubleBuffered = True ''' Me.OwnerDraw = True ''' End Sub ''' ''' Protected Overrides Sub OnDrawColumnHeader(e As DrawListViewColumnHeaderEventArgs) ''' ''' e.DrawDefault = True ''' MyBase.OnDrawColumnHeader(e) ''' End Sub ''' ''' Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs) ''' ''' e.DrawDefault = False ''' MyBase.OnDrawItem(e) ''' End Sub ''' ''' Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs) ''' ''' Dim selfDrawableSubItem As ISelfDrawableListViewSubItem = TryCast(e.SubItem, ISelfDrawableListViewSubItem) ''' If selfDrawableSubItem IsNot Nothing Then ''' selfDrawableSubItem.Draw(e.Graphics, e.Bounds) ''' Else ''' e.DrawDefault = True ''' End If ''' ''' MyBase.OnDrawSubItem(e) ''' End Sub ''' ''' End Class ''' </code> ''' </example> <Serializable> <TypeConverter(GetType(ExpandableObjectConverter))> <ToolboxItem(False)> <DesignTimeVisible(False)> <DefaultProperty("Text")> Public Class ListViewProgressBarSubItem : Inherits ListViewItem.ListViewSubItem : Implements ISelfDrawableListViewSubItem #Region " Fields " ''' <summary> ''' The default font of the text displayed by the subitem. ''' </summary> <NonSerialized> Protected defaultFont As Font = MyBase.Font ''' <summary> ''' The default background color of the subitem's text. ''' </summary> <NonSerialized> Protected defaultBackColor As Color = MyBase.BackColor ''' <summary> ''' The default foreground color of the subitem's text. ''' </summary> <NonSerialized> Protected defaultForeColor As Color = MyBase.ForeColor ''' <summary> ''' The default angle to draw the linear gradient specified by ''' <see cref="ListViewProgressBarSubItem.FillGradientColorLeft"/> ''' and <see cref="ListViewProgressBarSubItem.FillGradientColorRight"/> colors. ''' </summary> <NonSerialized> Protected defaultFillGradientAngle As Single = 0 ''' <summary> ''' The default starting linear gradient color to fill the progress area. ''' </summary> <NonSerialized> Protected defaultFillGradientColorLeft As Color = SystemColors.HighlightText ''' <summary> ''' The default ending linear gradient color to fill the progress area. ''' </summary> <NonSerialized> Protected defaultFillGradientColorRight As Color = SystemColors.Highlight ''' <summary> ''' The default color of the progress bar border. ''' </summary> <NonSerialized> Protected defaultBorderColor As Color = SystemColors.InactiveBorder ''' <summary> ''' The default <see cref="System.Windows.Forms.TextFormatFlags"/> that determine ''' how the subitem text is rendered and aligned. ''' </summary> <NonSerialized> Protected defaultTextFormatFlags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter Or TextFormatFlags.EndEllipsis Or TextFormatFlags.SingleLine #End Region #Region " Properties " ''' <summary> ''' Gets or sets the current progress percentage value to display in the progress bar. ''' <para></para> ''' The value should be between 0 to 100. ''' </summary> Public Property ProgressPercentage As Double Get Return Me.progressPercentage_ End Get <DebuggerStepThrough> Set(value As Double) Me.SetFieldValue(Me.progressPercentage_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.ProgressPercentage"/> property ) ''' <para></para> ''' The current progress percentage value to display in the progress bar. ''' </summary> Private progressPercentage_ As Double ''' <summary> ''' Gets or sets the number of decimal places displayed for the <see cref="ListViewProgressBarSubItem.ProgressPercentage"/> value. ''' <para></para> ''' Default value is zero. ''' </summary> Public Property DecimalPlaces As Short Get Return Me.decimalPlaces_ End Get <DebuggerStepThrough> Set(value As Short) Me.SetFieldValue(Me.decimalPlaces_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.DecimalPlaces"/> property ) ''' <para></para> ''' The number of decimal places displayed for the <see cref="ListViewProgressBarSubItem.ProgressPercentage"/> value. ''' </summary> Private decimalPlaces_ As Short ''' <summary> ''' Gets or sets the additional text displayed next to the <see cref="ListViewProgressBarSubItem.ProgressPercentage"/> value. ''' </summary> Public Property TextSuffix As String Get Return Me.textSuffix_ End Get <DebuggerStepThrough> Set(value As String) Me.SetFieldValue(Me.textSuffix_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.TextSuffix"/> property ) ''' <para></para> ''' The additional text displayed next to the <see cref="ListViewProgressBarSubItem.ProgressPercentage"/> value. ''' </summary> Private textSuffix_ As String ''' <summary> ''' Gets or sets the <see cref="System.Windows.Forms.TextFormatFlags"/> that determine ''' how the subitem text is rendered and aligned. ''' <para></para> ''' Default value is: ''' <see cref="System.Windows.Forms.TextFormatFlags.HorizontalCenter"/>, ''' <see cref="System.Windows.Forms.TextFormatFlags.VerticalCenter"/>, ''' <see cref="System.Windows.Forms.TextFormatFlags.EndEllipsis"/> and ''' <see cref="System.Windows.Forms.TextFormatFlags.SingleLine"/> ''' </summary> Public Property TextFormatFlags As TextFormatFlags Get Return Me.textFormatFlags_ End Get <DebuggerStepThrough> Set(value As TextFormatFlags) Me.SetFieldValue(Me.textFormatFlags_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.TextFormatFlags"/> property ) ''' <para></para> ''' The <see cref="System.Windows.Forms.TextFormatFlags"/> that determine how the subitem text is rendered. ''' </summary> Private textFormatFlags_ As TextFormatFlags ''' <summary> ''' Gets or sets the starting linear gradient color to fill the progress area. ''' <para></para> ''' Default value is <see cref="SystemColors.Control"/>. ''' </summary> Public Property FillGradientColorLeft As Color Get Return Me.fillGradientColorLeft_ End Get <DebuggerStepThrough> Set(value As Color) Me.SetFieldValue(Me.fillGradientColorLeft_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.FillGradientColorLeft"/> property ) ''' <para></para> ''' The starting linear gradient color to fill the progress area. ''' </summary> Private fillGradientColorLeft_ As Color ''' <summary> ''' Gets or sets the ending linear gradient color to fill the progress area. ''' <para></para> ''' Default value is <see cref="Color.LightGreen"/>. ''' </summary> Public Property FillGradientColorRight As Color Get Return Me.fillGradientColorRight_ End Get <DebuggerStepThrough> Set(value As Color) Me.SetFieldValue(Me.fillGradientColorRight_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.FillGradientColorRight"/> property ) ''' <para></para> ''' The ending linear gradient color to fill the progress area. ''' </summary> Private fillGradientColorRight_ As Color ''' <summary> ''' Gets or sets the angle to draw the linear gradient specified by ''' <see cref="ListViewProgressBarSubItem.FillGradientColorLeft"/> ''' and <see cref="ListViewProgressBarSubItem.FillGradientColorRight"/> colors. ''' <para></para> ''' Default value is zero. ''' </summary> Public Property FillGradientAngle As Single Get Return Me.fillGradientAngle_ End Get <DebuggerStepThrough> Set(value As Single) Me.SetFieldValue(Me.fillGradientAngle_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.FillGradientAngle"/> property ) ''' <para></para> ''' The angle to draw the linear gradient specified by ''' <see cref="ListViewProgressBarSubItem.FillGradientColorLeft"/> ''' and <see cref="ListViewProgressBarSubItem.FillGradientColorRight"/> colors. ''' </summary> Private fillGradientAngle_ As Single ''' <summary> ''' Gets or sets the color of the progress bar border. ''' <para></para> ''' Default value is <see cref="SystemColors.ActiveBorder"/>. ''' </summary> Public Property BorderColor As Color Get Return Me.borderColor_ End Get <DebuggerStepThrough> Set(value As Color) Me.SetFieldValue(Me.borderColor_, value) End Set End Property ''' <summary> ''' ( Backing Field of <see cref="ListViewProgressBarSubItem.BorderColor"/> property ) ''' <para></para> ''' The color of the progress bar border. ''' </summary> Private borderColor_ As Color ''' <summary> ''' Gets or sets the background color of the subitem cell. ''' </summary> Public Shadows Property BackColor As Color Get Return MyBase.BackColor End Get <DebuggerStepThrough> Set(value As Color) Me.SetFieldValue(MyBase.BackColor, value) End Set End Property ''' <summary> ''' Gets or sets the foreground color of the subitem's text. ''' </summary> Public Shadows Property ForeColor As Color Get Return MyBase.ForeColor End Get <DebuggerStepThrough> Set(value As Color) Me.SetFieldValue(MyBase.ForeColor, value) End Set End Property ''' <summary> ''' Gets or sets the font of the text displayed by the subitem. ''' </summary> Public Shadows Property Font As Font Get Return MyBase.Font End Get Set(value As Font) Me.SetFieldValue(MyBase.Font, value) End Set End Property ''' <summary> ''' Gets the text of the subitem. ''' </summary> Public Shadows ReadOnly Property Text As String Get Return Me.progressPercentage_.ToString("N" & Me.decimalPlaces_) & "%" & If(String.IsNullOrEmpty(Me.textSuffix_), Nothing, " " & Me.textSuffix_) End Get End Property #End Region #Region " Constructors " ''' <summary> ''' Initializes a new instance of the <see cref="ListViewProgressBarSubItem"/> class ''' associated with the given <see cref="ListViewItem"/>. ''' </summary> ''' ''' <param name="owner"> ''' A <see cref="ListViewItem"/> that represents the item that owns this <see cref="ListViewProgressBarSubItem"/>. ''' </param> <DebuggerStepThrough> Public Sub New(owner As ListViewItem) MyBase.New(owner, String.Empty) Me.ResetStyle() End Sub ''' <summary> ''' Initializes a new instance of the <see cref="ListViewProgressBarSubItem"/> class. ''' </summary> <DebuggerStepThrough> Public Sub New() Me.ResetStyle() End Sub #End Region #Region " Public Methods " ''' <summary> ''' Resets the styles applied to the subitem to the default font and colors. ''' </summary> <DebuggerStepThrough> Public Shadows Sub ResetStyle() MyBase.Font = Me.defaultFont MyBase.BackColor = Me.defaultBackColor MyBase.ForeColor = Me.defaultForeColor Me.textFormatFlags_ = Me.defaulttextFormatFlags Me.fillGradientColorLeft_ = Me.defaultFillGradientColorLeft Me.fillGradientColorRight_ = Me.defaultFillGradientColorRight Me.fillGradientAngle_ = Me.defaultFillGradientAngle Me.borderColor_ = Me.defaultBorderColor Me.RefreshSubItem() End Sub #End Region #Region " Private Methods " ''' <summary> ''' Sets the value of the specified field using <see cref="EqualityComparer(Of T)"/> to check value equality. ''' <para></para> ''' If the new value is different from the current one, ''' it then calls <see cref="ListViewProgressBarSubItem.RefreshSubItem"/> method. ''' </summary> ''' ''' <typeparam name="T"> ''' The type of the property value. ''' </typeparam> ''' ''' <param name="refField"> ''' A reference to the backing field of the property. ''' </param> ''' ''' <param name="newValue"> ''' The new value to set. ''' </param> <DebuggerStepThrough> Private Sub SetFieldValue(Of T)(ByRef refField As T, newValue As T) If Not EqualityComparer(Of T).Default.Equals(refField, newValue) Then refField = newValue Me.RefreshSubItem() End If End Sub ''' <summary> ''' Refreshes the visual representation of this <see cref="ListViewProgressBarSubItem"/> subitem ''' in the owner <see cref="ListView"/> by invalidating its bounding rectangle. ''' </summary> ''' ''' <remarks> ''' This method uses reflection to access the non-public "owner" field of the base ''' <see cref="ListViewItem.ListViewSubItem"/> class in order to identify the parent item and column index. ''' It then triggers a redraw of the specific subitem area within the parent ListView. ''' </remarks> <DebuggerStepThrough> Private Sub RefreshSubItem() Dim fieldInfo As FieldInfo = GetType(ListViewItem.ListViewSubItem).GetField("owner", BindingFlags.NonPublic Or BindingFlags.Instance) If fieldInfo IsNot Nothing Then Dim ownerObj As Object = fieldInfo.GetValue(Me) If ownerObj IsNot Nothing Then Dim lvi As ListViewItem = DirectCast(ownerObj, ListViewItem) Dim colIndex As Integer = lvi.SubItems.IndexOf(Me) If colIndex >= 0 AndAlso lvi.ListView IsNot Nothing Then Dim subItemBounds As Rectangle = lvi.SubItems(colIndex).Bounds lvi.ListView.Invalidate(subItemBounds, invalidateChildren:=False) End If End If End If End Sub #End Region #Region " ISelfDrawableListViewSubItem Implementation " ''' <summary> ''' Draws the subitem within the specified bounds using the provided <see cref="Graphics"/> surface. ''' <para></para> ''' This method must be called from the <see cref="ListView.OnDrawSubItem"/> method of the owning <see cref="ListView"/>. ''' </summary> ''' ''' <param name="g"> ''' The <see cref="Graphics"/> surface on which to render the subitem. ''' </param> ''' ''' <param name="bounds"> ''' The <see cref="Rectangle"/> that defines the drawing area for the subitem. ''' </param> <DebuggerStepThrough> Protected Sub Draw(g As Graphics, bounds As Rectangle) Implements ISelfDrawableListViewSubItem.Draw ' Draw subitem background (progress bar background). If Me.BackColor <> Color.Empty AndAlso Me.BackColor <> Color.Transparent Then Using backBrush As New SolidBrush(Me.BackColor) g.FillRectangle(backBrush, bounds) End Using End If ' Draw linear gradient to fill the current progress of the progress bar. If (Me.fillGradientColorLeft_ <> Color.Empty AndAlso Me.fillGradientColorLeft_ <> Color.Transparent) OrElse (Me.fillGradientColorRight_ <> Color.Empty AndAlso Me.fillGradientColorRight_ <> Color.Transparent) Then Using brGradient As New Drawing2D.LinearGradientBrush( New Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height), Me.fillGradientColorLeft_, Me.fillGradientColorRight_, Me.fillGradientAngle_, isAngleScaleable:=True) Dim progressWidth As Integer = CInt((Me.progressPercentage_ / 100) * (bounds.Width - 2)) g.FillRectangle(brGradient, bounds.X + 1, bounds.Y + 2, progressWidth, bounds.Height - 3) End Using End If ' Draw subitem text. Dim text As String = Me.Text If Not String.IsNullOrEmpty(text) Then TextRenderer.DrawText(g, text, Me.Font, bounds, Me.ForeColor, Me.TextFormatFlags) End If ' Draw border around the progress bar. If Me.borderColor_ <> Color.Empty AndAlso Me.borderColor_ <> Color.Transparent Then Using borderPen As New Pen(Me.borderColor_) g.DrawRectangle(borderPen, bounds.X, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2) End Using End If End Sub #End Region End Class
Ejemplo de uso: Public Class Form1 Private WithEvents CustomListView1 As New CustomListView() Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim lv As ListView = Me.CustomListView1 Dim item As New ListViewItem("My item") Dim subItem As New ListViewProgressBarSubItem(item) With { .DecimalPlaces = 2, .TextSuffix = Nothing, .BorderColor = Color.Empty, .BackColor = Color.Empty, .ForeColor = Color.Red, .FillGradientColorLeft = SystemColors.Highlight, .FillGradientColorRight = SystemColors.Highlight, .FillGradientAngle = 0 } item.SubItems.Add(subItem) lv.Items.Add(item) End Sub End Class Public Class CustomListView : Inherits ListView Public Sub New() MyBase.New() Me.DoubleBuffered = True Me.OwnerDraw = True End Sub Protected Overrides Sub OnDrawColumnHeader(e As DrawListViewColumnHeaderEventArgs) e.DrawDefault = True MyBase.OnDrawColumnHeader(e) End Sub Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs) e.DrawDefault = False MyBase.OnDrawItem(e) End Sub Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs) Dim selfDrawableSubItem As ISelfDrawableListViewSubItem = TryCast(e.SubItem, ISelfDrawableListViewSubItem) If selfDrawableSubItem IsNot Nothing Then selfDrawableSubItem.Draw(e.Graphics, e.Bounds) Else e.DrawDefault = True End If MyBase.OnDrawSubItem(e) End Sub End Class
|
|
« Última modificación: Ayer a las 14:25 por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Cómo iniciar el programa warp-cli.exe de la VPN de Cloudflare Warp pasándole un comandoUn simple método para ejecutar el programa warp-cli.exe de la VPN de Cloudflare Warp pasándole un comando (ej. "connect", "disconnect", etc): ''' <summary> ''' Sends a custom command to the Cloudflare Warp CLI executable (<c>warp-cli.exe</c>) ''' and captures both standard output and error output. ''' </summary> ''' ''' <param name="command"> ''' The command-line argument to be passed to warp-cli executable. ''' For example: <c>connect</c>, <c>disconnect</c>, <c>status</c>, etc. ''' </param> ''' ''' <param name="refOutput"> ''' Returns the standard output returned by the warp-cli process. ''' </param> ''' ''' <param name="refErrorOutput"> ''' Returns the standard error output returned by the warp-cli process. ''' </param> ''' ''' <param name="warpCliFilePath"> ''' Optional path to the warp-cli executable. If <c>Nothing</c> is specified, the method defaults to: ''' <c>%ProgramFiles%\Cloudflare\Cloudflare Warp\warp-cli.exe</c>. ''' </param> ''' ''' <returns> ''' The exit code returned by the warp-cli process. A value of 0 typically indicates success. ''' </returns> ''' ''' <exception cref="System.IO.FileNotFoundException"> ''' Thrown if the specified or default warp-cli executable file is not found on the system. ''' </exception> ''' ''' <exception cref="System.TimeoutException"> ''' Thrown if the warp-cli process takes longer than 60 seconds to complete. ''' </exception> ''' ''' <exception cref="System.Exception"> ''' Thrown if any other unexpected error occurs while attempting to execute the warp-cli process. ''' The original exception is wrapped as the inner exception. ''' </exception> <DebuggerStepThrough> Public Shared Function CloudflareWarpCliSendCommand(command As String, ByRef refOutput As String, ByRef refErrorOutput As String, Optional warpCliFilePath As String = Nothing) As Integer ' Prevents concurrent execution of the method from multiple threads within the same process. ' This static lock object ensures that only one thread can execute the critical section at a time, ' avoiding race conditions or conflicts when invoking the Warp CLI. Static WarpCliLock As New Object() Static spaceChar As Char = " "c SyncLock WarpCliLock If String.IsNullOrEmpty(warpCliFilePath) Then warpCliFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Cloudflare\Cloudflare Warp\warp-cli.exe") End If Try If Not System. IO. File. Exists(warpCliFilePath ) Then Throw New System.IO.FileNotFoundException("The Warp CLI executable was not found.", warpCliFilePath) End If Using pr As New Process() pr.StartInfo.FileName = warpCliFilePath pr.StartInfo.Arguments = command pr.StartInfo.UseShellExecute = False pr.StartInfo.CreateNoWindow = True pr.StartInfo.RedirectStandardOutput = True pr.StartInfo.RedirectStandardError = True pr.Start() If Not pr.WaitForExit(60000) Then ' Waits a maximum of 60 seconds pr.Kill() Throw New TimeoutException("warp-cli process has timed out.") End If refOutput = pr.StandardOutput.ReadToEnd().Trim(Environment.NewLine.ToCharArray().Concat({spaceChar}).ToArray()) refErrorOutput = pr.StandardError.ReadToEnd().Trim(Environment.NewLine.ToCharArray().Concat({spaceChar}).ToArray()) Return pr.ExitCode End Using Catch ex As Exception Throw New Exception($"Failed to execute warp-cli process. See inner exception for details.", ex) End Try End SyncLock End Function
Casos de uso reales: para conectar a la red de Cloudflare WARP en cualquier proyecto donde hagamos solicitudes http, por ejemplo en un web-crawler, a sitios web con riesgo de que puedan acabar bloqueando nuestra IP. Tres métodos de extensión para dibujar texto sobre una imagen, o dibujar encima otra imagen (con capacidad opcional de usar transparencia) o un valor numérico, con una escala proporcional a la imagen y en una posición alineada a cualquiera de las esquinas o zonas centrales de la imagen (centro absoluto, parte superior central o parte inferior central) de la imagen.Demostración de resultado de la extensión que dibuja un valor numérico (de forma alineada a la esquina inferior derecha de la imagen):  ''' <summary> ''' Draws an overlay image onto the specified <see cref="Image"/> at a given position and scale factor. ''' </summary> ''' ''' <param name="refImg"> ''' The source <see cref="Image"/> to modify. The overlay image will be drawn directly on this image. ''' </param> ''' ''' <param name="overlayImg"> ''' The overlay image to draw on the source <paramref name="refImg"/>. ''' </param> ''' ''' <param name="scale"> ''' The relative image scale factor to determine overlay image size. Lower values increase the size of the overlay image. ''' </param> ''' ''' <param name="position"> ''' The position/alignment where the overlay image should be drawn (e.g., bottom-right). ''' </param> ''' ''' <param name="margin"> ''' The margin (in pixels) from the edge of the image to position the overlay image. ''' <para></para> ''' This value has different meaning depending on <paramref name="position"/> parameter: ''' <para></para> ''' <list type="bullet"> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>, ''' <para></para> ''' <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the vertical offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> is ignored.</description> ''' </item> ''' </list> ''' </param> ''' ''' <param name="transparentColor"> ''' Optional. A <see cref="Color"/> to use as transparency to draw the overlay image. ''' </param> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Sub DrawImageScaled(ByRef refImg As Image, overlayImg As Image, scale As Single, position As ContentAlignment, margin As Single, Optional transparentColor As Color? = Nothing) If refImg Is Nothing Then Throw New ArgumentNullException(NameOf(refImg)) End If If overlayImg Is Nothing Then Throw New ArgumentNullException(NameOf(overlayImg)) End If If margin < 0 Then Throw New ArgumentOutOfRangeException(NameOf(margin), margin, "Margin must be greater than or equal to 0.") End If If scale < 1 Then Throw New ArgumentOutOfRangeException(NameOf(scale), scale, "Font scale must be greater than or equal to 1.") End If Using g As Graphics = Graphics.FromImage(refImg) g.SmoothingMode = SmoothingMode.AntiAlias g.InterpolationMode = InterpolationMode.HighQualityBicubic g.PixelOffsetMode = PixelOffsetMode.HighQuality g.CompositingQuality = CompositingQuality.HighQuality Dim targetSize As Single = Math.Max(refImg.Width, refImg.Height) / scale Dim aspectRatio As Single = CSng(overlayImg.Width / overlayImg.Height) Dim drawWidth As Single Dim drawHeight As Single If overlayImg.Width >= overlayImg.Height Then drawWidth = targetSize drawHeight = targetSize / aspectRatio Else drawHeight = targetSize drawWidth = targetSize * aspectRatio End If Dim posX As Single = 0 Dim posY As Single = 0 Select Case position Case ContentAlignment.TopLeft posX = margin posY = margin Case ContentAlignment.TopCenter posX = (refImg.Width - drawWidth) / 2 posY = margin Case ContentAlignment.TopRight posX = refImg.Width - drawWidth - margin posY = margin Case ContentAlignment.MiddleLeft posX = margin posY = (refImg.Height - drawHeight) / 2 Case ContentAlignment.MiddleCenter posX = (refImg.Width - drawWidth) / 2 posY = (refImg.Height - drawHeight) / 2 Case ContentAlignment.MiddleRight posX = refImg.Width - drawWidth - margin posY = (refImg.Height - drawHeight) / 2 Case ContentAlignment.BottomLeft posX = margin posY = refImg.Height - drawHeight - margin Case ContentAlignment.BottomCenter posX = (refImg.Width - drawWidth) / 2 posY = refImg.Height - drawHeight - margin Case ContentAlignment.BottomRight posX = refImg.Width - drawWidth - margin posY = refImg.Height - drawHeight - margin Case Else Throw New InvalidEnumArgumentException(NameOf(position), position, GetType(ContentAlignment)) End Select If transparentColor.HasValue Then Using attr As New Imaging.ImageAttributes() attr.SetColorKey(transparentColor.Value, transparentColor.Value) Dim destRect As New Rectangle(CInt(posX), CInt(posY), CInt(drawWidth), CInt(drawHeight)) g.DrawImage(overlayImg, destRect, 0, 0, overlayImg.Width, overlayImg.Height, GraphicsUnit.Pixel, attr) End Using Else g.DrawImage(overlayImg, posX, posY, drawWidth, drawHeight) End If End Using End Sub ''' <summary> ''' Draws text onto the specified <see cref="Image"/> at a given position and scale factor. ''' </summary> ''' ''' <param name="refImg"> ''' The <see cref="Image"/> to modify. The text will be drawn directly on this image. ''' </param> ''' ''' <param name="text"> ''' The text to draw on the image. ''' </param> ''' ''' <param name="scale"> ''' The relative image scale factor to determine font size. Lower values increase the size of the text. ''' <para></para> ''' Suggested value is from 10 to 20. ''' </param> ''' ''' <param name="position"> ''' The position/alignment where the text should be drawn (e.g., bottom-right). ''' </param> ''' ''' <param name="margin"> ''' The margin (in pixels) from the edge of the image to position the text. ''' <para></para> ''' This value has different meaning depending on <paramref name="position"/> parameter: ''' <para></para> ''' <list type="bullet"> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>, ''' <para></para> ''' <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the vertical offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> is ignored.</description> ''' </item> ''' </list> ''' </param> ''' ''' <param name="font"> ''' Optional. A custom <see cref="Font"/> to use. If not provided, a bold <c>Arial</c> font is used. ''' <para></para> ''' Note: Custom font size (<see cref="System.Drawing.Font.Size"/>) is ignored. It is determined by <paramref name="scale"/> parameter. ''' </param> ''' ''' <param name="textColor"> ''' Optional. The color of the text. ''' <para></para> ''' Default value is <see cref="Color.White"/>. ''' </param> ''' ''' <param name="outlineColor"> ''' Optional. The color of the text outline. ''' <para></para> ''' Default value is <see cref="Color.Black"/>. ''' </param> ''' ''' <param name="outlineThickness"> ''' Optional. The thickness of the outline, in pixels. ''' <para></para> ''' Default value is 2 pixels. ''' </param> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Sub DrawTextScaled(ByRef refImg As Image, text As String, scale As Single, position As ContentAlignment, margin As Single, Optional font As Font = Nothing, Optional textColor As Color = Nothing, Optional outlineColor As Color = Nothing, Optional outlineThickness As Short = 2) If margin < 0 Then Throw New ArgumentOutOfRangeException(NameOf(margin), margin, "Margin must be greater than or equal to 0.") End If If scale < 1 Then Throw New ArgumentOutOfRangeException(NameOf(scale), scale, "Font scale must be greater than or equal to 1.") End If If textColor = Nothing Then textColor = Color.White End If If outlineColor = Nothing Then outlineColor = Color.Black End If Using g As Graphics = Graphics.FromImage(refImg) g.SmoothingMode = SmoothingMode.AntiAlias g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit g.InterpolationMode = InterpolationMode.HighQualityBicubic g.PixelOffsetMode = PixelOffsetMode.HighQuality g.CompositingQuality = CompositingQuality.HighQuality Dim rawFontSize As Single = Math.Max(refImg.Width, refImg.Height) / scale Dim maxAllowedFontSize As Single = Math.Min(refImg.Width, refImg.Height) Dim fontSize As Single = Math.Min(rawFontSize, maxAllowedFontSize) Using textFont As Font = If(font IsNot Nothing, New Font(font.FontFamily, fontSize, font.Style, GraphicsUnit.Pixel, font.GdiCharSet, font.GdiVerticalFont), New Font("Arial", fontSize, FontStyle.Bold, GraphicsUnit.Pixel)) Dim textSize As SizeF = g.MeasureString(text, textFont) Dim posX As Single = 0 Dim posY As Single = 0 Select Case position Case ContentAlignment.TopLeft posX = margin posY = margin Case ContentAlignment.TopCenter posX = (refImg.Width - textSize.Width) / 2 posY = margin Case ContentAlignment.TopRight posX = refImg.Width - textSize.Width - margin posY = margin Case ContentAlignment.MiddleLeft posX = margin posY = (refImg.Height - textSize.Height) / 2 Case ContentAlignment.MiddleCenter posX = (refImg.Width - textSize.Width) / 2 posY = (refImg.Height - textSize.Height) / 2 Case ContentAlignment.MiddleRight posX = refImg.Width - textSize.Width - margin posY = (refImg.Height - textSize.Height) / 2 Case ContentAlignment.BottomLeft posX = margin posY = refImg.Height - textSize.Height - margin Case ContentAlignment.BottomCenter posX = (refImg.Width - textSize.Width) / 2 posY = refImg.Height - textSize.Height - margin Case ContentAlignment.BottomRight posX = refImg.Width - textSize.Width - margin posY = refImg.Height - textSize.Height - margin Case Else Throw New InvalidEnumArgumentException(NameOf(position), position, GetType(ContentAlignment)) End Select Using outlineBrush As New SolidBrush(outlineColor) For dx As Short = -outlineThickness To outlineThickness For dy As Short = -outlineThickness To outlineThickness If dx <> 0 OrElse dy <> 0 Then g.DrawString(text, textFont, outlineBrush, posX + dx, posY + dy) End If Next dy Next dx End Using Using textBrush As New SolidBrush(textColor) g.DrawString(text, textFont, textBrush, posX, posY) End Using End Using ' font End Using ' g End Sub ''' <summary> ''' Draws a number onto the specified <see cref="Image"/> at a given position and scale factor. ''' </summary> ''' ''' <param name="refImg"> ''' The <see cref="Image"/> to modify. The number will be drawn directly on this image. ''' </param> ''' ''' <param name="number"> ''' The number to draw on the image. ''' </param> ''' ''' <param name="scale"> ''' The relative image scale factor to determine font size. Lower values increase the size of the text. ''' <para></para> ''' Suggested value is from 10 to 20. ''' </param> ''' ''' <param name="position"> ''' The position/alignment where the number should be drawn (e.g., bottom-right). ''' </param> ''' ''' <param name="margin"> ''' The margin (in pixels) from the edge of the image to position the text. ''' <para></para> ''' This value has different meaning depending on <paramref name="position"/> parameter: ''' <para></para> ''' <list type="bullet"> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>, ''' <para></para> ''' <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> specifies the vertical offset.</description> ''' </item> ''' <item> ''' <term> ''' <see cref="ContentAlignment.MiddleCenter"/> ''' </term> ''' <description><para></para><paramref name="margin"/> is ignored.</description> ''' </item> ''' </list> ''' </param> ''' ''' <param name="font"> ''' Optional. A custom <see cref="Font"/> to use. If not provided, a bold <c>Arial</c> font is used. ''' <para></para> ''' Note: Custom font size (<see cref="System.Drawing.Font.Size"/>) is ignored. It is determined by <paramref name="scale"/> parameter. ''' </param> ''' ''' <param name="textColor"> ''' Optional. The color of the text. ''' <para></para> ''' Default value is <see cref="Color.White"/>. ''' </param> ''' ''' <param name="outlineColor"> ''' Optional. The color of the text outline. ''' <para></para> ''' Default value is <see cref="Color.Black"/>. ''' </param> ''' ''' <param name="outlineThickness"> ''' Optional. The thickness of the outline, in pixels. ''' <para></para> ''' Default value is 2 pixels. ''' </param> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Sub DrawNumberScaled(ByRef refImg As Image, number As Integer, scale As Single, position As ContentAlignment, margin As Single, Optional font As Font = Nothing, Optional textColor As Color = Nothing, Optional outlineColor As Color = Nothing, Optional outlineThickness As Short = 2) DrawTextScaled(refImg, CStr(number), scale, position, margin, font, textColor, outlineColor, outlineThickness) End Sub
|
|
« Última modificación: Hoy a las 01:49 por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Cuatro métodos de extensión para el tipo DateTime con los que obtener una representación de fecha o fecha y hora realmente amistosa.Ejemplos: Fecha en inglés: 11 May, 2025 Fecha en español: 11 de mayo de 2025 Fecha en alemán: 11. Mai 2025 Fecha y hora en inglés: 11 May, 2025 at 23:59:59 Fecha y hora en español: 11 de mayo de 2025 a las 23:59:59 No soy experto en la representación por escrito de fechas en otros idiomas así que solo intenté perfeccionar estos tres. La representación en alemán estaría bien según me he informado, ya que se supone que se añade un punto de esa forma. En definitiva, creo que para ir tirando está bien así. ''' <summary> ''' Converts a <see cref="Date"/> object to a long friendly date string based on the current culture. ''' <para></para> ''' For example: ''' <list type="bullet"> ''' <item><description>English<para></para>11 May, 2025</description></item> ''' <item><description>Spanish<para></para>11 de mayo de 2025</description></item> ''' <item><description>German<para></para>11. Mai 2025</description></item> ''' </list> ''' </summary> ''' ''' <param name="[date]"> ''' The <see cref="Date"/> object to be formatted. ''' </param> ''' ''' <returns> ''' A string representing the formatted date, based on the current culture. ''' </returns> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Function ToLongFriendlyDateString([date] As Date) As String Return DateExtensions.ToLongFriendlyDateString([date], CultureInfo.CurrentCulture) End Function ''' <summary> ''' Converts a <see cref="Date"/> object to a long friendly date string based on the specified culture. ''' <para></para> ''' For example: ''' <list type="bullet"> ''' <item><description>English<para></para>11 May, 2025</description></item> ''' <item><description>Spanish<para></para>11 de mayo de 2025</description></item> ''' <item><description>German<para></para>11. Mai 2025</description></item> ''' </list> ''' </summary> ''' ''' <param name="[date]"> ''' The <see cref="Date"/> object to be formatted. ''' </param> ''' ''' <param name="provider"> ''' The culture information used to format the date. ''' </param> ''' ''' <returns> ''' A string representing the formatted date, based on the specified culture. ''' </returns> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Function ToLongFriendlyDateString([date] As Date, provider As IFormatProvider) As String Dim culture As CultureInfo = TryCast(provider, CultureInfo) If culture IsNot Nothing Then Select Case culture.TwoLetterISOLanguageName.ToLower() Case "es", "ca", "gl", "pt" ' Spanish, Catalonian, Galego, Portuguese Return [date].ToString("dd 'de' MMMM 'de' yyyy", provider) Case "de" ' Deutsch Return [date].ToString("dd'.' MMMM yyyy", provider) Case Else ' Do nothing. Exit Select End Select End If Return [date].ToString("dd MMMM, yyyy", provider) End Function ''' <summary> ''' Converts a <see cref="Date"/> object to a long friendly date string based on the current culture. ''' <para></para> ''' For example: ''' <list type="bullet"> ''' <item><description>English<para></para>11 May, 2025 at 23:59:59</description></item> ''' <item><description>Spanish<para></para>11 de mayo de 2025 a las 23:59:59</description></item> ''' </list> ''' </summary> ''' ''' <param name="[date]"> ''' The <see cref="Date"/> object to be formatted. ''' </param> ''' ''' <returns> ''' A string representing the formatted date, based on the current culture. ''' </returns> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Function ToLongFriendlyDateAndTimeString([date] As Date) As String Return DateExtensions.ToLongFriendlyDateAndTimeString([date], CultureInfo.CurrentCulture) End Function ''' <summary> ''' Converts a <see cref="Date"/> object to a long friendly date string based on the specifies culture. ''' <para></para> ''' For example: ''' <list type="bullet"> ''' <item><description>English<para></para>11 May, 2025 at 23:59:59</description></item> ''' <item><description>Spanish<para></para>11 de mayo de 2025 a las 23:59:59</description></item> ''' </list> ''' </summary> ''' ''' <param name="[date]"> ''' The <see cref="Date"/> object to be formatted. ''' </param> ''' ''' <param name="provider"> ''' The culture information used to format the date. ''' </param> ''' ''' <returns> ''' A string representing the formatted date, based on the specified culture. ''' </returns> <DebuggerStepThrough> <Extension> <EditorBrowsable(EditorBrowsableState.Always)> Public Function ToLongFriendlyDateAndTimeString([date] As Date, provider As IFormatProvider) As String Dim culture As CultureInfo = TryCast(provider, CultureInfo) If culture IsNot Nothing Then Select Case culture.TwoLetterISOLanguageName.ToLower() Case "en" ' English Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' 'at' HH:mm:ss", provider) Case "es" ' Spanish Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' 'a las' HH:mm:ss", provider) Case Else ' Do nothing. Exit Select End Select End If Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' '—' HH:mm:ss", provider) End Function
|
|
« Última modificación: Hoy a las 03:14 por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.926
|
Librería .NET para automatizar el uso de rar.exe de RARLab (WinRAR)Esto es un wrapper .NET completo para la herramienta por línea de comandos rar.exe oficial de RARLab. Esta librería permite a los desarrolladores de .NET acceder y controlar fácilmente casi todas las funciones de rar.exe, como comprimir, extraer, listar, testar, crear volúmenes de recuperación y administrar archivos RAR, desde sus aplicaciones. Llevaba mucho tiempo queriendo hacer esto, bastantes años hace que se me ocurrió la idea por que hay infinidad de librerías disponibles en la mayoría de lenguajes de programación para manejar formatos ZIP y 7Zip entre otros muchos, pero para el formato RAR, en especial el formato RARv5 son muy escasas... probablemente por desinterés y/o por ser un formato privativo. Lo cierto es que no conozco ningún otro wrapper del executable rar.exe, ni tampoco un wrapper que en lugar de depender de rar.exe haga llamadas nativas a una librería oficial de RARLab. El caso es que nunca empecé este proyecto por simple pereza. Me parecía muy interesante pero al mismo tiempo no me resultaba necesario en realidad desarrollar una infraestructura completa para configurar el lanzamiento del proceso de rar.exe pasándole un comando cualquiera, cosa que podía escribir en una sola línea como esta: Process.Start(".\rar.exe", "argumentos") — pero claro, esto es algo muy codificado en el código por así decirlo, no es tan bonito o elegante o profesional como configurar una sofisticada clase para construir los argumentos y controlar el lanzamiento del proceso con sus códigos de salida y demás. Así que siempre lo estuve aplazando. Y cuando finalmente decidí empezar, hace cosa de unas semanas, esperaba poder compartirlo con ustedes en formato de "snippet" en este hilo, es decir algo de un tamaño reducido, pero fui demasiado ingenuo ya que al final el trabajo ha alcanzado la cantidad de 9 clases para representar diversos comandos, 17 enumeraciones y otras tantas clases para otros elementos integrados, haciendo un total de 37 archivos separados de código fuente. Así que no me ha quedado más remedio que compartirlo en GitHub, y aquí lo comparto con ustedes: 👉 📦 RARLab's rar.exe .NET Wrapper LibraryComo he dicho, esto es una librería, un archivo dll para administrar el uso del archivo rar.exe. Es totalmente "universal", se puede usar en proyectos de VB.NET o de C#, bajo .NET Framework o NET 5.0+ (el proyecto habría que migrarlo), no hay dependencias más allá del archivo 'rar.exe' de WinRAR y la licencia del producto, que deben ser administrados por el usuario.
El README.md del repositorio en GitHub incluye un ejemplo de uso para VB.NET y también para C#. Además, en el código fuente de todas las nueve clases que representan los 'Comandos', incluyen un apartado, arriba del todo de la clase, con un ejemplo de uso para VB.NET, y también en la propia documentación XML de la clase. De todas formas, aquí les dejo un ejemplo de uso completo para VB.NET — Construir un Comando para la creación de archivos RAR utilizando la clase RarCreationCommand:Imports DevCase.RAR Imports DevCase.RAR.Commands
Dim archivePath As String = "C:\New Archive.rar" Dim filesToAdd As String = "C:\Directory to add\" Dim command As New RarCreationCommand(RarCreationMode.Add, archivePath, filesToAdd) With { .RarExecPath = ".\rar.exe", .RarLicenseData = "(Your license key)", .RecurseSubdirectories = True, .EncryptionProperties = Nothing, .SolidCompression = False, .CompressionMode = RarCompressionMode.Normal, .DictionarySize = RarDictionarySize.Mb__128, .OverwriteMode = RarOverwriteMode.Overwrite, .FilePathMode = RarFilePathMode.ExcludeBaseDirFromFileNames, .FileTimestamps = RarFileTimestamps.All, .AddQuickOpenInformation = TriState.True, .ProcessHardLinksAsLinks = True, .ProcessSymbolicLinksAsLinks = TriState.True, .DuplicateFileMode = RarDuplicateFileMode.Enabled, .FileChecksumMode = RarFileChecksumMode.BLAKE2sp, .ArchiveComment = New RarArchiveComment("Hello world!"), .RecoveryRecordPercentage = 0, .VolumeSplitOptions = Nothing, .FileTypesToStore = Nothing }
— Para obtener los argumentos completos de la línea de comandos de nuestro Comando:Console.WriteLine($"Command-line arguments: {command}")
MessageBox.Show(command.ToString())
— Ejecutar nuestro Comando usando la clase RarCommandExecutor:Using rarExecutor As New RarCommandExecutor(command) AddHandler rarExecutor.OutputDataReceived, Sub(sender As Object, e As DataReceivedEventArgs) Console.WriteLine($"[Output] {Date.Now:yyyy-MM-dd HH:mm:ss} - {e.Data}") End Sub AddHandler rarExecutor.ErrorDataReceived, Sub(sender As Object, e As DataReceivedEventArgs) If e.Data IsNot Nothing Then Console.WriteLine($"[Error] {Date.Now:yyyy-MM-dd HH:mm:ss} - {e.Data}") End If End Sub AddHandler rarExecutor.Exited, Sub(sender As Object, e As EventArgs) Dim pr As Process = DirectCast(sender, Process) Dim rarExitCode As RarExitCode = DirectCast(pr.ExitCode, RarExitCode) Console.WriteLine($"[Exited] {Date.Now:yyyy-MM-dd HH:mm:ss} - rar.exe process has terminated with exit code {pr.ExitCode} ({rarExitCode})") End Sub Dim exitcode As RarExitCode = rarExecutor.ExecuteRarAsync().Result End Using
|
|
« Última modificación: Hoy a las 19:37 por Eleкtro »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Librería de Snippets en C/C++
« 1 2 3 4 »
Programación C/C++
|
z3nth10n
|
31
|
27,501
|
2 Agosto 2013, 17:13 pm
por 0xDani
|
|
|
[APORTE] [VBS] Snippets para manipular reglas de bloqueo del firewall de Windows
Scripting
|
Eleкtro
|
1
|
4,301
|
3 Febrero 2014, 20:19 pm
por Eleкtro
|
|
|
Librería de Snippets para Delphi
« 1 2 »
Programación General
|
crack81
|
15
|
22,832
|
25 Marzo 2016, 18:39 pm
por crack81
|
|
|
Una organización en Github para subir, proyectos, snippets y otros?
Sugerencias y dudas sobre el Foro
|
z3nth10n
|
0
|
3,270
|
21 Febrero 2017, 10:47 am
por z3nth10n
|
|
|
índice de la Librería de Snippets para VB.NET !!
.NET (C#, VB.NET, ASP)
|
Eleкtro
|
7
|
6,942
|
4 Julio 2018, 21:35 pm
por Eleкtro
|
|