Ну ладно Открою тайну
Я делаю Add-In для второй версии FireNativeDLL.
Так вот, понадобилось мне отслеживать момент компиляции проекта, и совершать с бинарником определённые действия. Причём, естественно, делать эти действия нужно только если тип проекта = ActiveXDLL или ActiveXControl.
Ничего сложного. Есть библиотека Microsoft Visual Basic 6.0 Extensibillity, которая предоставляет нужные классы. На самом деле ничего она не предоставляет, а является простой TLB-шкой, в которой описаны классы и интерфейсы, которые используются внутри VBIDE. Но не важно, важно то, что там есть казалось бы всё необходимое, чтобы реализовать задуманное.
Если бы взялись за эту задачу, к вам бы сразу пришла мысль (ну или по крайней мере - должна была придти) о том, что в одном экземпляре VBIDE может разрабатываться сразу несколько проектов, они могут в любом порядке добавлять и удаляться.
Нет проблем. У нас есть класс свойство VBE.VBProjects класса VBIDE.VBProjects, через которое мы можем получать информацию о всех проектах и отслеживать их создание/удаление.
Хорошо, проблем нет (казалось бы). Так как нам нужно обрабатывать события объектов (по одному для каждого проекта) класса VBIDE.FileControlEvents, нам нужен специальный класс (потому что обработчики событий могут быть только в классе).
Значит, когда в IDE добавляется проект, нам нужно создавать этот специальный класс, а когда удаляется - убивать. Славно. Но мы помним, что нас интересуют проекты лишь двух типов: ActiveXDLL и ActiveXControl. Т.е. создавать объект специального класса и удалять его нужно только для проектов этих двух типов.
Отлично. Получаем что-то вроде этого:
- Код: Выделить всё
Private Sub Projects_ItemAdded(ByVal VBProject As VBIDE.VBProject)
If (VBProject.Type = vbext_pt_ActiveXControl) Or _
(VBProject.Type = vbext_pt_ActiveXDll) Then
Dim NewSatellite As New CProjectSatellite
With NewSatellite
Set .Project = VBProject
.Update
End With
Satellites.Add NewSatellite, VBProject.Name
End If
End Sub
Private Sub Projects_ItemRemoved(ByVal VBProject As VBIDE.VBProject)
Satellites.Remove VBProject.Name
End Sub
И тут наш мозг посещает мысль: А ведь пользователь может в любой момент изменить тип проекта. Это чревато двумя косяками:
1) Ссылки на проекты, которые раньше были валидных (для нас) типов, а теперь перестали таковыми быть, не будут удаляться из коллекции Satellites. Это плохо, потому что во-первых, memory leak, а во-вторых, это наверняка приведёт к багам в работе VBIDE.
2) Если проект вдруг стал валидным для нас, то при его удалении Add-in будет пытаться удалить соответствующий элемент коллекции Satellites, которого там нет (и быть не может).
Ну, вы скажите - надо отлавливать изменение типа проекта и в зависимости от того, что стало с типом, удалять/добавлять проект из коллекции. Конечно, так бы я и сделал, если бы не облом со стороны MS - не существует какого-либо способа отловить изменение типа проекта. Ни событий, ничего. Я уж подумал, может быть при изменении типа проекта он удаляется и добавляется заново (потому что для меня это был бы идеальный вариант - не надо было бы писать доп. кода) - нет же.
Что это значит?
Это значит, что классы надо создавать для всех типов проектов, а уже некоторые действия при компиляции совершать только над проектами определённых (нужных нам) типов.
В принципе, большой проблемы в этом нет - редко кто работает с большим количеством проектов одновременно. Но всё-таки, обидно.