Public Declare Function StrRest(ByRef string1 as Byte) as Long
Dim abytTest() as Byte
Dim lngAPIReturn as Long
abytTest = "Мама мыла папу." & vbNullChar
lngAPIReturn = StrRest(abytTest(0))
TEH3OP писал(а):Сабж.
1) Прописать функцию так:
- Код: Выделить всё
Public Declare Function StrRest(ByRef string1 as Byte) as Long
, а работать с функцией так:
- Код: Выделить всё
Dim abytTest() as Byte
Dim lngAPIReturn as Long
abytTest = "Мама мыла папу." & vbNullChar
lngAPIReturn = StrRest(abytTest(0))
Public Declare Function StrRest(ByVal string1 as Long) as Long
Dim lngAPIReturn as Long
lngAPIReturn = StrRest(StrPtr("Мама мыла папу."))
Dim lngPtr as long
Dim bstTest as String
bstTest = "Здесь был Я!"
lngPtr = StrPtr(bstTest)
StrRest lngPtr
Dim bstTest as String
bstTest = "Здесь был Я!"
StrRest StrPtr(bstTest)
Dim bstTest as String
bstTest = "Здесь был Я!"
StrRest VarPtr(VarPtr(ByVal bstTest)) 'вроде так... сорры VB нет под рукой, чтобы проверить.
AfxWin.h писал(а):typedef WCHAR OLECHAR;
...
typedef OLECHAR* BSTR;
Public Declare Function StrRest(ByRef str as String) as Long
long StrRest(BSTR*str)
{
str++;//Учитываем длину заголовка
...
}
ANDLL писал(а):tyomitch писал(а):Указатель на данные строки, тогда как VarPtr - указатель на дескриптор (BSTR) строки
Т.е. StrPtr=VarPtr+4???
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Sub Main()
Dim s As String, l As Long
s = "Hello!"
CopyMemory l, ByVal VarPtr(s), 4
Debug.Print l, StrPtr(s)
End Sub
TEH3OP писал(а):2 tyomitch: я не говорю, что этот способ самый наилучший, зачем делать такое лицо. Я просто рассказал про то, что есть такой способ.
Кстати, BSTR -- это НЕ дескриптор. >;-\
TEH3OP писал(а):2 ANDLL: Там всё немного хитрее. Главное, что такой код
- Код: Выделить всё
Dim lngPtr as long
Dim bstTest as String
bstTest = "Здесь был Я!"
lngPtr = StrPtr(bstTest)
StrRest lngPtr
-- опасен и може привести к неожиданному результату, вплоть до Memory Exeption'на.
TEH3OP писал(а):
- Код: Выделить всё
Dim bstTest as String
bstTest = "Здесь был Я!"
StrRest VarPtr(VarPtr(ByVal bstTest)) 'вроде так... сорры VB нет под рукой, чтобы проверить.
будет вполне нормально работать.
ANDLL писал(а):И соответственно:
- Код: Выделить всё
long StrRest(BSTR*str)
{
str++;//Учитываем длину заголовка
...
}
ANDLL писал(а):Господа! Чтите MSDN - це великая рукопись! К примеру там указано простейшее решение моей проблемы(сам недавно нашел):
- Код: Выделить всё
Public Declare Function StrRest(ByRef str as String) as Long
И соответственно:
- Код: Выделить всё
long StrRest(BSTR*str)
{
str++;//Учитываем длину заголовка
...
}
Вот как все иногда просто! VB не преобразует строку в ASCII если она передаеться по адресу.
Ennor писал(а):Брюс МакКинни в своей книге "Hardcore Visual Basic" утверждает, что басик в принципе не позволяет работать с юникод-версиями АПИ-шных функций, за исключением одного-единственного способа - через TLB. Так что... думайте сами, нужно оно вам или нет.
Option Explicit
Private Declare Function MessageBoxW Lib "user32" (ByVal hWnd As Long, ByVal lpText As Long, ByVal lpCaption As Long, ByVal wType As Long) As Long
Sub Main()
MessageBoxW 0, StrPtr("VB прекрасно может работать с Unicode API!"), StrPtr("Наглый гон!"), vbInformation
End Sub
Ennor писал(а):2 tyomitch:
Хм. А кто тебе сказал, что туда передается действительно Unicode-данные? Вот иероглифов или диакритики туда насуй и посмотри... А корректное отображение русского - это не доказательство.
Option Explicit
Private Declare Function MessageBoxW Lib "user32" (ByVal hWnd As Long, ByVal lpText As Long, ByVal lpCaption As Long, ByVal wType As Long) As Long
Sub Main()
Dim Proof As String
Proof = "Диакритика: " & ChrW(&HC1) & ChrW(&HD5) & ChrW(&HE9) & vbCrLf & _
"Греческий: " & ChrW(&H39E) & ChrW(&H3B3) & ChrW(&H3C7) & vbCrLf & _
"Еврейский: " & ChrW(&H5D0) & ChrW(&H5E4) & ChrW(&H5E9) & vbCrLf & _
"Арабский: " & ChrW(&H626) & ChrW(&H63A) & ChrW(&H64A) & vbCrLf & _
"Тайский: " & ChrW(&HE04) & ChrW(&HE18) & ChrW(&HE2C) & vbCrLf & _
"Ещё надо?"
MessageBoxW 0, StrPtr(Proof), StrPtr("Наглый гон!"), vbInformation
End Sub
Ennor писал(а):Ну что я могу сказать... Значит, МакКинни облажался.
Ennor писал(а):С другой стороны, лично мне еще ни разу не требовалось посылать WCHAR-строки апишкам, хотя то, что это принципиальное ограничение снято, не может не радовать. Правда, остается еще один важный вопрос: как передавать юникод, если строка является частью структуры? Думаю, опять-таки потребуется эксперимент.
Option Explicit
Private Declare Function MessageBoxW Lib "user32" (ByVal hWnd As Long, ByVal lpText As Long, ByVal lpCaption As Long, ByVal wType As Long) As Long
Type SameAsString
Data As String * 256
End Type
Sub Main()
Dim Proof As SameAsString
Proof.Data = "VB прекрасно может работать с Unicode-строками даже в структурах!"
MessageBoxW 0, VarPtr(Proof), StrPtr("МакКинни нас всех нае***!"), vbInformation
End Sub
Ты не понял сути проблемы. Надо не передать Unicode-строку, хранящуюся в структуре, а передать структуру, содержащую в себе Unicode-строку. Так что у меня всё правильно. И действительно, это просто в данном конкретном случае указатели совпадают.GSerg писал(а):Маленькое уточнение: varptr(proof.data). Это только в данном конкретном случае указатели совпадают
tyomitch писал(а):ANDLL писал(а):И соответственно:
- Код: Выделить всё
long StrRest(BSTR*str)
{
str++;//Учитываем длину заголовка
...
}
Непонятно, почему нужно увеличивать str. Ты этот код проверял?
Мне кажется, что в данном случае (BSTR*str) *str указывает на первый символ строки, (*str + 2) - на второй и т.д.
У тебя же получается нечётный адрес, где имхо ничего лежать не может.
ANDLL писал(а):tyomitch писал(а):ANDLL писал(а):И соответственно:
- Код: Выделить всё
long StrRest(BSTR*str)
{
str++;//Учитываем длину заголовка
...
}
Непонятно, почему нужно увеличивать str. Ты этот код проверял?
Мне кажется, что в данном случае (BSTR*str) *str указывает на первый символ строки, (*str + 2) - на второй и т.д.
У тебя же получается нечётный адрес, где имхо ничего лежать не может.
Да, проверял. Если к примеру str=15, то после str++, str будет равно 17.(Так работает оператор инкремента с указателями).
Сдвигать надо, что бы учесть длинну заголовка BSTR.(т.е. *str указывает на число символов в строке, а дальше уже идет сама строка)
long StrRest(BSTR*str)
{
str++;
MessageBoxW(NULL,*str,L"Строка",0);
return 0;
...
}
Private Declare Function StrRest Lib "X-Lib.dll" (ByRef xStr As String) As Long
StrRest "VB-String"
ANDLL писал(а):Длина строки конечно, по-идее должна быть DWORD(4 байта), а не WORD(2 байта).
В-общем так:
- Код: Выделить всё
long StrRest(BSTR*str)
{
str++;
MessageBoxW(NULL,*str,L"Строка",0);
return 0;
...
}
И:
- Код: Выделить всё
Private Declare Function StrRest Lib "X-Lib.dll" (ByRef xStr As String) As Long
StrRest "VB-String"
И сее работает. Если убрать str++, то не работает.
Я пока еще не совсем вник, но могу сказать, что операция str++ увеличивает str не на два байта.
Объяснение: str есть BSTR* -> OLECHAR**. sizeof(OLECHAR*) равно DWORD(т.е. 4, т.к. указатель)
Не проверял, но по идее так.
long StrRest(BSTR*str)
{
MessageBoxA(NULL,*str,"Строка",0);
return 0;
...
}
Сейчас этот форум просматривают: AhrefsBot, Google-бот, Yandex-бот и гости: 15