"Caret Position" in VB.NET for syntax highlighting - vb.net

I'm trying to make a TextBox with syntax highlighting (for (HTML/CSS) in VB.NET 2008.
I figured that if I use RichTextBox.Find(), I can color specific text, but then I need to call RichTextBox.DeselectAll().
The problem is that the the cursor jumps to the beginning of the RTB.
I'm using WinForms.
Any ideas?

You can get and set the cursor position using the SelectionStart property.
Therefore, you can write,
Dim selStart As Integer = rtb.SelectionStart
'Do things
rtb.SelectionStart = selStart

Imports System.Text.RegularExpressions
Public Class Form1
'Create a Html Keyword Regex
Dim htmlkeywords As New System.Text.RegularExpressions.Regex("<html>|</html>|<head>|</head>|<meta|<p>|</p>|<div>|</div>") <----add as many terms as you like between the () don't forget the pipe symbol between each term in the Regex.
'Then in your Richtextbox textchanged event add this
Private Sub rtText_TextChanged(sender As Object, e As EventArgs) Handles rtText.TextChanged
Dim selStart As Integer = rtText.SelectionStart
Do Until False
For Each keyWordMatch As Match In htmlkeywords.Matches(rtText.Text)
rtText.Select(keyWordMatch.Index, keyWordMatch.Length)
rtText.SelectionColor = Color.Purple
rtText.SelectionStart = rtText.Text.Length 'this puts the caret at the end
rtText.SelectionLength = 0 ' of the word
Next keyWordMatch
Exit Do
Loop
rtText.SelectionColor = Color.Black
rtText.SelectionStart = selStart ' this makes sure that if your caret is behind a word and you press enter to move a text down a line; the caret will stay in position on the next line that you start typing on. You can remove this code to see what I'm talking about
End Sub
rtText is my RichTextBox name. This will change the word you want to whatever color then change it back to black, which you can change which colors do what. Hope this helps!

Related

Visual Basic: reference label control from variable derived from checkbox control

I'm writing a simple Windows Form app in VB using VS Community 2017.
I have 64 checkboxes with 64 associated labels, named chk1 / lbl1 up to chk64 / lbl64. When a checkbox is checked, I want to extract a character from a string and show the answer in the label: e.g. if chk12 is checked, I want lbl12 to be enabled and the text to display the 12th character of the string.
To save writing 64 separate handlers I'm trying to do it in one. I can extract the checked number (e.g. 12) OK and write it to a string, but when I try to manipulate the label control I get an 'Object reference not set to an instance of an object' error.
The code I've come up with so far (largely from searching in here) is:
Private Sub CheckedChanged(sender As Object, e As EventArgs) _
Handles chk1.CheckedChanged, chk2.CheckedChanged 'etc. to 64
' wanted behaviour
'If chk1.Checked Then
' lbl1.Enabled = True
' lbl1.Text = GetChar(userString, 1)
'End If
'If chk2Checked Then
' lbl2.Enabled = True
' lbl2.Text = GetChar(userString, 2)
'End If
' etc. (to 64)
Dim resultsLabel As String
Dim userCheckedBox As Integer
userCheckedBox = CInt(DirectCast(sender, CheckBox).Text)
resultsLabel = "lbl" & DirectCast(sender, CheckBox).Text
Me.Controls(resultsLabel).Enabled = True
Me.Controls(resultsLabel).Text = GetChar(userString, userCheckedBox)
End Sub
I'd be very grateful if someone can nudge me over the line with this. Many thanks!
There is the old trick to use the Tag property of your checkboxes.
You can set the Tag property to the matching label name at design time using the WinForms Designer. So in the chk1.Tag property you will have the "lbl1" string assigned and so on for all the 64 checkboxes.
At this point your code in the event handler is simply
Dim chk = DirectCast(sender, CheckBox)
if chk IsNot Nothing Then
Me.Controls(chk.Tag.ToString()).Enabled = True
Me.Controls(chk.Tag.ToString()).Text = GetChar(userString, CInt(chk.Text))
End If

Change Font Style on All Instances of a String in a RichTextBox

I'm working on a VB.NET 4.5 project in VS2013.
I have a richtextbox on a form and when a button is clicked I need to toggle the BOLD setting on all instances of a specific string found in the richtextbox.
I put together some code based on this question.
Private Sub ToggleBold()
rtxtOutputText.SelectionStart = rtxtOutputText.Find("##$%", RichTextBoxFinds.None)
rtxtOutputText.SelectionFont = New Font(rtxtOutputText.Font, FontStyle.Bold)
End Sub
However when the toggle bold button is clicked it only bolds the first instance of the string "##$%".
How can I set all instances of the string to bold? There can also be several of them strung together ("##$%##$%##$%"), so each of those would need to be bolded too.
(I know I mentioned toggling bold, but I'll set up the toggle portion later, right now I'm just trying to get the bold on all instances working right...)
Just add a loop to it and use the RichTextBox.Find(String, Int32, RichTextBoxFinds) overload to specify from where to start looking. Look from the current index + 1 so that it doesn't return the same again.
You also ought to actually select the word as well, so that you're sure the bold applies to the current instance only and not the text around it.
Private Sub ToggleBold()
'Stop the control from redrawing itself while we process it.
rtxtOutputText.SuspendLayout()
Dim LookFor As String = "##$%"
Dim PreviousPosition As Integer = rtxtOutputText.SelectionStart
Dim PreviousSelection As Integer = rtxtOutputText.SelectionLength
Dim SelectionIndex As Integer = -1
Using BoldFont As New Font(rtxtOutputText.Font, FontStyle.Bold)
While True
SelectionIndex = rtxtOutputText.Find(LookFor, SelectionIndex + 1, RichTextBoxFinds.None)
If SelectionIndex < 0 Then Exit While 'No more matches found.
rtxtOutputText.SelectionStart = SelectionIndex
rtxtOutputText.SelectionLength = LookFor.Length
rtxtOutputText.SelectionFont = BoldFont
End While
End Using
'Allow the control to redraw itself again.
rtxtOutputText.ResumeLayout()
'Restore the previous selection.
rtxtOutputText.SelectionStart = PreviousPosition
rtxtOutputText.SelectionLength = PreviousSelection
End Sub
Credit to Plutonix for telling me to dispose the font.

Problems when calling a public sub

I'm facing a deadend When trying to call this sub :
Public Sub backblue(ByVal frm As Form, ByVal boxname As String)
For i = 1 To 3
CType(frm.Controls(boxname & i.ToString()), TextBox).BackColor = Color.LightBlue
Next
End Sub
with button click event :
Private Sub Button1_click and bla bla....
backblue(Me, "txb1_")
End Sub
Can anybody show me a suggestion to fix the code.
It throws "Object Referrence not set to an instance bla bla" error
For information the textbox names are :
txb1_1 , txb1_2 , txb1_3
(these are some of the many textboxes in the form that i want its bakcolor changed)
and these three textboxes are already created through designer, not from execution.
i did check the textboxes names and there's nothing wrong.
the form class is also public.
if they are the only textboxs on said form you can just loop through
For Each box as Textbox In frm.Controls
box.BackColor = Color.LightBlue
Next
This error will occur if you do not declare the Form class to be public.
Also, make sure the textbox names are really correct, although this will probably cause a different error.
If you create the textboxes during execution, make sure they are initialized with New and added to the form's Controls collection.
Try this....
Public Sub backblue(ByVal frm As Form, ByVal prefix As String)
For i = 1 To 3
Dim bxName as String = prefix & i.ToString()
Dim bx as TextBox = CType(frm.Controls(bxName), TextBox)
If bx Is Nothing Then
MsgBox("Unable to find text box " +bxName)
Dim mtch() As Control = frm.Controls.Find(bxName, true)
If mtch.Length> 0 then
bx = mtch(0)
Else
Continue For
End if
End If
Bx.BackColor = Color.LightBlue
Next
End Sub
Although, a better solution would be to either create the textboxes inside a control and pass that control to BackBlue or to create an collection that has the controls and pass that in. Which brings up what is most likely yor problem your control is contained in a sub component and thus is not in the main form control collection
Alternative, you could use either the tag of the control or create a component control that implements IExtenderProvider and add it to the form --all of the above would effectively allow you to define the controls and/how they should be handled at designtime.
It may really seem that the names generated by this loop may not be the names of the original textboxes. My suggestion is before setting this Color property verify that the names generated by this loop are indeed the actual names. Maybe output this in a messagebox:
MessageBox.Show(boxname & i.ToString()) for each loop before you set the property

Force a MultiLine TextBox Horizontal ScrollBar to the left

