TextBox для вывода логов

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

TextBox для вывода логов

Сообщение sosed213 » 08.06.2021 (Вт) 19:38

Здравствуйте.

Какую стратегию применить чтобы добавлять строки в TextBox, и количество символов или строк не превышало, например, 10000, а верхние (старые) строки удалялись? При этом не должно быть дерганья вертикального ScrollBar.


Теперь объясню.
В своих проектах часто использую процедуру Public Sub PutLog(ByVal intxtLog As String), которая выводит какой то "лог" в TextBox с добавление новых строк.

Раньше я делал так:
Код: Выделить всё
TextBox_Log.Text = TextBox_Log.Text & vbNewLine & intxtLog
TextBox_Log.SelStart = Len(TextBox_Log.Text)


Потом начал делать через API:
Код: Выделить всё
'Добавляю новый лог
txtLen = SendMessage(TextBox_hwnd, WM_GETTEXTLENGTH, 0, 0) + 1
SendMessage TextBox_hwnd, EM_SETSEL, txtLen, txtLen
SendMessage TextBox_hwnd, EM_REPLACESEL, False, ByVal intxtLog

'Удаляю символы сверху
txtLen = SendMessage(TextBox_hwnd, WM_GETTEXTLENGTH, 0, ByVal 0&) + 1
If txtLen > 10000 Then
SendMessage TextBox_hwnd, EM_SETSEL, ByVal CLng(0), ByVal CLng(txtLen - 10000)
'SendMessage TextBox_hwnd, WM_CLEAR, ByVal 0&, ByVal  0&
SendMessage TextBox_hwnd, EM_REPLACESEL, False, ByVal "" ' & vbNewLine
End If


Так вот.
Первое: Почему то, я так и не разобрался, не срабатывает WM_CLEAR, поэтому временно использую EM_REPLACESEL.
Второе: чтобы удалить символы сверху приходится сначала выделить их (EM_SETSEL), и удалить (WM_CLEAR - почему-то не работает, поэтому пока EM_REPLACESEL). Из-за этого происходит дерганье вертикального ScrollBar.

Прошу помощи в этом вопросе. Как выделять текст не по кол-ву символов, а по кол-ву строку (EM_GETLINECOUNT), и удалять текст, чтобы не перемещался фокус вслед за кареткой?
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 09.06.2021 (Ср) 8:00

Видимо WM_CLEAR не имеет никакого отношения к Edit Control.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 09.06.2021 (Ср) 9:57

Ура! Я решил свою задачу.

