Очередной прокол MS.

Модератор: Хакер

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Очередной прокол MS.

Сообщение Хакер » 21.12.2007 (Пт) 23:22

Понадобилось мне сейчас (собственно, понадобилось давно, но руки дошли только сейчас) сделать некий Add-in, в котором при определённых действиях над проектом выполнялся бы некоторый код. Причём, не над всеми проектами, а над проектами только конкретных типов.

Ну ладно :) Открою тайну :)

Я делаю 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 - не существует какого-либо способа отловить изменение типа проекта. Ни событий, ничего. Я уж подумал, может быть при изменении типа проекта он удаляется и добавляется заново (потому что для меня это был бы идеальный вариант - не надо было бы писать доп. кода) - нет же.

Что это значит?
Это значит, что классы надо создавать для всех типов проектов, а уже некоторые действия при компиляции совершать только над проектами определённых (нужных нам) типов.

В принципе, большой проблемы в этом нет - редко кто работает с большим количеством проектов одновременно. Но всё-таки, обидно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 22.12.2007 (Сб) 22:28

Всё-таки...
Всё-таки эти недочёты меня достали. Я захотел возможность в нужный мне момент добавить в проект модуль кода, в в нужный момент - удалить. Чего-либо вроде CodePanes.Add я не нашёл.

Ладно, думаю, фиг с ним, можно извратиться и создать модуль с помощью VBE.CommandBars(...).Controls(...).Execute.

А как удалить модуль? Я никакого способа не нашёл, даже через CommandBars.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Мой блог

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9

    TopList