Поделиться через


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 
)

Заметки

w7a36sdf.collapse_all(ru-ru,VS.110).gifПараметры

  • theClass
    Имя класса.

  • pszName
    Внешнее имя свойства.

  • memberName
    Имя переменной, в которой свойство хранится для участника.

  • pfnAfterSet
    Имя функции-члена, вызываемый при изменении свойства.

  • vtPropType
    Значение, указывающее тип свойства.

Заметки

Этот макрос DISP_PROPERTY аналогично, за исключением того, что он принимает дополнительный аргумент.Дополнительный аргумент, pfnAfterSet, должен быть функцией-членом, который не возвращает никаких действий и не принимает параметров, «пустое OnPropertyNotify ()».Он вызывается после переменную-член будет изменена.

Описание DISP_PROPERTY_PARAM - макрос

DISP_PROPERTY_PARAM( 
   theClass,
   pszName,
   pfnGet,
   pfnSet,
   vtPropType,
   vtsParams 
)

Заметки

w7a36sdf.collapse_all(ru-ru,VS.110).gifПараметры

  • 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 
)

Заметки

w7a36sdf.collapse_all(ru-ru,VS.110).gifПараметры

  • 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 ).

w7a36sdf.collapse_all(ru-ru,VS.110).gifИзвлечение интерфейса 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 осуществляется по умолчанию).

См. также

Другие ресурсы

Технические замечания по номеру

Технические замечания по категориям