Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
HTML IntelliSense 1.5 - HtmlTextBox.vb

HtmlTextBox.vb

Caricato da: Totem
Scarica il programma completo

  1. Imports System.Text.RegularExpressions
  2. Imports System.ComponentModel
  3. Public Class HtmlTextBox
  4.     Inherits RichTextBox
  5.     Implements ICloneable
  6.  
  7.     Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
  8.        (ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
  9.        ByVal wParam As Integer, ByVal lParam As Integer) As Integer
  10.  
  11.     Private Declare Function LockWindowUpdate Lib "user32" _
  12.         (ByVal hWnd As Integer) As Integer
  13.  
  14.     Private Shared TagRegex As New Regex("\<(?<TagName>[\w\d]+)\s*(\s*(?<Attribute>[\-\w]+)\s*\=\s*(?<Value>((?<Q>(""|')).*?\k<Q>|\S+))\s*|\s*(?<Attribute>\[\w+\])\s*)*\>", RegexOptions.Multiline)
  15.     Private Shared CloseTagRegex As New Regex("\<\/(?<TagName>[\w\d]+)\>", RegexOptions.Multiline)
  16.     Private Shared CommentRegex As New Regex("\<\!\-\-.+?\-\-\>", RegexOptions.Multiline)
  17.  
  18.     Private _HtmlChangedEnabled As Boolean = True
  19.     Private _SyntaxHighlightingEnabled As Boolean = True
  20.     Private _IsBusy As Boolean
  21.  
  22.     Private _TagColor As Color = Color.Blue
  23.     Private _AttributeColor As Color = Color.Red
  24.     Private _BooleanAttributeColor As Color = Color.Orange
  25.     Private _ValueColor As Color = Color.Purple
  26.     Private _CommentColor As Color = Color.Green
  27.  
  28.     Private _TagFont As Font = Me.Font
  29.     Private _AttributeFont As Font = Me.Font
  30.     Private _BooleanAttributeFont As Font = Me.Font
  31.     Private _ValueFont As Font = Me.Font
  32.     Private _CommentFont As Font = Me.Font
  33.  
  34.     Private _RtfLines() As String
  35.  
  36.     Public Event HtmlChanged As EventHandler
  37.  
  38.     Public Property HtmlChangedEnabled() As Boolean
  39.         Get
  40.             Return _HtmlChangedEnabled
  41.         End Get
  42.         Set(ByVal value As Boolean)
  43.             _HtmlChangedEnabled = value
  44.         End Set
  45.     End Property
  46.  
  47.     Public Property SyntaxHighlightingEnabled() As Boolean
  48.         Get
  49.             Return _SyntaxHighlightingEnabled
  50.         End Get
  51.         Set(ByVal value As Boolean)
  52.             _SyntaxHighlightingEnabled = value
  53.         End Set
  54.     End Property
  55.  
  56.  
  57.     <Browsable(True), Description("The color with which tags are highlighted.")> _
  58.     Public Property TagColor() As Color
  59.         Get
  60.             Return _TagColor
  61.         End Get
  62.         Set(ByVal Value As Color)
  63.             _TagColor = Value
  64.         End Set
  65.     End Property
  66.  
  67.     <Browsable(True), Description("The color with which attributes are highlighted.")> _
  68.     Public Property AttributeColor() As Color
  69.         Get
  70.             Return _AttributeColor
  71.         End Get
  72.         Set(ByVal Value As Color)
  73.             _AttributeColor = Value
  74.         End Set
  75.     End Property
  76.  
  77.     <Browsable(True), Description("The color with which boolean attributes are highlighted.")> _
  78.     Public Property BooleanAttributeColor() As Color
  79.         Get
  80.             Return _BooleanAttributeColor
  81.         End Get
  82.         Set(ByVal Value As Color)
  83.             _BooleanAttributeColor = Value
  84.         End Set
  85.     End Property
  86.  
  87.     <Browsable(True), Description("The color with which attributes' values are highlighted.")> _
  88.     Public Property ValueColor() As Color
  89.         Get
  90.             Return _ValueColor
  91.         End Get
  92.         Set(ByVal value As Color)
  93.             _ValueColor = value
  94.         End Set
  95.     End Property
  96.  
  97.     Public Property CommentColor() As Color
  98.         Get
  99.             Return _CommentColor
  100.         End Get
  101.         Set(ByVal value As Color)
  102.             _CommentColor = value
  103.         End Set
  104.     End Property
  105.  
  106.  
  107.     <Browsable(True), Description("The font with which tags are highlighted.")> _
  108.     Public Property TagFont() As Font
  109.         Get
  110.             Return _TagFont
  111.         End Get
  112.         Set(ByVal Value As Font)
  113.             _TagFont = Value
  114.         End Set
  115.     End Property
  116.  
  117.     <Browsable(True), Description("The font with which attributes are highlighted.")> _
  118.     Public Property AttributeFont() As Font
  119.         Get
  120.             Return _AttributeFont
  121.         End Get
  122.         Set(ByVal Value As Font)
  123.             _AttributeFont = Value
  124.         End Set
  125.     End Property
  126.  
  127.     <Browsable(True), Description("The font with which boolean attributes are highlighted.")> _
  128.     Public Property BooleanAttributeFont() As Font
  129.         Get
  130.             Return _BooleanAttributeFont
  131.         End Get
  132.         Set(ByVal Value As Font)
  133.             _BooleanAttributeFont = Value
  134.         End Set
  135.     End Property
  136.  
  137.     <Browsable(True), Description("The font with which attributes' values are highlighted.")> _
  138.     Public Property ValueFont() As Font
  139.         Get
  140.             Return _ValueFont
  141.         End Get
  142.         Set(ByVal Value As Font)
  143.             _ValueFont = Value
  144.         End Set
  145.     End Property
  146.  
  147.     Public Property CommentFont() As Font
  148.         Get
  149.             Return _CommentFont
  150.         End Get
  151.         Set(ByVal value As Font)
  152.             _CommentFont = value
  153.         End Set
  154.     End Property
  155.  
  156.     <Browsable(True), Description("The font of the control.")> _
  157.     Public Shadows Property Font() As Font
  158.         Get
  159.             Return MyBase.Font
  160.         End Get
  161.         Set(ByVal value As Font)
  162.             Me.TagFont = value
  163.             Me.AttributeFont = value
  164.             Me.BooleanAttributeFont = value
  165.             Me.ValueFont = value
  166.             MyBase.Font = value
  167.         End Set
  168.     End Property
  169.  
  170.  
  171.     Public ReadOnly Property IsBusy() As Boolean
  172.         Get
  173.             Return _IsBusy
  174.         End Get
  175.     End Property
  176.  
  177.     Public ReadOnly Property CurrentLineIndex() As Int32
  178.         Get
  179.             Return Me.GetLineFromCharIndex(Me.SelectionStart)
  180.         End Get
  181.     End Property
  182.  
  183.     Public ReadOnly Property RtfLines() As String()
  184.         Get
  185.             Return _RtfLines
  186.         End Get
  187.     End Property
  188.  
  189.     Public ReadOnly Property RtfCurrentLineIndex() As Int32
  190.         Get
  191.             Return Me.CurrentLineIndex + 2
  192.         End Get
  193.     End Property
  194.  
  195.     'Contiene costanti usate nell'inviare messaggi all'API di windows
  196.     Private Enum EditMessages
  197.         LineIndex = 187
  198.         LineFromChar = 201
  199.         GetFirstVisibleLine = 206
  200.         CharFromPos = 215
  201.         PosFromChar = 1062
  202.     End Enum
  203.  
  204.     Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
  205.         'Non colora tutte le linee visibili, bensì solo la riga dove si
  206.         'trova il cursorse: in questo modo l'applicazione risulta più
  207.         'veloce. L'unico caso in cui questo approccio non funzione è
  208.         'quando si copia un testo all'interno della richtextbox. In
  209.         'quel caso ci sarà un pulsante apposito
  210.         If Me.HtmlChangedEnabled Then
  211.             Dim LineIndex As Int32 = Me.GetLineFromCharIndex(Me.SelectionStart)
  212.             Me.ColorLineNumber(LineIndex)
  213.             RaiseEvent HtmlChanged(Me, EventArgs.Empty)
  214.         End If
  215.     End Sub
  216.  
  217.     Friend Sub UpdateRtfLines()
  218.         _RtfLines = Me.Rtf.Split(vbCrLf)
  219.     End Sub
  220.  
  221.     'Colora tutta la RichTextBox
  222.     Public Sub ColorRtb()
  223.         For I As Int32 = 0 To Me.Lines.Length - 1
  224.             ColorLineNumber(I)
  225.         Next
  226.     End Sub
  227.  
  228.     'Colora solo le linee visibili
  229.     Public Sub ColorVisibleLines()
  230.         Dim FirstLine As Integer = FirstVisibleLine()
  231.         Dim LastLine As Integer = LastVisibleLine()
  232.  
  233.         If (FirstLine = 0) And (LastLine = 0) Then
  234.             'Non c'è testo
  235.             Exit Sub
  236.         Else
  237.             While FirstLine < LastLine
  238.                 ColorLineNumber(FirstLine)
  239.                 FirstLine += 1
  240.             End While
  241.         End If
  242.     End Sub
  243.  
  244.     'Questa è la nuova versione: nelle stesso condizioni sopra citate,
  245.     'impiega 50ms, quasi la metà! L'algoritmo vecchio per SQl
  246.     'ne impiegava 10, ma non era in grado di supportare tag vicini
  247.     'come quelli dell'HTML
  248.     Public Sub ColorLineNumber(ByVal LineIndex As Int32)
  249.         Try
  250.             If Me.Lines(LineIndex).Length = 0 Then
  251.                 Exit Sub
  252.             End If
  253.         Catch Ex As Exception
  254.             Exit Sub
  255.         End Try
  256.  
  257.         If Me.SyntaxHighlightingEnabled = False Then
  258.             Exit Sub
  259.         End If
  260.  
  261.         Dim PrevState As Boolean = Me.HtmlChangedEnabled
  262.         Me.HtmlChangedEnabled = False
  263.         _IsBusy = True
  264.  
  265.         'Indice del primo carattere della linea
  266.         Dim FirstCharIndex As Int32 = _
  267.             Me.GetFirstCharIndexFromLine(LineIndex)
  268.         'Tiene traccia del cursore
  269.         Dim SelectionAt As Integer = Me.SelectionStart
  270.         Dim Line As String = Me.Lines(LineIndex)
  271.         Dim Tags As MatchCollection = TagRegex.Matches(Line)
  272.         Dim ClosedTags As MatchCollection = CloseTagRegex.Matches(Line)
  273.         Dim Comments As MatchCollection = CommentRegex.Matches(Line)
  274.  
  275.         'Blocca il refresh
  276.         LockWindowUpdate(Me.Handle.ToInt32)
  277.  
  278.         Me.Select(FirstCharIndex, Line.Length)
  279.         Me.SelectionColor = Me.ForeColor
  280.         Me.SelectionFont = Me.Font
  281.         Me.DeselectAll()
  282.  
  283.         For Each Tag As Match In Tags
  284.             With Tag.Groups("TagName")
  285.                 '-1 per comprendere anche il "<" iniziale
  286.                 Me.Select(FirstCharIndex + .Index - 1, .Length + 1)
  287.                 Me.SelectionColor = Me.TagColor
  288.                 Me.SelectionFont = Me.TagFont
  289.             End With
  290.  
  291.             If Tag.Groups("Attribute") IsNot Nothing Then
  292.                 For Each C As Capture In Tag.Groups("Attribute").Captures
  293.                     Me.Select(FirstCharIndex + C.Index, C.Length)
  294.                     If C.Value.StartsWith("[") Then
  295.                         Me.SelectionColor = Me.BooleanAttributeColor
  296.                         Me.SelectionFont = Me.BooleanAttributeFont
  297.                     Else
  298.                         Me.SelectionColor = Me.AttributeColor
  299.                         Me.SelectionFont = Me.AttributeFont
  300.                     End If
  301.                 Next
  302.  
  303.                 For Each C As Capture In Tag.Groups("Value").Captures
  304.                     Me.Select(FirstCharIndex + C.Index, C.Length)
  305.                     Me.SelectionColor = Me.ValueColor
  306.                     Me.SelectionFont = Me.ValueFont
  307.                 Next
  308.             End If
  309.  
  310.             'Colora il ">" finale
  311.             Me.Select(FirstCharIndex + Tag.Index + Tag.Length - 1, 1)
  312.             Me.SelectionColor = Me.TagColor
  313.             Me.SelectionFont = Me.TagFont
  314.             Me.DeselectAll()
  315.         Next
  316.  
  317.         For Each ClosedTag As Match In ClosedTags
  318.             With ClosedTag.Groups("TagName")
  319.                 '-2 per comprendere anche il "</" iniziale
  320.                 Me.Select(FirstCharIndex + .Index - 2, .Length + 3)
  321.                 Me.SelectionColor = Me.TagColor
  322.                 Me.SelectionFont = Me.TagFont
  323.             End With
  324.             Me.DeselectAll()
  325.         Next
  326.  
  327.         For Each Comment As Match In Comments
  328.             Me.Select(FirstCharIndex + Comment.Index, Comment.Length)
  329.             Me.SelectionColor = Me.CommentColor
  330.             Me.SelectionFont = Me.CommentFont
  331.             Me.DeselectAll()
  332.         Next
  333.  
  334.         'Ripristina la selezione
  335.         Me.SelectionStart = SelectionAt
  336.         Me.SelectionLength = 0
  337.         'E il colore
  338.         Me.SelectionColor = Me.ForeColor
  339.  
  340.         'Riprende il refresh
  341.         LockWindowUpdate(0)
  342.         Me.HtmlChangedEnabled = PrevState
  343.         _IsBusy = False
  344.     End Sub
  345.  
  346.     Public Sub ColorCurrentLine()
  347.         Me.ColorLineNumber(Me.GetLineFromCharIndex(Me.SelectionStart))
  348.     End Sub
  349.  
  350.     'Ottiene la prima linea visibile
  351.     Public Function FirstVisibleLine() As Integer
  352.         Return SendMessage(Me.Handle, EditMessages.GetFirstVisibleLine, 0, 0)
  353.     End Function
  354.  
  355.     'Ottiene l'ultima linea visibile
  356.     Public Function LastVisibleLine() As Integer
  357.         Dim LastLine As Integer = FirstVisibleLine() + _
  358.             (Me.Height / Me.Font.Height)
  359.  
  360.         If LastLine > Me.Lines.Length Or LastLine = 0 Then
  361.             LastLine = Me.Lines.Length
  362.         End If
  363.  
  364.         Return LastLine
  365.     End Function
  366.  
  367.     Private Function CloneMe() As Object Implements System.ICloneable.Clone
  368.         Return Me.MemberwiseClone
  369.     End Function
  370.  
  371.     Public Function Clone() As HTML_IntelliSense.HtmlTextBox
  372.         Return Me.CloneMe
  373.     End Function
  374. End Class