Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Eleкtro

#2581
¿Cómo manipular imágenes GIF animadas?

La librería de clases de .NET Framework no expone ningún tipo para representar de forma específica una imagen GIF. Tenemos el tipo Bitmap, Icon, e Image para representar de forma global cualquier tipo de imagen (incluyendo un GIF). Pero... ¿y si queremos representar de forma específica una imagen GIF con todos sus frames?, pues esta clase que he desarrollado sería un buen comienzo para llevarlo a cabo:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 02-April-2017
' ***********************************************************************

#Region " Public Members Summary "

#Region " Constructors "

' New(String)
' New(FileInfo)
' New(Image)

#End Region

#Region " Properties "

' Image As Image
' FrameCount As Integer
' Frames(Integer) As Bitmap
' ActiveFrame As Bitmap
' ActiveFrameIndex As Integer
' EndOfFrames As Boolean

#End Region

#Region " Functions "

' NextFrame() As Bitmap
' GetFrames() As List(Of Bitmap)

#End Region

#End Region

#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO

#End Region

#Region " GIF "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Represents a GIF image.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Public Class GIF

#Region " Properties "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the GIF image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The GIF image.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Public ReadOnly Property Image As Image

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the frame count of the GIF image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The frame count of the GIF image.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Public ReadOnly Property FrameCount As Integer

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the frame at the specified index.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The frame index.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Default Public Overridable ReadOnly Property Frames(ByVal index As Integer) As Bitmap
           <DebuggerStepperBoundary>
           Get
               Using img As Image = DirectCast(Me.Image.Clone(), Image)
                   img.SelectActiveFrame(FrameDimension.Time, index)
                   Return New Bitmap(img) ' Deep copy of the frame (only the frame).
               End Using
           End Get
       End Property

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the active frame.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The active frame.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Public Overridable ReadOnly Property ActiveFrame As Bitmap
           <DebuggerStepperBoundary>
           Get
               Return New Bitmap(Me.Image) ' Deep copy of the frame (only the frame).
           End Get
       End Property

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the index in the frame count of the current active frame.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The index in the frame count of the current active frame.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Public Property ActiveFrameIndex As Integer
           <DebuggerStepThrough>
           Get
               Return Me.activeFrameIndexB
           End Get
           <DebuggerStepperBoundary>
           Set(ByVal value As Integer)
               If (value <> Me.activeFrameIndexB) Then
                   Me.Image.SelectActiveFrame(FrameDimension.Time, value)
                   Me.activeFrameIndexB = value
                   Me.eof = (value = Me.FrameCount)
               End If
           End Set
       End Property
       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' ( Backing Field )
       ''' The index in the frame count of the current active frame.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       Private activeFrameIndexB As Integer

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets a value indicating whether the frame count is at EOF,
       ''' this means there is no more frames to advance in the GIF image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' <see langword="True"/> if there is no more frames to advance in the GIF image; otherwise, <see langword="False"/>.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       Public ReadOnly Property EndOfFrames As Boolean
           <DebuggerStepThrough>
           Get
               Return Me.eof
           End Get
       End Property
       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' ( Backing Field )
       ''' A value indicating whether the frame count is at EOF,
       ''' this means there is no more frames to advance in the GIF image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       Private eof As Boolean

#End Region

#Region " Constructors "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Prevents a default instance of the <see cref="GIF"/> class from being created.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerNonUserCode>
       Private Sub New()
       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="GIF"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="filepath">
       ''' The filepath.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal filepath As String)

           Me.New(Image.FromFile(filepath))

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="GIF"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="file">
       ''' The image file.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal file As FileInfo)

           Me.New(Image.FromFile(file.FullName))

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="GIF"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="img">
       ''' The image.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal img As Image)

           Me.Image = img
           Me.FrameCount = Me.Image.GetFrameCount(FrameDimension.Time)

       End Sub

#End Region

#Region " Public Methods "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Advances one position in the frame count and returns the next frame.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The next frame.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Overridable Function NextFrame() As Bitmap

           If (Me.eof) Then
               Throw New IndexOutOfRangeException()

           Else
               Dim frame As Bitmap = Me.Frames(Me.activeFrameIndexB)
               Me.activeFrameIndexB += 1
               Me.eof = (Me.activeFrameIndexB >= Me.FrameCount)
               Return frame

           End If

       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets a <see cref="List(Of Bitmap)"/> containing all the frames in the image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' A <see cref="List(Of Bitmap)"/> containing all the frames in the image.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Overridable Function GetFrames() As List(Of Bitmap)

           Using img As Image = DirectCast(Me.Image.Clone(), Image)
               Return GetFramesFromImage(img)
           End Using

       End Function

#End Region

#Region " Private Methods "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets a <see cref="List(Of Bitmap)"/> containing all the frames in the source GIF image.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="img">
       ''' The source <see cref="Image"/>.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting percentage difference value between the two specified images.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       Private Shared Function GetFramesFromImage(ByVal img As Image) As List(Of Bitmap)

           Dim imgs As New List(Of Bitmap)
           Dim frameCount As Integer = img.GetFrameCount(FrameDimension.Time)

           For i As Integer = 0 To (frameCount - 1)
               img.SelectActiveFrame(FrameDimension.Time, i)
               imgs.Add(New Bitmap(img)) ' Deep copy of the frame (only the frame).
           Next

           Return imgs

       End Function

#End Region

   End Class

#End Region


Ejemplos de uso:
Código (vbnet) [Seleccionar]
Dim pcb As PictureBox = Me.PictureBox1
Dim gif As New GIF("C:\File.gif")

Do Until gif.EndOfFrames ' Iterate frames until the end of frame count.

   ' Free previous Bitmap object.
   If (pcb.Image IsNot Nothing) Then
       pcb.Image.Dispose()
       pcb.Image = Nothing
   End If

   pcb.Image = gif.NextFrame()
   Thread.Sleep(60) ' Simulate a FPS thingy.
   Application.DoEvents()

   If (gif.EndOfFrames) Then
       ' Set active frame to 0 for infinite loop:
       gif.ActiveFrameIndex = 0
   End If

Loop


Nótese que el método GIF.GetFrames() devuelve una colección de Bitmaps con todos los frames de la imagen GIF. Las posibilidades son infinitas con esta colección, podemos añadir, editar o eliminar frames para crear un nuevo GIF, o simplemente mostrar la secuencia de frames...

¡Saludos!
#2582
.NET (C#, VB.NET, ASP) / Re: Toolbox en C#
2 Abril 2017, 22:18 PM
Cita de: Nolohagan en  2 Abril 2017, 19:56 PMeste codigo... adonde va?

El código iría en un archivo de clase individual, "MyTreeView.cs" por ejemplo.

Cita de: Nolohagan en  2 Abril 2017, 19:56 PMese codigo, que es tuyo, no contiene un InitializeComponent como el Form1.cs*.

La clase "Form1.cs" contiene un método llamado InitializeComponent el cual no es más que un código de inicialización auto generadop por Visual Studio, ese método está en la clase Form1.Designer.cs.

La clase MyTreeView no es un Form, sino un control de usuario. Cuando compilas la clase MyTreeView (y solo cuando la hayas compilado) se agregará un nevo control al ToolBox de controles de VisualStudio, arriba del todo del ToolBox, donde podrás ver ese nuevo TreeView que has compilado.

Cita de: Nolohagan en  2 Abril 2017, 19:56 PMNo entiendo.

En Visual Studio puedes crear controles, puedes tomar como base el aspecto y el comportamiento de un TreeView y añadirle modificaciones (modificaciones estéticas, o de lo que sea), a esto se le llama Class Inheritance o Herencia de Clases.

Pues bien, la clase "MyTreeView" hereda de la clase System.Windows.Forms.TreeView, ¿por qué, cual es el propósito?, pues basicamente por que tu pregunta inicial fue "¿Cómo crear un TreeView que tenga un ListBox adentro?", y para ello hay que tomar como base un TreeView para añadirle un control de tipo ListBox adentro de su colección de controles...

...Pero ya no estoy seguro de que realmente eso es lo que quieres hacer. Siento decirlo y espero no ofender pero no te estás explicando nada bien, creo que ese código de la clase "MyTreeView" y las explicaciones que he estado dándote hasta ahora al final lo hice para nada por que creo que realmente no quieres crear un TreeView con un ListBox adentro, sino más bien un TreeView normal y corriente de toda la vida y simplemente añadirle un nodo con el texto "ListBox".




Cita de: Nolohagan en  2 Abril 2017, 19:56 PMLo que queria hacer es arrastrar un Listbox desde el TreeView hasta el panel y que cuando se termino de arrastrar en el panel, que se genere un ListBox en el panel.

Eso no concuerda con la imagen que pusiste:

Cita de: NoLoHagan

En ese TreeView no hay ningún control de tipo ListBox hablando literálmente, tan solo una etiqueta/nodo con el texto "ListBox".

Lo vuelvo a preguntar: ¿Realmente quieres arrastar un ListBox, o lo que quieres hacer es arrastrar una nodo del TreeView?.

Me la voy a jugar para decir que yo creo que lo que tú realmente quieres hacer no es arrastrar un ListBox como has estado diciendo hasta ahora, sino arrastrar etiquetas/nodos del Treeview, tal que así:



...Y que lo del ListBox lo has dicho por no saber explicar mejor lo que querías hacer.

Bien, pues si estoy en lo correcto entonces para llevar a cabo esa tarea se puede aprovechar parte del código que te enseñé arriba. Si eso es lo que realmente quieres hacer, entonces primero de todo elimina la clase "MyTreeView", por que entonces esa clase no te sirve para nada.

Este sería el código del Form, he dejado comentarios explicando el propósito de cada cosa:

Código (csharp) [Seleccionar]
// Los nodos hijos de controles.
static TreeNode[]  childControlNodes = {
   new TreeNode("Label") { Tag = typeof(Label) },
   new TreeNode("ListBox") { Tag = typeof(ListBox) },
   new TreeNode("ListView") { Tag = typeof(ListView) },
   new TreeNode("TextBox") { Tag = typeof(TextBox) }
};

// El nodo principal de controles.
static TreeNode controlsNode = new TreeNode("Controls", childControlNodes);

private void Form1_Load(object sender, EventArgs e)
{
   this.panel1.AllowDrop = true; // Permitir soltar objetos en el panel.
   this.treeView1.Nodes.Add(controlsNode); // Añadir el nodo de controles al TreeView.
   // Asociación de eventos en tiempo de ejecución:
   this.treeView1.MouseDown += this.TreeView1_MouseDown;
   this.panel1.DragEnter += this.Panel1_DragEnter;
   this.panel1.DragOver += this.Panel1_DragOver;
   this.panel1.DragDrop += this.Panel1_DragDrop;
}

private void TreeView1_MouseDown(object sender, MouseEventArgs e) {
 
   // Obtenemos el control TreeView que disparé este evento.
   TreeView tree = (TreeView)sender;

   // Asigname el nodo seleccionado, el nodo en el que hemos echo click.
   tree.SelectedNode = tree.GetNodeAt(e.Location);

   // Si el nodo no es nulo...
   if ((tree.SelectedNode != null)) {

       // Obtenemos una referencia del nodo.
       TreeNode node = tree.SelectedNode;

       // Si el nodo contiene un Tag...
       if (node.Tag != null)
       {
           // Determinamos el tipo de control del tag.
           Type t = (Type)node.Tag;
           // Creamos una instancia del tipo de control.
           Control ctrl = (Control)Activator.CreateInstance(t);
           ctrl.Text = node.Text;
           // Iniciamos la operación de arrastrar y soltar del control.
           DragDropEffects result = tree.DoDragDrop(ctrl, DragDropEffects.Move);
           // Si el control no se movió...
           if ((result == DragDropEffects.None))
           {
               // Liberamos los recursos del control.
               ctrl.Dispose();
               // Anulamos la referencia del control,
               // para que el recolector de basura (Garbage Collector) lo deseche cuanto antes.
               ctrl = null;
           }

       }

   }

}

private void Panel1_DragEnter(object sender, DragEventArgs e)
{
   Control ctrl = e.Data.GetData(e.Data.GetFormats()[0]) as Control;
   Panel pan = (Panel)sender;
   if (ctrl != null)
   {
       ctrl.Location = pan.PointToClient(new Point(e.X, e.Y));
       pan.Controls.Add(ctrl);
   }
}

private void Panel1_DragOver(object sender, DragEventArgs e)
{
   Control ctrl = e.Data.GetData(e.Data.GetFormats()[0]) as Control;
   Panel pan = (Panel)sender;
   if ((ctrl != null))
   {
       ctrl.Location = pan.PointToClient(new Point(e.X, e.Y));
   }
   e.Effect = DragDropEffects.Move;
}

// Cuando el control se soltó en el panel...
private void Panel1_DragDrop(object sender, DragEventArgs e)
{
   Control ctrl = e.Data.GetData(e.Data.GetFormats()[0]) as Control;
   // ...
   if ((ctrl != null))
   {
       // ctrl.BackColor = Control.DefaultBackColor;
       ctrl.ForeColor = Control.DefaultForeColor;
   }
}


Te dejo aquí el proyecto en C# para que te sea todavía más facil:


¡Saludos!
#2583
Cita de: Fron99 en  2 Abril 2017, 10:58 AM¿Alguien sabria decirme cual es el error.?

Alma de cántaro, tienes que escapar los caracteres reservados/especiales de Batch. Los paréntesis y símbolos de porciento, entre otros.

Aparte de eso, en cada linea tienes argumentos abiertos sin comillas dobles de cierre " "

Prueba así:
ECHO IF NOT EXIST ".\%%USERNAME%%" ^(MD ".\%%USERNAME%%"^)
ECHO attrib +h +s ".\%%USERNAME%%"
ECHO cd ".\%%USERNAME%%"
ECHO for /R "%%USERPROFILE%%\Pictures\" %%%%x in ^(*.pdf,*.docx,*.xlsx,*.pptx,*.txt,*.jpg,*.jpeg^) do copy %%%%x ".\"


Saludos!
#2584
@Constance, yo te apoyo cuando tienes razón, pero todas las publicaciones del foro incluyendo las del foro libre deben conllevar una finalidad que se pueda debatir entre los usuarios, debe ser un post con sentido, vaya, un post con un... algo, lo que sea, pero no esto de publicar un post a las 3 A.M solamente para comentar el primer pensamiento chorra que te ronde por la cabeza para decirnos como vives las horas del día y como te afectan las horas del sueño...

Supongo que no compartiremos la misma percepción del sentido común (ya sabes, soy Virgo :xD) pero espero que entiendas el motivo, este hilo estaría condenado al offtopic y la divagación infinita si no se le pone fin desde ya...

Tema Cerrado.
#2585
Cita de: Orubatosu en  1 Abril 2017, 22:12 PMEuropa, con una democracia consolidada

¿Demo qué?. No me hagas reir, ningún país Europeo tiene una democracia real, eso es una fachada para tapar otro tipo de sistema, el Sistema Representativo, una DICTADURA moderna y consentida por el pueblo, con sus programas electorales llenos de falsas promesas, engaños, competitividad deshonesta con los demás partidos y todo ese tipo de mierd@as a las que estamos acostumbrados en cualquier gobierno de hoy en día, pero claro, nos han ido metiendo la mentira tan a fondo en el cerebro que ya la gente se ha acostumbrado a llamarlo "Democracia" desde tiempos inmemorables, y lo peor de todo es que practicamente todo el mundo realmente creen que están viviendo en una Democracia... por que no han tenido la oportunidad de conocer una Democracia real.

[youtube=640,360]https://www.youtube.com/watch?v=UoP_mSIHqTY[/youtube]

#2586
En lugar de tener que estar escribiendo >>Archivo.txt al final de cada linea, puedes usar los operadores de agrupación de comando (los paréntesis) para simplificarlo así:

Código (dos) [Seleccionar]
(
Echo Linea1
Echo Linea2
Echo Linea3
Echo etc...
)>"Output.txt"


¡Saludos!
#2587
¿Cómo determinar cual es la versión más reciente instalada de .NET Framework en la máquina actual?.

Aquí les dejo el código fuente completo:

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Determines which is the most recent version of the .NET Framework runtimes installed on the current machine.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim frameworkVersion As Version = GetMostRecentInstalledFrameworkVersion()
''' Console.WriteLine(frameworkVersion.ToString())
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' Credits to Microsoft: <see href="http://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting .NET Framework <see cref="Version"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepperBoundary>
Private Shared Function GetMostRecentInstalledFrameworkVersion() As Version

   ' .NET 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1
   Using ndpKey As RegistryKey =
       RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).
                   OpenSubKey("SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\", writable:=False)

       If (ndpKey IsNot Nothing) AndAlso (ndpKey.GetValue("Release") IsNot Nothing) Then
           Dim releaseVersion As Integer = CInt(ndpKey.GetValue("Release"))
           Select Case releaseVersion
               Case >= 394254
                   Return New Version(4, 6, 1)
               Case >= 393295
                   Return New Version(4, 6)
               Case >= 379893
                   Return New Version(4, 5, 2)
               Case >= 378675
                   Return New Version(4, 5, 1)
               Case >= 378389
                   Return New Version(4, 5)
           End Select
       End If
   End Using

   ' .NET 1.0, 2.0, 3.0, 3.5, 4.0
   Using ndpKey As RegistryKey =
       RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "").
                   OpenSubKey("SOFTWARE\Microsoft\NET Framework Setup\NDP\", writable:=False)

       For Each versionKeyName As String In ndpKey.GetSubKeyNames().OrderByDescending(Function(x As String) x)
           If versionKeyName.ToLower().StartsWith("v") Then
               Return New Version(versionKeyName.ToLower().TrimStart("v"c))
           End If
       Next versionKeyName
   End Using

   Return New Version()

End Function


Personálmente recomiendo decorar esta funcionalidad mediante una propiedad de sólo lectura, tal que así:
Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a value that determines which is the most recent version of the .NET Framework runtimes installed
''' on the current machine.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <value>
''' A value that determines which is the most recent version of the .NET Framework runtimes installed
''' on the current machine.
''' </value>
''' ----------------------------------------------------------------------------------------------------
Public Shared ReadOnly Property MostRecentInstalledFrameworkVersion As Version
   <DebuggerStepThrough>
   Get
       Return GetMostRecentInstalledFrameworkVersion()
   End Get
End Property


Modo de empleo:
Código (vbnet) [Seleccionar]
Dim frameworkVersion As Version = GetMostRecentInstalledFrameworkVersion()
Console.WriteLine(frameworkVersion.ToString())


Notas: Faltaría implementar la versión de .NET 4.6.2. Aparte de eso no he podio testear en profundidad el resultado obtenido en un equipo que tenga instalado .NET 1.0, 2.0, 3.0, 3.5 o 4.0, si encuentran algún error diganmelo.




Códigos de error Win32.

Esto que voy a compartir a continuación es una enumeración con todos los errores Win32 de la API de Windows, en total son +13.000 lineas de código, así que os dejo un enlace externo:


El propósito de gigantesca enumeración es proveer una manera sencilla, directa y eficiente de determinar que error nos devuelve en ocasiones una función de la API de Windows y cual es el significado de dicho código de error.

No confundir un código de error Win32 con un código de error H_RESULT, esto último define muchos errores Win32 pero con otros valores.

Recordad que la librería de clases de .NET Framework expone algunos miembros muy útiles para la evaluación de errores de funciones no administradas, Marshal.GetLastWin32Error(), Marshal.GetHRForLastWin32Error() y Marshal.ThrowExceptionForHR() así como el tipo excepción System.ComponentModel.Win32Exception que podemos invocar para informarle de un error Win32 específico al usuario.




¿Cómo prevenir el Flickering de un control Win32?.

Uno de los mayores problemas estéticos y también de lo más común al trabajar con los controles de la tecnología WindowsForms es el Flickering. El Flicker consiste en un desagradable parpadeo de la imagen en donde la imagen desaparece por un breve tiempo lapso de tiempo hasta que vuelve a aparecer, como un parpadeo. Es un problema visual que afecta a la estética del control, y suele producirse muy a menudo cuando el control necesita realizar operaciones de dibujo muy expensivas, o cuando estamos trabajando con transparencias.

Una descripción más detallada del flickering: https://en.wikipedia.org/wiki/Flicker_(screen)

¿Cómo se soluciona el Flickering?, pues lamentablemente no se puede solucionar completamente, pero si que podemos llegar a reducir el Flickering considerablemente y en el mejor de los casos hasta llegar a dejar de percibirlo del todo y poder decir que ya no hay Flickering en el control, ¿pero cómo se hace?, pues una solución cotidiana sería con un bufer doble de memoria, o double buffering.

Cuando el double buffering está activado, todas las operaciones de dibujado del control son renderizadas primero a un bufer de memoria en vez de ser renderizadas directamente a la superficie de dibujado en la pantalla. Cuando todas las operaciones de dibujado han sido completadas, el bufer de memoria es copiado directamente a la superficie de dibujado asociada a él.

Para tratar de solventar los problemas de Flickering cuando estamos desarrollando un control de usuario, he desarrollado una interfáz con nombre IBufferedControl, la cual implementariamos en nuestro control:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 20-March-2017
' ***********************************************************************

#Region " Public Members Summary "

#Region " Properties "

' CreateParams As CreateParams
' DoubleBuffered As Boolean
' PreventFlickering As Boolean

#End Region

#End Region

#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Windows.Forms

#End Region

#Region " IBufferedControl "

Namespace Types

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Provides simple double buffering (anti flickering) functionality for a Windows Forms <see cref="Control"/>,
   ''' such for example a <see cref="TextBox"/>.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Public Interface IBufferedControl

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets the required creation parameters when the control handle is created.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' The creation parameters.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       <Browsable(False)>
       <EditorBrowsable(EditorBrowsableState.Advanced)>
       ReadOnly Property CreateParams As CreateParams
       ' Implementation Exmple:
       '
       ' Protected Overrides ReadOnly Property CreateParams As CreateParams Implements IBufferedControl.CreateParams
       '     Get
       '         If (Me.preventFlickeringB) Then
       '             Dim cp As CreateParams = MyBase.CreateParams
       '             cp.ExStyle = (cp.ExStyle Or CInt(WindowStylesEx.Composited))
       '             Return cp
       '         Else
       '             Return MyBase.CreateParams
       '         End If
       '     End Get
       ' End Property

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets or sets a value indicating whether this control should redraw its surface using a secondary buffer
       ''' to reduce or prevent flicker.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' <see langword="True"/> if the surface of the control should be drawn using double buffering;
       ''' otherwise, <see langword="False"/>.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       <Browsable(True)>
       <EditorBrowsable(EditorBrowsableState.Always)>
       <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
       <Localizable(True)>
       <Category("Behavior")>
       <Description("Indicates whether this control should redraw its surface using a secondary buffer to reduce or prevent flicker.")>
       <DefaultValue(GetType(Boolean), "True")>
       Property DoubleBuffered As Boolean
       ' Implementation Exmple:
       '
       ' Public Overridable Shadows Property DoubleBuffered As Boolean Implements IBufferedControl.DoubleBuffered
       '     Get
       '         Return MyBase.DoubleBuffered
       '     End Get
       '     Set(ByVal value As Boolean)
       '         Me.SetStyle(ControlStyles.DoubleBuffer, value)
       '         MyBase.DoubleBuffered = value
       '     End Set
       ' End Property

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Gets or sets a value that indicates whether the control should avoid unwanted flickering effects.
       ''' <para></para>
       ''' If <see langword="True"/>, this will avoid any flickering effect on the control, however,
       ''' it will also have a negative impact by slowing down the responsiveness of the control about to 30% slower.
       ''' <para></para>
       ''' This negative impact doesn't affect to the performance of the application itself,
       ''' just to the performance of this control.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <value>
       ''' A value that indicates whether the control should avoid unwanted flickering effects.
       ''' </value>
       ''' ----------------------------------------------------------------------------------------------------
       <Browsable(True)>
       <EditorBrowsable(EditorBrowsableState.Always)>
       <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
       <Localizable(True)>
       <Category("Behavior")>
       <Description("Indicates whether the control should avoid unwanted flickering effects. If True, this will avoid any flickering effect on the control, however, it will also have a negative impact by slowing down the responsiveness of the control about to 30% slower.")>
       <DefaultValue(GetType(Boolean), "False")>
       Property PreventFlickering As Boolean
       ' Implementation Exmple:
       '
       ' Public Overridable Property PreventFlickering As Boolean Implements IBufferedControl.PreventFlickering
       '     Get
       '         Return Me.preventFlickeringB
       '     End Get
       '     Set(ByVal value As Boolean)
       '         Me.preventFlickeringB = value
       '     End Set
       ' End Property
       ' ''' ----------------------------------------------------------------------------------------------------
       ' ''' <summary>
       ' ''' ( Backing Field )
       ' ''' A value that indicates whether the control should avoid unwanted flickering effects.
       ' ''' </summary>
       ' ''' ----------------------------------------------------------------------------------------------------
       ' Private preventFlickeringB As Boolean

   End Interface

End Namespace

#End Region


Un ejemplo de implementación:
Código (vbnet) [Seleccionar]
<DisplayName("MyControl")>
<Description("A extended control.")>
<DesignTimeVisible(True)>
<DesignerCategory("UserControl")>
<ToolboxBitmap(GetType(UserControl))>
<ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Require)>
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")>
Public Class MyControl : Inherits UserControl : Implements IBufferedControl

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets the required creation parameters when the control handle is created.
   ''' <para></para>
   ''' The information returned by the <see cref="CreateParams"/> property is used to pass information about the
   ''' initial state and appearance of this control, at the time an instance of this class is being created.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <value>
   ''' The creation parameters.
   ''' </value>
   ''' ----------------------------------------------------------------------------------------------------
   <Browsable(False)>
   <EditorBrowsable(EditorBrowsableState.Advanced)>
   <Description("The required creation parameters when the control handle is created.")>
   Protected Overrides ReadOnly Property CreateParams As CreateParams Implements IBufferedControl.CreateParams
       Get
           If (Me.preventFlickeringB) Then
               Dim cp As CreateParams = MyBase.CreateParams
               cp.ExStyle = (cp.ExStyle Or CInt(WindowStylesEx.Composited))
               Return cp
           Else
               Return MyBase.CreateParams
           End If
       End Get
   End Property

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets or sets a value indicating whether this control should redraw its surface using a secondary buffer
   ''' to reduce or prevent flicker.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <value>
   ''' <see langword="True"/> if the surface of the control should be drawn using double buffering;
   ''' otherwise, <see langword="False"/>.
   ''' </value>
   ''' ----------------------------------------------------------------------------------------------------
   <Browsable(True)>
   <EditorBrowsable(EditorBrowsableState.Always)>
   <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
   <Localizable(True)>
   <Category("Behavior")>
   <Description("Indicates whether this control should redraw its surface using a secondary buffer to reduce or prevent flicker.")>
   <DefaultValue(GetType(Boolean), "False")>
   Public Overridable Shadows Property DoubleBuffered As Boolean Implements IBufferedControl.DoubleBuffered
       Get
           Return MyBase.DoubleBuffered
       End Get
       Set(ByVal value As Boolean)
           Me.SetStyle(ControlStyles.DoubleBuffer, value)
           MyBase.DoubleBuffered = value
       End Set
   End Property

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets or sets a value that indicates whether the control should avoid unwanted flickering effects.
   ''' <para></para>
   ''' If <see langword="True"/>, this will avoid any flickering effect on the control, however,
   ''' it will also have a negative impact by slowing down the responsiveness of the control about to 30% slower.
   ''' <para></para>
   ''' This negative impact doesn't affect to the performance of the application itself,
   ''' just to the performance of this control.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <value>
   ''' A value that indicates whether the control should avoid unwanted flickering effects.
   ''' </value>
   ''' ----------------------------------------------------------------------------------------------------
   <Browsable(True)>
   <EditorBrowsable(EditorBrowsableState.Always)>
   <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
   <Localizable(False)>
   <Category("Behavior")>
   <Description("Indicates whether the control should avoid unwanted flickering effects. If True, this will avoid any flickering effect on the control, however, it will also have a negative impact by slowing down the responsiveness of the control about to 30% slower.")>
   <DefaultValue(GetType(Boolean), "False")>
   Public Overridable Property PreventFlickering As Boolean Implements IBufferedControl.PreventFlickering
       Get
           Return Me.preventFlickeringB
       End Get
       Set(ByVal value As Boolean)
           Me.preventFlickeringB = value
       End Set
   End Property
   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' ( Backing Field )
   ''' A value that indicates whether the control should avoid unwanted flickering effects.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private preventFlickeringB As Boolean

   Public Sub New()
       MyBase.SuspendLayout()
       ' MyBase.DoubleBuffered = True
       ' Me.preventFlickeringB = True
       MyBase.ResumeLayout(performLayout:=False)
   End Sub

End Class





¿Cómo calcular la distancia (de 2 dimensiones) entre dos puntos?.

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Calculates the distance between two points in two dimensions in the coordinate system.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' Pythagorean theorem: <see href="http://en.wikipedia.org/wiki/Pythagorean_theorem"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim distance As Double = CalculateDistance2D(New PointF(1, 1), New PointF(2, 2))
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="pointA">
''' The first point.
''' </param>
'''
''' <param name="pointB">
''' The second point.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting distance.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function CalculateDistance2D(ByVal pointA As PointF, ByVal pointB As PointF) As Double

   ' Pythagoras theorem: c^2 = a^2 + b^2
   ' thus c = square root(a^2 + b^2)
   Dim a As Double = (pointB.X - pointA.X)
   Dim b As Double = (pointB.Y - pointA.Y)

   Return Math.Sqrt(a * a + b * b)