I have a MultiLine TextBox that is updated over a period of time as an app runs, and I've managed to make it so that the TextBox scrolls to the bottom, ensuring that the latest entry is always shown.
However, sometimes the text is quite long and goes off of the side of the TextBox, so the Horizontal ScrollBar scrolls to the right.
How can I amend the code below so that the ScrollBar is always to the left, meaning that the beginning of lines is always visible? Please note that I do not wish to wrap text, as I can't have one entry on multiple lines. Thanks.
Private Sub UpdateCurrentProgress(ByVal Text As String)
If Text = "" Then Exit Sub
Dim Textbox As TextBox = Me.txtCurrentProgress
If Textbox.Text <> "" Then Text = vbCrLf & Text
Textbox.AppendText(Text)
Textbox.Select(Textbox.TextLength, 0)
Textbox.ScrollToCaret()
End Sub
You can select the first char at the current line like this:
Me.TextBox1.Select(Me.TextBox1.GetFirstCharIndexOfCurrentLine(), 0)
If I understand your problem correctly, then you need to get first the last line index and then select the first char of that line.
Dim lineNumber = textBox1.Lines.Count()-1
textBox1.Select(textBox1.GetFirstCharIndexFromLine(lineNumber), 0)

ASCII Conversion Tool Help VB.NET

I'm trying to make something along the lines of the Branah Unicode Converter to decode lines like this for instance: [99,97,108,108,32,99]. http://www.branah.com/unicode-converter. I found this. I'm guessing the form has a textbox and 2 buttons. One is using Asc to get the textbox's ASCII code and the other using Chr to convert the ASCII code in the textbox into a character.
So, last time I posted this, it got closed because it wasn't "a real question". Let me be blunt. I haven NO idea how to get this working. Labeling of things is very confusing. What do I declare Text1, Text2, Text3 and Label 6 as because it's giving me the error that they're not declared? I'm also getting an error that TextBox1 cannot be converted to an integer from this line: Text2 = Text2 + Chr(TextBox1). How do I fix that? Am I not importing something that I should be?
Private Sub EncodeButton_Click()
'Code the character
TextBox1 = Asc(Text1)
'clears text box
Text1 = ""
' adds the coded character to the textbox (Textbox1)
LABEL6 = LABEL6 + "," + TextBox1
' set focus to textbox
Text1.SetFocus
'decodes the coded character
Text2 = Text2 + Chr(TextBox1)
End Sub
Private Sub DecodeButton_Click()
'this part decodes the coded number
TextBox1 = Text3
Text3 = ""
LABEL6 = LABEL6 + "," + TextBox1
Text2 = Text2 + Chr(TextBox1)
Text3.SetFocus
End Sub
Here's how to make this code work in VB.NET:
Create a new Windows Forms project.
In the project there is a form, open it and create the following items:
Three TextBoxes, named Text1, Text2, Text3
Two Buttons, named EncodeButton and DecodeButton
A Label named Label6
Right click the form in solution explorer and select "View Code".
Paste the following code into the code window:
Public Class Form1
Private Sub EncodeButton_Click(sender As System.Object, e As System.EventArgs) Handles EncodeButton.Click
Dim sTextBox1 As String
sTextBox1 = Asc(Text1.Text)
Text1.Text = ""
Label6.Text = Label6.Text & "," & sTextBox1
Text1.Focus()
Text2.Text = Text2.Text + Chr(sTextBox1)
End Sub
Private Sub DecodeButton_Click(sender As System.Object, e As System.EventArgs) Handles DecodeButton.Click
Dim sTextBox1 As Integer
sTextBox1 = Val(Text3.Text)
Text3.Text = ""
Label6.Text = Label6.Text & "," & sTextBox1
Text2.Text = Text2.Text & Chr(sTextBox1)
Text3.Focus()
End Sub
End Class
Run the project.
Type a single letter into Text1 and click EncodeButton
Type a number into Text3 (try one of the numbers that appeared in Label6 first) and click DecodeButton
This should accomplish everything the sample you pasted was designed to accomplish. If you have difficulty with any of these steps, I suggest looking up a good Windows Forms tutorial online.
Part of your problem is probably that you need to understand that controls like TextBoxes have properties and methods.
So, to GET the value from a TextBox called Text1 and SET it to a TextBox called TextBox1 you'd do this:
TextBox1.Text = Asc(Text1.Text)
If you type in the name of a control and hit the fullstop (".") character afterwards, the intellisense will give you a very helpful list of propertyies and methods you can use.
If you've copied this code from somewhere else, you may also need to create a Form, and drag/drop some TextBox controls onto it and give then names to match your code.