
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.164] |
![]() |
|
![]() |
|
|
Всем привет.
Хочу разъяснить что такое строка в Visual Basic и как она работает. Как извесно, строки в VB хранятся в виде BSTR (о том что это, подробно написал ANDLL здесь) Формат весьма универсальный. Однако это не единственная фишка VB в строках. Если быть внимательным, то можно заметить, что для получения адресов переменных используется функция VarPtr, но только не для строковых. Для них испольуется StrPtr. Возникает 2 резонных вопроса: почему отдельная функция? и почему StrPtr и VarPtr возвращают разные знания? Всё дело в том, что строка в VB это всего-лишь 4 байта, являющиеся указателем на BSTR строку, причём не на её начало, а на данные (тоесть начало BSTR строки + 4 байта)! Вот так всё просто и универсально. Функция VarPtr возвращает адрес ячейки памяти, где лежит адрес BSTR строки + 4, а функция StrPtr возвращает число из этой ячейки. Да и функции StrPtr физически не существует ![]() На рисунке сделал визуализацияю для упрощения понимания ![]() Кстати появляется возможность быстрого "копирования" строки или создания строк, данные в которых будут общими. Прикреплённая картинка
|
Сообщ.
#2
,
|
|
|
Цитата Итак, первый тип, BSTR(именно он использовуется в переменных типа String в VB6) - строка из unicode-символов, которая кончается двухбайтовым терминатором и перед которой стоит ее длина. Ввиду того, что сама строка содержит свою длину она может содержать произвольные символы. Во второй тип, ABSTR, VB преобразует строки перед тем как передать их в API-функции. Этот тип отличается от BSTR тем, что содержит однобайтовые символы, вместо двухбайтовых. Тогда вопрос: почему по умолчанию (тоесть в АПИ-вьювере) используются только *А функции (то есть принимающие строки в кодировке ASCII)? Если строки в VB изначально хранятся в Unicode формате, то не разумнее ли было бы использовать *W функции, опуская тем самым преобразование Unicode->ASCII (BSTR->ABSTR)? Поправьте меня если я что-то не так понял |
Сообщ.
#3
,
|
|
|
тривиальный тест:
![]() ![]() Option Explicit Private Declare Function GetTickCount& Lib "kernel32" () Const DC_ACTIVE = &H1 Const DC_NOTACTIVE = &H2 Const DC_ICON = &H4 Const DC_TEXT = &H8 Const BDR_SUNKENOUTER = &H2 Const BDR_RAISEDINNER = &H4 Const EDGE_ETCHED = (BDR_SUNKENOUTER Or BDR_RAISEDINNER) Const BF_BOTTOM = &H8 Const BF_LEFT = &H1 Const BF_RIGHT = &H4 Const BF_TOP = &H2 Const BF_RECT = (BF_LEFT Or BF_TOP Or BF_RIGHT Or BF_BOTTOM) Const DFC_BUTTON = 4 Const DFC_POPUPMENU = 5 'Only Win98/2000 !! Const DFCS_BUTTON3STATE = &H10 Const DT_CENTER = &H1 Const DC_GRADIENT = &H20 'Only Win98/2000 !! Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Declare Function DrawCaption Lib "user32" (ByVal hWnd As Long, ByVal hdc As Long, pcRect As RECT, ByVal un As Long) As Long Private Declare Function DrawEdge Lib "user32" (ByVal hdc As Long, qrc As RECT, ByVal edge As Long, ByVal grfFlags As Long) As Long Private Declare Function DrawFocusRect Lib "user32" (ByVal hdc As Long, lpRect As RECT) As Long Private Declare Function DrawFrameControl Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) As Long Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long Private Declare Function DrawText2 Lib "user32" Alias "DrawTextW" (ByVal hdc As Long, ByRef lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As Long, ByVal y As Long) As Long Dim ret As Long, i As Long Private Sub Command1_Click() Dim R As RECT 'Clear the form Me.Cls 'API uses pixels Me.ScaleMode = vbPixels 'Set the rectangle's values SetRect R, 0, 0, Me.ScaleWidth, 20 'Draw a caption on the form ret& = GetTickCount& For i = 1 To 100000 DrawText Me.hdc, "Hello World !", Len("Hello World !"), R, DT_CENTER Next i ret& = GetTickCount& - ret& MsgBox Str$(ret) End Sub Private Sub Command2_Click() Dim R As RECT Dim strTemp As String 'Clear the form Me.Cls 'API uses pixels Me.ScaleMode = vbPixels 'Set the rectangle's values SetRect R, 0, 0, Me.ScaleWidth, 20 'Draw a caption on the form strTemp = "Hello World !" ret& = GetTickCount& For i = 1 To 100000 DrawText2 Me.hdc, strTemp, Len(strTemp), R, DT_CENTER Next i ret& = GetTickCount& - ret& MsgBox Str$(ret) End Sub Выдает результаты 790 / 1200 не в пользу *W функции! Для меня это пока удивительно... К тому же выводимая абракадабра *W-функцией говорит о том, что либо VB преобразует BSTR в ABSTR независимо от вызываемой функции, либо строка уже ABSTR... Чудно однако, поясните, плиз, кто в этом разбирается, сложившуюся ситуацию, что *A-функция работает быстрее *W-функции. (Я вижу пока только одно объяснение: VB преобразует BSTR в ABSTR независимо от вызываемой функции) |
![]() |
Сообщ.
#4
,
|
|
Во первых термины
ASCII это кодировка. A-функции от слова ANSI, это целый набор кодировок разработанный угадайте кем. Unicode это не кодировка. В MSDN везде пишут unicode, но вообще полезно знать что в понятие Unicode входит дофига кодировок, а windows nt использует в себе конкретно UTF-16 Далее. Большинство(если не все) W-функций не работают в windows 98 без одного патча. Если бы VB считал что функция ожидает двухбайтовые симолы, то программ написанные на нем оказались бы весьма непотребными в течении долгого времени. Почему в картинке четыре нуля в конце? Цитата EvgenyR_(Djoser) @ Ага. Как он должен угадывать где у тебя A-функция а где нет? Я вижу пока только одно объяснение: VB преобразует BSTR в ABSTR независимо от вызываемой функции |
Сообщ.
#5
,
|
|
|
Цитата ANDLL @ Почему в картинке четыре нуля в конце? Этот вопрос к чему относится? Цитата ANDLL @ Как он должен угадывать где у тебя A-функция а где нет? Ну мы же прямо декларим: Цитата EvgenyR_(Djoser) @ Alias "DrawTextW" Получить последний символ в названии задекларенной функции такая уж проблема для VB? Цитата ANDLL @ A-функции от слова ANSI, это целый набор кодировок разработанный угадайте кем. American National Standard Institute ![]() Добавлено А вообще надо дизасмить и смотреть ![]() |
![]() |
Сообщ.
#6
,
|
|
Цитата EvgenyR_(Djoser) @ Буква в конце названия функции это не отражение в имени. Согласно соглашениям содержимое функции от имени не зависит. Исходя из этого дальше допрешь? Получить последний символ в названии задекларенной функции такая уж проблема для VB? Добавлено Цитата EvgenyR_(Djoser) @ Не к чему, а к кому, к автору топика. Этот вопрос к чему относится? |
Сообщ.
#7
,
|
|
|
Данный факт кстати и получен методом великой IDA и OllyDebugger.
В последнее время очень увлёкся внутреннестями VB ![]() Цитата EvgenyR_(Djoser) @ Если строки в VB изначально хранятся в Unicode формате, то не разумнее ли было бы использовать *W функции, опуская тем самым преобразование Unicode->ASCII (BSTR->ABSTR)? Поправьте меня если я что-то не так понял Поправлять нечего. Так и есть, перед каждым вызовом API, строка перегоняется из юникода. VB на самом деле криво работает с Unicode, хотя это является его родной кодировкой. Данным вопросом задавались здесь (читал по диагонали поэтому не могу сказать об информативности статьи) Цитата ANDLL @ Почему в картинке четыре нуля в конце? Да, скосячил, поправлю. На самом деле там должно быть 2 нулевых байта, если верить этому |
Сообщ.
#8
,
|
|
|
Строки в VB6 http://silicontaiga.ru/home.asp?artId=5110
|