Объяснить код

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Объяснить код

Сообщение Don Leno » 05.01.2017 (Чт) 18:16

Выдернул из нета код для работы с Текстбоксом который считает кол-во строк. С кодом проблем нет. Просто хочу разобраться как он работает. Может кто нить сможет прокомментировать что делает код построчно?! Буду очень признателен)))
Вот сам код функции:
Код: Выделить всё
Public Function GetLine(hWnd As Long, Line As Long) As String
Dim sBuf As String, nLen As Long, nIndex As Long
nIndex = SendMessage(hWnd, EM_LINEINDEX, Line - 1, ByVal 0&)
If nIndex < 0 Or Line <= 0 Then Exit Function
nLen = SendMessage(hWnd, EM_LINELENGTH, nIndex, ByVal 0&)
sBuf = Space(nLen + 1)
Mid$(sBuf, 1, 1) = Chr$(nLen And &HFF)
Mid$(sBuf, 2, 1) = Chr$(nLen \ 256)
SendMessage hWnd, EM_GETLINE, Line - 1, ByVal sBuf
GetLine = Left$(sBuf, nLen)
End Function

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

Re: Объяснить код

Сообщение Хакер » 05.01.2017 (Чт) 19:02

Первое, что нужно сделать с этим кодом, это привести его к человеческому виду:
Код: Выделить всё
Public Function GetLine(hWnd As Long, Line As Long) As String
    Dim sBuf As String, nLen As Long, nIndex As Long
    nIndex = SendMessage(hWnd, EM_LINEINDEX, Line - 1, ByVal 0&)
    If nIndex < 0 Or Line <= 0 Then Exit Function
    nLen = SendMessage(hWnd, EM_LINELENGTH, nIndex, ByVal 0&)
    sBuf = Space(nLen + 1)
    Mid$(sBuf, 1, 1) = Chr$(nLen And &HFF)
    Mid$(sBuf, 2, 1) = Chr$(nLen \ 256)
    SendMessage hWnd, EM_GETLINE, Line - 1, ByVal sBuf
    GetLine = Left$(sBuf, nLen)
End Function

Теперь можно начать его читать.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Объяснить код

Сообщение Teranas » 05.01.2017 (Чт) 19:39

Если лень учить «басик», то с этим никто помочь не сможет…
А что касается единственной АПИ функции, то её надо ещё объявить…
Код: Выделить всё
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

PS Использовать АПИ для работы со стандартным текстбоксом не имеет никакого смысла, так как он принимает только 32 кб текста.
Последний раз редактировалось Teranas 05.01.2017 (Чт) 19:55, всего редактировалось 1 раз.
С уважением, Андрей.

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 05.01.2017 (Чт) 19:45

Я же говорю код - вполне работоспособный и мне не нужны объявления Апи и тп. Я лишь прошу объяснить как работает код. А именно хотелось бы понять что делают вот эти три строки:

Код: Выделить всё
Mid$(sBuf, 1, 1) = Chr$(nLen And &HFF)
Mid$(sBuf, 2, 1) = Chr$(nLen \ 256)

и
Код: Выделить всё
GetLine = Left$(sBuf, nLen)


Я знаю что делает эта функция, просто я пытаюсь разобраться как и что делает каждая строчка этого кода!
Кстати, вот исходник полностью:
Вложения
построчно.rar
(1.97 Кб) Скачиваний: 168

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Объяснить код

Сообщение Teranas » 05.01.2017 (Чт) 20:08

Код: Выделить всё
Public Function GetLine(TextB As TextBox, Line As Long) As String
  Dim s() As String
  s() = Split(TextB.Text, vbCrLf)
  GetLine = s(Line - 1)
End Function
С уважением, Андрей.

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 05.01.2017 (Чт) 20:33

Teranas ты приводишь совсем другой код!!!! Проверь мой исходник и свой код и увидишь разницу!!! В тексте нет vbCRLF и твой код вернет весь текст в GetLine!! Мой исходник считывает строку так как она видна в текстовом поле, то есть именно видимую строку текстового поля!!!

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 05.01.2017 (Чт) 20:34

Я натыкался на тысячи таких кодов в нете, пока искал то что мне нужно. Так что твой код мне не в новинку)))

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

Re: Объяснить код

Сообщение Mikle » 05.01.2017 (Чт) 22:23

Don Leno писал(а):хотелось бы понять что делают вот эти три строки:
Mid$(sBuf, 1, 1) = Chr$(nLen And &HFF)
Mid$(sBuf, 2, 1) = Chr$(nLen \ 256)

Переменная nLen, видимо Integer, делится на два байта, младший байт засылается в строку sBuf на место первого символа, старший - на место второго.
Don Leno писал(а):GetLine = Left$(sBuf, nLen)

Строковой переменной GetLine присваивается кусок строки sBuf длиной nLen слева.

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

Re: Объяснить код

Сообщение The trick » 06.01.2017 (Пт) 0:09

Сообщение EM_LINEINDEX возвращает индекс первого символа указанной строки (нумерация строк от 0), в nIndex у тебя будет номер символа.
Сообщение EM_LINELENGTH возвращает длину строки по индексу символа в искомой строке; в nLen - получается длина строки.
Сообщение EM_GETLINE возвращает строку в буфер sBuf. В качестве первого Integer'а (а точнее WORD'а) должна быть указана длина буфера в байтах/символах. Строки с Mid как раз и делают эту операцию (хотя правильнее было передать туда массив). Последний Left не имеет смысла, также нужно выделять буфер просто как nLen символов (т.к. формат строк в VB6 уже подразумевает нуль-терминал).
UA6527P

