Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)

Iniciado por Eleкtro, 18 Diciembre 2012, 22:23 PM

0 Miembros y 4 Visitantes están viendo este tema.

Eleкtro

Las siguientes funciones pueden adaptarlas fácilmente para pasarle el handle de la ventana, yo preferí usar diréctamente el nombre del proceso en cuestión.






Mueve la ventana de un proceso

Código (vbnet) [Seleccionar]
#Region " Move Process Window "

    ' [ Move Process Window ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' Move the notepad window at 10,50 (X,Y)
    ' Move_Process_Window("notepad.exe", 10, 50)
    '
    ' Move the notepad window at 10 (X) and preserving the original (Y) process window position
    ' Move_Process_Window("notepad.exe", 10, Nothing)

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As Rectangle) As Boolean
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, Width As Integer, Height As Integer, repaint As Boolean) As Boolean
    End Function

    Private Sub Move_Process_Window(ByVal ProcessName As String, ByVal X As Integer, ByVal Y As Integer)

        ProcessName = If(ProcessName.ToLower.EndsWith(".exe"), _
                         ProcessName.Substring(0, ProcessName.LastIndexOf(".")), _
                         ProcessName)

        Dim rect As Rectangle = Nothing
        Dim proc As Process = Nothing

        Try
            ' Find the process
            proc = Process.GetProcessesByName(ProcessName).First

            ' Store the process Main Window positions and sizes into the Rectangle.
            GetWindowRect(proc.MainWindowHandle, rect)

            ' Move the Main Window
            MoveWindow(proc.MainWindowHandle, _
                       If(Not X = Nothing, X, rect.Left), _
                       If(Not Y = Nothing, Y, rect.Top), _
                       (rect.Width - rect.Left), _
                       (rect.Height - rect.Top), _
                       True)

        Catch ex As InvalidOperationException
            'Throw New Exception("Process not found.")
            MessageBox.Show("Process not found.", Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        Finally
            rect = Nothing
            If proc IsNot Nothing Then proc.Dispose()

        End Try

    End Sub

#End Region







Redimensiona la ventana de un proceso

Código (vbnet) [Seleccionar]

#Region " Resize Process Window "

    ' [ Resize Process Window ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '         
    ' Resize the notepad window at 500x250 (Width x Height)
    ' Resize_Process_Window("notepad.exe", 500, 250)
    '
    ' Resize the notepad window at 500 (Width) and preserving the original (Height) process window size.
    ' Resize_Process_Window("notepad.exe", 500, Nothing)

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As Rectangle) As Boolean
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, Width As Integer, Height As Integer, repaint As Boolean) As Boolean
    End Function

    Private Sub Resize_Process_Window(ByVal ProcessName As String, _
                                      ByVal Width As Integer, _
                                      ByVal Height As Integer)

        ProcessName = If(ProcessName.ToLower.EndsWith(".exe"), _
                         ProcessName.Substring(0, ProcessName.LastIndexOf(".")), _
                         ProcessName)

        Dim rect As Rectangle = Nothing
        Dim proc As Process = Nothing

        Try
            ' Find the process
            proc = Process.GetProcessesByName(ProcessName).First

            ' Store the process Main Window positions and sizes into the Rectangle.
            GetWindowRect(proc.MainWindowHandle, rect)

            ' Resize the Main Window
            MoveWindow(proc.MainWindowHandle, _
                       rect.Left, _
                       rect.Top, _
                       If(Not Width = Nothing, Width, (rect.Width - rect.Left)), _
                       If(Not Height = Nothing, Height, (rect.Height - rect.Top)), _
                       True)

        Catch ex As InvalidOperationException
            'Throw New Exception("Process not found.")
            MessageBox.Show("Process not found.", Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        Finally
            rect = Nothing
            If proc IsNot Nothing Then proc.Dispose()

        End Try

    End Sub

#End Region






Desplaza la posición de la ventana de un proceso

Código (vbnet) [Seleccionar]
#Region " Shift Process Window Position "

    ' [ Shift Process Window Position ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' Shift the notepad window +10,-50 (X,Y)
    ' Shift_Process_Window_Position("notepad.exe", +10, -50)
    '
    ' Shift the notepad window +10 (X) and preserving the original (Y) position
    ' Shift_Process_Window_Position_Position("notepad.exe", +10, Nothing)

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As Rectangle) As Boolean
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, Width As Integer, Height As Integer, repaint As Boolean) As Boolean
    End Function

    Private Sub Shift_Process_Window_Position(ByVal ProcessName As String, ByVal X As Integer, ByVal Y As Integer)

        ProcessName = If(ProcessName.ToLower.EndsWith(".exe"), _
                         ProcessName.Substring(0, ProcessName.LastIndexOf(".")), _
                         ProcessName)

        Dim rect As Rectangle = Nothing
        Dim proc As Process = Nothing

        Try
            ' Find the process
            proc = Process.GetProcessesByName(ProcessName).First

            ' Store the process Main Window positions and sizes into the Rectangle.
            GetWindowRect(proc.MainWindowHandle, rect)

            ' Move the Main Window
            MoveWindow(proc.MainWindowHandle, _
                       If(Not X = Nothing, rect.Left + X, rect.Left), _
                       If(Not Y = Nothing, rect.Top + Y, rect.Top), _
                       (rect.Width - rect.Left), _
                       (rect.Height - rect.Top), _
                       True)

        Catch ex As InvalidOperationException
            'Throw New Exception("Process not found.")
            MessageBox.Show("Process not found.", Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        Finally
            rect = Nothing
            If proc IsNot Nothing Then proc.Dispose()

        End Try

    End Sub

#End Region







Desplaza el tamaño de la ventana de un proceso

Código (vbnet) [Seleccionar]
#Region " Shift Process Window Size "

    ' [ Shift Process Window Size ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '         
    ' Shift the size of notepad window to +10 Width and -5 Height
    ' Shift_Process_Window_Size("notepad.exe", +10, -5)
    '
    ' Shift the size of notepad window to +10 Width and preserving the original Height process window size.
    ' Shift_Process_Window_Size("notepad.exe", +10, Nothing)

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As Rectangle) As Boolean
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, Width As Integer, Height As Integer, repaint As Boolean) As Boolean
    End Function

    Private Sub Shift_Process_Window_Size(ByVal ProcessName As String, _
                                      ByVal Width As Integer, _
                                      ByVal Height As Integer)

        ProcessName = If(ProcessName.ToLower.EndsWith(".exe"), _
                         ProcessName.Substring(0, ProcessName.LastIndexOf(".")), _
                         ProcessName)

        Dim rect As Rectangle = Nothing
        Dim proc As Process = Nothing

        Try
            ' Find the process
            proc = Process.GetProcessesByName(ProcessName).First

            ' Store the process Main Window positions and sizes into the Rectangle.
            GetWindowRect(proc.MainWindowHandle, rect)

            ' Resize the Main Window
            MoveWindow(proc.MainWindowHandle, _
                       rect.Left, _
                       rect.Top, _
                       If(Not Width = Nothing, (rect.Width - rect.Left) + Width, (rect.Width - rect.Left)), _
                       If(Not Height = Nothing, (rect.Height - rect.Top) + Height, (rect.Height - rect.Top)), _
                       True)

        Catch ex As InvalidOperationException
            'Throw New Exception("Process not found.")
            MessageBox.Show("Process not found.", Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        Finally
            rect = Nothing
            If proc IsNot Nothing Then proc.Dispose()

        End Try

    End Sub

#End Region








Eleкtro

Volver todos los elementos de un Array a Lower-Case:

Código (vbnet) [Seleccionar]
#Region " Array ToLower-Case "

    ' [ Array ToLower-Case ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' Dim Elements As IEnumerable = Array_ToLowerCase({"abC", "DEf", "GhI", Nothing, ""})

    Private Function Array_ToLowerCase(ByVal [Array] As IEnumerable) As IEnumerable

        Return From str In [Array] _
               Select If(String.IsNullOrEmpty(str), _
                         String.Empty, str.ToLower())

    End Function

#End Region







Volver todos los elementos de un Array a Upper-Case:

Código (vbnet) [Seleccionar]
#Region " Array_ToUpperCase "

    ' [ Array_ToUpperCase ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' Dim Elements As IEnumerable = Array_ToUpperCase({"abC", "DEf", "GhI", Nothing, ""})

    Private Function Array_ToUpperCase(ByVal [Array] As IEnumerable) As IEnumerable

        Return From str In [Array] _
               Select If(String.IsNullOrEmpty(str), _
                         String.Empty, str.ToUpper())

    End Function

#End Region







101 Ejemplos de como usar LINQ: http://msdn.microsoft.com/en-us/vstudio/bb688088.aspx






Ejemplos de uso de la librería "TypedUnits" -> http://www.codeproject.com/Articles/611731/Working-with-Units-and-Amounts

Sirve para manejar cálculos y convertir casi todo tipo de unidades a otras unidades (Ej: Newtons, kilometros, kilogramos).


Código (vbnet) [Seleccionar]
         Dim Conversion As TypedUnits.Amount = _
             TypedUnits.UnitManager.ConvertTo(New TypedUnits.Amount( _
                                              2, _
                                              StandardUnits.TimeUnits.Minute), _
                                              StandardUnits.TimeUnits.Second)
       
         MsgBox(Conversion.Value & " Seconds") ' Result: 120 Seconds


         Dim unit As TypedUnits.Amount = _
             New TypedUnits.Amount(1, StandardUnits.LengthUnits.KiloMeter)
       
         MsgBox(unit.Unit.Factor) ' Result: 1000









Eleкtro

Mutear la aplicación:

Código (vbnet) [Seleccionar]
#Region " Mute Application "

    ' [ Mute Application ]
    '
    ' Examples :
    ' MuteApplication()

    <System.Runtime.InteropServices.DllImport("winmm.dll")> _
    Private Shared Function waveOutSetVolume(hwo As IntPtr, dwVolume As UInteger) As Integer
    End Function

    Public Shared Sub MuteApplication()
        Dim NewVolume As Integer = 0
        Dim NewVolumeAllChannels As UInteger = ((CUInt(NewVolume) And &HFFFF) Or (CUInt(NewVolume) << 16))
        waveOutSetVolume(IntPtr.Zero, NewVolumeAllChannels)
    End Sub

#End Region








Eleкtro

#323
· Seleccionar items en un Listbox sin que el Listbox salte a la posición del nuevo item seleccionado.

Código (vbnet) [Seleccionar]
#Region " [ListBox] Select item without jump "

   ' [ListBox] Select item without jump
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   '
   ' Select_Item_Without_Jump(ListBox1, 50, ListBoxItemSelected.Select)
   '
   ' For x As Integer = 0 To ListBox1.Items.Count - 1
   '    Select_Item_Without_Jump(ListBox1, x, ListBoxItemSelected.Select)
   ' Next

   Public Enum ListBoxItemSelected
       [Select] = 1
       [Unselect] = 0
   End Enum

   Public Shared Sub Select_Item_Without_Jump(lb As ListBox, index As Integer, selected As ListBoxItemSelected)
       Dim i As Integer = lb.TopIndex ' Store the selected item index
       lb.BeginUpdate() ' Disable drawing on control
       lb.SetSelected(index, selected) ' Select the item
       lb.TopIndex = i ' Jump to the previous selected item
       lb.EndUpdate() ' Eenable drawing
   End Sub

#End Region







· Desactivar/Activar el Dibujado (Drawing) en un control

Código (vbnet) [Seleccionar]
#Region " Enable-Disable Drawing on Control"

   ' Enable-Disable Drawing on Control
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   '
   ' To disable drawing:
   ' Control_Drawing(ListBox1, DrawingEnabled.Disable)
   '  
   ' To enable drawing:
   ' Control_Drawing(ListBox1, DrawingEnabled.Enable)

   <System.Runtime.InteropServices.DllImport("user32.dll", _
   EntryPoint:="LockWindowUpdate", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
   Public Shared Function LockWindow(Handle As IntPtr) As IntPtr
   End Function

   Private Enum DrawingEnabled
       Enable
       Disable
   End Enum

   Private Sub Control_Drawing(ByVal ctrl As Control, ByVal DrawingEnabled As DrawingEnabled)

       Select Case DrawingEnabled

           Case DrawingEnabled.Enable
               LockWindow(ctrl.Handle)
               LockWindow(IntPtr.Zero)


           Case DrawingEnabled.Disable
               LockWindow(ctrl.Handle)

       End Select

   End Sub

#End Region








Eleкtro

#324
Una Class que nos facilitará mucho la tarea de descargar archivos de forma asincronica, para descargar archivos de forma simultanea.

Código (vbnet) [Seleccionar]
#Region " DownloadFileAsyncExtended "

#Region " Usage Examples "

' Public Class Form1
'
' ' // Instance a new Downlaoder Class
' Private WithEvents Downloader As New DownloadFileAsyncExtended
'
' ' // create a listview to update.
' Private lv As New ListView With {.View = View.Details, .Dock = DockStyle.Fill}
'
' ' // create a listview item to update.
' Private lvi As New ListViewItem
'
' ' // Set an url file to downloads.
' Dim url As String = "http://msft.digitalrivercontent.net/win/X17-58857.iso"


' Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
'
'     ' Add columns to listview.
'     lv.Columns.AddRange({New ColumnHeader With {.Text = "Filename"}, _
'                          New ColumnHeader With {.Text = "Size"}, _
'                          New ColumnHeader With {.Text = "Status"}, _
'                          New ColumnHeader With {.Text = "Completed"}, _
'                          New ColumnHeader With {.Text = "Progress"}, _
'                          New ColumnHeader With {.Text = "Speed"}, _
'                          New ColumnHeader With {.Text = "Time Elapsed"}, _
'                          New ColumnHeader With {.Text = "Time Left"} _
'                        })
'
'     ' Add subitems to listview item.
'     lvi.SubItems.AddRange({"Filename", "Size", "Status", "Completed", "Progress", "Speed", "Time Elapsed", "Time Left"})
'
'     ' Add a Object tag to the listview item,
'     ' so later we can reffer to this download to pause/resume or cancel it.
'     lvi.Tag = Downloader
'
'     ' Add the Listview control into the UI.
'     Me.Controls.Add(lv)
'     ' Add the Listview item into the Listview.
'     lv.Items.Add(lvi)
'
'     ' Set Application simultaneous internet downloads limit.
'     Net.ServicePointManager.DefaultConnectionLimit = 5
'
'     '// IMPORTANT !!
'     '// If you don't add this line, then all events are raised on a separate thread,
'     '// and you will get cross-thread errors when accessing the Listview,
'     '// or other controls directly in the raised events.
'     Downloader.SynchronizingObject = Me
'
'     '// Update frequency.
'     '// A value higher than 500 ms will prevent the DownloadProgressChanged event,
'     '// from firing continuously and hogging CPU when updating the controls.
'     '// If you download small files that could be downloaded within a second,
'     '// then set it to "NoDelay" or the progress might not be visible.
'     Downloader.ProgressUpdateFrequency = DownloadFileAsyncExtended.UpdateFrequency.MilliSeconds_500
'
'     '// The method to actually download a file. The "userToken" parameter can,
'     '// for example be a control you wish to update in the DownloadProgressChanged,
'     '// and DownloadCompleted events. It is a ListViewItem in this example.
'     Downloader.DowloadFileAsync(url, "C:\Downloaded file.iso", lvi)
'
' End Sub


' '// This event allows you to show the download progress to the user.
'
' ' e.BytesReceived = Bytes received so far.
' ' e.DownloadSpeedBytesPerSec = Download speed in bytes per second.
' ' e.DownloadTimeSeconds = Download time in seconds so far.
' ' e.ProgressPercentage = Percentage of the file downloaded.
' ' e.RemainingTimeSeconds = Remaining download time in seconds.
' ' e.TotalBytesToReceive = Total size of the file that is being downloaded.
' ' e.userToken = Usually the control(s) you wish to update.
' Private Sub DownloadProgressChanged(ByVal sender As Object, ByVal e As FileDownloadProgressChangedEventArgs) _
' Handles Downloader.DownloadProgressChanged
'
'     ' Get the ListViewItem we passed as "userToken" parameter, so we can update it.
'     Dim lvi As ListViewItem = DirectCast(e.userToken, ListViewItem)
'
'     ' Update the ListView item subitems.
'     lvi.SubItems(0).Text = url
'     lvi.SubItems(1).Text = String.Format("{0:#,#} KB", (e.TotalBytesToReceive / 1024))
'     lvi.SubItems(2).Text = "Downloading"
'     lvi.SubItems(3).Text = String.Format("{0:#,#} KB", (e.BytesReceived / 1024))
'     lvi.SubItems(4).Text = e.ProgressPercentage & "%"
'     lvi.SubItems(5).Text = (e.DownloadSpeedBytesPerSec \ 1024).ToString & " kB/s"
'     lvi.SubItems(6).Text = String.Format("{0}:{1}:{2}", _
'                            (e.DownloadTimeSeconds \ 3600).ToString("00"), _
'                            ((e.DownloadTimeSeconds Mod 3600) \ 60).ToString("00"), _
'                            (e.DownloadTimeSeconds Mod 60).ToString("00"))
'     lvi.SubItems(7).Text = String.Format("{0}:{1}:{2}", _
'                            (e.RemainingTimeSeconds \ 3600).ToString("00"), _
'                            ((e.RemainingTimeSeconds Mod 3600) \ 60).ToString("00"), _
'                            (e.RemainingTimeSeconds Mod 60).ToString("00"))
'
' End Sub


' '// This event lets you know when the download is complete.
' '// The download finished successfully, the user cancelled the download or there was an error.
' Private Sub DownloadCompleted(ByVal sender As Object, ByVal e As FileDownloadCompletedEventArgs) _
' Handles Downloader.DownloadCompleted
'
'     ' Get the ListViewItem we passed as userToken parameter, so we can update it.
'     Dim lvi As ListViewItem = DirectCast(e.userToken, ListViewItem)
'
'     If e.ErrorMessage IsNot Nothing Then ' Was there an error.
'
'         lvi.SubItems(2).Text = "Error: " & e.ErrorMessage.Message.ToString
'
'         ' Set an Error ImageKey.
'         ' lvi.ImageKey = "Error"
'
'     ElseIf e.Cancelled Then ' The user cancelled the download.
'
'         lvi.SubItems(2).Text = "Paused"
'
'         ' Set a Paused ImageKey.
'         ' lvi.ImageKey = "Paused"
'
'     Else ' Download was successful.
'
'         lvi.SubItems(2).Text = "Finished"
'
'         ' Set a Finished ImageKey.
'         ' lvi.ImageKey = "Finished"
'
'     End If
'
'     ' Set Tag to Nothing in order to remove the wClient class instance,
'     ' so this way we know we can't resume the download.
'     lvi.Tag = Nothing
'
' End Sub


' '// To Resume a file:
' ' Download_Helper.Resume_Download(lvi.Tag)

' '// To pause or cancel a file:
' ' Download_Helper.PauseCancel_Download(lvi.Tag)


' End Class

#End Region

Imports System.IO
Imports System.Net
Imports System.Threading

'// This is the main download class.
Public Class DownloadFileAsyncExtended

#Region "Methods"

    Private _URL As String = String.Empty
    Private _LocalFilePath As String = String.Empty
    Private _userToken As Object = Nothing
    Private _ContentLenght As Long = 0
    Private _TotalBytesReceived As Long = 0

    '// Start the asynchronous download.
    Public Sub DowloadFileAsync(ByVal URL As String, ByVal LocalFilePath As String, ByVal userToken As Object)

        Dim Request As HttpWebRequest
        Dim fileURI As New Uri(URL) '// Will throw exception if empty or random string.

        '// Make sure it's a valid http:// or https:// url.
        If fileURI.Scheme <> Uri.UriSchemeHttp And fileURI.Scheme <> Uri.UriSchemeHttps Then
            Throw New Exception("Invalid URL. Must be http:// or https://")
        End If

        '// Save this to private variables in case we need to resume.
        _URL = URL
        _LocalFilePath = LocalFilePath
        _userToken = userToken

        '// Create the request.
        Request = CType(HttpWebRequest.Create(New Uri(URL)), HttpWebRequest)
        Request.Credentials = Credentials
        Request.AllowAutoRedirect = True
        Request.ReadWriteTimeout = 30000
        Request.Proxy = Proxy
        Request.KeepAlive = False
        Request.Headers = _Headers '// NOTE: Will throw exception if wrong headers supplied.

        '// If we're resuming, then add the AddRange header.
        If _ResumeAsync Then
            Dim FileInfo As New FileInfo(LocalFilePath)
            If FileInfo.Exists Then
                Request.AddRange(FileInfo.Length)
            End If
        End If

        '// Signal we're busy downloading
        _isbusy = True

        '// Make sure this is set to False or the download will stop immediately.
        _CancelAsync = False

        '// This is the data we're sending to the GetResponse Callback.
        Dim State As New HttpWebRequestState(LocalFilePath, Request, _ResumeAsync, userToken)

        '// Begin to get a response from the server.
        Dim result As IAsyncResult = Request.BeginGetResponse(AddressOf GetResponse_Callback, State)

        '// Add custom 30 second timeout for connecting.
        '// The Timeout property is ignored when using the asynchronous BeginGetResponse.
        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, New WaitOrTimerCallback(AddressOf TimeoutCallback), State, 30000, True)

    End Sub

    '// Here we receive the response from the server. We do not check for the "Accept-Ranges"
    '// response header, in order to find out if the server supports resuming, because it MAY
    '// send the "Accept-Ranges" response header, but is not required to do so. This is
    '// unreliable, so we'll just continue and catch the exception that will occur if not
    '// supported and send it the DownloadCompleted event. We also don't check if the
    '// Content-Length is '-1', because some servers return '-1', eventhough the file/webpage
    '// you're trying to download is valid. e.ProgressPercentage returns '-1' in that case.
    Private Sub GetResponse_Callback(ByVal result As IAsyncResult)

        Dim State As HttpWebRequestState = CType(result.AsyncState, HttpWebRequestState)
        Dim DestinationStream As FileStream = Nothing
        Dim Response As HttpWebResponse = Nothing
        Dim Duration As New Stopwatch
        Dim Buffer(8191) As Byte
        Dim BytesRead As Long = 0
        Dim ElapsedSeconds As Long = 0
        Dim DownloadSpeed As Long = 0
        Dim DownloadProgress As Long = 0
        Dim BytesReceivedThisSession As Long = 0

        ''// Get response
        Response = CType(State.Request.EndGetResponse(result), HttpWebResponse)

        '// Asign Response headers to ReadOnly ResponseHeaders property.
        _ResponseHeaders = Response.Headers

        '// If the server does not reply with an 'OK (200)' message when starting
        '// the download or a 'PartialContent (206)' message when resuming.
        If Response.StatusCode <> HttpStatusCode.OK And Response.StatusCode <> HttpStatusCode.PartialContent Then
            '// Send error message to anyone who is listening.
            OnDownloadCompleted(New FileDownloadCompletedEventArgs(New Exception(Response.StatusCode), False, State.userToken))
            Return
        End If

        '// Create/open the file to write to.
        If State.ResumeDownload Then
            '// If resumed, then create or open the file.
            DestinationStream = New FileStream(State.LocalFilePath, FileMode.OpenOrCreate, FileAccess.Write)
        Else
            '// If not resumed, then create the file, which will delete the existing file if it already exists.
            DestinationStream = New FileStream(State.LocalFilePath, FileMode.Create, FileAccess.Write)
            '// Get the ContentLength only when we're starting the download. Not when resuming.
            _ContentLenght = Response.ContentLength
        End If

        '// Moves stream position to beginning of the file when starting the download.
        '// Moves stream position to end of the file when resuming the download.
        DestinationStream.Seek(0, SeekOrigin.End)

        '// Start timer to get download duration / download speed, etc.
        Duration.Start()

        '// Get the Response Stream.
        Using responseStream As Stream = Response.GetResponseStream()
            Do
                '// Read some bytes.
                BytesRead = responseStream.Read(Buffer, 0, Buffer.Length)

                If BytesRead > 0 Then
                    '// Write incoming data to the file.
                    DestinationStream.Write(Buffer, 0, BytesRead)
                    '// Count the total number of bytes downloaded.
                    _TotalBytesReceived += BytesRead
                    '// Count the number of bytes downloaded this session (Resume).
                    BytesReceivedThisSession += BytesRead
                    '// Get number of elapsed seconds (need round number to prevent 'division by zero' error).
                    ElapsedSeconds = CLng(Duration.Elapsed.TotalSeconds)

                    '// Update frequency
                    If (Duration.ElapsedMilliseconds - DownloadProgress) >= ProgressUpdateFrequency Then
                        DownloadProgress = Duration.ElapsedMilliseconds
                        '// Calculate download speed in bytes per second.
                        If ElapsedSeconds > 0 Then
                            DownloadSpeed = (BytesReceivedThisSession \ ElapsedSeconds)
                        End If
                        '// Send download progress to anyone who is listening.
                        OnDownloadProgressChanged(New FileDownloadProgressChangedEventArgs(_TotalBytesReceived, _ContentLenght, ElapsedSeconds, DownloadSpeed, State.userToken))
                    End If

                    '// Exit loop when paused.
                    If _CancelAsync Then Exit Do

                End If
            Loop Until BytesRead = 0

        End Using

        Try
            '// Send download progress once more. If the UpdateFrequency has been set to
            '// HalfSecond or Seconds, then the last percentage returned might be 98% or 99%.
            '// This makes sure it's 100%.
            OnDownloadProgressChanged(New FileDownloadProgressChangedEventArgs(_TotalBytesReceived, _ContentLenght, Duration.Elapsed.TotalSeconds, DownloadSpeed, State.userToken))

            If _CancelAsync Then
                '// Send completed message (Paused) to anyone who is listening.
                OnDownloadCompleted(New FileDownloadCompletedEventArgs(Nothing, True, State.userToken))
            Else
                '// Send completed message (Finished) to anyone who is listening.
                OnDownloadCompleted(New FileDownloadCompletedEventArgs(Nothing, False, State.userToken))
            End If

        Catch ex As Exception
            '// Send completed message (Error) to anyone who is listening.
            OnDownloadCompleted(New FileDownloadCompletedEventArgs(ex, False, State.userToken))

        Finally
            '// Close the file.
            If DestinationStream IsNot Nothing Then
                DestinationStream.Flush()
                DestinationStream.Close()
                DestinationStream = Nothing
            End If
            '// Stop and reset the duration timer.
            Duration.Reset()
            Duration = Nothing
            '// Signal we're not downloading anymore.
            _isbusy = False

        End Try

    End Sub

    '// Here we will abort the download if it takes more than 30 seconds to connect, because
    '// the Timeout property is ignored when using the asynchronous BeginGetResponse.
    Private Sub TimeoutCallback(ByVal State As Object, ByVal TimedOut As Boolean)

        If TimedOut Then
            Dim RequestState As HttpWebRequestState = CType(State, HttpWebRequestState)
            If RequestState IsNot Nothing Then
                RequestState.Request.Abort()
            End If
        End If

    End Sub

    '// Cancel the asynchronous download.
    Private _CancelAsync As Boolean = False
    Public Sub CancelAsync()
        _CancelAsync = True
    End Sub

    '// Resume the asynchronous download.
    Private _ResumeAsync As Boolean = False
    Public Sub ResumeAsync()

        '// Throw exception if download is already in progress.
        If _isbusy Then
            Throw New Exception("Download is still busy. Use IsBusy property to check if download is already busy.")
        End If

        '// Throw exception if URL or LocalFilePath is empty, which means
        '// the download wasn't even started yet with DowloadFileAsync.
        If String.IsNullOrEmpty(_URL) AndAlso String.IsNullOrEmpty(_LocalFilePath) Then
            Throw New Exception("Cannot resume a download which hasn't been started yet. Call DowloadFileAsync first.")
        Else
            '// Set _ResumeDownload to True, so we know we need to add
            '// the Range header in order to resume the download.
            _ResumeAsync = True
            '// Restart (Resume) the download.
            DowloadFileAsync(_URL, _LocalFilePath, _userToken)
        End If

    End Sub

#End Region

#Region "Properties"

    Public Enum UpdateFrequency
        _NoDelay = 0
        MilliSeconds_100 = 100
        MilliSeconds_200 = 200
        MilliSeconds_300 = 300
        MilliSeconds_400 = 400
        MilliSeconds_500 = 500
        MilliSeconds_600 = 600
        MilliSeconds_700 = 700
        MilliSeconds_800 = 800
        MilliSeconds_900 = 900
        Seconds_1 = 1000
        Seconds_2 = 2000
        Seconds_3 = 3000
        Seconds_4 = 4000
        Seconds_5 = 5000
        Seconds_6 = 6000
        Seconds_7 = 7000
        Seconds_8 = 8000
        Seconds_9 = 9000
        Seconds_10 = 10000
    End Enum

    '// Progress Update Frequency.
    Public Property ProgressUpdateFrequency() As UpdateFrequency

    '// Proxy.
    Public Property Proxy() As IWebProxy

    '// Credentials.
    Public Property Credentials() As ICredentials

    '// Headers.
    Public Property Headers() As New WebHeaderCollection

    '// Is download busy.
    Private _isbusy As Boolean = False
    Public ReadOnly Property IsBusy() As Boolean
        Get
            Return _isbusy
        End Get
    End Property

    '// ResponseHeaders.
    Private _ResponseHeaders As WebHeaderCollection = Nothing
    Public ReadOnly Property ResponseHeaders() As WebHeaderCollection
        Get
            Return _ResponseHeaders
        End Get
    End Property

    '// SynchronizingObject property to marshal events back to the UI thread.
    Private _synchronizingObject As System.ComponentModel.ISynchronizeInvoke
    Public Property SynchronizingObject() As System.ComponentModel.ISynchronizeInvoke
        Get
            Return Me._synchronizingObject
        End Get
        Set(ByVal value As System.ComponentModel.ISynchronizeInvoke)
            Me._synchronizingObject = value
        End Set
    End Property

#End Region

#Region "Events"

    Public Event DownloadProgressChanged As EventHandler(Of FileDownloadProgressChangedEventArgs)
    Private Delegate Sub DownloadProgressChangedEventInvoker(ByVal e As FileDownloadProgressChangedEventArgs)
    Protected Overridable Sub OnDownloadProgressChanged(ByVal e As FileDownloadProgressChangedEventArgs)
        If Me.SynchronizingObject IsNot Nothing AndAlso Me.SynchronizingObject.InvokeRequired Then
            'Marshal the call to the thread that owns the synchronizing object.
            Me.SynchronizingObject.Invoke(New DownloadProgressChangedEventInvoker(AddressOf OnDownloadProgressChanged), _
                                          New Object() {e})
        Else
            RaiseEvent DownloadProgressChanged(Me, e)
        End If
    End Sub

    Public Event DownloadCompleted As EventHandler(Of FileDownloadCompletedEventArgs)
    Private Delegate Sub DownloadCompletedEventInvoker(ByVal e As FileDownloadCompletedEventArgs)
    Protected Overridable Sub OnDownloadCompleted(ByVal e As FileDownloadCompletedEventArgs)
        If Me.SynchronizingObject IsNot Nothing AndAlso Me.SynchronizingObject.InvokeRequired Then
            'Marshal the call to the thread that owns the synchronizing object.
            Me.SynchronizingObject.Invoke(New DownloadCompletedEventInvoker(AddressOf OnDownloadCompleted), _
                                          New Object() {e})
        Else
            RaiseEvent DownloadCompleted(Me, e)
        End If
    End Sub

#End Region

End Class

Public Class Download_Helper

    ''' <summary>
    ''' Resumes a file download.
    ''' </summary>
    Public Shared Sub Resume_Download(ByVal File As Object)

        Dim Downloader As DownloadFileAsyncExtended

        Try
            Downloader = DirectCast(File, DownloadFileAsyncExtended)
            Downloader.CancelAsync()

        Catch ex As Exception
            MessageBox.Show(ex.Message, Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        End Try


    End Sub

    ''' <summary>
    ''' Pauses or cancel a file download.
    ''' </summary>
    Public Shared Sub PauseCancel_Download(ByVal File As Object)

        Dim Downloader As DownloadFileAsyncExtended

        Try

            Downloader = DirectCast(File, DownloadFileAsyncExtended)

            If Not Downloader.IsBusy Then
                Downloader.ResumeAsync()
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error)

        End Try

    End Sub

