Re[4]: одновременная работа со строками в разных кодировках
От: ma3ai  
Дата: 22.04.03 15:36
Оценка:
Здравствуйте, LantY, Вы писали:

Спасибо за участие в моём вопросе.

LY>... (подозреваю, что это проблема редактора)

точно
LY>ОДНО НО!!! Пришлось использовать не стандартные VB компоненты, а библиотеку MS Forms 2.0
то же самое
LY>Я уже писал в предыдущем сообщении: попробуй работать со входными строками AS IS. И забуть про конвертацию.
И да и нет. Не всё так просто если используется какой-нибудь API (из-за чего собс-но всё заварилось) Всё зависит от того, как енту строку подставить.
В моём случае это было так (очень коротко для простоты):
FindNextFileW(ID,FileInfo)
Теперь в FileInfo.cFileName Unicode строка но записанная в ANSI секцию VB строки (см. ниже)
т.е. строка “ABC” (побайтно — 41 00 42 00 43 00) записывается как (41 00 00 00 42 00 00 00 43 00 00 00) Вот и видим что-то типа этого
Ну и как тут не задумаешся о том что это безобразие надо-бы конвертнуть куда-нибудь с глаз долой ?

В общем, в конечном счёте обнаружилось множество интересных нюансов (где-то можно сказать — багов) в работе и взаимодействии некоторых почтенных приложений.
Т.е. где-то поддержку Unicode “вгрызли” на последних минутах разработки, где-то сказались привычки “зубров” писать только C_строки. Бурелом какой-то.

Самое главное, о чём я до этого не подозревал это то, что VB фактически хранит 2 (!) строки в разных местах:
1 — Однобайтовая (ANSI) строка. Для передачи в API типа FuncA
2 — Двухбайтовая (Unicode) строка для себя или для API ф-ий типа FuncW.
Проверить можно кодом ниже. Это ж какая расточительность, блин – на каждый символ 3 байта.

А вообще для работы с API+Unicode+VB теперь использую массивы – нету многих заморочек и местами быстрей до 30% Такой вот расклад. Если интересно – пишите письма.

Public Sub TestStrings()
    Dim str As String
    Const Bytes As Long = 16
    str = "AC-ïðî"
    Debug.Print String(Bytes * 3 + 18, "=")
    Debug.Print "ANSI    " & DumpANSI(str, Bytes)
    Debug.Print "Unicode " & DumpUnicode(str, Bytes)
End Sub

Private Function DumpANSI(ByRef str As String, ByRef Bytes As Long) As String
    Dim addr As Long
    CopyMemory addr, str, 4
    DumpANSI = HexDump(addr, Bytes)
End Function

Private Function DumpUnicode(ByRef str As String, ByRef Bytes As Long) As String
    DumpUnicode = HexDump(StrPtr(str), Bytes)
End Function

Private Function HexDump(ByRef addr As Long, ByRef Bytes As Long) As String
    Dim arr() As Byte
    Dim Iterator As Long
    If addr = 0 Then
        Err.Raise 5000, , "Not valid address."
    End If
    ReDim arr(Bytes - 1)
    CopyMemory arr(0), ByVal addr, Bytes
    For Iterator = 0 To (Bytes - 1)
        HexDump = HexDump & Right$("0" & Hex(arr(Iterator)), 2) & " "
    Next
    HexDump = "0x" & Right$("00000000" & Hex(addr), 8) & " " & HexDump
End Function
...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.