Valhalla Legends Forums Archive | Battle.net Bot Development | Removing Portions of a RichTextBox

AuthorMessageTime
HiVe
I'm currently making a bot for chatting purposes and I'd like to know how to remove just certain sections from a richtextbox. Like if the richtextbox has 5000 or more characters, delete the first 1000 that would be at the top. If someone could help me I'd really appreciate it. Thanks. :-\

I know this is possible. It's present in bots such as Prophecy Chat and Shadow Chat.
April 12, 2003, 7:38 PM
St0rm.iD
[code]
rtb.text = right(rtb.text,len(rtb.text) - 1000)
[/code]

Chances are this post will be ignored just like all my other ones.
April 12, 2003, 11:18 PM
HiVe
Ugh thanks anyway, st0rm, but I found my own way to do it before you made the post.

If Len(frmMain.txtRecieve.text) >= 9000 Then
frmMain.txtRecieve.SelStart = 0
frmMain.txtRecieve.SelLength = 1000
frmMain.txtRecieve.SelText = ""
frmMain.txtRecieve.SelStart = Len(frmMain.txtRecieve.text)
frmMain.txtRecieve.SelLength = 0
frmMain.txtRecieve.SelText = ""
April 12, 2003, 11:28 PM
Spht
Instead of counting the characters in the text object, I suggest using the EM_GETLINECOUNT message to get the amount of lines there are. Then if that number exceeds the limit you want set, remove the top line (search for nearest vbCrLf from beginning of text object). Using your method, you'd end up removing more than one line from the top, and in most cases the resulting top line will be truncated.
April 13, 2003, 12:25 AM
Grok
Use SELTEXT instead of TEXT property when possible. It is much faster. I tested a loop of 5000 new lines to an RTB. Using RTB.Text = RTB.Text & "**********" & vbCrlf it took 139 seconds. Using RTB.SelStart = Len(RTB.Text)+1: RTB.SelText = "**************" & vbCrlf took only 36 seconds on my slow 733mhz computer. The point being the speed differential shows the faster method for adding text, when not using API directly.
April 14, 2003, 12:56 AM
FyRe
[code]Private Sub rtbChat_Change()
On Local Error Resume Next
'If Len(frmMain.rtbChat.text) >= 1000 Then
' Do Until Len(frmMain.rtbChat.text) < 1000
' frmMain.rtbChat.text = Mid(frmMain.rtbChat.text, InStr(frmMain.rtbChat.text, vbCrLf))
' Loop
'End If
Dim lngLineIndex As Long
lngLineIndex = GetLineFromChar(frmMain.rtbChat.SelStart)
DelLine GetLineFromChar(lngLineIndex)
End Sub

Public Function GetCharFromLine(LineIndex As Long)
'Returns the index of the first character of the line
'check if LineIndex is valid
Dim LineCount As Long
LineCount = SendMessage(frmMain.rtbChat.hwnd, _
EM_GETLINECOUNT, _
0&, _
ByVal 0&)
If LineIndex < LineCount Then
GetCharFromLine = SendMessage(frmMain.rtbChat.hwnd, EM_LINEINDEX, LineIndex, 0&)
End If
End Function
Public Function LineLen(CharPos As Long)
'Returns the number of character of the line that
'contains the character position specified by CharPos
LineLen = SendMessage(frmMain.rtbChat.hwnd, EM_LINELENGTH, CharPos, 0&)
End Function
Public Function TopLine() As Long
'Returns the zero based line index of the first
'visible line in a multiline textbox.
'Or the position of the first visible character
'in a none multiline textbox
TopLine = SendMessage(frmMain.rtbChat.hwnd, EM_GETFIRSTVISIBLELINE, 0&, 0&)
End Function
Public Function GetLineFromChar(CharPos As Long) As Long
'Returns the zero based line number of the line
'that contains the specified character index
GetLineFromChar = SendMessage(frmMain.rtbChat.hwnd, EM_LINEFROMCHAR, CharPos, 0&)
End Function
Public Function LineCount() As Long
'Returns the number of lines in the textbox
LineCount = SendMessage(frmMain.rtbChat.hwnd, EM_GETLINECOUNT, 0&, 0&)
End Function
Public Sub DelLine(LineIndex As Long)
'Deletes the specified line from the textbox
Dim lngSelStart As Long 'used to save the caret position
Dim lngLineLen As Long 'the length of the line to delete
Dim lngCharPos As Long 'the index of the first character on the line