pronto
Постоялец
Постоялец
 
Сообщения: 597
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Re: Объяснить код

Сообщение pronto » 06.01.2017 (Пт) 7:51

Позвольте немного «чёрной магии» :)
Код: Выделить всё
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal Dest As Long, ByVal Source As Long, ByVal Length As Long)
Private Declare Sub PutMem2 Lib "msvbvm60" (ByVal Addr As Long, ByVal NewVal As Integer)

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal msg As Long, ByVal wp As Long, lp As Any) As Long
Const EM_LINEINDEX = &HBB
Const EM_LINELENGTH = &HC1
Const EM_GETLINE = &HC4

Public Function GetLine(hWnd As Long, Line As Long) As String
   Dim nLen As Long, nIndex As Long
   
   nIndex = SendMessage(hWnd, EM_LINEINDEX, Line - 1, ByVal 0&)
   
   If nIndex < 0 Or Line <= 0 Then Exit Function
   
   nLen = SendMessage(hWnd, EM_LINELENGTH, nIndex, ByVal 0&)
   
   GetLine = Space(nLen)
   
   CopyMemory StrPtr(GetLine), VarPtr(nLen), 2 ' так
   ' PutMem2 StrPtr(GetLine), CInt(nLen)         ' или так
   
   SendMessage hWnd, EM_GETLINE, Line - 1, ByVal GetLine
End Function
O, sancta simplicitas!

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

Re: Объяснить код

Сообщение bon818 » 06.01.2017 (Пт) 8:29

Teranas писал(а):PS Использовать АПИ для работы со стандартным текстбоксом не имеет никакого смысла, так как он принимает только 32 кб текста.

Для WINAPI стандартный vb6-текстбокс, это всего лишь стандартное (ОКНО РЕДАКТИРОВАНИЯ ТЕКСТА), с именем класса EDIT и не имеет ограничений на длину текста и.т.п.
То есть, использовать WINAPI и vb6-текстбокс, можно и нужно.

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 06.01.2017 (Пт) 16:58

Майкл, Трик, Пронто спс вам!!!!!!!)))) Очень помогли!!!
Вот еще вопросы:
Решил проделать тоже самое только с RichTextBox, но в нем вместо строки выходили "иероглифы". Таже строка только неправильно отображалась. В итоге я изменил строку
Код: Выделить всё
Mid$(sBuf, 2, 1) = Chr$(nLen \ 256)

на
Код: Выделить всё
Mid$(sBuf, 2, 1) = Chr$(nLen)

И все заработало! Вопрос что было неправильно?! Почему так происходит? И может там надо по другому код написать?
Ниже исходник:
Вложения
Rich построчно.rar
(2.35 Кб) Скачиваний: 144
Последний раз редактировалось Don Leno 06.01.2017 (Пт) 17:02, всего редактировалось 2 раз(а).

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 06.01.2017 (Пт) 17:00

Кстати, pronto, спасибо за улучшения))) Трик спасибо, за разъяснения по сообщениям!! Макл, а тебе спс за то, что ответил то чего я и ожидал! И всех с новым годом и с возвращением форума Vbstreets!!))))

Don Leno
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 421
Зарегистрирован: 13.10.2013 (Вс) 14:05

Re: Объяснить код

Сообщение Don Leno » 06.01.2017 (Пт) 17:09

А вот с примером pronto через CopyMemory все работает даже и с RichTextBox))))
Переменная nLen, видимо Integer, делится на два байта, младший байт засылается в строку sBuf на место первого символа, старший - на место второго.

По видимому для Ричтекстбокса не надо менять местами младший и старший байты nLen, достаточно просто передать Chr(nLen). Я правильно понимаю?! (всегда путаюсь с младшими и старшими ;) )

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Объяснить код

Сообщение ger_kar » 06.01.2017 (Пт) 18:26

pronto писал(а):Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal Dest As Long, ByVal Source As Long, ByVal Length As Long)
Вот объясните мне почему все используют функцию RtlMoveMemory, вместо RtlCopyMemory. Что это привычка? Или есть какие то особенности о которых я не знаю? Если нужно скопировать блок памяти (именно скопировать, а не переместить) и области явно не пересекаются, то зачем использовать более громоздкую RtlMoveMemory?
Бороться и искать, найти и перепрятать

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

Re: Объяснить код

Сообщение Хакер » 06.01.2017 (Пт) 20:09

ger_kar писал(а):Вот объясните мне почему все используют функцию RtlMoveMemory, вместо RtlCopyMemory. Что это привычка? Или есть какие то особенности о которых я не знаю?

Ты не знаешь, что RtlCopyMemory не существует в виде экспортируемой функции. Не экспортируется такая функция ни kernel32, ни ntdll. Это макрос в виндовых заголовочных файлах для C/C++.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Объяснить код

Сообщение ger_kar » 07.01.2017 (Сб) 13:30

Вот так и знал, что где-то кроется подвох :) Теперь точно знаю где!
Бороться и искать, найти и перепрятать


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

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

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

    TopList