Чтение онлайн

ЖАНРЫ

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

 DWORD m_dwCookie;

Первая из них есть указатель на интерфейс нашего COM-сервера, который мы создавали несколько раньше. Тип IMyInterfacePtr любезно предоставила нам директива #import, после того как мы подключили файл PointServer.tlb. С помощью данного импорта мы приобрели много полезной информации о нашем сервере. Она находится в файлах PointServer.tlh и PointServer.tli, в том числе и определение IMyInterfacePtr. Изучите эти файлы на досуге и, возможно, вы откроете для себя что-то новое.

Вторая переменная (m_dwCookie) есть уникальный идентификатор, который вернет нам функция AfxConnectionAdvise. Помните, я уже рассказывал о механизме подписки

клиентов на сообщения от сервера. Тогда мы говорили о функциях Advise и Unadvise интерфейса IConnectionPoint. Здесь же мы будем использовать аналоги этих функций — AfxConnectionAdvise и AfxConnectionUnadvise, предоставляемые библиотекой MFC. Так вот, m_dwCookie — это идентификатор нашей подписки, который вернет нам сервер в случае успешной регистрации нашего соединения. Зачем он нам нужен? Ну, хотя бы для того, чтобы отдать его серверу, когда мы пожелаем отписаться от принятия сообщений, ведь должен же сервер знать, кого он будет удалять из своего списка. Другими словами, m_dwCookie — это аналог того номерка, что дают вам злые тети в раздевалках, если вы сдаете одежду, при походах в театр, библиотеку и т.д. Сохраните сделанные нами изменения и закройте этот файл.

Теперь займемся файлом реализации класса CPointClientDlg. Для этого откройте файл PointClientDlg.cpp, найдите функцию OnInitDialog и строку в ней

// TODO: Add extra initialization here

Вот вместо этого напоминания мы сейчас и напишем наш код. Здесь будет находиться код загрузки COM-сервера, а также функция подписки на его события. Итак, вместо комментариев, указанных мастером вставьте следующие строки:

EnableAutomation;

UUID uuid;

m_MyInterface = NULL;

uuid = __uuidof(MyInterface);

m_MyInterface.CreateInstance(uuid);

m_dwCookie = 0;

BOOL Ret = AfxConnectionAdvise(

 m_MyInterface,

 DIID_IFireClassEvents,

 this->GetIDispatch(FALSE), // get the IDispatch assocaiated with Mainframe...

 FALSE, // donod addref

 &m_dwCookie); // cookie to break connection later...

С помощью __uuidof мы получим UUID интерфейса IMyInterface, который затем подставим в функцию CreateInstance. Таким образом, мы вызовем загрузку нашего COM-сервера.

После того, как функция CreateInstance будет успешно выполнена, мы подпишемся на сообщения от интерфейса IFireClassEvents с помощью функции AfxConnectionAdvise. В случае корректного завершения которой мы получим наш идентификатор – m_dwCookie. Приведенный код не содержит механизма обработки возможных ошибок, чтобы не загромождать главную идею, которую мы сейчас рассматриваем. В случае необходимости вы можете добавить его сами. Ну вот, к тому моменту, как мы увидим на экране диалог нашего клиента, COM-сервер будет уже загружен и готов посылать нам событие, что мы реализовали в его коде.

Сразу же добавим код отписки от событий, который вставим в обработчик нажатия кнопки ОК:

void CPointClientDlg::OnOK {

 if (m_MyInterface) {

AfxConnectionUnadvise(m_MyInterface, DIID_IFireClassEvents, this->GetIDispatch(FALSE), FALSE, m_dwCookie);

m_MyInterface = NULL;

 }

 CDialog::OnOK;

}

Здесь

все предельно ясно. Передавая нашу «куку» (m_dmCookie) функции AfxConnectionUnadvise, мы тем самым отписываемся от рассылки событий. После чего делаем m_MyInterface = NULL, чем вызываем выгрузку COM-сервера.

Последним штрихом добавим код в обработчик второй нашей кнопки:

void CPointClientDlg::OnFireevent {

 m_MyInterface->FireMyEvent;

}

Сохраните все сделанные нами изменения и постройте проект. Если все сделали правильно, то должны были получить 2 сообщения об ошибке, рисунок 11.

Рисунок 11

Все правильно. Для того, чтобы эти функции не вызывали ошибок нужно сделать следующее подключение:

#include <afxctl.h>

Попробуйте снова. Сейчас все должно быть без ошибок.

Устали? Я тоже. Подождите, осталось совсем немного. Сейчас мы реализуем код функции, что будет вызывать у нас сервер, и на этом закончим. Итак, откройте файл PointClientDlg.h и сразу после декларации карты сообщений вставьте ещё несколько определений:

DECLARE_DISPATCH_MAP

DECLARE_INTERFACE_MAP

BOOL OnMyEvent;

Таким способом вы объявите две карты: DISPATCH MAP и INTERFACE MAP, которые нам необходимы. А также объявите обработчик OnMyEvent события MyEvent. Сохраните, сделанные изменения и закройте файл.

Теперь откройте файл реализации класса CPointClientDlg, PointClientDlg.cpp, и сразу после окончания реализации карты сообщений вставьте следующий код:

BEGIN_DISPATCH_MAP(CPointClientDlg, CDialog)

 DISP_FUNCTION_ID(CPointClientDlg, "MyEvent",1, OnMyEvent, VT_BOOL, VTS_NONE)

END_DISPATCH_MAP

BEGIN_INTERFACE_MAP(CPointClientDlg, CDialog)

 INTERFACE_PART(CPointClientDlg, DIID_IFireClassEvents, Dispatch)

END_INTERFACE_MAP

BOOL CPointClientDlg::OnMyEvent {

 AfxMessageBox("Event!!!!!!!!");

 return TRUE;

}

Что же это означает?

Во-первых, между макросами BEGIN_DISPATCH_MAP и END_DISPATCH_MAP, с помощью DISP_FUNCTION_ID по номеру метода (1 — см. ODL-файл сервера) мы указываем имя события (MyEvent), его обработчик (OnMyEvent), тип возвращаемого значения (VT_BOOL), а также тип аргументов (VTS_NONE — в данном случае их нет).

Далее идет реализация интерфейсной карты и реализация функции обработчика события OnMyEvent.

На этом, пожалуй, все. Сохраните файл, постройте проект и запустите на выполнение нашего клиента. Если вы все делали правильно, то по нажатию на кнопку "Fire Event", должны получить результат как на рисунке 12.

Рисунок 12

На этом я закончу. Надеюсь, что этот материал кому-то окажет помощь в трудную минуту.

Поделиться с друзьями: