|
Программирование >> Перегруженные имена функций и идентификаторы
предлагающих функциональность интерфейса IDispatch, поэтому для создания объекта, готового к автоматизации, необходимо всего лишь несколько раз щелкнуть мышкой в ClassWizard Visual C++. Что касается способа доступа и динамического создания ваших внутренних dispatch объектов, то тут тут тоже все довольно просто - данные об объекте хранятся в реестре под специальным кодовым именем, которое называется Progld. Например, progid программы Excel - Excel.Application. Создать в любой процедуре на VBScript достаточно легко - надо только вызвать функцию CreateObject, в которую передать нужный ProglD. Функция вернет указатель на созданный объект. В MFC существует специальный класс, под названием CCmdTarget. Наследуя свои классы от CCmdTarget, вы можете обеспечить для них необходимую функциональность в dispatch виде - как раз как ее понимают скрипты. При создании нового класса в ClassWizard (View <> ClassWizard * Add Class <> New), наследуемого от CCmdTarget, просто щелкните на кнопке Automation или Creatable by ID, чтобы обеспечить возможность создания экземпляра объекта по его ProglD. Заметим, что дя программ, реализующих внутреннюю автоматизацию, это не нужно. Для приложений, реализующих внешнюю и смешанную автоматизацию, это необходимо для корневых объектов. COM-объекты можно создавать только динамически. Это связано с тем, что объект может использоваться несколькими приложениями одновременно, а значит, удаление объекта из памяти не может выполнить ни одно из них. Разумно предположить, что объект сам должен отвечать за свое удаление. Такой механизм реализован при помощи механизма ссылок (reference count). Когда приложение получает указатель на объект, он увеличивает свой внутренний счетчик ссылок, а когда приложение освобождает объект - счетчик ссылок уменьшается. При достижении счетчиком нуля, объект удаляет сам себя. Если наш объект был создан по ProgID другим приложением, то программа CTestApp (другими словами, Automation-Server) не завершится до тех пор, пока счетчик ссылок CTestAutomatedClass не станет равным нулю. Создаваемые через ProgID COM-объекты, обычно являются Proxy-компонентами. Реально они не содержат никакой функциональности, но имеют доступ к приложению и его внутренним, не доступным извне, функциям. Хотя можно организовать все таким образом, чтобы всегда создавался только один COM-объект, а все остальные вызовы на создание возвращали указатели на него. Метод интерфейса CCmdTarget GetIDispatch(), позволяет получить указатель на реализованный интерфейс IDispatch. В параметрах можно указать, нужно ли увеличивать счетчик ссылок или нет. Оболочка из классов для COM Программировать с использованием COM настолько трудно, что вы не должны даже пробовать это без MFC. Правильно или неправильно? Абсолютная чушь! Рекламируемые OLE и его преемник COM имеют элегантность гиппопотама, занимающегося фигурным катанием. Но размещение MFC на вершине COM подобно одеванию гиппопотама в клоунский костюм еще больших размеров. Итак, что делать программисту, когда он столкнется с потребностью использовать возможности оболочки Windows, которые являются доступными только через интерфейсы COM? Для начала, всякий раз, когда вы планируете использовать COM, вы должны сообщить системе, чтобы она инициализировала COM подсистему. Точно так же всякий раз, когда вы заканчиваете работу, вы должны сообщить системе, чтобы она выгрузила COM. Самый простой способ это сделать заключается в определении объекта, конструктор которого инициализирует COM, а деструктор выгружает ее. Самое лучшее место, для внедрения данного механизма - это объект Controller. class Controller public: Controller (HWND hwnd, CREATESTRUCT * pCreate); Controller (); ... private: UseCom comUser; Im a COM user Model model; View view; HINSTANCE hInst; Этот способ гарантирует, что COM подсистема будет проинициализирована прежде, чем к ней будут сделаны любые обращения и что она будет освобождена после того, как программа осуществит свои разрушения (то есть, после того, как Вид и Модель будут разрушены). Класс UseCom очень прост. class UseCom { public: UseCom () HRESULT err = Colnitialize (0); if (err != S OK) throw Couldnt initialize COM ; ~UseCom () CoUninitialize (); Пока не б1о слишком трудно, не так ли? Дело в том, что мы не коснулись главной мерзости COM программирования - подсчета ссылок. Вам должно быть известно, что каждый раз, когда вы получаете интерфейс, его счетчик ссылок увеличивается. И вам необходимо явно уменьшать его. И это становится более чем ужасным тогда, когда вы начинаете запрашивать интерфейсы, копировать их, передавать другим и т.д. Но ловите момент: мы знаем, как управляться с такими проблемами! Это называется управлением ресурсами. Мы никогда не должны касаться интерфейсов COM без инкапсуляции их в интеллектуальных указателях на интерфейсы. Ниже показано, как это работает. template <class T>class SIfacePtr public: ~SIfacePtr ()
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |