• Welcome to Valhalla Legends Archive.
 

Removing Portions of a RichTextBox

Started by HiVe, April 12, 2003, 02:38 PM

Previous topic - Next topic

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.

Banana fanna fo fanna


rtb.text = right(rtb.text,len(rtb.text) - 1000)


Chances are this post will be ignored just like all my other ones.

HiVe

#2
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 = ""

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.

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.

FyRe

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


Excuse the hugeness.  This doesn't work completely right and I was wondering what I'm doing wrong?

Stealth


           With rtbChat
               .Visible = False
               .SelStart = 0
               .SelLength = InStr(1, .Text, vbLf, vbTextCompare)
               .SelText = ""
               .Visible = True
           End With


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?
- Stealth
Author of StealthBot

K

using LockWindowUpdate() on the handle of the rich text box beforehand and then unlocking it afterwards will also work.

Skywing

#8
Quote from: K on April 16, 2003, 10:29 AM
using LockWindowUpdate() on the handle of the rich text box beforehand and then unlocking it afterwards will also work.
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).

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 ;)
- Stealth
Author of StealthBot

Banana fanna fo fanna

LockWindowUpdate is bad.

It generally makes my screen refresh each time it's called, even when the textbox is not visible.

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.

Stealth

#12
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. :)
- Stealth
Author of StealthBot

dxoigmn

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.
Source: http://www.vbaccelerator.com/codelib/ssubtmr/titlecol.htm