Best component for a text window?
|
|
Thread rating:  |
Brian - 31 Oct 2004 05:02 GMT I'm converting a text game to Visual Basic. My problem is finding a suitable component (listbox, textbox, labelbox etc so In can display text line by line.
Example TEXT1.TEXT="FIRST LINE OF TEXT TEXT1.TEXT="SECOND LINE OF TEXT
When I run the program only the words "SECOND LINE OF TEXT" is displayed.
The game requires that text be displayed to the player each time the player makes a move. Some of the text could be several lines long. When the text window is full then new text causes the old text to move up (scolling).
Hoping for a reply.
Regards Brian
Steve Gerrard - 31 Oct 2004 05:27 GMT | I'm converting a text game to Visual Basic. | My problem is finding a suitable component (listbox, textbox, labelbox [quoted text clipped - 6 lines] | When I run the program only the words "SECOND LINE OF TEXT" is | displayed. Your second line of code in effect says: I want to replace whatever is in Text1.Text at the moment with the string "Second Line of Text", which is just what happens.
You have several choices. For a text box, be sure it has MultiLine = True, and ScrollBars = 2 Vertical. Then you can write Text1.Text = Text1.Text & vbNewLine & "Next Line of Text"
For your purposes, a better approach might be Text.SelStart = Len(Text1.Text) which positions the caret at the end of existing text, followed by Text.SelText = vbNewLine & "Next Line of Text" This method saves building an intermediate string.
You could also use a list box, although it doesn't have wrapping of long lines, with something like List1.AddItem "Next Line of Text" List1.ListIndex = List1.NewIndex where the second line keeps the last item scrolled into view.
Is it Adventure, by any chance? "You are in a darkened cave. Passages lead north and east. There is a stream nearby." Ahh, those were the days...
Brian - 31 Oct 2004 06:04 GMT >| I'm converting a text game to Visual Basic. >| My problem is finding a suitable component (listbox, textbox, labelbox [quoted text clipped - 32 lines] >lead north and east. There is a stream nearby." Ahh, those were the >days... Thanks Steve for your help and the example code. Yes it is an adventure program that I'm converting for a friend. It was originally written in BASIC and run in a DOS environment so there was no problem with the scrolling text. I have temp used a listbox but will consider your suggestions.
Regards Brian
Frank Adam - 31 Oct 2004 05:44 GMT >I'm converting a text game to Visual Basic. >My problem is finding a suitable component (listbox, textbox, labelbox [quoted text clipped - 6 lines] >When I run the program only the words "SECOND LINE OF TEXT" is >displayed. That's because you are replacing the text in the window. With a textbox, the correct way is to set it's "Multiline" property to True and then:
text1.text = "FIRST LINE OF TEXT" text1.text = Text1.text & vbCrLf & "SECOND LINE OF TEXT" & vbCrLF
The first line would be a one off. After that, all subsequent lines have to be added as the second line shows. As a matter of fact the first line is actually redundant in a real application, as you would reset the textbox with 'text1.text = ""' when starting a new game.
>The game requires that text be displayed to the player each time the >player makes a move. Some of the text could be several lines long. >When the text window is full then new text causes the old text to move >up (scolling). You'll have to think about how long this game goes for. The standard textbox for instance have a limit of about 32,000 characters, so if your game may display more than that, you have to look at using a RichTextBox instead, which has virtually no limit, it also has some nice features like colored, bold, italic or underlined text, which you may find quite useful especially in a game.
However, with both boxes, adding a string to the end of your textbox with the classic VB method as shown above, requires that VB reads in the old text, appends the new line(s) and then reassigns the lot back to the textbox. This will be ok for a while, but after a few hundred lines of text is displayed, it will slow down your application quite noticably.
A quicker method is to use the Win32 APIs or even the control's built in selstart and seltext properties. This also ensures that the box will be scrolled near the end of the text at all times. Your code then would change as such. Note this works for both the RTB and the standard texbox(when set to multiline), but i do recommend that you use the RTB.
Private sub AddText(sLines as string) rtb.selstart = len(rtb.text) 'set caret at end of text rtb.seltext = sLines ' add text. End Sub
And you'd call that with something like this. Call AddText "First line" & vbCrLf & "Second Line" & vbCrLf
And in case you want to get a bit fancy<g>, this is only for the RTB :
Private Sub AddText(sLines as String, optional color as long = -1, optional isBold As Boolean = False) rtb.selstart = len(text1.text) 'set caret at end of text if color <> -1 then rtb.selcolor = color rtb.selbold = isBold rtb.seltext = sLines ' add text. End Sub
Call it with : AddText "hello world" & vbCrLf, vbBlue, False AddText "Hello world" & vbCrLf, vbBlue, True Addtext "Hello world" & vbCrLf, vbYellow, True etc..
HTH :)
 Signature
