Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/25: Рейтинг темы: голосов - 25, средняя оценка - 4.60
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786

Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?

27.09.2023, 11:31. Показов 7039. Ответов 125

Студворк — интернет-сервис помощи студентам
Всем привет! У меня есть листбокс List1 в VB6 и я пытаюсь добавить в этот список много строк, скажем 10 тысяч строк, но я хочу добавить их таким образом, чтобы они добавились быстро по времени, а не ждать целую секунду... Я этого делать не умею, поэтому помогите пожалуйста! Единственный лайфхак который я нашёл это сначала скрывать список а потом показывать так можно добавить в список много строк в 3 раза быстрее, но для 10 тысяч строк это всё равно занимает целых пол секунды времени...

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const LB_INITSTORAGE = &H1A8
Private Const LB_ADDSTRING = &H180
 
Private Sub Command1_Click()
    Dim i As Integer
    Dim tick As Long
    
    List1.Clear
    tick = GetTickCount
    
    For i = 0 To 10000
        List1.AddItem i
    Next
    Me.Caption = GetTickCount - tick ' 1311 ml
End Sub
 
Private Sub Command2_Click()
    Dim i As Integer
    Dim tick As Long
    
    List1.Clear
    tick = GetTickCount
    
    List1.Visible = False
    
    For i = 0 To 10000
        List1.AddItem i
    Next
    
    List1.Visible = True
    
    Me.Caption = GetTickCount - tick ' 468 ml
End Sub
 
 
Private Sub Command3_Click()
    Dim i As Integer
    Dim tick As Long
    Dim str As String
    Dim hwndList As Long
    
    str = "123"
    hwndList = List1.hwnd
    
    List1.Clear
    tick = GetTickCount
    
    'List1.Visible = False
    
    Debug.Print SendMessage(hwndList, LB_INITSTORAGE, 10001, CLng(LenB(str) * 10001))
    
    For i = 0 To 10000
        SendMessage hwndList, LB_ADDSTRING, 0, StrPtr(str)
    Next
    'List1.Visible = True
    
    Me.Caption = GetTickCount - tick ' 1310 ml
End Sub
Я начал читать в MSDN про сообщение LB_INITSTORAGE но у меня ничего не получилось почему-то всё равно строки в список добавляются очень медленно! Помогите плиз!

Добавлено через 24 минуты
Вопрос: почему не работает сообщение LB_INITSTORAGE?

Добавлено через 24 секунды
Скорость добавления в листбокс никак не изменилась!
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.09.2023, 11:31
Ответы с готовыми решениями:

Как быстро создать список на большое количество элементов?
День добрый! Ищу информацию по такому вопросу. Например, в С++ объявить массив с сотней элементов можно простой строкой. string...

Максимально быстро записать большое количество строк SQLite
Приветствую всех. Думаю из заголовка понятно в чём вопрос как максимально эффективно и быстро записать в таблицу базы данных SQLite большое...

Как сделать так чтобы из продуктов можно было добавить в блюда и это списывалось все на кухне
Как сделать так чтобы из продуктов можно было добавить в блюда и это списывалось все на со склада

125
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.05.2024, 18:59  [ТС]
Студворк — интернет-сервис помощи студентам
testuser2, Без всяких сомнений, конечно, твой проект очень интересный, но я взял на себя смелость протестировать скорость твоего проекта немного изменив код:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Option Explicit
Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExW" (ByVal dwExStyle As Long, ByVal lpClassName As Long, ByVal lpWindowName As Long, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
 
Private Const WS_CHILD          As Long = &H40000000
Private Const WS_VISIBLE        As Long = &H10000000
Private Const ES_AUTOVSCROLL    As Long = &H40&
Private Const WS_EX_CLIENTEDGE  As Long = &H200&
Private Const WS_VSCROLL = &H200000
Private Const WM_SETREDRAW = &HB
Private Const LB_ADDSTRING = &H180
 
Dim hwndListBox As Long
 
Private Sub Command1_Click()
    List1.AddItem "Строка " & List1.ListCount + 1
