Пишется на дельфях, но не суть, т.к. всё равно на api.
Что есть
Есть сторонний ActiveX-контрол, выставляющий несколько интерфейсов через механизм ConnectionPoint'ов. Как я понял, стандартный дельфёвский мастер импорта ActiveX-ов не мудрствует: вытягивает выставляемые через IConnectionPointContainer интерфейсы, IPropertyNotifySink пропускает (обрабатывает специфически), а, видимо, первый попавшийся не IPropertyNotifySink оборачивает классом и позволяет получать соответствующие калбэки.
Иногда удобно, но мало.
Что надо
Сторонний контрол имеет десяток версий. Нужный мне ConnectionInterface присутствует во всех версиях, набор методов одинаков, но у этих ConnectionInterface'ов разные guid'ы, и DispID'ы у методов могут различаться. Дельфёвский мастер жёстко прописывает guid ConnectionInterface'а, и это как раз не подходит.
CLSIDFromProgId'ом легко находится guid текущей версии контрола, а вот
как наиболее правильно затратно найти нужный мне ConnectionInterface?
Сейчас так: у уже созданного инстанса контрола запрашивается IConnectionPointContainer, далее EnumConnectionPoints — в общем, IConnectionPoint'ы известны, через их GetConnectionInterface известны IID'ы выставляемых ConnectionInterface'ов. IID-ы — это то, что лежит в HKCR\Interface\{iid}. Вытягиваю оттуда TypeLib и Version. Гружу, получаю ITypeLib, оттуда беру ITypeInfo для IID'ов ConnectionInterface'ов и тупо сравниваю наборы и объявления методов с нужным. Не всё в такой реализации устраивает, поэтому
Вопросы
Возможно ли по CLSID получить LibID (guid библиотеки типов), если в ветке HKCR\CLSID\{clsid_того_контрола} не прописаны ни TypeLib, ни Version, и о чём это говорит — я не знаю
Есть какие-то функции типа CSLIDFromProgID для IID'ов, чтобы не в реестре рыться, а вроде как через "официальный вход" ходить? (для получения, например, ProxyStubCLSID32, TypeLib)
Здравствуйте, Maratius, Вы писали:
M>Есть сторонний ActiveX-контрол, выставляющий несколько интерфейсов через механизм ConnectionPoint'ов. Как я понял, стандартный дельфёвский мастер импорта ActiveX-ов не мудрствует: вытягивает выставляемые через IConnectionPointContainer интерфейсы, IPropertyNotifySink пропускает (обрабатывает специфически), а, видимо, первый попавшийся не IPropertyNotifySink оборачивает классом и позволяет получать соответствующие калбэки.
M>Иногда удобно, но мало.
Неверно. Нет никаких вытягиваний IConnectionPointContainer, потому что эта операция — времени выполнения, а не компиляции или дизайна. Обычно анализируется библиотека типов, в которой для каждого класса указан событийный интерфейс по умолчанию ([default, source]).
M>CLSIDFromProgId'ом легко находится guid текущей версии контрола, а вот как наиболее правильно затратно найти нужный мне ConnectionInterface?
M>Сейчас так: у уже созданного инстанса контрола запрашивается IConnectionPointContainer, далее EnumConnectionPoints — в общем, IConnectionPoint'ы известны, через их GetConnectionInterface известны IID'ы выставляемых ConnectionInterface'ов. IID-ы — это то, что лежит в HKCR\Interface\{iid}. Вытягиваю оттуда TypeLib и Version. Гружу, получаю ITypeLib, оттуда беру ITypeInfo для IID'ов ConnectionInterface'ов и тупо сравниваю наборы и объявления методов с нужным.
Контролы обычно поддерживают интерфейс IProvideClassInfo (и выше), который через GetClassInfo вернет интерфейс ITypeInfo с методом GetContainingTypeLib, возвращающем ITypeLib библиотеки типов контрола, в котором описаны все тебе нужные событийные интерфейсы.
M>Возможно ли по CLSID получить LibID (guid библиотеки типов), если в ветке HKCR\CLSID\{clsid_того_контрола} не прописаны ни TypeLib, ни Version, и о чём это говорит — я не знаю
Если только пройти перебором по всем зарегистрированным библиотекам типа и в каждой посмотреть описан ли нужный кокласс с CLSID, но это так тягомотно, что проще сказать — не возможно.
M>Есть какие-то функции типа CSLIDFromProgID для IID'ов, чтобы не в реестре рыться, а вроде как через "официальный вход" ходить? (для получения, например, ProxyStubCLSID32, TypeLib)
Нет, таких функций нет.