End Function





¿Cómo subscribirnos a eventos del sistema?.

Microsoft Windows expone una infraestructura llamada WMI (Windows Management Instrumentation) mediante la que provee una serie de classes que podemos utilizar para subscribbirnos a eventos del sistema o dicho coloquiálmente "monitorizar eventos", como por ejemplo cambios de hardware, cambios de aplicaciones instaladas o desinstaladas, cambios en el nivel de batería de un portatil, cambios en el registro de Windows, y un largo etcétera.

La lista de classes podemos encontrarla en MSDN: https://msdn.microsoft.com/en-us/library/aa394554(v=vs.85).aspx

Hay varios tipos de classes, un tipo de classes serían representativas, es decir para representar información de consultas realizadas a WMI, y otro tipo serían las classes de eventos. Una class de evento la utilizariamos para subscribirnos al tipo de evento que provee.

Para subscribirnos a una clase de evento, la librería de clases de .NET Framework espone la clase ManagementEventWatcher. Yo he desarrollado la siguiente class que hereda de la class ManagementEventWatcher, con la intención de añadir algunos constructores específicos para facilitar todavía más su uso y abstraer en mayor medida el nivel de complejidad.

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 21-March-2017
' ***********************************************************************

#Region " Public Members Summary "

#Region " Constructors "

