Imports System.ComponentModel
Imports System.Text.RegularExpressions
Public Class HexBox
Inherits RichTextBox
Public Event SelectedBytesChanged As EventHandler
Private EventsDisabled As Boolean = False
Private HexValueRegex As New Regex("[ABCDEFabcdef\d]{2}", RegexOptions.Multiline)
Private _Columns As Int16
Private _Bytes() As Byte
Private _SelectedByte As Byte
Private _SelectedBytes() As Byte
Public Property Columns() As Int16
Get
Return _Columns
End Get
Set(ByVal value As Int16)
_Columns = value
If (Me.Bytes IsNot Nothing) AndAlso (Me.Bytes.Length > 0) Then
Dim Temp() As Byte = Me.Bytes
_Bytes = Nothing
Me.LoadBytes(Temp)
End If
End Set
End Property
Public ReadOnly Property Bytes() As Byte()
Get
Return _Bytes
End Get
End Property
<Browsable(False)> _
Public ReadOnly Property SelectedByte() As Byte
Get
Return _SelectedByte
End Get
End Property
<Browsable(False)> _
Public Property SelectedBytes() As Byte()
Get
Return _SelectedBytes
End Get
Set(ByVal value As Byte())
If value Is Nothing Then
Exit Property
End If
Dim Matches As MatchCollection = HexValueRegex.Matches(Me.SelectedText)
Dim Temp(Me.Bytes.Length - Matches.Count + value.Length - 1) As Byte
Array.ConstrainedCopy(Me.Bytes, 0, Temp, 0, Me.CurrentIntOffset)
Array.ConstrainedCopy(value, 0, Temp, Me.CurrentIntOffset, value.Length)
Array.ConstrainedCopy(Me.Bytes, Me.CurrentIntOffset + Matches.Count, Temp, Me.CurrentIntOffset + value.Length, Me.Bytes.Length - Me.CurrentIntOffset - Matches.Count)
Me.LoadBytes(Temp)
End Set
End Property
Public ReadOnly Property CurrentLineIndex() As Int32
Get
Return Me.GetLineFromCharIndex(Me.SelectionStart)
End Get
End Property
<Browsable(False)> _
Public Property CurrentHexOffset() As String
Get
Return HexValue.ToHexadecimal(Me.CurrentIntOffset)
End Get
Set(ByVal value As String)
Try
Me.SelectionStart = HexValue.ToDecimal(value) * 3
Me.SelectionLength = 2
Catch ex As Exception
End Try
End Set
End Property
<Browsable(False)> _
Public Property CurrentIntOffset() As Int64
Get
Return Me.SelectionStart \ 3
End Get
Set(ByVal value As Int64)
Me.SelectionStart = value * 3
Me.SelectionLength = 2
End Set
End Property
<Browsable(False)> _
Public Property CurrentBinOffset() As BinaryValue.BitArray
Get
Return BinaryValue.ToBinary(Me.CurrentIntOffset)
End Get
Set(ByVal value As BinaryValue.BitArray)
Me.SelectionStart = BinaryValue.ToDecimal(value) * 3
Me.SelectionLength = 2
End Set
End Property
Sub New()
Me.Columns = 16
_Bytes = New Byte() {}
End Sub
Public Sub LoadBytes(ByVal Bytes() As Byte)
Dim Odd As Boolean = True
Dim Text As New System.Text.StringBuilder
Me.Text = ""
For I As Int32 = 0 To Bytes.Length - 1 Step Columns
Dim Max As Int16
If Bytes.Length - I >= Columns Then
Max = Columns - 1
Else
Max = Bytes.Length - I - 1
End If
For C As Int16 = 0 To Max
Text.AppendFormat("{0:X2}", Bytes(I + C))
If C < Max Then
Text.Append(" ")
End If
Next
If Max = Columns - 1 Then
Text.AppendLine()
End If
Next
Me.Text = Text.ToString
_Bytes = Bytes
End Sub
Public Sub ReloadBytes()
Me.LoadBytes(Me.Bytes)
End Sub
Private Sub Me_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If EventsDisabled Then
Exit Sub
End If
If e.KeyCode = Keys.Right Then
If Me.SelectionStart >= 0 Then
Dim Start As Int32 = ((Me.SelectionStart + 1) \ 3) * 3 + 3
Me.Select(Start, 2)
ElseIf Me.TextLength >= 2 Then
Me.Select(0, 2)
End If
End If
If e.KeyCode = Keys.Left Then
If Me.SelectionStart >= 2 Then
Dim Start As Int32 = ((Me.SelectionStart + 1) \ 3) * 3 - 3
Me.Select(Start, 2)
ElseIf Me.TextLength >= 2 Then
Me.Select(0, 2)
End If
End If
If e.KeyCode = Keys.Up Then
If Me.CurrentLineIndex > 0 Then
Dim LinePos As Int32 = ((Me.SelectionStart + 1) \ 3) * 3 - Me.GetFirstCharIndexOfCurrentLine
Dim PrevLine As Int32 = Me.CurrentLineIndex - 1
Me.Select(Me.GetFirstCharIndexFromLine(PrevLine) + LinePos, 2)
ElseIf Me.TextLength >= 2 Then
Me.Select(0, 2)
End If
End If
If e.KeyCode = Keys.Down Then
If Me.CurrentLineIndex < Me.Lines.Length - 1 Then
Dim LinePos As Int32 = ((Me.SelectionStart + 1) \ 3) * 3 - Me.GetFirstCharIndexOfCurrentLine
Dim SuccLine As Int32 = Me.CurrentLineIndex + 1
Me.Select(Me.GetFirstCharIndexFromLine(SuccLine) + LinePos, 2)
End If
End If
Try
If Me.SelectedText.Length <= 3 Then
_SelectedByte = HexValue.ToDecimal(Me.SelectedText)
RaiseEvent SelectedBytesChanged(Me, EventArgs.Empty)
End If
Catch ex As Exception
End Try
e.SuppressKeyPress = True
e.Handled = True
End Sub
Private Sub Me_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.SelectionChanged
If EventsDisabled Then
Exit Sub
End If
Try
Dim Matches As MatchCollection = HexValueRegex.Matches(Me.SelectedText)
Dim Bytes(Matches.Count - 1) As Byte
For I As Int32 = 0 To Bytes.Length - 1
Bytes(I) = HexValue.ToDecimal(Matches(I).Value)
Next
_SelectedBytes = Bytes
RaiseEvent SelectedBytesChanged(Me, EventArgs.Empty)
Catch ex As Exception
End Try
End Sub
Public Sub DisableEvents()
EventsDisabled = True
End Sub
Public Sub EnableEvents()
EventsDisabled = False
End Sub
End Class