End Class

'// This class is passed as a parameter to the GetResponse Callback,
'// so we can work with the data in the Response Callback.
Public Class HttpWebRequestState

    Private _LocalFilePath As String
    Private _Request As HttpWebRequest
    Private _ResumeDownload As Boolean
    Private _userToken As Object

    Public Sub New(ByVal LocalFilePath As String, ByVal Request As HttpWebRequest, ByVal ResumeDownload As Boolean, ByVal userToken As Object)
        _LocalFilePath = LocalFilePath
        _Request = Request
        _ResumeDownload = ResumeDownload
        _userToken = userToken
    End Sub

    Public ReadOnly Property LocalFilePath() As String
        Get
            Return _LocalFilePath
        End Get
    End Property

    Public ReadOnly Property Request() As HttpWebRequest
        Get
            Return _Request
        End Get
    End Property

    Public ReadOnly Property ResumeDownload() As Boolean
        Get
            Return _ResumeDownload
        End Get
    End Property

    Public ReadOnly Property userToken() As Object
        Get
            Return _userToken
        End Get
    End Property

End Class


'// This is the data returned to the user for each download in the
'// Progress Changed event, so you can update controls with the progress.
Public Class FileDownloadProgressChangedEventArgs
    Inherits EventArgs

    Private _BytesReceived As Long
    Private _TotalBytesToReceive As Long
    Private _DownloadTime As Long
    Private _DownloadSpeed As Long
    Private _userToken As Object

    Public Sub New(ByVal BytesReceived As Long, ByVal TotalBytesToReceive As Long, ByVal DownloadTime As Long, ByVal DownloadSpeed As Long, ByVal userToken As Object)
        _BytesReceived = BytesReceived
        _TotalBytesToReceive = TotalBytesToReceive
        _DownloadTime = DownloadTime
        _DownloadSpeed = DownloadSpeed
        _userToken = userToken
    End Sub

    Public ReadOnly Property BytesReceived() As Long
        Get
            Return _BytesReceived
        End Get
    End Property

    Public ReadOnly Property TotalBytesToReceive() As Long
        Get
            Return _TotalBytesToReceive
        End Get
    End Property

    Public ReadOnly Property ProgressPercentage() As Long
        Get
            If _TotalBytesToReceive > 0 Then
                Return Math.Ceiling((_BytesReceived / _TotalBytesToReceive) * 100)
            Else
                Return -1
            End If
        End Get
    End Property

    Public ReadOnly Property DownloadTimeSeconds() As Long
        Get
            Return _DownloadTime
        End Get
    End Property

    Public ReadOnly Property RemainingTimeSeconds() As Long
        Get
            If DownloadSpeedBytesPerSec > 0 Then
                Return Math.Ceiling((_TotalBytesToReceive - _BytesReceived) / DownloadSpeedBytesPerSec)
            Else
                Return 0
            End If
        End Get
    End Property

    Public ReadOnly Property DownloadSpeedBytesPerSec() As Long
        Get
            Return _DownloadSpeed
        End Get
    End Property

    Public ReadOnly Property userToken() As Object
        Get
            Return _userToken
        End Get
    End Property

End Class


'// This is the data returned to the user for each download in the
'// Download Completed event, so you can update controls with the result.
Public Class FileDownloadCompletedEventArgs
    Inherits EventArgs

    Private _ErrorMessage As Exception
    Private _Cancelled As Boolean
    Private _userToken As Object

    Public Sub New(ByVal ErrorMessage As Exception, ByVal Cancelled As Boolean, ByVal userToken As Object)
        _ErrorMessage = ErrorMessage
        _Cancelled = Cancelled
        _userToken = userToken
    End Sub

    Public ReadOnly Property ErrorMessage() As Exception
        Get
            Return _ErrorMessage
        End Get
    End Property

    Public ReadOnly Property Cancelled() As Boolean
        Get
            Return _Cancelled
        End Get
    End Property

    Public ReadOnly Property userToken() As Object
        Get
            Return _userToken
        End Get
    End Property

End Class

#End Region



Y aquí una Class para entender su funcionamiento.
(Copiar y pegar la class y compilar)




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

    ' // Instance a new Downlaoder Class
    Private WithEvents Downloader As New DownloadFileAsyncExtended

    ' // create a listview to update.
    Private lv As New ListView With {.View = View.Details, .Dock = DockStyle.Fill}

    ' // create a listview item to update.
    Private lvi As New ListViewItem

    '// Set an url file to downloads.
    Dim url As String = "http://msft.digitalrivercontent.net/win/X17-58857.iso"

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

        ' Add columns to listview.
        lv.Columns.AddRange({New ColumnHeader With {.Text = "Filename"}, _
                             New ColumnHeader With {.Text = "Size"}, _
                             New ColumnHeader With {.Text = "Status"}, _
                             New ColumnHeader With {.Text = "Completed"}, _
                             New ColumnHeader With {.Text = "Progress"}, _
                             New ColumnHeader With {.Text = "Speed"}, _
                             New ColumnHeader With {.Text = "Time Elapsed"}, _
                             New ColumnHeader With {.Text = "Time Left"} _
                           })

        ' Add subitems to listview item.
        lvi.SubItems.AddRange({"Filename", "Size", "Status", "Completed", "Progress", "Speed", "Time Elapsed", "Time Left"})

        ' Add a Object tag to the listview item,
        ' so later we can reffer to this download to pause/resume or cancel it.
        lvi.Tag = Downloader

        ' Add the Listview control into the UI.
        Me.Controls.Add(lv)
        ' Add the Listview item into the Listview.
        lv.Items.Add(lvi)

        ' Set Application simultaneous internet downloads limit.
        Net.ServicePointManager.DefaultConnectionLimit = 5

        '// IMPORTANT !!
        '// If you don't add this line, then all events are raised on a separate thread,
        '// and you will get cross-thread errors when accessing the Listview,
        '// or other controls directly in the raised events.
        Downloader.SynchronizingObject = Me

        '// Update frequency.
        '// A value higher than 500 ms will prevent the DownloadProgressChanged event,
        '// from firing continuously and hogging CPU when updating the controls.
        '// If you download small files that could be downloaded within a second,
        '// then set it to "NoDelay" or the progress might not be visible.
        Downloader.ProgressUpdateFrequency = DownloadFileAsyncExtended.UpdateFrequency.MilliSeconds_500

        '// The method to actually download a file. The "userToken" parameter can,
        '// for example be a control you wish to update in the DownloadProgressChanged,
        '// and DownloadCompleted events. It is a ListViewItem in this example.
        Downloader.DowloadFileAsync(url, "C:\Downloaded file.iso", lvi)

    End Sub


    '// This event allows you to show the download progress to the user.
    '
    ' e.BytesReceived = Bytes received so far.
    ' e.DownloadSpeedBytesPerSec = Download speed in bytes per second.
    ' e.DownloadTimeSeconds = Download time in seconds so far.
    ' e.ProgressPercentage = Percentage of the file downloaded.
    ' e.RemainingTimeSeconds = Remaining download time in seconds.
    ' e.TotalBytesToReceive = Total size of the file that is being downloaded.
    ' e.userToken = Usually the control(s) you wish to update.
    Private Sub DownloadProgressChanged(ByVal sender As Object, ByVal e As FileDownloadProgressChangedEventArgs) _
    Handles Downloader.DownloadProgressChanged

        ' Get the ListViewItem we passed as "userToken" parameter, so we can update it.
        Dim lvi As ListViewItem = DirectCast(e.userToken, ListViewItem)

        ' Update the ListView item subitems.
        lvi.SubItems(0).Text = url
        lvi.SubItems(1).Text = String.Format("{0:#,#} KB", (e.TotalBytesToReceive / 1024))
        lvi.SubItems(2).Text = "Downloading"
        lvi.SubItems(3).Text = String.Format("{0:#,#} KB", (e.BytesReceived / 1024))
        lvi.SubItems(4).Text = e.ProgressPercentage & "%"
        lvi.SubItems(5).Text = (e.DownloadSpeedBytesPerSec \ 1024).ToString & " kB/s"
        lvi.SubItems(6).Text = String.Format("{0}:{1}:{2}", _
                               (e.DownloadTimeSeconds \ 3600).ToString("00"), _
                               ((e.DownloadTimeSeconds Mod 3600) \ 60).ToString("00"), _
                               (e.DownloadTimeSeconds Mod 60).ToString("00"))
        lvi.SubItems(7).Text = String.Format("{0}:{1}:{2}", _
                               (e.RemainingTimeSeconds \ 3600).ToString("00"), _
                               ((e.RemainingTimeSeconds Mod 3600) \ 60).ToString("00"), _
                               (e.RemainingTimeSeconds Mod 60).ToString("00"))

    End Sub


    '// This event lets you know when the download is complete.
    '// The download finished successfully, the user cancelled the download or there was an error.
    Private Sub DownloadCompleted(ByVal sender As Object, ByVal e As FileDownloadCompletedEventArgs) _
    Handles Downloader.DownloadCompleted

        ' Get the ListViewItem we passed as userToken parameter, so we can update it.
        Dim lvi As ListViewItem = DirectCast(e.userToken, ListViewItem)

        If e.ErrorMessage IsNot Nothing Then ' Was there an error.

            lvi.SubItems(2).Text = "Error: " & e.ErrorMessage.Message.ToString

            ' Set an Error ImageKey.
            ' lvi.ImageKey = "Error"

        ElseIf e.Cancelled Then ' The user cancelled the download.

            lvi.SubItems(2).Text = "Paused"

            ' Set a Paused ImageKey.
            ' lvi.ImageKey = "Paused"

        Else ' Download was successful.

            lvi.SubItems(2).Text = "Finished"

            ' Set a Finished ImageKey.
            ' lvi.ImageKey = "Finished"

        End If

        ' Set Tag to Nothing in order to remove the wClient class instance,
        ' so this way we know we can't resume the download.
        lvi.Tag = Nothing

    End Sub

    ' Private Sub Button_Resume_Click(sender As Object, e As EventArgs) Handles Button_Resume.Click
    '// To Resume a file:
    ' Download_Helper.Resume_Download(lvi.Tag)
    'End Sub

    'Private Sub Button_Pause_Click(sender As Object, e As EventArgs) Handles Button_Pause.Click
    '// To pause or cancel a file:
    ' Download_Helper.PauseCancel_Download(lvi.Tag)
    'End Sub

