общее руководство по написанию операторов объявления VBA для использования произвольных Win32 API.
Вот как я это делаю.
I go to https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types и найдите нужный мне тип данных ( Ctrl + F ).
Если он определен в терминах другого типа с той же страницы, Я тоже ищу это ( Ctrl + F ), пока не приду к типу basi c.
Затем я использую тип подходящего размера из VB. int
- это Long
, short
- Integer
, char*
- String
, wchar_t*
- LongPtr
, где вам нужно передать StrPtr
, void*
- LongPtr
.
Я так понимаю, что «As Any» по-прежнему подходит для VBA. Но когда я его использую? Для API, которые принимают VOID? Или pVOID? или LPVOID?
As Any
полезно, когда
- вы не хотите объявлять фактический тип, который он получает (например, это сложная структура, параметр является необязательным , и вы его не используете)
- Там может быть несколько разных вещей, которые могут быть переданы туда, и вы хотите передать их все в разных точках
В противном случае это всегда возможно, безопасно и правильно повторно объявить As Any
с использованием фактического типа, указанного в заголовке API. Часто это указатель ByVal LongPtr
.
Сохранение As Any
накладывает больше ответственности на вызывающего, но дает им больше гибкости. Повторное объявление As Any
как фактического типа устраняет опасность за счет указанной гибкости.
CopyMemory
- прекрасный пример этого принципа.
Объявление pDest As Any, pSrc As Any
является наиболее гибким и может использоваться как:
Dim a As Long, b As Long
CopyMemory a, b, ... ' Copying from variable b to a (a = b)
CopyMemory ByVal VarPtr(a), ByVal VarPtr(b), ... ' Same
Dim a As LongPtr, b As LongPtr
CopyMemory ByVal a, ByVal b, ... ' Copying from memory pointed to by b to memory pointed to by a
, что является гибким, но при неправильном использовании:
Dim a As Long, b As Long
CopyMemory ByVal a, ByVal b, ... ' Wrong: passing values as pointers; likely memory access violation
CopyMemory VarPtr(a), VarPtr(b), ... ' Wrong: passing pointers to pointers;
' Overwrites the temporary storage VB provides
' No crash, but no meaningful copying either
Dim a As LongPtr, b As LongPtr
CopyMemory a, b, ... ' Likely wrong: copying the pointer value of b into a (a = b)
вы можете взломать sh и / или повредить data.
Объявив те же параметры, что и ByVal pDest As LongPtr, ByVal pSrc As LongPtr
, вы теряете возможность передавать Long
s ByRef, как в первом примере, и вам нужно будет явно использовать VarPtr
каждый раз, но вы выиграли ' Не нужно слишком много думать, как вызвать функцию. Тем не менее, есть некоторая опасность, потому что вы все равно можете называть его CopyMemory a, b
с параметрами Long
, и он будет сканировать sh для передачи значений в качестве указателей, но, по крайней мере, вы увидите из определения функции, что вы передаете что-то не так, а As Any
не подскажет.