''    Dim i As Long
''    Dim str As String
''
''    SendMessage hwndListBox, WM_SETREDRAW, 0, 0
''
''    For i = 0 To 9999
''        str = i + 1
''        SendMessage hwndListBox, LB_ADDSTRING, 0, StrPtr(str)
''    Next
''
''    SendMessage hwndListBox, WM_SETREDRAW, 1, 0
End Sub
 
Private Sub Command2_Click()
     Dim itmCnt&
     Dim Tick As Long
     
     Tick = GetTickCount
     itmCnt = CLng(Text1.Text)
     
     If itmCnt Then AddItems itmCnt
     
     Print GetTickCount - Tick
End Sub
 
'Private Sub Form_Load()
'        Dim i&
'        List1.AddItem RandomString(10)
'        For i = 1 To 299
'            List1.AddItem i
'        Next
'    hwndListBox = CreateWindowEx(WS_EX_CLIENTEDGE, StrPtr("LISTBOX"), ByVal 0&, WS_CHILD Or WS_VISIBLE Or WS_VSCROLL Or ES_AUTOVSCROLL, _
'    16, 16, 233, 420, Me.hwnd, 0&, 0&, ByVal 0&)
'End Sub
 
Private Sub List1_Click()
    If Not blAdding Then
    With List1
        MsgBox "Вы выбрали строку № " & .ListIndex + 1 & vbCr & .List(.ListIndex)
    End With
    Else: blAdding = False
    End If
End Sub
Чтобы вывести на экран результат в миллисекундах. И вот что мы видим твоё добавление 10 тысяч строк, твоим методом, занимает больше времени чем у меня! Твой метод ажно целых 140 миллисекунд, а у меня всего за 47!!!

Так и вот у меня вопрос: стоит ли это всё свеч, если в итоге получилось даже медленнее, чем по моей технологии через простые API такие как CreateWindowEx и SendMessage ?
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?   Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.05.2024, 19:05  [ТС]
Приношу извинения, проблема в рандомайзе именно он тут тормозит, убрав рандом получилось в среднем за 32 млск, чуть быстрее, чем у меня всё же значит. Но незначительно.
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.05.2024, 19:07  [ТС]
Но твоя технология ограничевается 32767 строк добавления в листбокс, а я могу хоть сто тысяч добавить.
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.05.2024, 19:11  [ТС]
32767 строки у тебя добавляется тоже за 32 млск, а у меня за 78. у тебя получается всё же чуть-чуть быстрее значит.
Но зато мой код может добавлять больше чем 32767 строк.
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?   Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
1
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
09.05.2024, 19:12
У меня еще медленный join надо учитывать. А так просто интересно было протестировать механизм работы, что будет если писать все напрямую писать в память. Но я ранее подобное уже тестировал в экселе при записи в ячейки и н.др. и там также работало.
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
09.05.2024, 19:20  [ТС]
У майкрософта кстати есть глюк в кодах организации вертикальной полосы прокрутки в листбоксе, когда я добавляю сразу 100 тысяч строк, а потом беру мышкой за ползунок вертикальной полосы прокрутки и прокручиваю до самого низу вниз то прокручивается вниз максимум только до 34464 позиции, понятно что это уже ограничение майкров, это их баг. не рассчитыывали они что в листбокс я буду сто тысяч строк добавлять видимо.

Добавлено через 4 минуты
testuser2, спасибо, так же буду очень благодарен, если ты напишешь этот код, чтобы так же работал и с красивыми стилизованными окнами тоже.
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 04:42
Цитата Сообщение от HackerVlad Посмотреть сообщение
я вот например, посмотрел через мою любимую программу ProcessHacker память твой программки EXE которую ты прислал, я запустил этот твой примерчик в EXE у меня заработал, и посмотрел память нашёл эти строки листбокса. Скрин прилагаю. Напрямую пробовал перезаписывать память через ProcessHacker и действительно строчки меняются
А что это за опция, что-то не могу ее найти? Я сделал думпы обоих прог с манифестом и без, и нашел в обоих этот буфер, где строки идут через нуль, так что есть над чем поработать.
Дампы примерно одинаковые по размеру получаются.
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
1
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 13:19
Сделал вариант для патченного манифестом эксешника. С манифестом заголовочная структура листбокса чуть отличается, она имеет размер 188 (против 216 без мф), и смещение указателя буфера в ней 44 (против 48 без мф)
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Type ListBoxHeader 'без манифеста
    la1(7) As Long
    itmCnt As Long
    maxCnt As Long
    pMrk As Long
    unuse11 As Long
    pBuf As Long
    unuse13 As Long
    szBufMax As Long
    szBuf As Long
    'la2(37) As Long