Regards, Frank
Brian - 31 Oct 2004 06:12 GMT >>I'm converting a text game to Visual Basic. >>My problem is finding a suitable component (listbox, textbox, labelbox [quoted text clipped - 71 lines] >HTH :) > Thanks for your help and suggestions Frank.
As the text box is going to display a lot of text then having a limited size for the textbox could be a problem. I might consider a richtext box as you suggested. I was trying to avoid extra DLL files that would be needed but looks like I'll need them in the end if I'm to use a non standard (Rich Text Box) component. I'm temporary using a listbox but if I lot of text is displayed then I might have a memory problem. The user is not likely to want to scroll back to the beginning so I might be able to write a routine that deletes some of the earlier text. If using a RichText box can there be a limit on how much text is kept to overcome any out of memory problem?
Thanks for the example code Regards Brian
Frank Adam - 31 Oct 2004 07:24 GMT >I'm temporary using a listbox but if I lot of text is displayed then I >might have a memory problem. The user is not likely to want to scroll The Listbox will kill over at around 32Ks too. VB is stuck in it's 16 bit days with standard controls. :-/
>back to the beginning so I might be able to write a routine that >deletes some of the earlier text. Yes, you can do that, again the fast way would be to use the SelStart and SelLength properties. Perhaps :
if Len(rtb.text) > 30,000 then 'characters rtb.selstart = 0 'position to start rtb.sellength = 15,000 'length to about half way rtb.seltext = "" ' clear it. Perhaps do a refresh here. rtb.selstart = len(rtb.text) 'reposition to end endif
There are ways of counting and chopping on number of lines, but then you have to start using the APIs.
>If using a RichText box can there be a limit on how much text is kept >to overcome any out of memory problem? Using the above should take care of it, but as i recall, the RTB's limit is only limited by the system's memory. So i think holding in the vicinity of 5-10Megs is not going to be a problem on even the less than average machines.
Another option of course is to use a picture box and VB's Print or the APIs to draw the text. This being low level, does require a fair bit more to do like maintaining your own text buffer, providing for scrolling manually, working out where to wrap words, etc... but it does put all limitations in your hands and allows you to omit the RichText OCX.
For instance you can have something like this :
dim row as long row = 0 with picture1 .cls .font = "times new roman" .currentX = 1 .currentY = row * .textheight("Z") picture1.print "Hello world" .currentX = 1 row = row + 1 .currentY = row * .textheight("Z") picture1.print "New line" end with
That should print neatly one line under the other, but as you can see, you'd have to track the 'row' at least and you'd also have to know the maximum lines that you can display before running off the bottom. Then when you'd hit 'maxlines', you'd have to redraw the whole text starting from the (stored) last offset of the buffer's lines + 1. And of course wrapping on the right side will make all that just a little more complicated again. It's not horribly difficult though, but obviously more so than using a rich text box. If you opt for this, there are plenty of guys here who can help you to get that working quite well.
 Signature Regards, Frank
Steve Gerrard - 31 Oct 2004 07:28 GMT | >You'll have to think about how long this game goes for. The standard | >textbox for instance have a limit of about 32,000 characters, so if | >your game may display more than that, you have to look at using a | >RichTextBox instead, which has virtually no limit, it also has some | >nice features like colored, bold, italic or underlined text, which you | >may find quite useful especially in a game.
| Thanks for your help and suggestions Frank. | [quoted text clipped - 4 lines] | like I'll need them in the end if I'm to use a non standard (Rich Text | Box) component. Here is a bit of extra code that will maintain a maximum length limit on the text in either a regular or rich text box, shown here with a regular text box.
I wouldn't worry too much about adding the ocx file for the rich textbox, it doesn't seem to be one of the pesky ones as far as I know. It does have some nice features; for instance, I just noticed it has a SelProtected property that allows you to prevent editing of some text while allowing editing of other text.
Private Sub Command1_Click() Static N As Long 'for testing Const MaxLen = 300 'short for testing Dim J As Long
' dummy text N = N + 1 Text1.SelStart = Len(Text1.Text) Text1.SelText = vbCrLf & "test line #" & N
' check length While Len(Text1.Text) > MaxLen J = InStr(1, Text1.Text, vbCrLf) If J > 0 Then ' clip off the first line of text Text1.Text = Mid$(Text1.Text, J + Len(vbCrLf)) End If Wend
' scroll last line into view Text1.SelStart = Len(Text1.Text)
End Sub
|
|
|