If LineCount < 10 Then Exit Sub
If LineCount = 0 Then Exit Sub
If LineIndex >= LineCount Then Exit Sub
lngSelStart = frmMain.rtbChat.SelStart
lngCharPos = GetCharFromLine(LineIndex)
lngLineLen = LineLen(lngCharPos)
frmMain.rtbChat = Left$(frmMain.rtbChat, lngCharPos) & Mid$(frmMain.rtbChat, lngCharPos + lngLineLen + 1)
frmMain.rtbChat.SelStart = lngSelStart
frmMain.rtbChat.SelLength = 0
frmMain.rtbChat.SelText = ""
End Sub

'Below Declarations are located in modDeclares Module
'RTBSize
Public Const EM_CANUNDO = &HC6
Public Const EM_GETFIRSTVISIBLELINE = &HCE
Public Const EM_GETLINE = &HC4
Public Const EM_GETLINECOUNT = &HBA
Public Const EM_GETMODIFY = &HB8
Public Const EM_LINEFROMCHAR = &HC9
Public Const EM_LINEINDEX = &HBB
Public Const EM_LINELENGTH = &HC1
Public Const EM_SETMODIFY = &HB9
Public Const EM_UNDO = &HC7
[/code]

Excuse the hugeness. This doesn't work completely right and I was wondering what I'm doing wrong?
April 16, 2003, 7:11 AM
Stealth
[code]
With rtbChat
.Visible = False
.SelStart = 0
.SelLength = InStr(1, .Text, vbLf, vbTextCompare)
.SelText = ""
.Visible = True
End With
[/code]

Nice and simple, and it works. Testing found the rtb tended to flicker as it removed the top line, and so after a bit of random screwing-around-with-things I found that making it invisible before making the change prevents flickers.

To the gurus, any noticeable problem(s) with this method?
April 16, 2003, 7:33 AM
K
using LockWindowUpdate() on the handle of the rich text box beforehand and then unlocking it afterwards will also work.
April 16, 2003, 3:29 PM
Skywing
[quote author=K link=board=17;threadid=1021;start=0#msg7954 date=1050506999]
using LockWindowUpdate() on the handle of the rich text box beforehand and then unlocking it afterwards will also work.
[/quote]Yes, I pointed this out in the channel yesterday when we were discussing this. I'm assuming setting/unsetting the Visible property in VB simply sets or clears the WS_VISIBLE bit; doing this may result in the RichEdit having to be completely repainted afterwards; LockWindowUpdate works quite differently.

You might try both methods to see which works best (i.e. doesn't cause noticible flickering after unlocking or setting the visible style).
April 16, 2003, 4:53 PM
Stealth
Testing with LockWindowUpdate reveals that it appears to work equally as well as setting visibility. I'm sticking with the API - chances are it's more efficient than using a VB built-in property ;)
April 16, 2003, 6:35 PM
St0rm.iD
LockWindowUpdate is bad.

It generally makes my screen refresh each time it's called, even when the textbox is not visible.
April 16, 2003, 10:48 PM
Camel
sure, lockwindowupdate isn't _perfect_, but it's a hell of a lot better than any other method i've seen. i even use it for my resize code, and i have no noticable flicker.
April 17, 2003, 5:49 AM
Stealth
My testing was done with the character-length cutoff at something like 2,000. Today, after setting the limit back to 17,000 where I originally had it, I began noticing a very annoying refreshing of my desktop.. I run roughly 4 stealthbots 24/7. The flickering was indeed directly tied to new messages being displayed in the bots, and occurred more drastically when they were minimized to the tray.

I switched back to the .Visible method, with no noticeable desktop or RTB flickering. :)
April 17, 2003, 7:34 AM
kamakazie
I don't know if this is the problem but I found this:

[quote]
LockWindowUpdate is an excellent call in that it completely stops window repainting and thereby speeds things up and stops distracting flicker. But you have to be careful when using it. If you cover or expose any area of another window whilst LockWindowUpdate is on, as soon as you turn it off again the entire desktop repaints, this is very slow, and causes probably worse flickering than if it wasn't turned on in the first place! So when using LockWindowUpdate, ensure you apply it to a window that does not change size or move. Often the parent window is a better choice than the window being updated.
[/quote]
Source: http://www.vbaccelerator.com/codelib/ssubtmr/titlecol.htm
April 20, 2003, 4:52 AM

Search