Remove end character in a textbox without rewriting all the data - vb.net

I am writing a program to communicate over the serial port. All data that is sent is mirrored back. Everything works fine except backspaces. When I hit the backspace button the only way I know how to remove the last character in the text box is to use a mid function then overwrite the current data with the new data. When a lot of data is inside the richtextbox it starts to flicker. I have tried using the richtextbox.text.remove function but I get this error. "Index and count must refer to a location within the string. Parameter name: count"
RichTextBox1.Text.Remove(RichTextBox1.TextLength, 1)
I have tried to throw some number into the function that does not cause it to error out but no data is removed from the richtextbox.
Here is the code that transmits data
KeyCharString = e.KeyChar 'stores key being pressed into KeyCharString
Try
SerialPort1.Write(KeyCharString) 'tx data for key being pressed
Catch ex As Exception
MsgBox(ex.Message) 'Displays error if serialport1 cannot be written to
End Try
If Asc(KeyCharString) = 8 Then 'If char is a backspace remove precious character and exit sub
RichTextBox1.Text = RichTextBox1.Text.Remove(RichTextBox1.TextLength, 1)
'RichTextBox1.Text = Mid(RichTextBox1.Text, 1, RichTextBox1.TextLength - 1)'Old code used to remove the character. Causes the richtextbox to flicker when rewriting the data
Exit Sub
End If
This is the code that receives data
receivedString = SerialPort1.ReadExisting.ToString
If Asc(receivedString) = 8 Then 'deletes the received data if it is a backspace
receivedString = ""
Exit Sub
End If
RichTextBox1.AppendText(receivedString) 'adds new data to the richtextbox
Is there a way to remove 1 character from the richtextbox without rewriting all the data inside it? Also, the richtextbox is read only.

The String.Remove method that you are using returns a String it does not do anything with the original string.
from MSDN Link:
Returns a new string in which all the characters in the current instance, beginning at a specified position and continuing through the last position, have been deleted.
Try this but I am not sure of the flicker:
RichTextBox1.Text = RichTextBox1.Text.Remove(RichTextBox1.TextLength - 1, 1)
or something like this:
RichTextBox1.SelectionStart = RichTextBox1.TextLength - 1
RichTextBox1.SelectionLength = 1
RichTextBox1.ReadOnly = False
RichTextBox1.SelectedText = ""
RichTextBox1.ReadOnly = True

Related

Reading Numbers from Webbrowser Vb.net

In my WebBrowser I got text like this: Remaining balance: 10$
I would like to convert it to another currency, I want just to read number from my browser, then after that I will send it to a Label or TextBox with the new converted currency. I am stuck here.
A screenshot of it
Private Sub LinkLabel2_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel2.LinkClicked
WebBrowser2.Navigate(TextBox9.Text + TextBox2.Text)
End Sub
Private Sub WebBrowser2_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser2.DocumentCompleted
Label1.Text = (WebBrowser2.Document.Body.InnerText)
End Sub
I have this suggestion (I know this is probably not the perfect solution):
First, try loading that same webpage in a normal web browser such as Google Chrome or Firefox or any browser which has the feature to "inspect elements", meaning to view their HTML code.
Find out the element which displays the price you want.
Note down the ID of the element (usually written something like id="someID")
Back to your program's code, include the following Function, which will get the text displayed and convert it to another currency:
Public Function ConvertDisplayedCurrency() As Decimal
Dim MyCurrencyElement As HtmlElement = WebBrowser2.Document.GetElementById("theIdYouGotInStep3") 'This will refer to the element you want.
Dim TheTextDisplayed As String = MyCurrencyElement.InnerText 'This will refer to the text that is displayed.
'Assuming that the text begins like "Remaining balance: ###", you need to strip off that first part, which is "Remaining balance: ".
Dim TheNumberDisplayed As String = TheTextDisplayed.Substring(19)
'The final variable TheNumberDisplayed will be resulting into a String like only the number.
Dim ParsedNumber As Decimal = 0 'A variable which will be used below.
Dim ParseSucceeded As Boolean = Decimal.TryParse(TheNumberDisplayed, ParsedNumber)
'The statement above will TRY converting the String TheNumberDisplayed to a Decimal.
'If it succeeds, the number will be set to the variable ParsedNumber and the variable
'ParseSucceeded will be True. If the conversion fails, the ParseSucceeded will be set
'to False.
If Not ParseSucceeded = True Then Return 0 : Exit Function 'This will return 0 and quit the Function if the parse was a failure.
'Now here comes your turn. Write your own statements to convert the number "ParsedNumber"
'to your new currency and finally write "Return MyFinalVariableName" in the end.
End Function
Call that Function probably when the document of the WebBrowser2 loads, that is, in the WebBrowser2_DocumentCompleted sub.
I hope it helps!