End Typ
Type ListBoxHeader 'с манифестом
    la1(7) As Long
    itmCnt As Long
    maxCnt As Long
    pMrk As Long
    pBuf As Long
    szBufMax As Long
    szBuf As Long
'    la2(32) As Long
End Type
Вложения
Тип файла: zip Patched.zip (16.9 Кб, 2 просмотров)
1
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 13:36
лол, не знал, что можно выбрать свой ответ в каестве лучшего, я не специально, просто эксперимент ))
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 17:30  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
можно выбрать свой ответ в каестве лучшего
можно только в чужих темах. пометь пожалуйста мой ответ №72 тоже как решение, пожалуйста, вот Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?

Добавлено через 6 минут
Цитата Сообщение от testuser2 Посмотреть сообщение
Сделал вариант для патченного манифестом эксешника
Да, видно ты очень старался, даже снял ограничение в 32767 строк
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 17:48
Цитата Сообщение от HackerVlad Посмотреть сообщение
Да, видно ты очень старался, даже снял ограничение в 32767 строк
Ни снимал, оно есть, там после него глюк идет с обратной нумерацией. Как я понимаю этот глюк связан внутренней работой методов, возвращающих индекс
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 17:55  [ТС]
testuser2, да это в стандартном VB'шном листбоксе так, скорее всего, по хорошему надо создавать ListBox через API. Но скорее всего, что там опять будет другая структура памяти в АПИшном листбоксе и твои коды уже не будут работать. Этот стандартный листбокс ВБшный не поддерживает юникод, к сожалению, поэтому лучше всего API'шный конечно...

Добавлено через 1 минуту
Но с другой стороны, юникодные символы можно нарисовать самому, даже в стандартном VB'шном ансишном листбоксе, через субклассирование и пользовательскую отрисовку листбокса...

Добавлено через 2 минуты
Но стандартный VB'шный листбокс не получает правильные индексы после 32767 строки, а так же не имеет возможности отключения перерисовки почему-то, то есть минусов хватает...
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 17:56
С другой стороны, там если строго идет обратная нумерация, то можно по ней вычислять правильное значение индекса. Наверное во внутреннем алгоритме там используются беззнаковые инты а в vb-шном лонге они интерпретируются неправильно после определенного значения
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 18:06  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
А что это за опция, что-то не могу ее найти? Я сделал думпы
Какая опция? Чтобы найти нужное содержимое памяти программы дамп создавать не надо

Добавлено через 2 минуты
Цитата Сообщение от testuser2 Посмотреть сообщение
С другой стороны, там если строго идет обратная нумерация, то можно по ней вычислять правильное значение индекса.
VB6 создавался во времена Windows 98, который не поддерживал листбоксы более 32768 строк, они тогда на то время и понятия не имели, что в будущем Windows сможет начать поддерживать более большие листбоксы с гораздо большим количеством строк. В VB6 чётко используется однобайтный Integer для опредения нумерации строк.

Добавлено через 58 секунд
Индекс листбокса в правильном значении, я думаю, можно будет легко получить через API

Добавлено через 6 минут
testuser2, ну ты сам же это можешь легко увидеть ну. В VB работать не будет, только в EXE, так как ты откомпилировал EXE с галочкой "Remove Integer Overflow Checks" которая обозначает пропускать ошибки если Integer вдруг будет больше чем 32767
0
1402 / 860 / 93
Регистрация: 08.02.2017
Сообщений: 3,673
Записей в блоге: 2
10.05.2024, 18:39
Вот так будет вычисляться правильный индекс. В коде формы:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Option Explicit
 
