Страницы: Пред. 1 2
RSS
Обеспечение совместимости Excel VBA приложения для систем разной разрядности и с разными региональными установками.
 
Здравствуйте, коллеги! Благодарю за внимание к теме.
Принципы работы с юникод-версиями Windows API описаны здесь. Главный инструмент исследования для автора этой темы, по меткому выражению Владимира (ZVI) - "грабли натоптанные". VBA Excel - отличный стенд для испытаний!
В пункте 3.4 сообщения #1 возможные инструменты перечислены в порядке предпочтения. Например, большинство Win API (юникод), предназначенных для файловых операций, "обернуты" соответствующими свойствами и методами объектов FSO и Shell.Application и их (API) прямое использование не имеет особого смысла. Справедливости ради упомяну, с другой стороны, функцию SHCreateDirectoryExW, не имеющую, насколько я понимаю, прямого аналога (см. также здесь).
Примеры вызова API (юникод) есть и во вложении к #1.

Если есть затруднения с переходом за юникод-версию с ANSI-версии какого-либо API, то думаю, что данная тема подходит для соответствующего обсуждения.
Изменено: sokol92 - 16.07.2019 16:18:24
Владимир
 
Уважаемый Korshi, в #1 изложена точка зрения автора, подкрепленная примерами во вложении. Если у Вас есть ее опровержение или дополнение, то будет интересно с этим ознакомиться. Сообщение #30 вряд ли подходит для данной темы, для конкретных вопросов есть основная ветвь форума.
Владимир
 
sokol92, как вы пришли к тому, что нужно использовать StrPtr? Я перешел по ссылке, которую вы дали, там нет StrPtr.
Вы просто в интернете нашли этот способ или сами его придумали, основываясь на своих знаниях?
Просто хотел бы найти достоверный способ работы с юникодными api-функциями.
Изменено: Korshi - 16.07.2019 19:56:05
 
Я с Excel работаю достаточно давно, так что на вопрос о том, когда и где узнал про функцию StrPtr, затрудняюсь ответить. Кроме VBA я писал программы и на C, что, несомненно, облегчает понимание данного предмета.

Будем считать подход, изложенный в #1, достоверным (проверен на многих функциях), пока не установлено обратное. :)  
Владимир
 
Цитата
Korshi написал:
Вы просто в интернете нашли этот способ или сами его придумали, основываясь на своих знаниях?
Какая разница? Вы можете проверить, так это или нет, а далее выбирать использовать или искать официальный документ, описывающий фичу или багу.
По вопросам из тем форума, личку не читаю.
 
БМВ, автор книги Эпплман пишет, что VB не приспособлен для работы с юникодными api-функциями.
Также этот автор книги пишет плохо про StrPtr.
Также этот автор нарисовал в книге какие-то действия с памятью.
Всё это меня и привело к тому, что мне захотелось найти достоверную информацию.
Изменено: Korshi - 16.07.2019 22:47:10
 
Цитата
Korshi написал:
мне захотелось найти достоверную информацию.
я беру и проверяю. Это единственная информация которой я доверяю, остальное все  - выводы других на основании того, что они получили в их условиях. Вот возьмите например тему рядом. Условия разные - разный результат и выводы, при этом словам Владимира, что одного, что другого, у меня лично нет повода не доверять, но результат то у ZVI отличен от результата у БМВ.
По вопросам из тем форума, личку не читаю.
 
Цитата
Korshi написал:...мне захотелось найти достоверную информацию
Чтобы понять все тонкости работы с массивами Unicode и ANSI в VB и API-функциях рекомендую почитать главу 6 книги  "Программирование в Win32 API на Visual Basic" автор - Стивен Роман. Наберите в поисковике это название и автора.
Вот пример:
Код
Option Explicit

#If VBA7 Then
  Declare PtrSafe Function CharUpper Lib "user32" Alias "CharUpperA" (ByVal lpsz As String) As String
  Declare PtrSafe Function CharUpper1 Lib "user32" Alias "CharUpperW" (ByVal lpsz As LongPtr) As LongPtr
#Else
  Declare Function CharUpper Lib "user32" Alias "CharUpperA" (ByVal lpsz As String) As Long
  Declare Function CharUpper1 Lib "user32" Alias "CharUpperW" (ByVal lpsz As Long) As Long
#End If

Sub Test1()
  Dim Txt As String
  Txt = "Текст"
  Debug.Print Txt
  Call CharUpper(Txt)
  Debug.Print Txt
End Sub

Sub Test2()
  Dim Txt As String
  Txt = "Текст"
  Debug.Print Txt
  Call CharUpper1(StrPtr(Txt))
  Debug.Print Txt
End Sub

Когда декларируется переменная Dim Txt As String, и затем Txt = "Текст",  то в памяти по адресу VarPtr(Txt) записывается адрес StrPtr(Txt) первого символа массива Unicode-символов с дополнительным нулевым Unicode-символом в конце, а в 4 байта перед этим адресом записывается количество байт этого массива без учета дополнительного символа (т.е. 10 Байт в данном случае - по 2 на каждый Unicode-символ).
Test2 выполняет преобразование непосредственно.
А в Test1 VB сначала преобразует массив Unicode-символов в массив ANSI-символов с нулевым байтом в конце и передает его в DLL, где массив ANSI преобразуется в UNICODE, чтобы использовать для преобразования CharUpperW, затем результат в DLL снова преобразуется в ANSI и возвращается в VB, а VB еще раз преобразует ANSI в UNICODE. Оно Вам надо? :)
Изменено: ZVI - 17.07.2019 18:28:44
 
Цитата
БМВ написал:
я беру и проверяю.
В книге Эпплмана есть изображения памяти и что-то он пишет про память, поэтому внутренние процессы я не вижу и может быть так, что видимых проблем нет, но есть скрытые проблемы. VBA сделан так, что программисту не нужно думать о памяти. А C++ сделан так, что программист должен думать о памяти, иначе могут быть непредсказуемые результаты. При использовании StrPtr с памятью работает не VBA, а С++ (api-функция, написанная на языке C++) (я так думаю).
Изменено: Korshi - 17.07.2019 08:36:57
 
Владимир, спасибо (хотел написать что-то подобное, проснулся, а всё уже сделано лучше задуманного). :)

Korshi, опасаться StrPtr нужно не более, чем вообще применения Windows API. И без этой функции неправильное использование API легко вырубает Excel, так что при отладке сохраняйте свои произведения как можно чаще. То, что некоторые называют функцию StrPtr недокументированной, это преувеличение, эта функция специально создана разработчиком для работы с API ("...указатели, которые могут передаваться операторам Declare").
Владимир
Страницы: Пред. 1 2
Наверх