End Class








Eleкtro

· Dibujar una barra de progreso en un Item de un ListView:







PD: Es preferible adaptar el siguiente código para hacer un user-control heredado de un Listview (solo hay que modificar 4 tonterías sencillas de este código) y añadirle anti-flickering al user-control, pero bueno, pueden dibujar el Listview desde otra Class como se muestra en este ejemplo, el código no es mio, solo lo he adaptado.

Código (vbnet) [Seleccionar]
#Region " [ListView] Draw ProgressBar "

    ' [ [ListView] Draw ProgressBar ]

    Private Listview_Column As Integer = 4 ' The column index to draw the ProgressBar

    Private Percent As Double = 0 ' The progress percentage
    Private Percent_DecimalFactor As Short = 1 ' Example: 0.1
    Private Percent_Text As String = "% Done" ' Example: 0.1% Done
    Private Percent_Forecolor As Brush = Brushes.Black
    Private Percent_Font As Font = Me.Font

    Private ProgressBar_BackColor As Brush = Brushes.White
    Private ProgressBar_BorderColor As Pen = Pens.LightGray
    Private ProgressBar_FillColor1 As Color = Color.YellowGreen
    Private ProgressBar_FillColor2 As Color = Color.White

    ' ListView [Layout]
    Private Sub ListView1_Layout(sender As Object, e As LayoutEventArgs) _
    Handles ListView1.Layout

        ' Set Listview OwnerDraw to True, so we can draw the progressbar.
        ListView1.OwnerDraw = True

    End Sub

    ' ListView [DrawColumnHeader]
    Private Sub ListView_DrawColumnHeader(ByVal sender As Object, ByVal e As DrawListViewColumnHeaderEventArgs) _
    Handles ListView1.DrawColumnHeader

        e.DrawDefault = True ' Draw default ColumnHeader.

    End Sub

    ' ListView [DrawItem]
    Private Sub ListView_DrawItem(ByVal sender As Object, ByVal e As DrawListViewItemEventArgs) _
    Handles ListView1.DrawItem

        e.DrawDefault = False ' Draw default main item.

    End Sub

    ' ListView [DrawSubItem]
    Private Sub ListView_DrawSubItem(ByVal sender As Object, ByVal e As DrawListViewSubItemEventArgs) _
    Handles ListView1.DrawSubItem

        If (e.ItemState And ListViewItemStates.Selected) <> 0 Then
            ' Item is highlighted.
            e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds)
        End If

        ' Draw the progressbar.
        If e.ColumnIndex = Listview_Column Then

            ' Center the text in the progressbar.
            Dim sf As New StringFormat
            sf.Alignment = StringAlignment.Center

            ' Background color of the progressbar is white.
            e.Graphics.FillRectangle(ProgressBar_BackColor, e.Bounds)

            ' Percentage of the progressbar to fill.
            Dim FillPercent As Integer = CInt(((Percent) / 100) * (e.Bounds.Width - 2))

            ' This creates a nice color gradient to fill.
            Dim brGradient As Brush = _
                New System.Drawing.Drawing2D.LinearGradientBrush(New Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height), _
                                                                 ProgressBar_FillColor1, ProgressBar_FillColor2, 270, True)
            ' Draw the actual progressbar.
            e.Graphics.FillRectangle(brGradient, _
                                     e.Bounds.X + 1, e.Bounds.Y + 2, _
                                     FillPercent, e.Bounds.Height - 3)

            ' Draw the percentage number and percent sign.
            ' NOTE: make sure that e.SubItem.Text only contains a number or an error will occur.
            e.Graphics.DrawString(Percent.ToString("n" & Percent_DecimalFactor) & Percent_Text, _
                                  Percent_Font, Percent_Forecolor, _
                                  CSng(e.Bounds.X + (e.Bounds.Width / 2)), e.Bounds.Y + 3, _
                                  sf)

            ' Draw a light gray rectangle/border around the progressbar.
            e.Graphics.DrawRectangle(ProgressBar_BorderColor, _
                                     e.Bounds.X, e.Bounds.Y + 1, _
                                     e.Bounds.Width - 1, e.Bounds.Height - 2)
        Else
            e.DrawDefault = True

        End If

    End Sub