VB.net load controls and content from textfile to textboxes

...Hopefully this question will be readable...
I have 27 textboxes.
The controlname and the text in the textboxes are written to a textfile like this:
System.DateTime.Now.ToString("yyyyMMdd") & "_Names_Config.txt"
Dim objWriter As New System.IO.StreamWriter(configfile, True)
'Textboxes
objwriter.Writeline("tbmax1") 'Control name
objwriter.Writeline("tbmax1.text) 'The text in the textbox
objWriter.WriteLine("tbname1") 'Control name
objWriter.WriteLine(tbname1.Text) 'The text in the textbox
objWriter.WriteLine("tbext1") 'Control name
objWriter.WriteLine(tbext1.Text) 'The text in the textbox
'And so on for all the the controls
This goes on for all the textboxes and controls, so 54 lines in total.
Works great. The textfile looks like this:
Alright, now the issue. There will be a load button that should search the textfile -> find the control matching the form's control -> use the line below and fill that spesific line in the control's textbox -> then find next control and do the same.
Load button: This is #1 attempt;
'Openfiledialog, then:
Using reader As New StreamReader(OpenFileDialog1.FileName.ToString)
Dim currentTextBox As TextBox = Nothing
While reader.Peek > -1
Dim line As String = reader.ReadLine()
If Not String.IsNullOrEmpty(line) Then
Dim tmpTextbox = Controls.Find(line, True) 'Try to find text according to line
If tmpTextbox.Any() Then 'It´s a textbox name
currentTextBox = DirectCast(tmpTextbox(0), TextBox)
Else
'?
End If
End If
End While
End Using
Here comes what I don't understand at all. See before and after picture of what happens to the 27 textboxes after I load the textfile.
What it SHOULD look like:
What it will look like:
"Edit channels" is actually the title of the form itself. I'm speechless. Because I totally don't understand why this happens and the load code, I moved on to another attempt.
#2 attempt:
Using reader As New StreamReader(OpenFileDialog1.FileName)
Dim Line As String = reader.ReadLine()
Dim Current As Integer = 0
Dim TB As TextBox = Nothing
While Not IsNothing(Line) 'It will be Nothing when file is over
'__________________________________________________________________1
If Line.StartsWith("tbext1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbext1.Text = Line
Next
End If
If Line.StartsWith("tbname1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbname1.Text = Line
Next
End If
If Line.StartsWith("tbmax1") Then
'We will increment CurrentChannel, as we changed the section
Current += 1
For onetonine = 1 To 9
tbmax1.Text = Line
Next
End If
'__________________________________________________________________2
'Then I guess this would go on for all the 27 textboxes (probably a really bad attempt)
End While
End Using
However, this just goes into break mode.
Your first approach works already if you fill the Else part:
If tmpTextbox.Any() Then
currentTextBox = DirectCast(tmpTextbox(0), TextBox)
ElseIf currentTextBox IsNot Nothing Then
currentTextBox.Text = line
End If
But you should not use it in production code:
Control-names are a very bad key for a database record or file entry:
They can change in future and you won't notice it
They are GUI related and not supposed to be identifiers for properties
is not fail-safe because there could be multiple controls with the same name
don't store key-value pairs on different lines, that makes it difficult, less readable and more error-prone to put them together afterwards
If you want to use one line you need a delimiter that a user never enters, it can be a combination of multiple characters like |::| or something similar. Then you can later use String.Split({"|::|"}, StringSplitOptions.None) to get both tokens back.
However, this is still not a good approach and also not 100% safe. So better approaches were
serialize/deserialize a List(Of String).
If you want to store it in a way that a human can read you should prefer XML.
Here's an example how you can write/read xml easily:
' write all TextBoxes to a file '
Dim allTextBoxes = TextBoxPanel.Controls.OfType(Of TextBox)()
Dim doc As New XDocument(New XElement("Channels"))
For Each txt In allTextBoxes
doc.Root.Add(New XElement(txt.Name, txt.Text.Trim()))
Next
doc.Save(OpenFileDialog1.FileName)
' later read it ... '
Dim xml As XDocument = XDocument.Load(OpenFileDialog1.FileName)
For Each element As XElement In xml.Descendants("Channels").Descendants()
Dim txt = allTextBoxes.FirstOrDefault(function(t) t.Name = element.Name)
If txt IsNot nothing
txt.Text = element.Value
End If
Next

Compare each line in a text file with text in Text/Combo box

I need to be able to compare each line of a text file with the text a user has typed in a Text or Combo Box for serial key check and blocking certain website. At the moment, the blocked content is inside the programs code itself.
If ComboBox1.Text = "website.com" Then
WB.DocumentText = My.Settings.BlockedPage
ComboBox1.Text = "Blocked"
Else
WB.Navigate(Me.ComboBox1.Text)
ComboBox1.Items.Add(ComboBox1.Text)
End If
I find this way to be annoying as it would increase the file size of the compiled executable and stop me from updating it without releasing a whole new executable.
I have used this approach in another program, but I am sure the code I have used would compare it to the whole text file and not a line.
Dim key As String
key = My.Computer.FileSystem.ReadAllText("key.txt")
If TextBox1.Text = key Then
'Do functions, such as create licence file
Me.Close()
Else
MsgBox("Incorrect key", MsgBoxStyle.Exclamation, "Key Check")
End If
Would I just be able to modify that code to allow me to do what I want?
Thanks.
Try
If ComboBox1.Text.Equals("website.com") Then
WB.DocumentText = My.Settings.BlockedPage
ComboBox1.Text = "Blocked"
Else
WB.Navigate(Me.ComboBox1.Text)
ComboBox1.Items.Add(ComboBox1.Text)
End If
or
If ComboBox1.Text.Contains("website.com") Then
WB.DocumentText = My.Settings.BlockedPage
ComboBox1.Text = "Blocked"
Else
WB.Navigate(Me.ComboBox1.Text)
ComboBox1.Items.Add(ComboBox1.Text)
End If
use .Equal() or .Contains(). Try using .contain() when your trying to compare with a .txt file
Here is a way of doing that:
Dim lines = System.IO.File.ReadAllLines("File path")
Dim text As String
For i = 0 To lines.Length - 1
text = lines(i).ToString
If text = "Your serial here" Then
MsgBox("Serial found")
else
Msgbox("Serial not found")
End If
Next
This code you can use for the webbrowser:
Dim lines = System.IO.File.ReadAllLines(Application.StartupPath + "file path")
Dim text As String
For i = 0 To lines.Length - 1
text = lines(i).ToString
If WebBrowser1.Url.ToString.Contains(text) Then
WebBrowser1.Navigate("")
End If
Next
The text in the textfile should be in the format of:
www.website.com

Error to validate the length of a barcode read

I have a project in Visual Studio 2005 with EMDK 2.6 with a MC1000 data collector over XP SP3 implemented on Windows CE.
I have this function within the project that gives me an error that I can't solve :
'Handle data from the reader
Private Sub HandleData(ByVal TheReaderData As Symbol.Barcode.ReaderData)
'MsgBox("Hello I'm reading ....")
If Me.DataTextBox.Text = "" Then
Me.DataTextBox.Text = TheReaderData.Text
' Here begins the verification of the length
If Len(Me.DataTextBox.Text) = Me.TextBox6.Text Then
' The length is ok
objStreamWriter.WriteLine(Me.DataTextBox.Text)
'Update the last read
Me.Label5.Text = Me.DataTextBox.Text
'Clean the field of the current read
Me.DataTextBox.Text = ""
'The counter of the code bars reads increases +1
Me.TextBox3.Text = Me.TextBox3.Text + 1
Else
Me.DataTextBox.Text = ""
MessageBox.Show("The length of the string read is not as expected", "Error !")
End If
End If
End Sub
The problem begins when I read a barcode with a length different to Me.TextBox6.Text (24 for example), the messagebox is shows ok, but inmediatelly another message box appear with the next error:
"StartRead Invalid Request Read already pending"
and the program continues fine, I need to eliminate this error because looks very bad.
Any help ?
Thanks in advance.
MessageBox does not stop your application from processing other events and it may be that a new barcode is read (or the same barcode is notified again) while you are still in the function processing the previous one.
Did you try to remove the call to MessageBox and check if this is still happening?
You may need to disable the reader before you call MessageBox.

autoscroll to bottom of multiline textbox being updated by backgroundworker

I have a background worker control that is set to perform a task, and update a multiline text box on my main UI using a delegate procedure. this is all working perfectly, however once the updating scrolls off the bottom of the text box, the scroll bars appear, but the continuous refreshing causes the text box to stay locked at the top. Ideally, I would like the text box to auto-scroll itself to the bottom to show the latest entry in real-time. What would be the best way to implement this?
I have tried using the scrolltocaret() method, with and without a SelectionStart = txtlog.Text.Length command preceding it. perhaps I'm putting it in the wrong place?
some code samples below:
Delegate code:
Delegate Sub updateresults_delegate(ByVal textbox As TextBox, ByVal text As String)
Private Sub updatelog_threadsafe(ByVal textbox As TextBox, ByVal text As String)
If textbox.InvokeRequired Then
Dim mydelegate As New updateresults_delegate(AddressOf updatelog_threadsafe)
Me.Invoke(mydelegate, New Object() {textbox, text})
'Me.txtlog.SelectionStart = txtlog.Text.Length
'Me.txtlog.ScrollToCaret()
Else
textbox.Text = text
End If
End Sub
main backgroundworker activity:
For i As Integer = val1 To val2
'generate an IP address from split host parts and current value of i
host = s1(0) & "." & s1(1) & "." & s1(2) & "." & i
Try 'attempt to ping the IP
Dim reply As PingReply = pingsender.Send(host, timeoutval, buffer, options)
If reply.Status = IPStatus.Success Then
name = System.Net.Dns.GetHostEntry(host)'get DNS entry
resulttext += String.Format("{1} - {2}: reply: Bytes={3} time{4} TTL={5}{0}", vbCrLf, name.HostName, reply.Address.ToString, reply.Buffer.Length, getms(reply.RoundtripTime), reply.Options.Ttl) 'print out success text
Else
resulttext += String.Format(" {1}: Ping failed. {2}{0}", vbCrLf, host, reply.Status.ToString) 'print out fail text
End If
updatelog_threadsafe(txtlog, resulttext) 'send text to textbox
System.Threading.Thread.Sleep(1000)
Catch ex As Exception
End Try
Next
I guess my main question is: I'm pretty certain that the textbox.scrolltocaret() is the correct method to use for what I want, but where is the best place for me to put it? I've tried it in the delegate, the main backgroundworker, as well as before & after the runworkerasync() method. none of these worked, and now I'm stumped!
Try it this way:
'textbox.Text = text
textbox.AppendText(text)
The code you commented out wasn't running on the GUI thread, and as M Granja pointed out, AppendText will automatically scroll to the appended text in the box, so no need to call ScrollToCaret.
xxx.SetFocus ' xxx = the name of the textbox
SendKeys "^{END}" ' pop to last line