Subhuman
asked on
TextBox - Need more functionality.
I'm working on a simple telnet client which at this stage uses two TextBoxes (among other components). One of these has the MultiLine property set and is used for displaying data received from the server and data that has been sent to the user (OutputBox). The other does not have the MultiLine property set, and is used for inputting commands/etc to send to the server (InputBox).
When I append data to the OutputBox I want it to automatically scroll so the newest data (at the bottom of the box) is visible on screen, rather than the old data (at the top).
I also want the OutputBox to display ANSI-formatted text appropriately (and without me having to manually parse the data for ANSI format codes and change font colours/styles accordingly).
How do I get a TextBox (or TextBox style component) with this type of functionality? I've seen these used in many mud clients (what I'm eventually hoping to turn this into), but how it has been achieved is beyond me.
When I append data to the OutputBox I want it to automatically scroll so the newest data (at the bottom of the box) is visible on screen, rather than the old data (at the top).
I also want the OutputBox to display ANSI-formatted text appropriately (and without me having to manually parse the data for ANSI format codes and change font colours/styles accordingly).
How do I get a TextBox (or TextBox style component) with this type of functionality? I've seen these used in many mud clients (what I'm eventually hoping to turn this into), but how it has been achieved is beyond me.
For example:
With List1
.AddItem "This is the first inserted line", 0
.AddItem "and this is the second", 0
End With
Item "and this..." will be displayed as the first line.
D'Mzzl!
RoverM
With List1
.AddItem "This is the first inserted line", 0
.AddItem "and this is the second", 0
End With
Item "and this..." will be displayed as the first line.
D'Mzzl!
RoverM
ASKER
Will that work? I'm skeptical but I'll give it a whirl. The data from the server comes in rather large clumps at times, which aren't going to fit into one line, and while I've never used a ListBox in VB, experience with other implementations thereof suggests to me that VB one's don't allow word-wrapping any more than C++/Java/Etc ones do (not to mention I've never seen another app using a wrapped list box).
Also, it doesn't solve the ANSI issue.
Also, it doesn't solve the ANSI issue.
Yep, you are right. It doesn't solve your lengthy texts and ANSI. However it would work for small texts and no ANSI's ;-).
Ok, replace the textbox for a richtextbox control.
Then look at this PAQ for ANSI:
https://www.experts-exchange.com/jsp/qShow.jsp?qid=10408537
D'Mzzl!
RoverM
Ok, replace the textbox for a richtextbox control.
Then look at this PAQ for ANSI:
https://www.experts-exchange.com/jsp/qShow.jsp?qid=10408537
D'Mzzl!
RoverM
Hi Subhuman,
It is possible to scroll the text in the text box. I have done that in my program. Just i m giving the sample code for you. Try this.
Text1.text control multiline property should be True.
Private Sub Command1_Click()
x = 1
st = 10
Do While x < 200
x = x + 1
Text1.Text = Text1.Text & x & vbCrLf
Text1.SelStart = Len(Text1.Text)
Loop
Text1 = Text1 & "Waiting for next loop"
Text1.SelStart = Len(Text1.Text)
Text1.SetFocus
End Sub
Try this if u have any problem let me know.
Regards
Sridhar
It is possible to scroll the text in the text box. I have done that in my program. Just i m giving the sample code for you. Try this.
Text1.text control multiline property should be True.
Private Sub Command1_Click()
x = 1
st = 10
Do While x < 200
x = x + 1
Text1.Text = Text1.Text & x & vbCrLf
Text1.SelStart = Len(Text1.Text)
Loop
Text1 = Text1 & "Waiting for next loop"
Text1.SelStart = Len(Text1.Text)
Text1.SetFocus
End Sub
Try this if u have any problem let me know.
Regards
Sridhar
BTW: The RichTextbox control wraps the line if it's too long.
ASKER
So basically the functional part of that was the
Text1.SelStart = Len(Text1.Text)
Text1.SetFocus
- bit. Hopefully it will work without being focused, because it would be extremely annoying having the focus shifting while you're trying to type in the InputBox (incidentally, to fit in with what I've specified above you ought to have used OutputBox rather than Text1, as they are being used for very different things).
-=-=-=-=-=-=-=-
roverm: Where would I find a RichTextBox control? It doesn't appear in the general controls toolbox by default (at least not in VB5, which I'm using), and I've only been using VB for roughly 3 hours, armed with an idiots guide and the online language reference, and haven't chanced across which component package the RichTextBox hides in (took me long enough to find the damn Winsock control).
Thanks for the PAQ link, I'll browse through it and see if it helps any.
Text1.SelStart = Len(Text1.Text)
Text1.SetFocus
- bit. Hopefully it will work without being focused, because it would be extremely annoying having the focus shifting while you're trying to type in the InputBox (incidentally, to fit in with what I've specified above you ought to have used OutputBox rather than Text1, as they are being used for very different things).
-=-=-=-=-=-=-=-
roverm: Where would I find a RichTextBox control? It doesn't appear in the general controls toolbox by default (at least not in VB5, which I'm using), and I've only been using VB for roughly 3 hours, armed with an idiots guide and the online language reference, and haven't chanced across which component package the RichTextBox hides in (took me long enough to find the damn Winsock control).
Thanks for the PAQ link, I'll browse through it and see if it helps any.
To append text, here is the best way:
Text1.SelStart = Len(Text1.Text)
Text1.SelText = yourstring ' or yourstring & vbCrLf
To have formatting and to allow for more data - use RichTextBox - the syntax for adding the text is the same.
To add RichTextBox component to toolbox, go to menu Project, Components, and check "Microsoft Rich Textbox Control 6.0"
Text1.SelStart = Len(Text1.Text)
Text1.SelText = yourstring ' or yourstring & vbCrLf
To have formatting and to allow for more data - use RichTextBox - the syntax for adding the text is the same.
To add RichTextBox component to toolbox, go to menu Project, Components, and check "Microsoft Rich Textbox Control 6.0"
ASKER
Ahh, sweet. Damn, this topic area is fast.
<looks up... Most popular topics: #1 Visual Basic>
No wonder. ;)
<looks up... Most popular topics: #1 Visual Basic>
No wonder. ;)
Of course it's popular - there are many VB programmer - you can be VB programmer after ... 3 hours. :-)
3 hours ? Hmmmmm, so I still have got a learning time left ;-)
ASKER
*grins*
*busily saving these pages to disk so I can get at them from my other computer, where I have VB installed*
*busily saving these pages to disk so I can get at them from my other computer, where I have VB installed*
ASKER
Ok, the OutputBox.SelStart = Len(OutputBox.Text) thing is working a treat. :)
Since I've been using the RichTextBox control, I've been getting a funny 'box' character at the start of each line of output. I tried copying this character and pasting it into the immediate window, inside a print asc("<char here>") command, but it pastes as a new line so I can't actually determine if it's chr(10) or chr(13), or some other character that causes line-breakage. I've tried filtering both out to no avail, but that is likely something wrong with my filter.
I'm also getting special characters occasionally (chr(251, 252 and 255) that I've come across so far), which neither telnet.exe nor GMud display. These are sent from the server like this:
-=-=-=-=-=-=-=-=-=-
By what name are you known (or "new" to create a new character):
[waits here for username]
Password: chr(255)(chr(251)chr(unkno wn)
[waits here for password]
chr(255)chr(252)Last connected from: [my ip]
Press enter...
-=-=-=-=-=-=-=-=-=-
The positioning of these characters around the password suggests that the combination 255,251 and 255,252 respectively tell the client to mask any input in between. Is this a standard thing that I should implement or just weirdness? I've also attempted to filter these characters out, but again to no avail.
Has anyone got a link to a site documenting the standard telnet escape sequences (or whatever these are called)?
-=-=-=-=-=-=-=-=-=-
Had a look through that thread on ANSI colour support. Pity it's an older one; the thread order has been scrambled making it pretty much impossible to follow. I'll start a new thread for the ANSI stuff once I've got the weird-characters-in-richte xtedit issue sorted out.
-=-=-=-=-=-=-=-=-=-
YourBuddyToo: Lots of telnet example code and applications, however most are servers and the clients have little to offer me that I can see. I'm downloading a few anyway to poke around in and will let you know what I come across, if anything.
Since I've been using the RichTextBox control, I've been getting a funny 'box' character at the start of each line of output. I tried copying this character and pasting it into the immediate window, inside a print asc("<char here>") command, but it pastes as a new line so I can't actually determine if it's chr(10) or chr(13), or some other character that causes line-breakage. I've tried filtering both out to no avail, but that is likely something wrong with my filter.
I'm also getting special characters occasionally (chr(251, 252 and 255) that I've come across so far), which neither telnet.exe nor GMud display. These are sent from the server like this:
-=-=-=-=-=-=-=-=-=-
By what name are you known (or "new" to create a new character):
[waits here for username]
Password: chr(255)(chr(251)chr(unkno
[waits here for password]
chr(255)chr(252)Last connected from: [my ip]
Press enter...
-=-=-=-=-=-=-=-=-=-
The positioning of these characters around the password suggests that the combination 255,251 and 255,252 respectively tell the client to mask any input in between. Is this a standard thing that I should implement or just weirdness? I've also attempted to filter these characters out, but again to no avail.
Has anyone got a link to a site documenting the standard telnet escape sequences (or whatever these are called)?
-=-=-=-=-=-=-=-=-=-
Had a look through that thread on ANSI colour support. Pity it's an older one; the thread order has been scrambled making it pretty much impossible to follow. I'll start a new thread for the ANSI stuff once I've got the weird-characters-in-richte
-=-=-=-=-=-=-=-=-=-
YourBuddyToo: Lots of telnet example code and applications, however most are servers and the clients have little to offer me that I can see. I'm downloading a few anyway to poke around in and will let you know what I come across, if anything.
ASKER
Now onto the code...
-=-=-=-=-={form1.frm}-=-=- =-=-=-
Option Explicit
Dim connected As Boolean 'no longer used but I haven't removed it yet (lazy) ;)
' writes given text to the outputbox.
' having this as a subroutine saves me typing the
' whole lot out every time I need output.
Public Sub OutputText(ByVal theText As String)
OutputBox.SelStart = Len(OutputBox.Text)
OutputBox.SelText = theText 'use vbCrLf for linefeed ;)
OutputBox.SelStart = Len(OutputBox.Text)
End Sub
' theoretically at least, determines if the character is
' stupid (ascii value greater than 127).
Public Function IsNotStupidBit(ByVal theChar As String) As Boolean
Dim stupidBits(0 To 2) As Integer
stupidBits(0) = 10
stupidBits(1) = 255
stupidBits(2) = 251
Dim i As Integer
For i = 0 To UBound(stupidBits)
' If stupidBits(i) = Asc(theChar) Then
If Asc(theChar) <= 127 Then
IsNotStupidBit = False
Exit For
End If
Next i
IsNotStupidBit = True
End Function
' removes characters from a string that are deemed 'stupid'
' (see above)
Public Function RemoveStupidBits(ByVal theString As String) As String
Dim temp As String
Dim i As Integer
For i = 1 To Len(theString)
Dim blah As String
blah = Mid(theString, i, 1)
If IsNotStupidBit(blah) Then
temp = temp & Mid(theString, i, 1)
End If
Next i
RemoveStupidBits = temp
End Function
' duh.
Private Sub Form_Load()
connected = False ' obsolete
End Sub
' this button opens the winsock connection
Private Sub ConnectButton_Click()
Text1.Text = "Connecting..."
If Winsock1.State = sckClosed Then
Winsock1.RemoteHost = ConnectionHost.Text
Winsock1.RemotePort = ConnectionPort.Text
Winsock1.Connect
connected = True
End If
'If Winsock1.State = sckConnected Then
' Text1.Text = Text1.Text & " Connected."
'OutputText "*** Connected."
'Else
' Text1.Text = Text1.Text & " Failed."
'End If
End Sub
' this button kills the connection
Private Sub DisconnectButton_Click()
Winsock1.Close
connected = False
'OutputText vbCrLf & "*** Disconnected."
Text1.Text = "Disconnected."
End Sub
' so text can be copied, but the output box can't be
' focused.
Private Sub OutputBox_GotFocus()
Clipboard.Clear
Clipboard.SetText OutputBox.SelText, vbCFText
InputBox.SetFocus
End Sub
' handle data coming in from the server
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim DataArrived As String
Winsock1.GetData DataArrived, vbString
'Text1.Text = DataArrived
RemoveStupidBits DataArrived
OutputText DataArrived
End Sub
' trap key presses in the InputBox, used to get Enter key
' among other things
Private Sub InputBox_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeyReturn Then
If Winsock1.State = sckConnected Then
Winsock1.SendData InputBox.Text & vbCrLf
OutputText InputBox.Text & vbCrLf
End If
InputBox.Text = ""
KeyAscii = 0
Else
Text1.Text = ""
End If
End Sub
' resizes form elements to fit the window.
' at the moment this crashes the app when it's minimised,
' but I think I can fix that.
Private Sub Form_Resize()
' Stop form from resizing smaller than it can be drawn
If Form1.Height < 2200 Then Form1.Height = 2200
OutputBox.Width = Form1.Width - 225
OutputBox.Height = Form1.Height - 1890
OutputBox.SelStart = 0
OutputBox.SelStart = Len(OutputBox)
InputBox.Top = Form1.Height - 1065
InputBox.Width = Form1.Width - 225
Text1.Top = Form1.Height - 705
End Sub
' detects when the connection is closed by peer
Private Sub Winsock1_Close()
Text1.Text = "Disconnected."
Winsock1.Close
End Sub
' detects when connection has successfully completed.
' don't yet know how to check for fail :/
Private Sub Winsock1_Connect()
Text1.Text = Text1.Text & " Connected"
InputBox.SetFocus
End Sub
-=-=-=-=-={form1.frm}-=-=-
Option Explicit
Dim connected As Boolean 'no longer used but I haven't removed it yet (lazy) ;)
' writes given text to the outputbox.
' having this as a subroutine saves me typing the
' whole lot out every time I need output.
Public Sub OutputText(ByVal theText As String)
OutputBox.SelStart = Len(OutputBox.Text)
OutputBox.SelText = theText 'use vbCrLf for linefeed ;)
OutputBox.SelStart = Len(OutputBox.Text)
End Sub
' theoretically at least, determines if the character is
' stupid (ascii value greater than 127).
Public Function IsNotStupidBit(ByVal theChar As String) As Boolean
Dim stupidBits(0 To 2) As Integer
stupidBits(0) = 10
stupidBits(1) = 255
stupidBits(2) = 251
Dim i As Integer
For i = 0 To UBound(stupidBits)
' If stupidBits(i) = Asc(theChar) Then
If Asc(theChar) <= 127 Then
IsNotStupidBit = False
Exit For
End If
Next i
IsNotStupidBit = True
End Function
' removes characters from a string that are deemed 'stupid'
' (see above)
Public Function RemoveStupidBits(ByVal theString As String) As String
Dim temp As String
Dim i As Integer
For i = 1 To Len(theString)
Dim blah As String
blah = Mid(theString, i, 1)
If IsNotStupidBit(blah) Then
temp = temp & Mid(theString, i, 1)
End If
Next i
RemoveStupidBits = temp
End Function
' duh.
Private Sub Form_Load()
connected = False ' obsolete
End Sub
' this button opens the winsock connection
Private Sub ConnectButton_Click()
Text1.Text = "Connecting..."
If Winsock1.State = sckClosed Then
Winsock1.RemoteHost = ConnectionHost.Text
Winsock1.RemotePort = ConnectionPort.Text
Winsock1.Connect
connected = True
End If
'If Winsock1.State = sckConnected Then
' Text1.Text = Text1.Text & " Connected."
'OutputText "*** Connected."
'Else
' Text1.Text = Text1.Text & " Failed."
'End If
End Sub
' this button kills the connection
Private Sub DisconnectButton_Click()
Winsock1.Close
connected = False
'OutputText vbCrLf & "*** Disconnected."
Text1.Text = "Disconnected."
End Sub
' so text can be copied, but the output box can't be
' focused.
Private Sub OutputBox_GotFocus()
Clipboard.Clear
Clipboard.SetText OutputBox.SelText, vbCFText
InputBox.SetFocus
End Sub
' handle data coming in from the server
Private Sub Winsock1_DataArrival(ByVal
Dim DataArrived As String
Winsock1.GetData DataArrived, vbString
'Text1.Text = DataArrived
RemoveStupidBits DataArrived
OutputText DataArrived
End Sub
' trap key presses in the InputBox, used to get Enter key
' among other things
Private Sub InputBox_KeyPress(KeyAscii
If KeyAscii = vbKeyReturn Then
If Winsock1.State = sckConnected Then
Winsock1.SendData InputBox.Text & vbCrLf
OutputText InputBox.Text & vbCrLf
End If
InputBox.Text = ""
KeyAscii = 0
Else
Text1.Text = ""
End If
End Sub
' resizes form elements to fit the window.
' at the moment this crashes the app when it's minimised,
' but I think I can fix that.
Private Sub Form_Resize()
' Stop form from resizing smaller than it can be drawn
If Form1.Height < 2200 Then Form1.Height = 2200
OutputBox.Width = Form1.Width - 225
OutputBox.Height = Form1.Height - 1890
OutputBox.SelStart = 0
OutputBox.SelStart = Len(OutputBox)
InputBox.Top = Form1.Height - 1065
InputBox.Width = Form1.Width - 225
Text1.Top = Form1.Height - 705
End Sub
' detects when the connection is closed by peer
Private Sub Winsock1_Close()
Text1.Text = "Disconnected."
Winsock1.Close
End Sub
' detects when connection has successfully completed.
' don't yet know how to check for fail :/
Private Sub Winsock1_Connect()
Text1.Text = Text1.Text & " Connected"
InputBox.SetFocus
End Sub
ASKER
Just found a typo in "Public Function IsNotStupidBit(ByVal theChar As String) As Boolean":
If Asc(theChar) <= 127 Then
- should be -
If Asc(theChar) > 127 Then
I'll fix that when I'm back on my other computer. It doesn't appear that it would affect anything though, since I'm getting regular characters coming through just as well as the stupid characters.
So - how can I make the BlahStupidBitsEtc functions work correctly to remove all the weird characters?
If Asc(theChar) <= 127 Then
- should be -
If Asc(theChar) > 127 Then
I'll fix that when I'm back on my other computer. It doesn't appear that it would affect anything though, since I'm getting regular characters coming through just as well as the stupid characters.
So - how can I make the BlahStupidBitsEtc functions work correctly to remove all the weird characters?
ASKER
Ok, I've got that to work. I removed the two StupidBits functions and replaced them with a Parse function:
Public Function Parse(ByVal theText As String) As String
Dim temp As String
Dim i As Integer
For i = 1 To Len(theText)
Select Case Asc(Mid(theText, i, 1))
Case 0 'null
Case 1 'local echo option code (I think)
If processCommand Then
If theCommand = 251 Then
localEcho = False
processCommand = False
theCommand = -1
ElseIf theCommand = 252 Then
localEcho = True
processCommand = False
theCommand = -1
End If
End If
Case 7 'beep
Beep
Case 8 'backspace
Case 9 'horizontal tab
Case 10 'LF
temp = temp & vbCrLf
Case 11 'vertical tab
temp = temp & vbCrLf & vbCrLf
Case 12 'form feed
Case 13 'CR
Case 251 'will [option code]
If processCommand Then theCommand = 251
Case 252 'won't [option code]
If processCommand Then theCommand = 252
Case 255 'interpret as command (then one or two chars)
processCommand = True
Case Else
temp = temp & Mid(theText, i, 1)
processCommand = False
theCommand = -1
End Select
Next i
Parse = temp
End Function
- and that works nicely.
I picked up a few RFCs from a friend, so I now know what those byte values above represent, and the select case lets me handle each one rather than just ignoring them all as I was attempting to do previously.
The chr(255) character tells the receiver that the next char should be interpreted as a command (IAC). The chr(251) and (252) are WILL and WON'T commands respectively, which take another parameter -- the command to perform. By the way it's used, I assume the value chr(1) represents Local Echo, which is turned on and off by the WILL and WON'T commands (that's how I'm handling it, at any rate).
I don't have an RFC that defines what the values of this parameter represent though. If anyone has one or knows where to find one...
YourBuddyToo: Interesting to note that one of the clients on that site that supports ANSI colours uses a PictureBox rather than a RichTextBox.
I can't find any documentation for using text inside a PictureBox though, so I'll stick with the RichTextBox. But that's a whole other thread which I'll get to later.
Just a thought - what's the maximum capacity of a RichTextBox? And, how should I go about preventing the box from running out of memory in the middle of an append?
Public Function Parse(ByVal theText As String) As String
Dim temp As String
Dim i As Integer
For i = 1 To Len(theText)
Select Case Asc(Mid(theText, i, 1))
Case 0 'null
Case 1 'local echo option code (I think)
If processCommand Then
If theCommand = 251 Then
localEcho = False
processCommand = False
theCommand = -1
ElseIf theCommand = 252 Then
localEcho = True
processCommand = False
theCommand = -1
End If
End If
Case 7 'beep
Beep
Case 8 'backspace
Case 9 'horizontal tab
Case 10 'LF
temp = temp & vbCrLf
Case 11 'vertical tab
temp = temp & vbCrLf & vbCrLf
Case 12 'form feed
Case 13 'CR
Case 251 'will [option code]
If processCommand Then theCommand = 251
Case 252 'won't [option code]
If processCommand Then theCommand = 252
Case 255 'interpret as command (then one or two chars)
processCommand = True
Case Else
temp = temp & Mid(theText, i, 1)
processCommand = False
theCommand = -1
End Select
Next i
Parse = temp
End Function
- and that works nicely.
I picked up a few RFCs from a friend, so I now know what those byte values above represent, and the select case lets me handle each one rather than just ignoring them all as I was attempting to do previously.
The chr(255) character tells the receiver that the next char should be interpreted as a command (IAC). The chr(251) and (252) are WILL and WON'T commands respectively, which take another parameter -- the command to perform. By the way it's used, I assume the value chr(1) represents Local Echo, which is turned on and off by the WILL and WON'T commands (that's how I'm handling it, at any rate).
I don't have an RFC that defines what the values of this parameter represent though. If anyone has one or knows where to find one...
YourBuddyToo: Interesting to note that one of the clients on that site that supports ANSI colours uses a PictureBox rather than a RichTextBox.
I can't find any documentation for using text inside a PictureBox though, so I'll stick with the RichTextBox. But that's a whole other thread which I'll get to later.
Just a thought - what's the maximum capacity of a RichTextBox? And, how should I go about preventing the box from running out of memory in the middle of an append?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ahh, thanks for that. Useful stuff. :)
Is the Text property of a RichTextBox stored as a String? I was looking through the documentation for the String data type. A fixed length String has a capacity of 64k; a variable-length String has a capacity of 2GB.
If it can hold 20MB, I'm going to hazard a guess that it's stored as a variable-length String and thus has a capacity of 2GB (?).
Is the Text property of a RichTextBox stored as a String? I was looking through the documentation for the String data type. A fixed length String has a capacity of 64k; a variable-length String has a capacity of 2GB.
If it can hold 20MB, I'm going to hazard a guess that it's stored as a variable-length String and thus has a capacity of 2GB (?).
Well, it is not stored as VB variable-length String, that control is certainly not created in VB.
If you have many MB of text, you should not use wrapping and you should not resize control.
Maybe you can test its capacity and tell us what is practical limit :-)
WordPad uses the same control (RichEdit).
MS Word is not very good if document is over 30MB.
Normal textbox can hold 20-30K.
If you have many MB of text, you should not use wrapping and you should not resize control.
Maybe you can test its capacity and tell us what is practical limit :-)
WordPad uses the same control (RichEdit).
MS Word is not very good if document is over 30MB.
Normal textbox can hold 20-30K.
ASKER
sridhar_PJ: go to https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20182221 and collect your points for the code to keep the TextBox scrolled to bottom.
roverm: https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20182223 for the RichTextBox suggestion.
roverm: https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20182223 for the RichTextBox suggestion.
ASKER
ameba: thanks for the general advice. :)
Thank you :)
Thanks !
D'Mzzl!
RoverM
D'Mzzl!
RoverM
ListBox1.AddItem "thenewstring", 0 '0 is the top index
D'Mzzl!
RoverM