' New(String)
' New(String, Single)
' New(String, Timespan)
' New(String, String, Single)
' New(String, String, Timespan)
' New(String, String, String(), UInteger)
' New(String, String, String(), Timespan)

' New(SelectQuery)
' New(SelectQuery, Single)
' New(SelectQuery, Timespan)
' New(SelectQuery, UInteger)

#End Region

#Region " Events "

' EventArrived As EventArrivedEventHandler

#End Region

#Region " Methods "

' Start()
' Stop()
' Dispose()

#End Region

#End Region

#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Management

#End Region

#Region " WMI Event Watcher "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' A WMI event monitor that notifies about event arrivals for the subscribed event class.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <DesignerCategory("code")>
   <ImmutableObject(False)>
   Public Class WMIEventWatcher : Inherits ManagementEventWatcher

#Region " Constructors "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Prevents a default instance of the <see cref="WMIEventWatcher"/> class from being created.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerNonUserCode>
       Private Sub New()
       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String)

           Me.New(eventClassName, condition:=String.Empty, withinInterval:=1.0F)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="eventClassName"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal withinInterval As Single)

           Me.New(eventClassName, condition:=String.Empty, withinInterval:=withinInterval)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="eventClassName"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal withinInterval As TimeSpan)

           Me.New(eventClassName, condition:=String.Empty, withinInterval:=withinInterval)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="condition">
       ''' The condition to be applied to events of the specified class in the
       ''' <paramref name="eventClassName"/> parameter.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="eventClassName"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal condition As String,
                      ByVal withinInterval As Single)

           Me.New(eventClassName, condition, TimeSpan.FromSeconds(withinInterval))

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="condition">
       ''' The condition to be applied to events of the specified class in the
       ''' <paramref name="eventClassName"/> parameter.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="eventClassName"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal condition As String,
                      ByVal withinInterval As TimeSpan)

           MyBase.Query = New WqlEventQuery(eventClassName:=eventClassName,
                                            condition:=condition,
                                            withinInterval:=withinInterval)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="condition">
       ''' The condition to be applied to events of the specified class in the
       ''' <paramref name="eventClassName"/> parameter.
       ''' </param>
       '''
       ''' <param name="groupByPropertyList">
       ''' The properties in the event class by which the events should be grouped.
       ''' </param>
       '''
       ''' <param name="groupWithinInterval">
       ''' The interval, in seconds, of the specified interval at which WMI sends one aggregate event,
       ''' rather than many events.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal condition As String,
                      ByVal groupByPropertyList As String(),
                      ByVal groupWithinInterval As UInteger)

           Me.New(eventClassName, condition, groupByPropertyList, TimeSpan.FromSeconds(groupWithinInterval))

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="eventClassName">
       ''' The name of the WMI event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="condition">
       ''' The condition to be applied to events of the specified class in the
       ''' <paramref name="eventClassName"/> parameter.
       ''' </param>
       '''
       ''' <param name="groupByPropertyList">
       ''' The properties in the event class by which the events should be grouped.
       ''' </param>
       '''
       ''' <param name="groupWithinInterval">
       ''' The interval, in seconds, of the specified interval at which WMI sends one aggregate event,
       ''' rather than many events.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal eventClassName As String,
                      ByVal condition As String,
                      ByVal groupByPropertyList As String(),
                      ByVal groupWithinInterval As TimeSpan)

           MyBase.Query = New WqlEventQuery(eventClassName:=eventClassName,
                                            condition:=condition,
                                            groupWithinInterval:=groupWithinInterval,
                                            groupByPropertyList:=groupByPropertyList)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="query">
       ''' The WMI select query of the event class to subscribe for.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal query As SelectQuery)

           Me.New(query.ClassName, condition:=query.Condition, withinInterval:=1.0F)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="query">
       ''' The WMI select query of the event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="query"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal query As SelectQuery,
                      ByVal withinInterval As Single)

           Me.New(query.ClassName, condition:=query.Condition, withinInterval:=TimeSpan.FromSeconds(withinInterval))

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="query">
       ''' The WMI select query of the event class to subscribe for.
       ''' </param>
       '''
       ''' <param name="withinInterval">
       ''' The interval, in seconds, that WMI will check for changes that occur to instances of the events of the
       ''' specified class in the <paramref name="query"/> parameter.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal query As SelectQuery,
                      ByVal withinInterval As TimeSpan)

           Me.New(query.ClassName, condition:=query.Condition, withinInterval:=withinInterval)

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Initializes a new instance of the <see cref="WMIEventWatcher"/> class.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="query">
       ''' The WMI select query of the event class to subscribe for and its selected properties.
       ''' </param>
       '''
       ''' <param name="groupWithinInterval">
       ''' The interval, in seconds, of the specified interval at which WMI sends one aggregate event,
       ''' rather than many events.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Sub New(ByVal query As SelectQuery,
                      ByVal groupWithinInterval As UInteger)

           Dim strArray As String() = New String(query.SelectedProperties.Count - 1) {}
           query.SelectedProperties.CopyTo(strArray, 0)

           MyBase.Query = New WqlEventQuery(eventClassName:=query.ClassName,
                                            condition:=query.Condition,
                                            groupWithinInterval:=TimeSpan.FromSeconds(groupWithinInterval),
                                            groupByPropertyList:=strArray)

       End Sub

#End Region

   End Class

#End Region


Ejemplo de uso para subscribirnos a la class Win32_VolumeChangeEvent, la cual nos informa de cambios de volumen, del montaje y desmontaje de particiones del sistema:

Código (vbnet) [Seleccionar]
Public NotInheritable Class Form1 : Inherits Form

   Private WithEvents eventWatcher As New WMIEventWatcher("Win32_VolumeChangeEvent", withinInterval:=0.5F)

   Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
       Me.eventWatcher.Scope = New ManagementScope("root\CIMV2", New ConnectionOptions() With {.EnablePrivileges = True})
       Me.eventWatcher.Start()
   End Sub

   Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing
       Me.eventWatcher.Dispose()
   End Sub

   Private Sub EventWatcher_EventArrived(ByVal sender As Object, ByVal e As EventArrivedEventArgs) _
   Handles eventWatcher.EventArrived
       Dim driveName As String = CStr(e.NewEvent.Properties("DriveName").Value)
       Dim eventType As Integer = CInt(e.NewEvent.Properties("EventType").Value)

       Console.WriteLine(String.Format("Drive Name: {0}", driveName))
       Console.WriteLine(String.Format("Event Type: {0}", eventType))
   End Sub

End Class


Ejemplo de uso para subscribirnos a la class Win32_LogicalDisk, mediante la cual con el uso de una condición en la consulta de WMI, nos reportará cambios de inserción y eyección en dispositivos de CD-ROM:

Código (vbnet) [Seleccionar]
Public Class Form1 : Inherits Form

   Private WithEvents eventWatcher As New WMIEventWatcher(
       "__InstanceModificationEvent",
       condition:="TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5",
       withinInterval:=0.5F
   )

   Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
       Me.eventWatcher.Scope = New ManagementScope("root\CIMV2", New ConnectionOptions() With {.EnablePrivileges = True})
       Me.eventWatcher.Start()
   End Sub

   Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles Me.FormClosing
       Me.eventWatcher.Dispose()
   End Sub

   Private Sub EventWatcher_EventArrived(ByVal sender As Object, ByVal e As EventArrivedEventArgs) Handles eventWatcher.EventArrived

       Using mo As ManagementBaseObject = DirectCast(pd.Value, ManagementBaseObject)

           Dim name As String = Convert.ToString(mo.Properties("Name").Value)
           string label = Convert.ToString(mo.Properties("VolumeName").Value);

           Dim di As DriveInfo = (From item In DriveInfo.GetDrives()
                                  Where String.IsNullOrEmpty(item.Name)
                                 ).Single()

           If Not String.IsNullOrEmpty(di.VolumeLabel) Then

               Console.WriteLine(String.Format("CD has been inserted in drive {0}.", di.Name))
           Else

               Console.WriteLine(String.Format("CD has been ejected from drive {0}.", di.Name))

           End If

       End Using

   End Sub

End Class

Nota: No he podido testear el ejemplo del dispositivo CD-ROM.




Todas estas funcionalidades y muchísimas más las podrán encontrar en mi Framework de pago ElektroKit.
#2588
Hace mucho tiempo que no publico nada aquí...

Vamos allá:




¿Cómo validar el número de una tarjeta de crédito?

Para ello podemos implementar el algoritmo Luhn.

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Uses the Luhn algorithm to determines whether the specified credit card number is valid.
''' <para></para>
''' Please de aware that not all valid credit cards can be verified with the Luhn algorithm because
''' it not covers all range of card numbers, however the Luhn algorithm does work for many, if not most, major credit cards.
''' <para></para>
''' The Luhn algorithm is simply used to prevent transpositional errors,
''' it is useful as a sanity check prior to submitting card numbers to a payment gateway,
''' but not suitable to absolutely validate whether a number is a valid card number.
''' <para></para>
''' The only way to absolutely verify a credit card number is to validate it via a payment gateway.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' Luhn algorithm: <see href="https://en.wikipedia.org/wiki/Luhn_algorithm"/>
''' <para></para>
''' Microsoft's Luhn algorithm implementation: <see href="http://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/CreditCardAttribute.cs"/>
''' <para></para>
''' Credits to: <see href="http://www.vcskicks.com/credit-card-verification.php"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim visaNumber As String = "4012888888881881"
''' Dim isValid As Boolean = ValidateCreditCardNumber(visaNumber)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="cardNumber">
''' The credit card number.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the specified card number is a valid card number; otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function ValidateCreditCardNumber(ByVal cardNumber As String) As Boolean

   cardNumber = cardNumber.Replace(" ", "").Replace("-", "").Trim()

   ' FIRST STEP: Double each digit starting from the right
   Dim doubledDigits As Integer() = New Integer(cardNumber.Length / 2 - 1) {}
   Dim k As Integer = 0
   For i As Integer = cardNumber.Length - 2 To 0 Step -2
       Dim digit As Integer
       If Not Integer.TryParse(cardNumber(i), digit) Then
           Return False
       End If
       doubledDigits(k) = digit * 2
       k += 1
   Next i

   ' SECOND STEP: Add up separate digits
   Dim total As Integer = 0
   For Each i As Integer In doubledDigits
       Dim number As String = i.ToString()
       For j As Integer = 0 To (number.Length - 1)
           total += Integer.Parse(number(j).ToString())
       Next j
   Next i

   ' THIRD STEP: Add up other digits
   Dim total2 As Integer = 0
   For i As Integer = cardNumber.Length - 1 To 0 Step -2
       Dim digit As Integer = Integer.Parse(cardNumber(i).ToString())
       total2 += digit
   Next i

   ' FOURTH STEP: Total
   Dim final As Integer = (total + total2)

   Return (final Mod 10 = 0) ' Well formed will divide evenly by 10.

End Function


Modo de empleo:
Código (vbnet) [Seleccionar]
' http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
Dim visaNumber As String = "4012888888881881"
Dim isValid As Boolean = ValidateCreditCardNumber(visaNumber)


Aquí les dejo unos números de tarjetas de crédito para testear:
Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Contains a collection of credit card numbers for testing purposes.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' For Each card As KeyValuePair(Of String, String()) In CreditCardsTestNumbers
'''     For Each cardnumber As String In card.Value
'''         Dim isValidNumber As Boolean = ValidateCreditCardNumber(cardnumber)
'''         Console.WriteLine("Card type: '{0}'; Number: '{1}'; Is Valid?: {2}", card.Key, cardnumber, isValidNumber)
'''     Next cardnumber
''' Next card
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
Public Shared ReadOnly CreditCardsTestNumbers As New Dictionary(Of String, String())(StringComparison.OrdinalIgnoreCase) From {
   {"American Express", {"378282246310005", "371449635398431"}},
   {"American Express Corporate", {"378734493671000"}},
   {"Australian BankCard", {"5610591081018250"}},
   {"Dankort (PBS)", {"5019717010103742", "76009244561"}},
   {"Diners Club", {"30569309025904", "38520000023237"}},
   {"Discover", {"6011111111111117", "6011000990139424"}},
   {"JCB", {"3530111333300000", "3566002020360505"}},
   {"Mastercard", {"5555555555554444", "5105105105105100"}},
   {"Switch/Solo (Paymentech)", {"6331101999990016"}},
   {"VISA", {"4111111111111111", "4012888888881881", "4222222222222"}}
}





¿Cómo auto-eliminar el executable de nuestra aplicación?

Para ello podemos escribir las instrucciones de eliminación en un archivo.bat externo, e iniciarlo.

¿Por qué Batch?, bueno, en un principio podriamos pensar en una solución usando puro código .NET por ejemplo compilando un código fuente en tiempo de ejecución para generar un executable de .NET temporal con las instrucciones de terminación del proceso y de eliminación del archivo, pero al hacer esto nos estaríamos metiendo en un círculo vicioso ya que el executable externo no se podría eliminar a si mismo, por ende, esta es una de las pocas ocasiones en las que Batch sirve para salvarnos de un apuro.

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Deletes the self application executable file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Shared Sub DeleteSelfApplication()
   DeleteSelfApplication(TimeSpan.FromMilliseconds(0))
End Sub

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Deletes the self application executable file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="delay">
''' A delay interval to wait (asynchronously) before proceeding to automatic deletion.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Shared Async Sub DeleteSelfApplication(ByVal delay As TimeSpan)

   If (delay.TotalMilliseconds > 0.0R) Then
       Dim t As New Task(Sub() Thread.Sleep(delay))
       t.Start()
       Await t
   End If

   Dim script As String = <a>
@Echo OFF
   
Set "exeName=%~nx1"
Set "exePath=%~f1"

:KillProcessAndDeleteExe
(TaskKill.exe /F /IM "%exeName%")1>NUL 2>&amp;1
If NOT Exist "%exePath%" (GoTo :SelfDelete)
(DEL /Q /F "%exePath%") || (GoTo :KillProcessAndDeleteExe)

:SelfDelete
(DEL /Q /F "%~f0")
</a>.Value

   Dim tmpFile As New FileInfo(Path.Combine(Path.GetTempPath, Path.GetTempFileName))
   tmpFile.MoveTo(Path.Combine(tmpFile.DirectoryName, tmpFile.Name & ".cmd"))
   tmpFile.Refresh()
   File.WriteAllText(tmpFile.FullName, script, Encoding.Default)

   Using p As New Process()
       With p.StartInfo
           .FileName = tmpFile.FullName
           .Arguments = String.Format(" ""{0}"" ", Application.ExecutablePath)
           .WindowStyle = ProcessWindowStyle.Hidden
           .CreateNoWindow = True
       End With
       p.Start()
       p.WaitForExit(0)
   End Using

   Environment.Exit(0)

End Sub


Modo de empleo:
Código (vbnet) [Seleccionar]
' Auto destruir el executable al instante:
DeleteSelfApplication()