Решением было запретить\разрешить Redraw тестового поля.
Запретить Redraw:
SendMessageW(TextBox_hwnd, WM_SETREDRAW, ByVal 0&, ByVal 0&

Разрешить Redraw:
SendMessageW(TextBox_hwnd, WM_SETREDRAW, ByVal 1&, ByVal 0&


По поводу ограничения строк, и удаления верхних (старых), тоже разобрался.
Получаем список строк:
SendMessageW(TextBox_hwnd, EM_GETLINECOUNT, 0, ByVal 0&)

Если превышает, например, 1000 строк, выделяем сверху текста лишние строки:
Call SendMessageW(TextBox_hwnd, EM_SETSEL, byval 0&, ByVal LineCount-1000)

И удаляем их, путём замены:
null_str=""
SendMessageW TextBox_hwnd, EM_REPLACESEL, ByVal 0&, ByVal StrPtr(null_str)



Получился такой своеобразный logrotate.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4147
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: TextBox для вывода логов

Сообщение Mikle » 09.06.2021 (Ср) 10:15

Какая разница, напрямую через API, или средствами VB?
Я сделал так:
Код: Выделить всё
Option Explicit

Dim LCnt As Long
Private Const MaxCnt As Long = 64

Private Sub Timer1_Timer()
  AddLog Str(Int(Rnd * 1000000))
End Sub

Private Sub AddLog(s As String)
  Dim i As Long

  LCnt = LCnt + 1
  If LCnt > MaxCnt Then
    i = 1
    While Asc(Mid(txt.Text, i, 1)) <> 13
      i = i + 1
    Wend
    txt.Text = Right(txt.Text, Len(txt.Text) - i - 1) & vbNewLine & s
    LCnt = MaxCnt
  Else
    txt.Text = txt.Text & vbNewLine & s
  End If
  txt.SelStart = Len(txt.Text)
End Sub

Да, скроллбар помаргивает. Потому, что текст перерисовывается, а окно у текста и скроллбара общее. Если поверх скроллбара поместить другой скроллбар, отдельный контрол - он не помаргивает. Осталось скроллбары синхронизировать.

Пока писал - ты написал решение. Про Refresh я подумал сразу, но в стандартных VB методах/свойствах текста этого нет.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4147
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: TextBox для вывода логов

Сообщение Mikle » 09.06.2021 (Ср) 10:19

sosed213 писал(а):И удаляем их, путём замены:
null_str=""

А это не приведёт к накоплению невидимых пустых строк?

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 09.06.2021 (Ср) 10:26

Нет.
Сейчас тестирую, и работает прекрасно)
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: TextBox для вывода логов

Сообщение Хакер » 09.06.2021 (Ср) 11:11

Для подобных логов TextBox просто неподходящий контрол. Я в таком случае делал свой контрол, сверхбыстрый и безглючный. По-моему я где-то выкладывал его уже на форуме.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 09.06.2021 (Ср) 12:59

"Сверхбыстрый" - это важный приоритет. Как показывает тестирование, TextBox плохо справляется.

Хакер, если сможешь вспомнить как он (твой контрол) назывался или может ссылка есть, скинь пожалуйста.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: TextBox для вывода логов

Сообщение Хакер » 09.06.2021 (Ср) 15:59

В общем-то, там не контрол, а отдельная лог-форма. Поэтому и не выкладывал наверное. Устраивает такое решение, возьмёшься переделывать в user-control?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 09.06.2021 (Ср) 16:19

Посмотреть интересно, но боюсь user-control не потяну.

Есть у меня ещё одна идея, может странная немного.
Иметь переменную-массив с основным текстом-лога, а в текст бокс выводить (отрисовывать) по 50 ( в зависимости от высоты текстового объекта) строк из этого массива. А нумерацию строк синхронизировать с отдельным скролл-баром. Тогда не придется "тягать" килограмм текста).

Получится примитивный аналог клиент-серверной модели базы данных.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4147
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: TextBox для вывода логов

Сообщение Mikle » 09.06.2021 (Ср) 16:28

sosed213 писал(а):Иметь переменную-массив с основным текстом-лога, а в текст бокс выводить (отрисовывать) по 50 ( в зависимости от высоты текстового объекта) строк из этого массива. А нумерацию строк синхронизировать с отдельным скролл-баром. Тогда не придется "тягать" килограмм текста

Я бы так и поступил.

The trick
Постоялец
Постоялец
 
Сообщения: 774
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: TextBox для вывода логов

Сообщение The trick » 09.06.2021 (Ср) 17:47

Для реализации лучше всего подойдет ListView со стилем LVS_OWNERDATA.
UA6527P

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 10.06.2021 (Чт) 13:12

"Горшочек вари :D "

Спасибо большое, сегодня почитал, примерно понял что это. Готовых примеров не нашел. Буду пробовать сам делать, и похоже это всё таки будет user-control.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 16.06.2021 (Ср) 19:24

Нашел готовый пример. Мне он показался очень интересным, как и весь репозиторий автора.
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

bon818
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 267
Зарегистрирован: 29.08.2009 (Сб) 4:49
Откуда: Ташкент

Re: TextBox для вывода логов

Сообщение bon818 » 16.06.2021 (Ср) 20:48

sosed213 писал(а):Нашел готовый пример. Мне он показался очень интересным, как и весь репозиторий автора.


Planet-Source-Code - видел спасенные архивы RAR в 7 гегов на Я.Диске, возможно, сейчас и больше.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: TextBox для вывода логов

Сообщение sosed213 » 13.07.2021 (Вт) 11:07

Это оказалось не так просто. За основу взял пример контрола ListView, и попробовал сделать его виртуальным.
Прикладываю пример того что у меня получилось и демонстрацию работы.

Не знаю, так и должно быть, или это косяк, при частом отправке сообщения LVM_SETITEMCOUNT происходит перерисование контрола, и как следствие мерцание.
Вложения
ListView-virtual_20210713_1345.rar
(82.99 Кб) Скачиваний: 70
Не могу сказать что знаю все, но и за дурака прошу меня не считать.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 9

    TopList