Для поиска строки в списке (ListBox) я поступаю так:
Const LB_FINDSTRINGEXACT = &H1A2
Private Declare Function SendMessageByString& Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String).
Все работает отлично. Когда я использую это же для поиска в DataCombo, то ничего у меня не выходит. Наверное, значение константы LB_FINDSTRINGEXACT надо поменять. Подскажите, на что ее заменить (если надо) или расскажите, каким образом найти строку в DataCombo (желательно с помощью API)?
Почему массивы работают быстрее коллекций и занимают меньше памяти?
Вопрос:
Почему массивы работают в десятки раз быстрее коллекций и занимают
меньше места в оперативной памяти.
Использовался VB .NET и коллекция ArrayList.
Ответ:
Не знаю, как обстоят дела в VB .NET, а в 6-ом VB коллекция
представляет собой целый объект. И сама по себе коллекция требует
намного больше памяти, чем массив с таким же типом данных.
И еще. Если обращаешься к элементу коллекции, вызывается несколько
попутных методов. А если ты склепал коллекцию средствами Строителя
Классов, то к этому ненужному обращению добавляется и низкая скорость
работы кода, написанного на VB. Но коллекции имеют одно неоспоримое
преимущество перед массивами - ты можешь в любое место коллекции вставить
элемент, или удалить элемент из любого места. С массивами такой фокус
не проходит. Добавлять элементы можно только в конец, а чтоб добавить
его в середину массива, потребуется сдвинуть все элементы на 1 вниз.
(а если там за 1000 элементов и добавить новый надо именно в
начало?). Такая же ситуация и с удалением из массива.
В общем, для конкретного случая нужно использовать то, что больше
подходит.
Артем Кривокрисенко
Допустим ты создаешь массив лонгов
dim i(30) as long
басик выделяет память mem размером 30*sizeof(long) (=30*4)
когда ты обращаешся допустим к 18-у элементу, то он делает так:
CopyMemory(ret,mem(18*4),4)
mem(18*4) - это начальная позиция откуда он копирует, как вариант, он
может просто вернуть этот адрес без копирования
ret - это то что тебе вернётся
При работе с коллекцией:
происходит работа типа со структурой (внутренняя организация)
struct item
{
lpPrev as long
lpNext as long
lpData as long
}
lpPrev и lpNext это указатели на такие же структуры (выделенные блоки
памяти)
lpData указатель на данные (который as any), откуда они и извлекаются
когда ты к ним обращаешься
Поэтому невозможен быстрый доступ к определённому элементу, как в
массиве, коллекция каждый раз перебирает все элементы пока не дойдёт
до нужного индекса.
Зато возможно удаление даже из середины, когда в элементе i+1 lpPrev
присваивается знаечение lpPrev из i, i-1 lpNext равно lpNext i-го
элемента, при этом освобождается блок памяти по адресу lpData, затем
освобождается блок данных содержащий эти указатели.
Это конечно упрощённый вариант, обычно структура содержит побольше
всяких данных, вплоть до элементов обеспечивающих безошибочный доступ
к данным из нескольких потоков.
Соответственно коллекция занимает больше потому что её приходиться
хранить ещё и структуры с указателями.
Никто не знает код, для шифрования отдельного файла? С использованием
ключей и без Call Crypt(App.path & "\" & "file.txt")
Ответ:
Public Function Encrypt(ByVal Source As String, ByVal Password As String) As String
'шифрование данных
Dim a As String
Dim b As String
Dim c As String
Dim d As String
Dim lentext As Long
Dim lenpass As Long
Dim cn As Long
'ввод исходных данных
'исходный текст для шифрования - запрашивается от пользователя, к примеру -
a = Source
'пароль: может запрашиваться от пользователя
b = Password
'итог шифрования
c = ""
'узнаем длины каждой из строк
lentext = Len(a)
lenpass = Len(b)
'собственно шифрование
For cn = 1 To lentext
'в этой строке разберитесь сами, здесь попросту выполняется функция Xor с каждым
'символом исходной строки и соответствующим символом пароля, как бы "повторенным"
'на всю длину исходного текста. Mid берет из середины строки символ, Asc - превращает
'его в ASCII-код, Str - превращает число в строку, Trim - удаляет пробелы
d = Trim(Str(Asc(Mid(a, cn, 1)) Xor Asc(Mid(b, ((cn - 1) Mod lenpass) + 1, 1))))
'а теперь сделаем так, чтобы каждый символ занимал ровно три позиции, вне зависимости
'от величины его ASCII-кода. А иначе как вы будете потом при расшифровке разбивать
'строку на символы?
Select Case Val(d)
Case 0 To 9
d = "00" + d
Case 10 To 99
d = "0" + d
End Select
c = c + d
'ну вот и все, и так - с каждым символом из исходной строки
Next cn
'в итоге в переменной с - зашифрованная строка, каждой исходной букве соответствует 3
'символа, ее можно записать в любое место - в документ, к примеру:
Encrypt = c
End Function
Public Function Decrypt(ByVal Code As String, ByVal Password As String) As String
'расшифровывание данных
Dim a As String
Dim b As String
Dim c As String
Dim d As String
Dim lentext As Long
Dim lenpass As Long
Dim cn As Long
'строка для расшифровки
c = Code
'пароль
b = Password
'итог расшифровывания
a = ""
'узнаем длины каждой из строк
lentext = Len(c)
lenpass = Len(b)
'собственно расшифровывание
For cn = 1 To lentext Step 3
a = a + Chr(Val(Mid(c, cn, 3)) Xor Asc(Mid(b, (Int(cn / 3) Mod lenpass) + 1, 1)))
Next cn
'в итоге в переменной a - расшифрованная строка, ее можно записать в любое место - в
документ, к примеру:
Decrypt = a
End Function
Private Sub Command1_Click()
Text1 = Encrypt("никому не скажу", "parol")
End Sub
Private Sub Command2_Click()
Text1 = Decrypt(Text1, "parol")
End Sub
'Покажем окно Общего диалога
CD.showopen
'Откроем файл для ввода с номером 1
open CD.filename for input as #1
'Выполняем цикл, пока не достигнем конца файла №1
do while not eof(1)
'Считаем во временную переменную следующую строку.
Line Input #1, strTemp
'Присоединим временную переменную к всей строке. В конце добавим
'символ новой строки.
strAll= strAll & strTemp & vbcrlf
loop
'Обрежем два последних символа (они являются не нужными переносами
'строки)
strAll=left (strall,len(strall)-2
'Закроем файл
Close #1
Как и с помощью каких АПИ создается многоуровневое динамическое меню
Ответ:
В режиме дизайна никакого меню не делаешь.
1. Создаешь верхнеуровневое меню функцией CreateMenu. А потом
цепляешь это меню к форме - SetMenu
2. Далее - CreatePopUpMenu. Создается подменю.
3. Добавляешь это подменю (2) в верхнеуровневое меню (его индентификатор ты
получил в пункте (1)) функцией AppendMenu.
4. Выполняешь пункты 2-3 до тех пор, пока не создащь все подменю.
5. Ты заполнил верхнеуровневое меню элементами подменю. Дальше -
функцией CreatePopUpMenu и AppendMenu создаешь и добавляешь подменю в
созданные подменю. И так, пока не создашь все подменю для существующих
подменю.
Выполняешь пункт 5 для созданных подменю и т.д. Так до тех пор, пока
не создашь всю иерархию. Потом функцией AppendMenu добавляешь
элементы, на которые можно будет нажимать в самые низкоуровневые
подменю.
Естественно, все это Чудо нужно будет субклассить.
Артем Кривокрисенко
Вопрос/Ответ
Здесь Вы можете задать вопрос, или ответить на уже имеющиеся вопросы.
Как узнать программным путем, какие папки в данный момент открыты другими пользователями в сети на моём компьютере, а также узнать список расшаренных ресурсов?
Как при написании своего ActiveX сделать у него свойство (Custom), т.е. чтобы при нажатии на кнопочку "..." вылазила какая-нибудь форма.
Для примера: У PictureBoxa есть свойство Picture при нажатии на него вылазит стандартное окно открытия файла, а мне нужно чтобы вместо него вылазила например form1. Короче, пишу контрол меню. Рассмотрю любые варианты.
1) у меня есть помещеный фаил *.exe в инете вот мне надо на VB.NET указать путь к этому адресу и чтобы узнать версию этого файла (этот фаил написан на VB и указана версия 1.1.0) ...
2) так же в инете выложен и *.txt фаил вот мне надо его скачать и чтобы содержимое этого файла было передено в label1.text