' Auto destruir el executable de forma asincrónica con un tiempo de espera de 5 segundos:
DeleteSelfApplication(TimeSpan.FromSeconds(5))


El contenido del archivo.bat generado sería el siguiente:
Código (dos) [Seleccionar]
@Echo OFF

Set "exeName=%~nx1"
Set "exePath=%~f1"

:KillProcessAndDeleteExe
(TaskKill.exe /F /IM "%exeName%")1>NUL 2>&amp;1
If NOT Exist "%exePath%" (GoTo :SelfDelete)
(DEL /Q /F "%exePath%") || (GoTo :KillProcessAndDeleteExe)

:SelfDelete
(DEL /Q /F "%~f0")

...Lo primero que hará el script será entrar en un búcle infinito donde se intentará matar el proceso, y una vez conseguido se dispondrá a eliminar el archivo, y por último eliminarse a sí mismo.




¿Cómo guardar y restaurar el estado expandido/colapsado de los nodos de un TreeView?

Pongámonos en situación, imaginemos que tenemos un control de tipo TreeView en el que tenemos que crear y destruir algunos de sus nodos o todos ellos de forma dinámica, y al hacerlo perderiamos el estado expandido/colapsado de cada nodo al refrescar la lista de nodos.

U otra situación distinta, en la que simplemente quisieramos guardar el estado del TreeView al cerrar la aplicación, para cargar ese estado en el próximo inicio de la aplicación.