Private Sub Command1_Click()
    Dim ind&
    ind = List1.ListCount
    If ind < 0 Then ind = &H8000& * 2 + ind
    List1.AddItem "Строка " & ind + 1 'List1.ListCount + 1
End Sub
 
Private Sub Command2_Click()
     Dim itmCnt&
     itmCnt = CLng(Text1.Text)
     If itmCnt Then AddItems itmCnt
End Sub
 
Private Sub List1_Click()
    Dim ind&
    
    With List1
        ind = .ListIndex
        If ind < 0 Then ind = &H8000& * 2 + ind
        MsgBox "Вы выбрали строку № " & ind + 1 & vbCr & .List(.ListIndex)
    End With
End Sub
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 19:13  [ТС]
testuser2, спасибо но это скорее всего только до 65535 строки, а потом правильно получиться вычислить уже только через API

Добавлено через 3 минуты
Да, как я и думал, 65536 последняя строка которую правильно вычислит это одно-байтная технология. Только через API дальше можно вычислять.

Добавлено через 28 минут
testuser2, молодец, что придумал новый улучшенный код обновления листбокса! мне это понравилось! но лучше всё равно написать oList.TopIndex = 0 вместо oList.TopIndex = 1
0
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 21:43  [ТС]
testuser2, знаешь я тебе очень благодарен за твои труды и поэтому я решил не полениться и сделать подбробную инструкцию в картинках Как посмотреть память процесса и найти нужные строковые значения в памяти процесса в программе Process Hacker при этом не копаясь сразу во всём дампе. Там же можно и менять прямо напрямую эти значения в памяти. Это удобно ковыряться и смотреть память. Может ты там сможешь и структуру листбокса рассмотреть.
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?   Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?   Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  

Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?   Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 21:46  [ТС]
На втором экране нужно будет ввести минимальное количество символов для поиска строки. Можно ввести например длину символов той строки которую ты будешь искать. Результат будет вот таким что ты сможешь точно увидеть все эти строки листбокса.
Миниатюры
Как добавить в список ListBox большое количество строк, чтобы это было быстро по времени?  
1
Вернулся
 Аватар для HackerVlad
1748 / 644 / 45
Регистрация: 10.09.2021
Сообщений: 2,786
10.05.2024, 21:58  [ТС]
testuser2, теперь ты тоже хакер) ты взломал память процесса и напрямую записал целлый массив строк листбокса, даже The Trick такое не сделал))))

Добавлено через 58 секунд
testuser2, мне интересен изначальный алгоритм поиска. Что ты ищешь в самом начале? Как ты определил заголовочную структуру листбокса? Как понял куда нужно записывать количество строк?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.05.2024, 21:58

Вывести файл на экран, чтобы в каждой строке было не больше 40 символов, и количество строк было минимальным
Дано файл f. Вывести этот файл на экран так что бы в каждой строчке было не больше, чем 40 символов и количество строк было минимальным.

Как исправить, чтобы количество столбцов и строк StringGrid было таким, как ввел пользователь
Подскажите, в чем дело, программа создает двумерный массив элементы которого вводят с клавиатуры, ввод осуществляется в stringGrid. При...

Как добавить значения с Листа в Listbox, если количество строк может меняться
Есть Лист с уже заданными значениями, но они могут изменяться (добавляться, удаляться). Нужно добавить этот столбец в Listbox. Помогите...

Как сделать так,чтобы количество строк и столбцов массива можно было менять через меню?
как сделать так,чтобы количество строк (n) и столбцов(m) массива можно было менять через меню? весь код #include...

Поиск минимального времени выполнения теста, чтобы количество набранных баллов было максимальным
Здравствуйте! Подскажите пожалуйста, в чем ошиблась у меня массив Examen структур с данными о номере Nomer. Для каждого номера дано время...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
120
Ответ Создать тему
Новые блоги и статьи
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru