Стою на асфальте я в лыжи обутый, то ли лыжи не едут то ли я ....
А теперь все по порядку.
Решил таки я изучить, как работает энумерация коллекций COM, так сказать изнутри. Но все оказалось довольно запутанным и туманным. Как оказалось каждая коллекция для того, что-бы поддерживалась обработка
For Each In ... Next имеет Property _NewEnum, который если верить документации различных источников и MSDN в т.ч. должен возвращать ссылку на интерфейс IEnumVARIANT, который наследуется от IUnknown и описан в
MSDN- Код: Выделить всё
interface IEnumVARIANT : IUnknown {
virtual HRESULT Next(unsigned long celt,
VARIANT FAR* rgvar,
unsigned long FAR* pceltFetched) = 0;
virtual HRESULT Skip(unsigned long celt) = 0;
virtual HRESULT Reset() = 0;
virtual HRESULT Clone(IEnumVARIANT FAR* FAR* ppenum) = 0;
};
Про то, что коллекция должна иметь _NemEnum, я конечно и раньше знал и не просто знал, а обязательно добавлял в коллекции, которые реализовывал в VB, но что конкретно из себя представляет это свойство узнал только сейчас. Интересненькое дельце, однако идем дальше ... Для реализации энумерации данный интерфейс содержит методы Next, Skip, Reset, Clone. Для перебора коллекции самый нужный метод Next, который описывается
так:
- Код: Выделить всё
HRESULT Next(
unsigned long celt,
VARIANT FAR* rgVar,
unsigned long FAR* pCeltFetched
);
Кажется все предельно ясным? Ага, аж два раза. С первого взгляда конечно, выглядит все предельно просто, но вот при реализации возникает куча непоняток. Казалось, бы получил ссылку на интерфейс IEnumVARIANT от _NewEnum, вызывай себе метод Next и спокойненько обрабатывай, но не тут то было.
Итак грабли №1:
Попытка получить ссылку на IEnumVARIANT от _NewEnum, не такая уж как оказалось тривиальная задача, ибо вызов вида
Object Get MyCollection._NewEnum To ObjMemberв PB не прокатывает, причем если заключить _NewEnum в скобки и использовать так [_NewEnum], ничего ровным счетом не меняет. Значит в лоб вызвать не получается, прийдется идти в обход... Интеренет советует по этому поводу вызов не по имени, а по DispID. По феншую Microsoft у _NewEnum всегда фиксированное имя и ID которое равно равно '-4'. Разумеется, что сразу же возник вопрос, а как вызывать то по этому ID, и что собственно этот ID из себя предствляет. На эту тему в интернете путнего ничего не нашел, поэтому все так и осталось покрыто туманом неведения и догадок. Если DispID это смещение в таблице VTable, то тогда можно организовать вызов по указателю, но вот само значение '-4' или Hex значение '&HFFFF FFFC' меня несколько ставит в тупик, ибо такое большое число как '&HFFFF FFFC' вряд ли может быть смещением. Конечно может смещение действительно равно -4 и смещается в другую сторону от начала таблицы? Типо того:
ID -4 XXXXXXXX
ID 0 XXXXXXXX Начало VTable (Базовый адресок )
ID 4 XXXXXXXX
ID ............Но тоже как то все это очень странно и нелогично.
Вобщем объясните знающие люди, что есть DispID и как его можно применить при вызове свойства/метода?