#End Region





· Un ejemplo que he hecho para mostrar como usar una expresión Lambda al Invocar propiedades de controles:

Código (vbnet) [Seleccionar]
#Region " Invoke Lambda "

    ' Create a thread.
    Private t As Threading.Thread = New Threading.Thread(AddressOf UI_Thread)

    ' Create two Textbox.
    Dim tb1 As New TextBox With {.Text = "Hello World!"}
    Dim tb2 As New TextBox With {.Location = New Point(tb1.Location.X, (tb1.Location.Y + tb1.Height))}

    Private Sub Form1_Load(sender As Object, e As EventArgs) _
    Handles MyBase.Load

        Me.Controls.AddRange({tb1, tb2}) ' Add the Textbox to the UI.
        t.Start() ' Start the thread.

    End Sub

    Private Sub UI_Thread()

        If tb2.InvokeRequired Then ' Check if invocation is required for the TextBox on the main thread.
            tb2.Invoke(Sub() tb2.Text = tb1.Text) ' Then Invoke a Lambda method.
        Else
            tb2.Text = tb1.Text
        End If

    End Sub

#End Region





· Un ejemplo que muestra como crear y usar un delegado para actualizar un control desde otro thread:

Código (vbnet) [Seleccionar]
#Region " Delegate Example "

   ' Create the delegate to be able to update the TextBox.
    Private Delegate Sub TextBoxUpdateUI(ByVal txt As String)

    ' Create a thread.
    Private t As Threading.Thread = New Threading.Thread(AddressOf UI_Thread)

    ' Create two Textbox.
    Dim tb1 As New TextBox With {.Text = "Hello World!"}
    Dim tb2 As New TextBox With {.Location = New Point(tb1.Location.X, (tb1.Location.Y + tb1.Height))}

    Private Sub Form1_Load(sender As Object, e As EventArgs) _
    Handles MyBase.Load

        Me.Controls.AddRange({tb1, tb2}) ' Add the Textbox to the UI.
        t.Start() ' Start the thread.

    End Sub

    Private Sub UI_Thread()

        If tb2.InvokeRequired Then ' Check if invocation is required for the TextBox on the main thread.
            Dim tb_delegate As New TextBoxUpdateUI(AddressOf UI_Thread) ' Set the TextBox delegate.
            tb2.Invoke(tb_delegate, Text) ' Invoke the delegate and the control property to update.
        Else
            tb2.Text = tb1.Text
        End If

    End Sub

#End Region








Eleкtro

#326
Le he hecho una revisión de código a un ListView extendio que ya compartí hace tiempo, le he añadido la ProgressBar que he comentado más arriba, no lo he testeado mucho pero parece que todo funciona como debe funcionar,
que lo disfruteis!

Código (vbnet) [Seleccionar]
'  /*                  *\
' |#* ListView Elektro *#|
'  \*                  */
'
' // By Elektro H@cker
'
'   Properties:
'   ...........
' · Disable_Flickering
' · Double_Buffer
' · GridLineColor
' · ItemHighlightColor
' · ItemNotFocusedHighlighColor
' · DrawCustomGridLines
' · UseDefaultGridLines
' · Enable_ProgressBar
' · Progressbar_Column
' · Percent
' · Percent_Decimal
' · Percent_Font
' · Percent_Text
' · Percent_Forecolor
' · Percent_Text_Allignment
' · ProgressBar_BackColor
' · ProgressBar_BorderColor
' · ProgressBar_FillColor1
' · ProgressBar_FillColor2
'
'   Events:
'   .......
' · ItemAdded
' · ItemRemoved
'
'   Methods:
'   .......
' · AddItem
' · RemoveItem

Public Class ListView_Elektro : Inherits ListView

    Public Event ItemAdded()
    Public Event ItemRemoved()

    Private _Disable_Flickering As Boolean = True
    Private _gridLines As Boolean = False
    Private _useDefaultGridLines As Boolean = False
    Private _gridLineColor As Color = Color.Black
    Private _itemHighlightColor As Color = Color.FromKnownColor(KnownColor.Highlight)
    Private _itemNotFocusedHighlighColor As Color = Color.FromKnownColor(KnownColor.MenuBar)

    Private _enable_progressbar As Boolean = False
    Private _progressbar_column As Integer = Nothing

    Private _percent As Double = 0
    Private _percent_decimal As Short = 2
    Private _percent_text As String = "%"
    Private _percent_text_allignment As StringAlignment = StringAlignment.Center
    Private _percent_stringformat As StringFormat = New StringFormat With {.Alignment = _percent_text_allignment}
    Private _percent_font As Font = Me.Font
    Private _percent_forecolor As SolidBrush = New SolidBrush(Color.Black)

    Private _progressBar_backcolor As SolidBrush = New SolidBrush(Color.Red)
    Private _progressBar_bordercolor As Pen = New Pen(Color.LightGray)
    Private _progressBar_fillcolor1 As Color = Color.YellowGreen
    Private _progressBar_fillcolor2 As Color = Color.White

    Public Sub New()

        Me.Name = "ListView_Elektro"
        Me.DoubleBuffered = True
        Me.UseDefaultGridLines = True

        ' Set Listview OwnerDraw to True, so we can draw the progressbar inside.
        If Me.Enable_ProgressBar Then Me.OwnerDraw = True

        ' Me.GridLines = True
        ' Me.MultiSelect = True
        ' Me.FullRowSelect = True
        ' Me.View = View.Details

    End Sub

