''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Blinks the specified text for the specified amount of times on the current attached console window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim pos As New Point(10, 2)
''' Dim str As String = "Hello World!"
'''
''' Console.SetCursorPosition(pos.X, pos.Y)
''' Console.Write(str)
'''
''' ' Start blinking the text written.
''' Dim len As Integer = str.Length
''' Dim interval As Integer = 500
''' Dim count As Integer = 10
''' ConsoleTextBlink(pos, len, interval, count)
'''
''' ' Terminate program.
''' Console.ReadKey(intercept:=False)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="position">
''' A <see cref="System.Drawing.Point"/> that indicates the start position of the text.
''' <para></para>
''' <see cref="System.Drawing.Point.X"/> specifies the column, <see cref="System.Drawing.Point.Y"/> the row.
''' </param>
'''
''' <param name="length">
''' The length of the text (or cells) to blink.
''' </param>
'''
''' <param name="interval">
''' The blink interval, in milliseconds.
''' </param>
'''
''' <param name="count">
''' The amount of times to blink the text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="CancellationTokenSource"/> object which you can use it to stop the blink at any time.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Function ConsoleTextBlink(ByVal position As Point, ByVal length As Integer, ByVal interval As Integer, count As Integer) As CancellationTokenSource
Return InternalConsoleTextBlink(position, length, TimeSpan.FromMilliseconds(interval), count)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Blinks the specified text for the specified amount of times on the current attached console window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim pos As New Point(10, 2)
''' Dim str As String = "Hello World!"
'''
''' Console.SetCursorPosition(pos.X, pos.Y)
''' Console.Write(str)
'''
''' ' Start blinking the text written.
''' Dim len As Integer = str.Length
''' Dim interval As TimeSpan = TimeSpan.FromMilliseconds(500)
''' Dim count As Integer = 10
''' ConsoleTextBlink(pos, len, interval, count)
'''
''' ' Terminate program.
''' Console.ReadKey(intercept:=False)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="position">
''' A <see cref="System.Drawing.Point"/> that indicates the start position of the text.
''' <para></para>
''' <see cref="System.Drawing.Point.X"/> specifies the column, <see cref="System.Drawing.Point.Y"/> the row.
''' </param>
'''
''' <param name="length">
''' The length of the text (or cells) to blink.
''' </param>
'''
''' <param name="interval">
''' The blink interval.
''' </param>
'''
''' <param name="count">
''' The amount of times to blink the text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="CancellationTokenSource"/> object which you can use it to stop the blink at any time.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Function ConsoleTextBlink(ByVal position As Point, ByVal length As Integer, ByVal interval As TimeSpan, count As Integer) As CancellationTokenSource
Return InternalConsoleTextBlink(position, length, interval, count)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Blinks the specified text for indefinitely time on the current attached console window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim pos As New Point(10, 2)
''' Dim str As String = "Hello World!"
'''
''' Console.SetCursorPosition(pos.X, pos.Y)
''' Console.Write(str)
'''
''' ' Start blinking the text written.
''' Dim len As Integer = str.Length
''' Dim interval As Integer = 500
''' Dim blinkCt As CancellationTokenSource = ConsoleTextBlink(pos, len, interval)
'''
''' ' Stop blinking after 5 seconds elapsed.
''' blinkCt.CancelAfter(5000)
'''
''' ' Terminate program.
''' Console.ReadKey(intercept:=False)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="position">
''' A <see cref="System.Drawing.Point"/> that indicates the start position of the text.
''' <para></para>
''' <see cref="System.Drawing.Point.X"/> specifies the column, <see cref="System.Drawing.Point.Y"/> the row.
''' </param>
'''
''' <param name="length">
''' The length of the text (or cells) to blink.
''' </param>
'''
''' <param name="interval">
''' The blink interval, in milliseconds.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="CancellationTokenSource"/> object which you can use it to stop the blink at any time.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Function ConsoleTextBlink(ByVal position As Point, ByVal length As Integer, ByVal interval As Integer) As CancellationTokenSource
Return InternalConsoleTextBlink(position, length, TimeSpan.FromMilliseconds(interval), Integer.MaxValue)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Blinks the specified text for indefinitely time on the current attached console window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim pos As New Point(10, 2)
''' Dim str As String = "Hello World!"
'''
''' Console.SetCursorPosition(pos.X, pos.Y)
''' Console.Write(str)
'''
''' ' Start blinking the text written.
''' Dim len As Integer = str.Length
''' Dim interval As TimeSpan = TimeSpan.FromMilliseconds(500)
''' Dim blinkCt As CancellationTokenSource = ConsoleTextBlink(pos, len, interval)
''' blinkCt.CancelAfter()
'''
''' ' Stop blinking after 5 seconds elapsed.
''' blinkCt.CancelAfter(5000)
'''
''' ' Terminate program.
''' Console.ReadKey(intercept:=False)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="position">
''' A <see cref="System.Drawing.Point"/> that indicates the start position of the text.
''' <para></para>
''' <see cref="System.Drawing.Point.X"/> specifies the column, <see cref="System.Drawing.Point.Y"/> the row.
''' </param>
'''
''' <param name="length">
''' The length of the text (or cells) to blink.
''' </param>
'''
''' <param name="interval">
''' The blink interval.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="CancellationTokenSource"/> object which you can use it to stop the blink at any time.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Function ConsoleTextBlink(ByVal position As Point, ByVal length As Integer, ByVal interval As TimeSpan) As CancellationTokenSource
Return InternalConsoleTextBlink(position, length, interval, Integer.MaxValue)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Blinks the specified text for the specified amount of times on the current attached console window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="position">
''' A <see cref="System.Drawing.Point"/> that indicates the start position of the text.
''' <para></para>
''' <see cref="System.Drawing.Point.X"/> specifies the column, <see cref="System.Drawing.Point.Y"/> the row.
''' </param>
'''
''' <param name="length">
''' The length of the text (or cells) to blink.
''' </param>
'''
''' <param name="interval">
''' The blink interval.
''' </param>
'''
''' <param name="count">
''' The amount of times to blink the text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="CancellationTokenSource"/> object which you can use it to stop the blink at any time.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Private Function InternalConsoleTextBlink(ByVal position As Point, ByVal length As Integer, ByVal interval As TimeSpan, ByVal count As Integer) As CancellationTokenSource
If (count <= 0) Then
Throw New ArgumentException(paramName:=NameOf(count), message:="Value greater than 0 is required.")
End If
If (interval.TotalMilliseconds <= 0) Then
Throw New ArgumentException(paramName:=NameOf(interval), message:="Value greater than 0 is required.")
End If
Dim cts As New CancellationTokenSource()
Dim t As New Task(
Sub()
Dim x As Short = CShort(position.X)
Dim y As Short = CShort(position.Y)
Dim width As Short = CShort(length)
Dim height As Short = 1S
Dim buffer As IntPtr = Marshal.AllocHGlobal(width * height * Marshal.SizeOf(GetType(Native.CharInfo)))
Dim blinkCount As Integer
Try
Dim bufferCoord As New Native.ConsoleCoordinate()
Dim bufferSize As New Native.ConsoleCoordinate With {
.X = width,
.Y = height
}
Dim rc As New Native.NativeRectangleSmall With {
.Left = x,
.Top = y,
.Right = (x + width - 1S),
.Bottom = (y + height - 1S)
}
Dim stdOutHandle As IntPtr = Native.GetStdHandle(Native.ConsoleStd.StandardOutput)
If Not Native.ReadConsoleOutput(stdOutHandle, buffer, bufferSize, bufferCoord, rc) Then
' Not enough storage is available to process this command' may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
Throw New Win32Exception(Marshal.GetLastWin32Error())
End If
Dim charInfoList As New List(Of Native.CharInfo)
Dim ptr As IntPtr = buffer
For heightIndex As Integer = 0 To (height - 1)
For widthIndex As Integer = 0 To (width - 1)
Dim ci As Native.CharInfo = DirectCast(Marshal.PtrToStructure(ptr, GetType(Native.CharInfo)), Native.CharInfo)
charInfoList.Add(ci)
ptr += Marshal.SizeOf(GetType(Native.CharInfo))
Next widthIndex
Next heightIndex
Do Until cts.Token.IsCancellationRequested
Dim oldCursorVisible As Boolean = Console.CursorVisible
Dim oldPos As New Point(Console.CursorLeft, Console.CursorTop)
Dim oldBackColor As ConsoleColor = Console.BackgroundColor
Dim oldForeColor As ConsoleColor = Console.ForegroundColor
Console.CursorVisible = False
Console.SetCursorPosition(position.X, position.Y)
Console.Write(New String(" "c, length))
Console.CursorVisible = oldCursorVisible
Console.SetCursorPosition(oldPos.X, oldPos.Y)
Thread.Sleep(interval)
Console.CursorVisible = False
For i As Integer = 0 To (charInfoList.Count - 1)
Dim ci As Native.CharInfo = charInfoList(i)
Dim chars As Char() = (From c As Char In Console.OutputEncoding.GetChars(ci.CharData)
Where (c <> Nothing)).ToArray()
Dim foreColor As ConsoleColor
If ((ci.Attributes And Native.CharInfoAttributes.ForeColorMask) <> 0) Then
foreColor = CType((CInt(ci.Attributes)) And Not Native.CharInfoAttributes.BackColorMask, ConsoleColor)
End If
Dim backColor As ConsoleColor
If ((ci.Attributes And Native.CharInfoAttributes.BackColorMask) <> 0) Then
' Turn background colors into foreground colors.
' https://referencesource.microsoft.com/#mscorlib/system/console.cs,7a88edaade340cdb
backColor = CType((CInt(ci.Attributes)) >> 4, ConsoleColor)
End If
Console.SetCursorPosition((position.X + i), position.Y)
Console.ForegroundColor = foreColor
Console.BackgroundColor = backColor
Console.Write(chars)
Next i
Console.SetCursorPosition(oldPos.X, oldPos.Y)
Console.CursorVisible = oldCursorVisible
Console.ForegroundColor = oldForeColor
Console.BackgroundColor = oldBackColor
If Interlocked.Increment(blinkCount) = count Then
If (cts.Token.CanBeCanceled) Then
cts.Cancel()
End If
Exit Do
End If
Thread.Sleep(interval)
Loop
Finally
Marshal.FreeHGlobal(buffer)
End Try
End Sub, cts.Token)
t.Start()
Return cts
End Function