Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB .NET > Rich Text Box


Автор: YoD 20.12.2004, 13:05
Подскажите пожалуйста, как в элементе упраления RichTextBox можно целиком выделить строчку, зная только её номер? А то метод Select требует указание начальной и конечной позиции выделения, как получить начальную и конечную позицию в текстбоксе нужной мне строки, я тоже не знаю...

Автор: -Mikle- 21.12.2004, 23:05
Можно получить номер строки, зная номер символа.

Код

LineNum = rtf.GetLineFromCharIndex(10)


В LineNum будет записан номер строки в которой находится 10-ый символ.
rtf - это имя RichTextBox'a

Тебе это подходит?

Автор: YoD 22.12.2004, 12:18
Спасибо, почти подходит. А как теперь зная номер строки выделить её?

Автор: -Mikle- 23.12.2004, 23:06
Есть одно предложение, организовать поиск в цикле, но для больших текстов, порядка 1Мб, наверное этот метод медленно будет работать.

На скорую руку примерно так:

Код
Sub SelectLineByNumer(ByVal rtfSrc As RichTextBox, ByVal NumLine As Integer)
   Dim i, n, p1, p2 As Integer
   Dim ln As Integer = rtfSrc.TextLength
   
   p1 = ln : p2 = ln
   For i = 0 To ln
       n = rtfSrc.GetLineFromCharIndex(i)
       If n = NumLine And p1 = ln Then p1 = i
       If n > NumLine Then p2 = i : Exit For
   Next

   rtfSrc.Select(p1, p2 - p1)
   rtfSrc.Focus()
End Sub

Вызывать так: SelectLineByNumer(rtfTestBox, 0) 'Выделить первую строку

Процедура пробежит по всему тексту, узнавая номер строки каждого символа, и запомнит индекс первого символа с искомым номером строки в переменной p1, и индекс последнего символа в p2. Во избежании ошибок, например при поиске не существующей строки, перед циклом переменные p1 и p2 инициализируются, указывая на конец текста.
Это не совсем красиво, но боюсь что единственный вариант. Для большого объема текста, целесообразно будет вначале сделать пару не точных поисков номера строки, и потом выполнить написанный выше цикл начиная не с нуля, а с приблизительно найденного индекса.

В другом случае, если требуется выделить строку в которой находится символ с известным индексом(например строку, в которой находится каретка), можно воспользоваться вот этим кодом:

Код
Sub SelectLineByCharIndex(ByVal rtfSrc As RichTextBox, ByVal CharIndex As Integer)
   Dim i, n, p1, p2 As Integer
   Dim ln As Integer = rtfSrc.TextLength

   p1 = 0 : p2 = ln
   n=rtfSrc.GetLineFromCharIndex(CharIndex)
   For i = CharIndex To 0 Step -1
       If rtfSrc.GetLineFromCharIndex(i) < n Then
           p1 = i + 1
           Exit For
       End If
   Next
   For i = CharIndex To ln
       If rtfSrc.GetLineFromCharIndex(i) > n Then
           p2 = i
           Exit For
       End If
   Next

   rtfSrc.Select(p1, p2 - p1)
   rtfSrc.Focus()
End Sub


Вызвать например так: SelectLineByCharIndex(rtf, rtf.SelectionStart) 'Выделит строку в которой находится курсор

Процедура запомнит в n номер строки в которой находится символ с индексом CharIndex. Затем в первом цикле, перебирая символы от CharIndex в сторону начала, запомнит в p1 индекс первого символа строки с номером n, а во втором цикле, перебирая символы от CharIndex в сторону конца текста, запомнит в p2 индекс последнего символа. На случай если в теле одного или обоих циклов не выполнится условие, перед циклами выполняется инициализация переменных p1 = 0 и p2 = ln(ln - длина текста). Впрочем p1 и так равна нулю, но для наглядности я все же написал инициализацию для нее. И еще можно обойтись без переменной i, указав вместо нее в первом цикле p1, а во втором - p2, но опять таки для большей наглядности не стал этого делать.

Удачи! Приходи еще smile

Автор: YoD 24.12.2004, 04:49
Спасибо за за информацию. Приду ещё smile

Автор: DarkDragon 19.8.2006, 18:29
О да!!! такой код только на шестисотый пентиум с 80Ghz и памятью 8 гб, и 128 разрядный процессор. А можно и на папиновом серваке.smile Не обижайтесь. Только такие вещи делают через API.


Public Declare Auto Function SendMessage Lib "User32" (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const EM_LINEINDEX As Short = &HBBS
Private Const EM_LINELENGTH As Short = &HC1S

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim intsl As Integer = RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart)
        Dim linelen = SendMessage(RichTextBox1.Handle.ToInt32, EM_LINELENGTH, RichTextBox1.SelectionStart, 0)
        Dim linestart = SendMessage(RichTextBox1.Handle.ToInt32, EM_LINEINDEX, intsl, 0)
        RichTextBox1.Select(linestart, linelen)
    End Sub


У ричтекст бокса поставь HideSelection = Flase.
Когда нажмешь на кнопку он выделит ту линию на каторой находится каретка (не важна где, важна на какой линии).
переменная intsl = это номер строки

вот то что тебе нужно. Работает быстро и все как надо(через АПИ, шустрые прогги получаются)!!! 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)