#Region " Properties "

    ''' <summary>
    ''' Enable/Disable any flickering effect on the ListView.
    ''' </summary>
    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            If _Disable_Flickering Then
                Dim cp As CreateParams = MyBase.CreateParams
                cp.ExStyle = cp.ExStyle Or &H2000000
                Return cp
            Else
                Return MyBase.CreateParams
            End If
        End Get
    End Property

    ''' <summary>
    ''' Set the Double Buffer.
    ''' </summary>
    Public Property Double_Buffer() As Boolean
        Get
            Return Me.DoubleBuffered
        End Get
        Set(ByVal Value As Boolean)
            Me.DoubleBuffered = Value
        End Set
    End Property

    ''' <summary>
    ''' Enable/Disable the flickering effects on this ListView.
    '''
    ''' This property turns off any Flicker effect on the ListView
    ''' ...but also reduces the performance (speed) of the ListView about 30% slower.
    ''' This don't affect to the performance of the application itself, only to the performance of this control.
    ''' </summary>
    Public Property Disable_Flickering() As Boolean
        Get
            Return _Disable_Flickering
        End Get
        Set(ByVal Value As Boolean)
            Me._Disable_Flickering = Value
        End Set
    End Property

    ''' <summary>
    ''' Changes the gridline color.
    ''' </summary>
    Public Property GridLineColor() As Color
        Get
            Return _gridLineColor
        End Get
        Set(ByVal value As Color)
            If value <> _gridLineColor Then
                _gridLineColor = value
                If _gridLines Then
                    Me.Invalidate()
                End If
            End If
        End Set
    End Property

    ''' <summary>
    ''' Changes the color when item is highlighted.
    ''' </summary>
    Public Property ItemHighlightColor() As Color
        Get
            Return _itemHighlightColor
        End Get
        Set(ByVal value As Color)
            If value <> _itemHighlightColor Then
                _itemHighlightColor = value
                Me.Invalidate()
            End If
        End Set
    End Property

    ''' <summary>
    ''' Changes the color when the item is not focused.
    ''' </summary>
    Public Property ItemNotFocusedHighlighColor() As Color
        Get
            Return _itemNotFocusedHighlighColor
        End Get
        Set(ByVal value As Color)
            If value <> _itemNotFocusedHighlighColor Then
                _itemNotFocusedHighlighColor = value
                Me.Invalidate()
            End If
        End Set
    End Property

    Private ReadOnly Property DrawCustomGridLines() As Boolean
        Get
            Return (_gridLines And Not _useDefaultGridLines)
        End Get
    End Property

    Public Shadows Property GridLines() As Boolean
        Get
            Return _gridLines
        End Get
        Set(ByVal value As Boolean)
            _gridLines = value
        End Set
    End Property

    ''' <summary>
    ''' use the default gridlines.
    ''' </summary>
    Public Property UseDefaultGridLines() As Boolean
        Get
            Return _useDefaultGridLines
        End Get
        Set(ByVal value As Boolean)
            If _useDefaultGridLines <> value Then
                _useDefaultGridLines = value
            End If
            MyBase.GridLines = value
            MyBase.OwnerDraw = Not value
        End Set
    End Property
#End Region

#Region " Procedures "

    ''' <summary>
    ''' Monitors when an Item is added to the ListView.
    ''' </summary>
    Public Function AddItem(ByVal Text As String) As ListViewItem
        RaiseEvent ItemAdded()
        Return MyBase.Items.Add(Text)
    End Function

    ''' <summary>
    ''' Monitors when an Item is removed from the ListView.
    ''' </summary>
    Public Sub RemoveItem(ByVal Item As ListViewItem)
        RaiseEvent ItemRemoved()
        MyBase.Items.Remove(Item)
    End Sub

    Protected Overrides Sub OnDrawColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
        e.DrawDefault = True
        MyBase.OnDrawColumnHeader(e)
    End Sub

    Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
        For Each selectedIndex As Integer In MyBase.SelectedIndices
            MyBase.RedrawItems(selectedIndex, selectedIndex, False)
        Next
        MyBase.OnLostFocus(e)
    End Sub

    Protected Overrides Sub OnDrawSubItem(ByVal e As DrawListViewSubItemEventArgs)

        Dim drawAsDefault As Boolean = False
        Dim highlightBounds As Rectangle = Nothing
        Dim highlightBrush As SolidBrush = Nothing

        'FIRST DETERMINE THE COLOR
        If e.Item.Selected Then
            If MyBase.Focused Then
                highlightBrush = New SolidBrush(_itemHighlightColor)
            ElseIf HideSelection Then
                drawAsDefault = True
            Else
                highlightBrush = New SolidBrush(_itemNotFocusedHighlighColor)
            End If
        Else
            drawAsDefault = True
        End If

        If drawAsDefault Then
            e.DrawBackground()
        Else
            'NEXT DETERMINE THE BOUNDS IN WHICH TO DRAW THE BACKGROUND
            If FullRowSelect Then
                highlightBounds = e.Bounds
            Else
                highlightBounds = e.Item.GetBounds(ItemBoundsPortion.Label)
            End If

            'ONLY DRAW HIGHLIGHT IN 1 OF 2 CASES
            'CASE 1 - FULL ROW SELECT (AND DRAWING ANY ITEM)
            'CASE 2 - NOT FULL ROW SELECT (AND DRAWING 1ST ITEM)
            If FullRowSelect Then
                e.Graphics.FillRectangle(highlightBrush, highlightBounds)
            ElseIf e.ColumnIndex = 0 Then
                e.Graphics.FillRectangle(highlightBrush, highlightBounds)
            Else
                e.DrawBackground()
            End If
        End If

        e.DrawText()

        If _gridLines Then
            e.Graphics.DrawRectangle(New Pen(_gridLineColor), e.Bounds)
        End If


        If FullRowSelect Then
            e.DrawFocusRectangle(e.Item.GetBounds(ItemBoundsPortion.Entire))
        Else
            e.DrawFocusRectangle(e.Item.GetBounds(ItemBoundsPortion.Label))
        End If

        MyBase.OnDrawSubItem(e)

    End Sub

#End Region

#Region " ProgressBar Properties "

    ''' <summary>
    ''' Enables the drawing of a ProgressBar
    ''' This property should be "True" to use any of the ProgressBar properties.
    ''' </summary>
    Public Property Enable_ProgressBar As Boolean
        Get
            Return _enable_progressbar
        End Get
        Set(ByVal value As Boolean)
            Me.OwnerDraw = value
            _enable_progressbar = value
        End Set
    End Property

    ''' <summary>
    ''' The column index to draw the ProgressBar
    ''' </summary>
    Public Property Progressbar_Column As Integer
        Get
            Return _progressbar_column
        End Get
        Set(ByVal value As Integer)
            _progressbar_column = value
        End Set
    End Property

    ''' <summary>
    ''' The ProgressBar progress percentage
    ''' </summary>
    Public Property Percent As Double
        Get
            Return _percent
        End Get
        Set(ByVal value As Double)
            _percent = value
        End Set
    End Property

    ''' <summary>
    ''' The decimal factor which should be displayed for the ProgressBar progress percentage
    ''' </summary>
    Public Property Percent_Decimal As Short
        Get
            Return _percent_decimal
        End Get
        Set(ByVal value As Short)
            _percent_decimal = value
        End Set
    End Property

    ''' <summary>
    ''' The Font to be used as the ProgressBar Percent text
    ''' </summary>
    Public Property Percent_Font As Font
        Get
            Return _percent_font
        End Get
        Set(ByVal value As Font)
            _percent_font = value
        End Set
    End Property

    ''' <summary>
    ''' The additional text to add to the ProgressBar Percent value
    ''' </summary>
    Public Property Percent_Text As String
        Get
            Return _percent_text
        End Get
        Set(ByVal value As String)
            _percent_text = value
        End Set
    End Property

    ''' <summary>
    ''' The ForeColor of the ProgressBar Percent Text
    ''' </summary>
    Public Property Percent_Forecolor As Color
        Get
            Return _percent_forecolor.Color
        End Get
        Set(ByVal value As Color)
            _percent_forecolor = New SolidBrush(value)
        End Set
    End Property

    ''' <summary>
    ''' The text allignment to use for the ProgressBar
    ''' </summary>
    Public Property Percent_Text_Allignment As StringAlignment
        Get
            Return _percent_stringformat.Alignment
        End Get
        Set(ByVal value As StringAlignment)
            _percent_stringformat.Alignment = value
        End Set
    End Property

    ''' <summary>
    ''' The ProgressBar BackColor
    ''' </summary>
    Public Property ProgressBar_BackColor As Color
        Get
            Return _progressBar_backcolor.Color
        End Get
        Set(ByVal value As Color)
            _progressBar_backcolor = New SolidBrush(value)
        End Set
    End Property

    ''' <summary>
    ''' The ProgressBar BorderColor
    ''' </summary>
    Public Property ProgressBar_BorderColor As Color
        Get
            Return _progressBar_bordercolor.Color
        End Get
        Set(ByVal value As Color)
            _progressBar_bordercolor = New Pen(value)
        End Set
    End Property

    ''' <summary>
    ''' The First ProgressBar Gradient color
    ''' </summary>
    Public Property ProgressBar_FillColor1 As Color
        Get
            Return _progressBar_fillcolor1
        End Get
        Set(ByVal value As Color)
            _progressBar_fillcolor1 = value
        End Set
    End Property

    ''' <summary>
    ''' The Last ProgressBar Gradient color
    ''' </summary>
    Public Property ProgressBar_FillColor2 As Color
        Get
            Return _progressBar_fillcolor2
        End Get
        Set(ByVal value As Color)
            _progressBar_fillcolor2 = value
        End Set
    End Property

#End Region

