TN039: реализация автоматизации MFC/OLE
![]() |
---|
Следующая техническая заметка не была обновлена со времени сначала была включена в подключенной документации.В результате некоторые процедуры и разделы могут оказаться устаревшей или неверны.Последние новости, рекомендуется поиск раздела процента в подключенном индексу документации. |
Общие сведения об OLE интерфейса IDispatch
Интерфейс IDispatch означает, которые приложения предоставляют методы и свойства, подобные, что другие приложения, например Visual Basic или другие языки могут использовать функции приложения.Наиболее важной частью этого интерфейса функция IDispatch::Invoke.MFC использует «диспетчер сопоставляет» для реализации IDispatch::Invoke.Сопоставление диспетчера предоставляет сведения о реализации MFC на структуре или «фигуре» для CCmdTarget- производных классов тем, что он может напрямую управлять свойства объекта или вызывает функции элементов в объект для удовлетворения запросов IDispatch::Invoke.
В большинстве случаев ClassWizard и MFC кооперируют, чтобы скрыть большая часть сведений ole-автоматизации от программиста приложения.Разработчик приложения концентрирует на существующей функциональности, чтобы предоставлять в приложении, а не нужно беспокоиться о базовом трубопроводе.
Case, однако, где важно понимать, что MFC выполняется незаметно для пользователя.Эта заметка рассматриваются как платформа присвоено DISPID s на функции-членам и свойствам.Набор знаний алгоритма MFC использует для присвоения DISPID s необходим только когда необходимо знать идентификаторы, например при создании типов «библиотеки» для объектов приложения.
Назначение MFC DISPID
Хотя пользователь автоматизации (Visual Basic) пользователя, например см. в разделе фактические имена свойств и методов, включенных автоматизацией в их коде (например, obj.ShowWindow), реализация IDispatch::Invoke не возвращает фактические имена.Для оптимизации он возвращает DISPID, «cookie» 32 (sp2 волшебный, описывающий метод или свойство, к которому выполняется доступ.Эти значения возвращаются DISPID от реализации IDispatch через другой метод с именем IDispatch::GetIDsOfNames.Без доставки GetIDsOfNames клиентского приложения автоматизации один раз для каждого элемента или свойства, он должен получить доступ и кэширует свои для последующих вызовов IDispatch::Invoke.Таким образом, дорогее ниже приведены только строки выполняется один раз на использование объекта, а не один раз на каждый вызов IDispatch::Invoke.
Определяет DISPID MFC для каждого метода и свойства, основанных на 2 вещах:
Расстояние от верхнего края сопоставления диспетчера (1) relative
Диапазон сопоставления диспетчера из наиболее производного класса (0 родственников)
DISPID Разделено на 2 части.LOWORDDISPID содержащий первый компонент, расстояние от верхнего края сопоставления диспетчера.HIWORD содержит диапазон от наиболее производного класса.Примеры.
class CDispPoint : public CCmdTarget
{
public:
short m_x, m_y;
...
DECLARE_DISPATCH_MAP()
...
};
class CDisp3DPoint : public CDispPoint
{
public:
short m_z;
...
DECLARE_DISPATCH_MAP()
...
};
BEGIN_DISPATCH_MAP(CDispPoint, CCmdTarget)
DISP_PROPERTY(CDispPoint, "x", m_x, VT_I2)
DISP_PROPERTY(CDispPoint, "y", m_y, VT_I2)
END_DISPATCH_MAP()
BEGIN_DISPATCH_MAP(CDisp3DPoint, CDispPoint)
DISP_PROPERTY(CDisp3DPoint, "z", m_z, VT_I2)
END_DISPATCH_MAP()
Как можно видеть, 2 класса, оба они предоставляют интерфейсы ole-автоматизации.Один из этих классов является производным от другого, и, таким образом, использует функциональность базового типа, в том числе часть ole-автоматизации (свойства «x» и «y», в данном случае).
MFC создает DISPID s для класса CDispPoint следующим образом:
property X (DISPID)0x00000001
property Y (DISPID)0x00000002
Поскольку свойства в базовом классе HIWORDDISPID всегда равно нулю (расстояние от наиболее производного класса для CDispPoint нуля).
MFC создает DISPID s для класса CDisp3DPoint следующим образом:
property Z (DISPID)0x00000001
property X (DISPID)0x00010001
property Y (DISPID)0x00010002
Присваивается свойству Z DISPID с нуля HIWORD поскольку определено в классе, который предоставляет свойства, CDisp3DPoint.С помощью свойства x и y, укажите в базовом классе HIWORDDISPID 1, поскольку класс, в котором эти свойства определяются в диапазоне одного вывода из наиболее производного класса.
![]() |
---|
LOWORD всегда определяется позицией в сопоставлении, даже если существуют записи в сопоставлении с явным DISPID (см. следующий раздел для информации о версиях _ID макросов DISP_PROPERTY и DISP_FUNCTION ). |
Расширенные функции сопоставления диспетчера MFC
Ряд дополнительных функций, ClassWizard не поддерживает с этим выпуском Visual C++.ClassWizard поддерживает DISP_FUNCTION, DISP_PROPERTY и DISP_PROPERTY_EX, которые указывают метод, свойство элемента переменной и получают/свойство функции-члена набора, соответственно.Обычно все эти возможности, необходимые для создания большинства серверы автоматизации.
Следующие дополнительные макросы могут использоваться, если макросы, поддерживаемые ClassWizard не адекватни: DISP_PROPERTY_NOTIFY и DISP_PROPERTY_PARAM.
Описание DISP_PROPERTY_NOTIFY - макрос
DISP_PROPERTY_NOTIFY(
theClass,
pszName,
memberName,
pfnAfterSet,
vtPropType
)
Заметки
Параметры
theClass
Имя класса.pszName
Внешнее имя свойства.memberName
Имя переменной, в которой свойство хранится для участника.pfnAfterSet
Имя функции-члена, вызываемый при изменении свойства.vtPropType
Значение, указывающее тип свойства.
Заметки
Этот макрос DISP_PROPERTY аналогично, за исключением того, что он принимает дополнительный аргумент.Дополнительный аргумент, pfnAfterSet, должен быть функцией-членом, который не возвращает никаких действий и не принимает параметров, «пустое OnPropertyNotify ()».Он вызывается после переменную-член будет изменена.
Описание DISP_PROPERTY_PARAM - макрос
DISP_PROPERTY_PARAM(
theClass,
pszName,
pfnGet,
pfnSet,
vtPropType,
vtsParams
)
Заметки
Параметры
theClass
Имя класса.pszName
Внешнее имя свойства.memberGet
Имя функции-члена, используемого для которого нужно получить свойство.memberSet
Имя функции-члена, используемого для задания свойства.vtPropType
Значение, указывающее тип свойства.vtsParams
Строка пробелы отделила VTS_ для каждого параметра.
Заметки
Дополнительные DISP_PROPERTY_EX в качестве макроса, этот макрос указывает свойство обращения к файлу с отдельной возвращает и присвойте функции-члены.Этот макрос, однако позволяет указать список параметров для свойств.Это полезно для реализации свойства, которые индексируются или параметризованными каким-либо другим способом.Параметры всегда будут размещены сначала выполнить новое значение для свойства.Примеры.
DISP_PROPERTY_PARAM(CMyObject, "item", GetItem, SetItem, VT_DISPATCH, VTS_I2 VTS_I2)
соответствует для получения и задания функции-члены:
LPDISPATCH CMyObject::GetItem(short row, short col)
void CMyObject::SetItem(short row, short col, LPDISPATCH newValue)
Description - макрос
DISP_FUNCTION_ID(
theClass,
pszName,
dispid,
pfnMember,
vtRetVal,
vtsParams
)
DISP_PROPERTY_ID(
theClass,
pszName,
dispid,
memberName,
vtPropType
)
DISP_PROPERTY_NOTIFY_ID(
theClass,
pszName,
dispid,
memberName,
pfnAfterSet,
vtPropType
)
DISP_PROPERTY_EX_ID(
theClass,
pszName,
dispid,
pfnGet,
pfnSet,
vtPropType
)
DISP_PROPERTY_PARAM_ID(
theClass,
pszName,
dispid,
pfnGet,
pfnSet,
vtPropType,
vtsParams
)
Заметки
Параметры
theClass
Имя класса.pszName
Внешнее имя свойства.dispid
Фиксированное DISPID для свойства или метода.pfnGet
Имя функции-члена, используемого для которого нужно получить свойство.pfnSet
Имя функции-члена, используемого для задания свойства.memberName
Имя переменной члена, который необходимо сопоставить к свойствуvtPropType
Значение, указывающее тип свойства.vtsParams
Строка пробелы отделила VTS_ для каждого параметра.
Заметки
Эти макросы позволяют определить DISPID MFC вместо позволяя автоматически присвоено одно.Эти сложные макросы имеют те же имена, за исключением того, что идентификатор добавляется к имени макроса (например.DISP_PROPERTY_ID) и идентификатор определяются параметром указанным сразу после параметра pszName.См. раздел AFXDISP.H дополнительные сведения об этих макросов.Записи _ID необходимо поместить в конце сопоставления диспетчера.Они повлияют на автоматическое создание DISPID точно так же, как версия _ID, отличного от макроса, но DISPID определяется позицией (s).Примеры.
BEGIN_DISPATCH_MAP(CDisp3DPoint, CCmdTarget)
DISP_PROPERTY(CDisp3DPoint, "y", m_y, VT_I2)
DISP_PROPERTY(CDisp3DPoint, "z", m_z, VT_I2)
DISP_PROPERTY_ID(CDisp3DPoint, "x", 0x00020003, m_x, VT_I2)
END_DISPATCH_MAP()
MFC создает идентификаторов dispid для класса CDisp3DPoint следующим образом:
property X (DISPID)0x00020003
property Y (DISPID)0x00000002
property Z (DISPID)0x00000001
Определение постоянного DISPID полезен для поддержания обратной совместимости к ранее существующему интерфейсу диспетчеризации или некоторую систему, указанная на реализацию методов и свойств (обычно отображаемые отрицательным DISPID, как коллекция DISPID_NEWENUM ).
Извлечение интерфейса IDispatch, COleClientItem
Многие серверы поддерживают автоматизацию в объекты документов вместе с функцией OLE-сервер.Для получения доступа к данному интерфейсу автоматизации, необходимо непосредственно обратиться к переменной-члену COleClientItem::m_lpObject.Приведенный ниже код извлекает интерфейс IDispatch для объекта, производного от COleClientItem.Можно включать приведенный ниже код в приложении если эта функциональность обязательная:
LPDISPATCH CMyClientItem::GetIDispatch()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
LPUNKNOWN lpUnk = m_lpObject;
Run(); // must be running
LPOLELINK lpOleLink = NULL;
if (m_lpObject->QueryInterface(IID_IOleLink,
(LPVOID FAR*)&lpOleLink) == NOERROR)
{
ASSERT(lpOleLink != NULL);
lpUnk = NULL;
if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
{
TRACE0("Warning: Link is not connected!\n");
lpOleLink->Release();
return NULL;
}
ASSERT(lpUnk != NULL);
}
LPDISPATCH lpDispatch = NULL;
if (lpUnk->QueryInterface(IID_IDispatch, &lpDispatch)
!= NOERROR)
{
TRACE0("Warning: does not support IDispatch!\n");
return NULL;
}
ASSERT(lpDispatch != NULL);
return lpDispatch;
}
Интерфейс диспетчеризации, возвращенный из этой функции может затем использоваться напрямую или вложен в COleDispatchDriver для типобезопасного доступа.Если используется непосредственно, убедитесь, что участник Выпуск вызовите его через с когда указатель (деструктор COleDispatchDriver осуществляется по умолчанию).