Атрибут
A VB_PredeclaredId
позволяет вашему идентификатору Class1
автоматически ссылаться на объект глобальной области с таким именем, например, UserForm1
- это имя модуля класса (один с конструктором, но эта часть не имеет значения), и это имя глобального, автоматизированного объекта, порожденного VBA во время выполнения, и компилятор знает, что Class1.DoStuff
допустимо , потому что знает, что Class1
имеет VB_PredeclaredId
, установленное в True
.
Благодаря работе и вкладу Уэйна Филлипса (vbWatchDog) и других участников, Rubberduck подключается к этому внутреннему API .
Как показано в связанном коде(C #), вы можете получить ITypeLib
для проекта VBA из его коллекции References
, превратив указатель в структуру с этим конкретным макетом:
[StructLayout(LayoutKind.Sequential)]
internal struct VBEReferencesObj
{
IntPtr _vTable1; // _References vtable
IntPtr _vTable2;
IntPtr _vTable3;
IntPtr _object1;
IntPtr _object2;
public IntPtr _typeLib; // <--- here's the pointer you want
IntPtr _placeholder1;
IntPtr _placeholder2;
IntPtr _refCount;
}
В VBA, который будетпользовательский Type
, который может выглядеть следующим образом:
Public Type VBEReferencesObj
vTable1 As LongPtr
vTable2 As LongPtr
vTable3 As LongPtr
object1 As LongPtr
object2 As LongPtr
typelibPointer As LongPtr '<~ only this one matters
placeholder1 As LongPtr
placeholder2 As LongPtr
refCount As LongPtr
End Type
Как только вы получите указатель на ITypeLib
, вы сможете получить библиотеку типов проекта VBA.
Оттуда вы захотите итерировать типыи оттуда определите, включен ли тип TYPEFLAGS
TYPEFLAG_PREDECLID
(мы делаем это здесь ).
Очевидно, это много экстремального сбоя- пробное и ошибочное кодирование, и я бы не рекомендовал делать это, но в любом случае это возможно , если не рекомендуется.
Не стесняйтесь учиться Rubberduck.VBEEditor.ComManagement.TypeLibs пространства имен.