#Region " ProgressBar EventHandlers "

    ' ListView [DrawColumnHeader]
    Public Sub Me_DrawColumnHeader(ByVal sender As Object, ByVal e As DrawListViewColumnHeaderEventArgs) Handles Me.DrawColumnHeader

        e.DrawDefault = True ' Draw default ColumnHeader.

    End Sub

    ' ListView [DrawItem]
    Public Sub Me_DrawItem(ByVal sender As Object, ByVal e As DrawListViewItemEventArgs) 'Handles Me.DrawItem

        e.DrawDefault = False ' Draw default main item.

    End Sub

    ' ListView [DrawSubItem]
    Public Sub Me_DrawSubItem(ByVal sender As Object, ByVal e As DrawListViewSubItemEventArgs) Handles Me.DrawSubItem

        If (e.ItemState And ListViewItemStates.Selected) <> 0 Then
            ' Item is highlighted.
            e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds)
        End If

        ' Draw the progressbar.
        If e.ColumnIndex = Me.Progressbar_Column Then

            If (Not Me.Enable_ProgressBar OrElse Me.Progressbar_Column = Nothing) Then Exit Sub

            ' Background color of the progressbar is white.
            e.Graphics.FillRectangle(Me._progressBar_backcolor, e.Bounds)

            ' This creates a nice color gradient to fill.
            Dim brGradient As Brush = _
                New System.Drawing.Drawing2D.LinearGradientBrush(New Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height), _
                                                                 Me.ProgressBar_FillColor1, Me.ProgressBar_FillColor2, 270, True)
            ' Draw the actual progressbar.
            e.Graphics.FillRectangle(brGradient, _
                                     e.Bounds.X + 1, e.Bounds.Y + 2, _
                                     CInt(((Me.Percent) / 100) * (e.Bounds.Width - 2)), e.Bounds.Height - 3)

            ' Draw the percentage number and percent sign.
            e.Graphics.DrawString(Me.Percent.ToString("n" & Me.Percent_Decimal) & Me.Percent_Text, _
                                  Me.Percent_Font, Me._percent_forecolor, _
                                  CSng(e.Bounds.X + (e.Bounds.Width / 2)), e.Bounds.Y + 3, _
                                  _percent_stringformat)

            ' Draw a light gray rectangle/border around the progressbar.
            e.Graphics.DrawRectangle(Me._progressBar_bordercolor, _
                                     e.Bounds.X, e.Bounds.Y + 1, _
                                     e.Bounds.Width - 1, e.Bounds.Height - 2)
        Else
            e.DrawDefault = True

        End If

    End Sub

#End Region

End Class








Eleкtro

#327
Unas sencillas funciones para convertir pluma/brocha a color, y viceversa.

Código (vbnet) [Seleccionar]
#Region " Color To Pen "

   ' [ Color To Pen ]
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   ' MsgBox(Color_To_Pen(Color.Red).Color.Name) ' Result: Red

   Private Function Color_To_Pen(ByVal color As Color) As Pen

       Dim _pen As Pen = Nothing

       Try
           _pen = New Pen(color)
           Return _pen

       Catch ex As Exception
           Throw New Exception(ex.Message)
           Return Nothing

       Finally
           If _pen IsNot Nothing Then _pen.Dispose()

       End Try

   End Function

#End Region


Código (vbnet) [Seleccionar]
#Region " Color To SolidBrush "

   ' [ Color To SolidBrush ]
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   ' MsgBox(Color_To_SolidBrush(Color.Red).Color.Name) ' Result: Red

   Private Function Color_To_SolidBrush(ByVal color As Color) As SolidBrush

       Dim _brush As SolidBrush = Nothing

       Try
           _brush = New SolidBrush(color)
           Return _brush

       Catch ex As Exception
           Throw New Exception(ex.Message)
           Return Nothing

       Finally
           If _brush IsNot Nothing Then _brush.Dispose()

       End Try

   End Function

#End Region


Código (vbnet) [Seleccionar]
#Region " Pen To Color "

   ' [ Pen To Color ]
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   ' MsgBox(Pen_To_Color(New Pen(Color.Red)).Name) ' Result: Red

   Private Function Pen_To_Color(ByVal pen As Pen) As Color
       Return pen.Color
   End Function

#End Region


Código (vbnet) [Seleccionar]
#Region " SolidBrush To Color "

   ' [ SolidBrush To Color ]
   '
   ' // By Elektro H@cker
   '
   ' Examples :
   ' MsgBox(SolidBrush_To_Color(New SolidBrush(Color.Red)).Name) ' Result: Red

   Private Function SolidBrush_To_Color(ByVal brush As SolidBrush) As Color
       Return brush.Color
   End Function

#End Region







Y otra sencilla función para parsear un valor de una enumeración:

Código (vbnet) [Seleccionar]
    #Region " Enum Parser "
     
       ' [ Enum Parser ]
       '
       ' // By Elektro H@cker
       '
       ' Examples :
       '
       ' MsgBox(Enum_Parser(Of Keys)(65).ToString) ' Result: A
       ' MsgBox(Enum_Parser(Of Keys)("A").ToString) ' Result: A
       ' TextBox1.BackColor = Color.FromKnownColor(Enum_Parser(Of KnownColor)("Red"))
     
    Private Function Enum_Parser(Of T)(Value As Object) As T

        Try
            Return [Enum].Parse(GetType(T), Value, True)

        Catch ex As ArgumentException
            Throw New Exception("Enum value not found")

        Catch ex As Exception
            Throw New Exception(String.Format("{0}: {1}}", _
                                ex.Message, ex.StackTrace))

        End Try

    End Function
     
    #End Region








Eleкtro

Otra función simple, que devuelve las medidas de la fuente de texto:

Código (vbnet) [Seleccionar]
#Region " Get Text Measure "

    ' [ Get Text Measure ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' MsgBox(Get_Text_Measure("Hello World!", New Font(New FontFamily("Lucida Console"), 12)).Width)  ' Result: 127
    ' MsgBox(Get_Text_Measure("Hello World!", New Font(New FontFamily("Lucida Console"), 12)).Height) ' Result: 16

    Private Function Get_Text_Measure(ByVal text As String, ByVal font As Font) As SizeF
        Return TextRenderer.MeasureText(text, font)
    End Function

#End Region







Esta función obtiene el texto de una ventana, pasándole como parámetro el handle de dicha ventana:

Código (vbnet) [Seleccionar]
#Region " Get Window Text "

    ' [ Get Window Text ]
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    ' Dim str as String = Get_Window_Text(hwnd)

    <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
    Private Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
    Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
    End Function

    Public Function Get_Window_Text(ByVal hWnd As IntPtr) As String

        If hWnd = IntPtr.Zero Then : Return Nothing

        Else

            Dim length As Integer = GetWindowTextLength(hWnd)

            If length = 0 Then
                Return Nothing
            End If

            Dim sb As New System.Text.StringBuilder("", length)

            GetWindowText(hWnd, sb, sb.Capacity + 1)
            Return sb.ToString()

        End If

    End Function

#End Region








Eleкtro

Con este código podemos heredar un TextBox y averiguar la opción que ha elegido el usuario en el CMT por defecto de Windows.

El código original no es mio, pero lo he adaptado apra que funcione corréctamente la opción "Cut", y le he añadido la constande de "Delete".

Modo de empleo:

Código (vbnet) [Seleccionar]
    Private Sub TextBox1_OnTextCommand(sender As Object, e As MyTextBox.ContextCommandEventArgs) _
    Handles MyTextBox1.OnCut, MyTextBox1.OnPaste, MyTextBox1.OnCopy, MyTextBox1.OnDelete

        MessageBox.Show("Activated " & e.Command.ToString())

    End Sub


Código (vbnet) [Seleccionar]
Class MyTextBox : Inherits TextBox

    Private Last_Command As ContextCommands = Nothing

    Private WithEvents CopyOrCut_Timer As New Timer _
            With {.Interval = 5, .Enabled = False}

    Public Enum ContextCommands
        WM_CUT = &H300
        WM_COPY = &H301
        WM_PASTE = &H302
        WM_DELETE = &H303
    End Enum

    Public Class ContextCommandEventArgs
        Inherits EventArgs
        Public Property Command As ContextCommands
    End Class

    Event OnCut(sender As Object, e As ContextCommandEventArgs)
    Event OnCopy(sender As Object, e As ContextCommandEventArgs)
    Event OnPaste(sender As Object, e As ContextCommandEventArgs)
    Event OnDelete(sender As Object, e As ContextCommandEventArgs)

    Protected Overrides Sub WndProc(ByRef m As Message)

        MyBase.WndProc(m)

        Select Case m.Msg

            Case ContextCommands.WM_COPY
                Last_Command = ContextCommands.WM_COPY
                CopyOrCut_Timer.Enabled = True

            Case ContextCommands.WM_CUT
                Last_Command = ContextCommands.WM_CUT

            Case ContextCommands.WM_PASTE
                RaiseEvent OnPaste(Me, New ContextCommandEventArgs() _
                                       With {.Command = ContextCommands.WM_PASTE})

            Case ContextCommands.WM_DELETE
                RaiseEvent OnDelete(Me, New ContextCommandEventArgs() _
                                        With {.Command = ContextCommands.WM_DELETE})

        End Select

    End Sub

    Private Sub Cut_Timer_Tick(sender As Object, e As EventArgs) _
    Handles CopyOrCut_Timer.Tick

        sender.enabled = False

        Select Case Last_Command

            Case ContextCommands.WM_COPY
                RaiseEvent OnCopy(Me, New ContextCommandEventArgs() _
                                      With {.Command = ContextCommands.WM_COPY})

            Case ContextCommands.WM_CUT
                RaiseEvent OnCut(Me, New ContextCommandEventArgs() _
                                     With {.Command = ContextCommands.WM_CUT})

        End Select

        Last_Command = Nothing

    End Sub

End Class