Bien, pues para solucionar ese tipo de problema primero crearíamos la siguiente función que nos devolverá una lista con todos los nodos y sus nodos hijos de un TreeView:

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets all the parent nodes and all its child nodes in the source <see cref="TreeView"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim nodeList As List(Of TreeNode) = Me.TreeView1.GetAllNodesAndChildnodes()
'''
''' For Each node As TreeNode In nodeList
'''     ' ...
''' Next node
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="sender">
''' The source <see cref="TreeView"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="List(Of TreeNode)"/> containing all the parent nodes and all its child nodes.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function GetAllNodesAndChildnodes(ByVal sender As TreeView) As List(Of TreeNode)

   Dim nodes As New List(Of TreeNode)
   Dim stack As New Stack(Of TreeNode)

   ' Bang all the top nodes into the queue.
   For Each top As TreeNode In sender.Nodes
       stack.Push(top)
   Next

   While (stack.Count > 0)
       Dim node As TreeNode = stack.Pop()
       If (node IsNot Nothing) Then
           ' Add the node to the list of nodes.
           nodes.Add(node)

           If (node.Nodes IsNot Nothing) And (node.Nodes.Count > 0) Then
               ' Enqueue the child nodes.
               For Each child As TreeNode In node.Nodes
                   stack.Push(child)
               Next child
           End If
       End If
   End While

   stack.Clear()
   stack = Nothing
   Return nodes

End Function


Ahora solo tenemos que crear una función para iterar los nodos obtenidos y así crear un "estado de guardado" (o save state), el cual consistitía en un diccionario que contendrá el código hash identificador de cada nodo, y un valor boolean indicando si el nodo está expandido o colapsado.

Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Saves the state of the source <see cref="TreeView"/> into a <see cref="Dictionary(Of Integer, Boolean)"/>
''' containing the hash code of each node and its expansion state.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim saveState As Dictionary(Of Integer, Boolean) = Me.TreeView1.SaveTreeState()
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="sender">
''' The source <see cref="TreeView"/>.
''' </param>
''' ---------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="Dictionary(Of Integer, Boolean)"/> containing the hash code of each node and its expansion state.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function SaveTreeState(ByVal sender As TreeView) As Dictionary(Of Integer, Boolean)

   Dim nodeList As List(Of TreeNode) = GetAllNodesAndChildnodes(sender)
   Dim nodeStates As New Dictionary(Of Integer, Boolean)()

   For Each node As TreeNode In nodeList
       nodeStates.Add(node.GetHashCode(), node.IsExpanded)
   Next

   Return nodeStates

End Function


Y por último la función para restaurar un estado de guardado:
Código (vbnet) [Seleccionar]
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Restores a state of the source <see cref="TreeView"/> previously saved using the <see cref="SaveTreeState"/> function.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim saveState As Dictionary(Of Integer, Boolean)
'''
''' Private Sub Button_SaveTreeState(sender As Object, e As EventArgs) Handles Button_SaveTreeState.Click
'''     saveState = Me.TreeView1.SaveTreeState()
''' End Sub
'''
''' Private Sub Button_RestoreTreeState(sender As Object, e As EventArgs) Handles Button_RestoreTreeState.Click
'''     Me.TreeView1.RestoreTreeState(saveState)
''' End Sub
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="sender">
''' The source <see cref="TreeView"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <param name="saveState">
''' A <see cref="Dictionary(Of Integer, Boolean)"/> containing the hash code of each node and its expansion state.
''' </param>
''' ----------------------------------------------------------------------------------------------------
Public Shared Sub RestoreTreeState(ByVal sender As TreeView, ByVal saveState As Dictionary(Of Integer, Boolean))

   Dim nodeList As List(Of TreeNode) = GetAllNodesAndChildnodes(sender)

   For Each node As TreeNode In nodeList

       Dim hash As Integer = node.GetHashCode()

       If saveState.ContainsKey(hash) Then

           If saveState(hash) Then
               node.Expand()
           Else
               node.Collapse()
           End If

       End If

   Next

End Sub





Todas estas funcionalidades y muchísimas más las podrán encontrar en mi Framework de pago ElektroKit.
#2589
Cita de: zotter en  1 Abril 2017, 11:00 AMseria posible, al igual que cuando reinstalas windows te aparece con algunos programas precargados del fabricante, tipo antivirus con 1 mes de prueba y cosas así, poder meter un programa yo para que al reinstalar windows se instale automáticamente??

Por supuesto que se puede, tan solo hay que editar la imagen Install.WIM del DVD de Windows la cual contiene las imágenes de instalación del sistema con todos los archivos y directorios que se instalan por defecto, se debe montar la imagen y realizar las modificaciones deseadas, pero esto es un procedimiento que requiere un mínimo de conocimiento sobre todo lo que ello implica.

Hay aplicaciones enfocadas a la edición de imágenes WIM para guiarte de una forma automatizada (y también limitada), como por ejemplo WinToolkit: https://www.wincert.net/forum/index.php?/files/file/5-win-toolkit/

Si prefieres aventurarte para realizar las modificacione de una forma más "manual" con la mayor libertad de posibilidades, aquí publiqué un tutorial:





Cita de: zotter en  1 Abril 2017, 11:00 AMLa pregunta es porque me han robado mi tablet recientemente que viene con Windows 10, y aunque he visto formas de localizarla por GPS de nada vale si el ladrón la formatea y reinstala windows, de ahi mi duda, si esto es posible hacerlo, para que cuando formateen la tablet automáticamente se instale un programa de seguimiento y me facilite donde esta la tablet en caso de futuros robos.

No tiene sentido eso. De nada te serviría preinstalar una aplicación en una imagen/DVD de Windows si luego un ladrón formatea el disco duro, donde se pierde todo, y además el susodicho ladrón al momento d instalar Windows utilizaría un DVD de Windows distinto donde no estaría preinstalada tu aplicación...
Evidéntemente no podría persistir a un formateo.

¡Saludos!
#2590
Los dos individuos serían "malas elecciones", pero uno siempre será peor que el otro... ningún ruso gana a un presidente Yankee a hijo de... "fruta", eso.

[youtube=640,360]https://www.youtube.com/watch?v=7gsexXkwXxU[/youtube]