Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

Вторая строка есть объявление интерфейса. Теперь сохраните файл MyInterface.h и закройте его.

Следующим этапом добавим в файл MyInterface.cpp то, о чем собственно говорили только что выше. Найдите в коде декларацию идентификатора IID_IMyInterface и сразу после него вставьте следующие строки (только не забывайте вставлять правильные числовые значения, если вы используете uuid, отличный от того, что создала мне утилита guidgen.exe):

#pragma warning( disable : 4211)

static const IID IID_IFireClassEvents = //(F7222740-2296-11d5-964D-00001CDC1022)

 {0xf7222740, 0x2296, 0x11d5, {0x96, 0x4d, 0x0, 0x0, 0x1c, 0xdc, 0x10, 0x22}};

#pragma warning(default : 4211)

Обратите внимание на две директивы препроцессора, которые окаймляют данное объявление. Первая из них гасит ненужное предупреждение компилятора, а вторая снова его разрешает. Теперь добавьте в карту интерфейсов интерфейс IConnectionPointContainer (MyInterface.cpp):

BEGIN_INTERFACE_MAP(CMyInterface, CCmdTarget)

 INTERFACE_PART(CMyInterface, IID_IMyInterface, Dispatch)

 INTERFACE_PART(CMyInterface, IID_IConnectionPointContainer, ConnPtContainer)

END_INTERFACE_MAP

И наконец, сразу за картой интерфейсов вставьте карту соединений:

BEGIN_CONNECTION_MAP(CMyInterface, CCmdTarget)

 CONNECTION_PART(CMyInterface, IID_IFireClassEvents, ObjCP)

END_CONNECTION_MAP

Затем добавьте в конструктор нашего класса вызов функции EnableConnections. Эта функция является недокументированной функцией класса CCmdTarget, однако если вы не вызовете её из конструктора класса, работающего с Connection point и являющегося потомком CCmdTarget, то у вас ничего не получится.

CMyInterface::CMyInterface {

 EnableAutomation;

 EnableConnections;

 // To keep the application running as long as an OLE automation

 // object is active, the constructor calls AfxOleLockApp.

 AfxOleLockApp;

}

Сохраните редактируемый файл и постройте наш проект. Если вы делали все правильно, то не должно быть ни ошибок, ни предупреждений. На данный момент у нас готов основной каркас. Займемся реализацией непосредственно самих функций. Однако сначала я хотел бы обратить ваше внимание на следующий факт. Я думаю, ни для кого не секрет, что COM-сервер может иметь сразу нескольких клиентов. Может случиться так, что этот сервер должен посылать событие клиентам в ответ на какое-либо действие пользователя. Например, сервер имеет графический интерфейс, и когда пользователь выбирает меню Файл, сервер должен уведомить ВСЕХ ЗАИНТЕРЕСОВАННЫХ клиентов об этом. Естественно возникает 2 вопроса:

1. Каким образом сервер сможет послать событие сразу всем клиентам.

2. Как определить, какой клиент заинтересован в получении событий, а какой нет?

Начнем со второго вопроса. Для этих целей интерфейс IConnectionPoint предусматривает специальные методы подписки на события Advise и Unadvise. С помощью первого из них клиент сообщает серверу, что он желает получать уведомления относительно какого-либо события, а вторая функция, наоборот, сообщает серверу, что данный клиент больше в таких сообщениях не нуждается. Соответственно, сервер должен иметь некий список, в который он заносит клиентов, подписанных на те или иные сообщения. И из которого он потом будет удалять отписавшихся клиентов. Таким образом, когда серверу нужно будет послать некое событие клиентам, то он в цикле пробежится по этому списку и отправит сообщения всем заинтересованным клиентам. Это и есть ответ на первый вопрос. Теперь приведем процедуру, которая реализует все выше сказанное. Вставьте её код в файл MyInterface.cpp а также не забудьте объявить её в MyInterfcae.h.

void CMyInterface::FireEvent {

 const CPtrArray* pConnections=m_xObjCP.GetConnections;

 int nConnections=pConnections->GetSize;

 for (int i=0; i<nConnections; i++) {

IDispatch* pClient=(IDispatch*)(pConnections->GetAt(i));

if (pClient) {

VARIANT varResult;

DISPPARAMS disp={0,0,0,0};

HRESULT hr = pClient->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);

}

 }

}

Итак, что же мы имеем? Скажу сразу, что MFC сильно облегчила нам жизнь. Здесь const CPtrArray* pConnections=m_xObjCP.GetConnections; мы объявляем указатель на CPtrArray и присваиваем ему значение полученное из m_xObjCP.GetConnections. Вот и все. Теперь мы имеем указатель на список всех наших потенциальных клиентов. Объект m_xObjCP поддерживается средствами CCmdTarget и самостоятельно, «без нашего участия» заносит в список подписавшихся и удаляет из него отписавшихся клиентов. Дальше все просто: мы перебираем в цикле всех наших клиентов и с помощью метода Invoke им события.

  • Читать дальше
  • 1
  • ...
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: